ramaze 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. data/Rakefile +20 -3
  2. data/bin/ramaze +1 -4
  3. data/doc/AUTHORS +2 -1
  4. data/doc/CHANGELOG +539 -32
  5. data/doc/LEGAL +4 -0
  6. data/doc/meta/announcement.txt +79 -47
  7. data/examples/blog/README +2 -2
  8. data/examples/blog/spec/blog.rb +33 -48
  9. data/examples/blog/src/controller.rb +15 -13
  10. data/examples/blog/src/model.rb +28 -10
  11. data/examples/blog/start.rb +0 -10
  12. data/examples/blog/template/edit.xhtml +1 -1
  13. data/examples/blog/template/index.xhtml +2 -2
  14. data/examples/facebook.rb +152 -0
  15. data/examples/linking.rb +28 -0
  16. data/examples/ramaise.rb +4 -11
  17. data/examples/rammit/spec/rammit.rb +30 -0
  18. data/examples/rammit/src/controller/main.rb +3 -0
  19. data/examples/rammit/src/controller/page.rb +16 -0
  20. data/examples/rammit/src/model.rb +33 -0
  21. data/examples/rammit/start.rb +7 -0
  22. data/examples/rammit/template/index.xhtml +14 -0
  23. data/examples/rammit/template/page/view.xhtml +4 -0
  24. data/examples/rapaste/Rakefile +28 -0
  25. data/examples/rapaste/public/css/active4d.css +114 -0
  26. data/examples/rapaste/public/css/all_hallows_eve.css +72 -0
  27. data/examples/rapaste/public/css/amy.css +147 -0
  28. data/examples/rapaste/public/css/blackboard.css +88 -0
  29. data/examples/rapaste/public/css/brilliance_black.css +605 -0
  30. data/examples/rapaste/public/css/brilliance_dull.css +599 -0
  31. data/examples/rapaste/public/css/cobalt.css +149 -0
  32. data/examples/rapaste/public/css/dawn.css +121 -0
  33. data/examples/rapaste/public/css/display.css +179 -0
  34. data/examples/rapaste/public/css/eiffel.css +121 -0
  35. data/examples/rapaste/public/css/espresso_libre.css +109 -0
  36. data/examples/rapaste/public/css/idle.css +62 -0
  37. data/examples/rapaste/public/css/iplastic.css +80 -0
  38. data/examples/rapaste/public/css/lazy.css +73 -0
  39. data/examples/rapaste/public/css/mac_classic.css +123 -0
  40. data/examples/rapaste/public/css/magicwb_amiga.css +104 -0
  41. data/examples/rapaste/public/css/pastels_on_dark.css +188 -0
  42. data/examples/rapaste/public/css/slush_poppies.css +85 -0
  43. data/examples/rapaste/public/css/spacecadet.css +51 -0
  44. data/examples/rapaste/public/css/sunburst.css +180 -0
  45. data/examples/rapaste/public/css/twilight.css +137 -0
  46. data/examples/rapaste/public/css/zenburnesque.css +91 -0
  47. data/examples/rapaste/public/js/jquery.js +11 -0
  48. data/examples/rapaste/rapaste.sqlite +0 -0
  49. data/examples/rapaste/spec/rapaste.rb +49 -0
  50. data/examples/rapaste/src/controller.rb +69 -0
  51. data/examples/rapaste/src/model.rb +61 -0
  52. data/examples/rapaste/start.rb +20 -0
  53. data/examples/rapaste/template/copy.xhtml +10 -0
  54. data/examples/rapaste/template/index.xhtml +9 -0
  55. data/examples/rapaste/template/layout.xhtml +22 -0
  56. data/examples/rapaste/template/list.xhtml +28 -0
  57. data/examples/rapaste/template/view.xhtml +37 -0
  58. data/examples/sourceview/sourceview.rb +3 -3
  59. data/examples/templates/template_amrita2.rb +1 -3
  60. data/examples/todolist/spec/todolist.rb +15 -18
  61. data/examples/whywiki/spec/whywiki.rb +15 -20
  62. data/examples/whywiki/start.rb +0 -1
  63. data/examples/wikore/spec/wikore.rb +14 -19
  64. data/examples/wiktacular/spec/wiktacular.rb +8 -15
  65. data/lib/proto/{src/controller → controller}/main.rb +4 -4
  66. data/lib/proto/public/css/ramaze_error.css +39 -3
  67. data/lib/proto/public/js/jquery.js +2039 -1020
  68. data/lib/proto/spec/main.rb +27 -0
  69. data/lib/proto/start.rb +5 -5
  70. data/lib/proto/view/error.xhtml +62 -0
  71. data/lib/proto/view/index.xhtml +34 -0
  72. data/lib/proto/view/page.xhtml +15 -0
  73. data/lib/ramaze.rb +9 -7
  74. data/lib/ramaze/action.rb +7 -3
  75. data/lib/ramaze/action/render.rb +15 -5
  76. data/lib/ramaze/adapter.rb +5 -5
  77. data/lib/ramaze/adapter/base.rb +2 -2
  78. data/lib/ramaze/adapter/cgi.rb +1 -1
  79. data/lib/ramaze/adapter/evented_mongrel.rb +1 -1
  80. data/lib/ramaze/adapter/fcgi.rb +2 -2
  81. data/lib/ramaze/adapter/mongrel.rb +1 -1
  82. data/lib/ramaze/adapter/swiftiplied_mongrel.rb +1 -1
  83. data/lib/ramaze/adapter/thin.rb +25 -0
  84. data/lib/ramaze/adapter/webrick.rb +1 -1
  85. data/lib/ramaze/cache.rb +3 -2
  86. data/lib/ramaze/cache/memcached.rb +1 -1
  87. data/lib/ramaze/cache/memory.rb +1 -1
  88. data/lib/ramaze/cache/yaml_store.rb +1 -1
  89. data/lib/ramaze/contrib.rb +1 -1
  90. data/lib/ramaze/contrib/auto_params.rb +12 -5
  91. data/lib/ramaze/contrib/auto_params/get_args.rb +1 -0
  92. data/lib/ramaze/contrib/facebook.rb +23 -0
  93. data/lib/ramaze/contrib/facebook/facebook.rb +168 -0
  94. data/lib/ramaze/contrib/gettext.rb +111 -0
  95. data/lib/ramaze/contrib/gettext/mo.rb +155 -0
  96. data/lib/ramaze/contrib/gettext/po.rb +109 -0
  97. data/lib/ramaze/contrib/gzip_filter.rb +1 -1
  98. data/lib/ramaze/contrib/route.rb +15 -5
  99. data/lib/ramaze/contrib/sequel/fill.rb +1 -1
  100. data/lib/ramaze/controller.rb +10 -4
  101. data/lib/ramaze/controller/error.rb +5 -13
  102. data/lib/ramaze/controller/main.rb +2 -0
  103. data/lib/ramaze/controller/resolve.rb +18 -10
  104. data/lib/ramaze/dispatcher.rb +1 -1
  105. data/lib/ramaze/dispatcher/action.rb +1 -1
  106. data/lib/ramaze/dispatcher/directory.rb +3 -2
  107. data/lib/ramaze/dispatcher/error.rb +5 -5
  108. data/lib/ramaze/dispatcher/file.rb +13 -2
  109. data/lib/ramaze/error.rb +1 -1
  110. data/lib/ramaze/gestalt.rb +2 -2
  111. data/lib/ramaze/global.rb +5 -5
  112. data/lib/ramaze/global/dsl.rb +1 -1
  113. data/lib/ramaze/global/globalstruct.rb +11 -5
  114. data/lib/ramaze/helper.rb +1 -1
  115. data/lib/ramaze/helper/aspect.rb +1 -1
  116. data/lib/ramaze/helper/auth.rb +2 -2
  117. data/lib/ramaze/helper/cache.rb +1 -1
  118. data/lib/ramaze/helper/cgi.rb +1 -1
  119. data/lib/ramaze/helper/file.rb +1 -1
  120. data/lib/ramaze/helper/flash.rb +1 -1
  121. data/lib/ramaze/helper/formatting.rb +1 -1
  122. data/lib/ramaze/helper/identity.rb +1 -1
  123. data/lib/ramaze/helper/inform.rb +1 -1
  124. data/lib/ramaze/helper/link.rb +4 -4
  125. data/lib/ramaze/helper/markaby.rb +1 -1
  126. data/lib/ramaze/helper/nitroform.rb +1 -1
  127. data/lib/ramaze/helper/pager.rb +2 -1
  128. data/lib/ramaze/helper/partial.rb +1 -1
  129. data/lib/ramaze/helper/redirect.rb +6 -1
  130. data/lib/ramaze/helper/sequel.rb +54 -0
  131. data/lib/ramaze/helper/stack.rb +1 -1
  132. data/lib/ramaze/inform.rb +1 -1
  133. data/lib/ramaze/inform/analogger.rb +1 -1
  134. data/lib/ramaze/inform/growl.rb +1 -1
  135. data/lib/ramaze/inform/hub.rb +1 -1
  136. data/lib/ramaze/inform/informer.rb +1 -1
  137. data/lib/ramaze/inform/informing.rb +2 -2
  138. data/lib/ramaze/inform/knotify.rb +1 -1
  139. data/lib/ramaze/inform/syslog.rb +1 -1
  140. data/lib/ramaze/inform/xosd.rb +1 -1
  141. data/lib/ramaze/snippets.rb +1 -1
  142. data/lib/ramaze/snippets/array/put_within.rb +1 -1
  143. data/lib/ramaze/snippets/blankslate.rb +7 -0
  144. data/lib/ramaze/snippets/dictionary.rb +6 -1
  145. data/lib/ramaze/snippets/divide.rb +1 -1
  146. data/lib/ramaze/snippets/kernel/__dir__.rb +1 -1
  147. data/lib/ramaze/snippets/kernel/acquire.rb +39 -0
  148. data/lib/ramaze/snippets/kernel/aquire.rb +1 -34
  149. data/lib/ramaze/snippets/kernel/constant.rb +1 -1
  150. data/lib/ramaze/snippets/kernel/pretty_inspect.rb +1 -1
  151. data/lib/ramaze/snippets/numeric/filesize_format.rb +1 -1
  152. data/lib/ramaze/snippets/object/traits.rb +1 -1
  153. data/lib/ramaze/snippets/ordered_set.rb +12 -7
  154. data/lib/ramaze/snippets/ramaze/caller_info.rb +1 -1
  155. data/lib/ramaze/snippets/ramaze/caller_lines.rb +1 -1
  156. data/lib/ramaze/snippets/string/camel_case.rb +1 -1
  157. data/lib/ramaze/snippets/string/color.rb +2 -4
  158. data/lib/ramaze/snippets/string/each.rb +1 -1
  159. data/lib/ramaze/snippets/string/ord.rb +15 -0
  160. data/lib/ramaze/snippets/string/snake_case.rb +1 -1
  161. data/lib/ramaze/snippets/struct/fill.rb +4 -2
  162. data/lib/ramaze/snippets/struct/values_at.rb +2 -2
  163. data/lib/ramaze/snippets/symbol/to_proc.rb +15 -8
  164. data/lib/ramaze/snippets/thread/into.rb +1 -1
  165. data/lib/ramaze/sourcereload.rb +4 -3
  166. data/lib/ramaze/spec/helper.rb +85 -32
  167. data/lib/ramaze/spec/helper/bacon.rb +7 -0
  168. data/lib/ramaze/spec/helper/browser.rb +1 -2
  169. data/lib/ramaze/spec/helper/mock_http.rb +1 -1
  170. data/lib/ramaze/spec/helper/pretty_output.rb +70 -0
  171. data/lib/ramaze/spec/helper/requester.rb +1 -1
  172. data/lib/ramaze/spec/helper/simple_http.rb +5 -4
  173. data/lib/ramaze/spec/helper/snippets.rb +6 -0
  174. data/lib/ramaze/store/default.rb +1 -1
  175. data/lib/ramaze/template.rb +1 -1
  176. data/lib/ramaze/template/amrita2.rb +6 -5
  177. data/lib/ramaze/template/erubis.rb +1 -1
  178. data/lib/ramaze/template/ezamar.rb +1 -1
  179. data/lib/ramaze/template/ezamar/element.rb +1 -1
  180. data/lib/ramaze/template/ezamar/engine.rb +1 -1
  181. data/lib/ramaze/template/ezamar/morpher.rb +1 -1
  182. data/lib/ramaze/template/ezamar/render_partial.rb +1 -1
  183. data/lib/ramaze/template/haml.rb +1 -1
  184. data/lib/ramaze/template/liquid.rb +1 -1
  185. data/lib/ramaze/template/markaby.rb +1 -1
  186. data/lib/ramaze/template/nagoro.rb +4 -6
  187. data/lib/ramaze/template/none.rb +1 -1
  188. data/lib/ramaze/template/remarkably.rb +1 -1
  189. data/lib/ramaze/template/sass.rb +1 -1
  190. data/lib/ramaze/tool.rb +1 -1
  191. data/lib/ramaze/tool/create.rb +7 -1
  192. data/lib/ramaze/tool/localize.rb +7 -14
  193. data/lib/ramaze/tool/mime.rb +1 -1
  194. data/lib/ramaze/tool/record.rb +1 -1
  195. data/lib/ramaze/trinity.rb +1 -1
  196. data/lib/ramaze/trinity/request.rb +4 -2
  197. data/lib/ramaze/trinity/response.rb +1 -1
  198. data/lib/ramaze/trinity/session.rb +7 -1
  199. data/lib/ramaze/version.rb +3 -3
  200. data/lib/vendor/bacon.rb +317 -0
  201. data/rake_tasks/conf.rake +1 -1
  202. data/rake_tasks/maintenance.rake +7 -5
  203. data/rake_tasks/spec.rake +54 -40
  204. data/spec/contrib/auto_params.rb +21 -4
  205. data/spec/contrib/route.rb +31 -4
  206. data/spec/contrib/sequel/fill.rb +3 -4
  207. data/spec/examples/caching.rb +5 -2
  208. data/spec/examples/css.rb +5 -2
  209. data/spec/examples/element.rb +5 -4
  210. data/spec/examples/hello.rb +1 -0
  211. data/spec/examples/linking.rb +18 -0
  212. data/spec/examples/simple.rb +13 -18
  213. data/spec/examples/templates/template_amrita2.rb +3 -2
  214. data/spec/examples/templates/template_erubis.rb +3 -2
  215. data/spec/examples/templates/template_ezamar.rb +2 -1
  216. data/spec/examples/templates/template_haml.rb +3 -2
  217. data/spec/examples/templates/template_liquid.rb +3 -2
  218. data/spec/examples/templates/template_markaby.rb +3 -2
  219. data/spec/examples/templates/template_remarkably.rb +3 -2
  220. data/spec/ramaze/action/basics.rb +4 -4
  221. data/spec/ramaze/action/cache.rb +11 -13
  222. data/spec/ramaze/action/layout.rb +47 -3
  223. data/spec/ramaze/action/render.rb +3 -3
  224. data/spec/ramaze/action/template/instancevars/layout.xhtml +1 -0
  225. data/spec/ramaze/adapter.rb +7 -7
  226. data/spec/ramaze/adapter/mongrel.rb +1 -1
  227. data/spec/ramaze/adapter/record.rb +7 -7
  228. data/spec/ramaze/adapter/webrick.rb +1 -1
  229. data/spec/ramaze/cache.rb +6 -8
  230. data/spec/ramaze/controller.rb +77 -65
  231. data/spec/ramaze/controller/resolve.rb +2 -1
  232. data/spec/ramaze/controller/template_resolving.rb +3 -4
  233. data/spec/ramaze/dispatcher.rb +3 -4
  234. data/spec/ramaze/dispatcher/directory.rb +35 -35
  235. data/spec/ramaze/dispatcher/file.rb +8 -5
  236. data/spec/ramaze/element.rb +4 -4
  237. data/spec/ramaze/error.rb +13 -11
  238. data/spec/ramaze/gestalt.rb +1 -1
  239. data/spec/ramaze/helper/aspect.rb +2 -1
  240. data/spec/ramaze/helper/auth.rb +4 -2
  241. data/spec/ramaze/helper/cache.rb +10 -9
  242. data/spec/ramaze/helper/cgi.rb +2 -2
  243. data/spec/ramaze/helper/file.rb +1 -0
  244. data/spec/ramaze/helper/flash.rb +5 -4
  245. data/spec/ramaze/helper/formatting.rb +1 -1
  246. data/spec/ramaze/helper/link.rb +3 -3
  247. data/spec/ramaze/helper/pager.rb +44 -80
  248. data/spec/ramaze/helper/partial.rb +2 -3
  249. data/spec/ramaze/helper/redirect.rb +10 -1
  250. data/spec/ramaze/helper/stack.rb +4 -3
  251. data/spec/ramaze/helper/template/loop.xhtml +2 -1
  252. data/spec/ramaze/inform/informer.rb +2 -2
  253. data/spec/ramaze/inform/syslog.rb +1 -1
  254. data/spec/ramaze/localize.rb +26 -26
  255. data/spec/ramaze/morpher.rb +6 -7
  256. data/spec/ramaze/params.rb +7 -8
  257. data/spec/ramaze/request.rb +27 -6
  258. data/spec/ramaze/request/mongrel.rb +1 -1
  259. data/spec/ramaze/request/thin.rb +9 -0
  260. data/spec/ramaze/session.rb +2 -1
  261. data/spec/ramaze/store/default.rb +14 -17
  262. data/spec/ramaze/template.rb +5 -7
  263. data/spec/ramaze/template/amrita2.rb +4 -1
  264. data/spec/ramaze/template/erubis.rb +2 -1
  265. data/spec/ramaze/template/ezamar.rb +2 -3
  266. data/spec/ramaze/template/ezamar/other__index.xhtml +1 -0
  267. data/spec/ramaze/template/haml.rb +2 -1
  268. data/spec/ramaze/template/liquid.rb +4 -2
  269. data/spec/ramaze/template/markaby.rb +4 -2
  270. data/spec/ramaze/template/nagoro.rb +3 -4
  271. data/spec/ramaze/template/remarkably.rb +4 -2
  272. data/spec/ramaze/template/sass.rb +3 -2
  273. data/spec/ramaze/template/xslt.rb +4 -7
  274. data/spec/ramaze/trinity/request.rb +4 -3
  275. data/spec/ramaze/trinity/session.rb +6 -4
  276. data/spec/snippets/array/put_within.rb +3 -2
  277. data/spec/snippets/divide.rb +1 -4
  278. data/spec/snippets/kernel/__dir__.rb +1 -1
  279. data/spec/snippets/kernel/acquire.rb +71 -0
  280. data/spec/snippets/kernel/constant.rb +4 -8
  281. data/spec/snippets/numeric/filesize_format.rb +1 -1
  282. data/spec/snippets/ordered_set.rb +9 -2
  283. data/spec/snippets/ramaze/caller_info.rb +3 -3
  284. data/spec/snippets/ramaze/caller_lines.rb +3 -3
  285. data/spec/snippets/string/camel_case.rb +1 -1
  286. data/spec/snippets/string/color.rb +2 -2
  287. data/spec/snippets/string/snake_case.rb +5 -1
  288. data/spec/snippets/string/unindent.rb +1 -1
  289. data/spec/snippets/struct/fill.rb +14 -15
  290. data/spec/snippets/struct/values_at.rb +15 -10
  291. data/spec/snippets/symbol/to_proc.rb +13 -0
  292. data/spec/snippets/thread/into.rb +3 -4
  293. metadata +458 -386
  294. data/doc/README.html +0 -729
  295. data/doc/changes.txt +0 -5044
  296. data/doc/changes.xml +0 -5046
  297. data/lib/proto/public/error.zmr +0 -61
  298. data/lib/proto/src/element/page.rb +0 -17
  299. data/lib/proto/src/model.rb +0 -6
  300. data/lib/proto/template/index.xhtml +0 -15
  301. data/lib/ramaze/spec/helper/layout.rb +0 -58
  302. data/lib/ramaze/spec/helper/minimal.rb +0 -23
  303. data/lib/ramaze/spec/helper/wrap.rb +0 -198
  304. data/spec/snippets/kernel/aquire.rb +0 -71
@@ -1,28 +1,20 @@
1
1
  require 'ramaze'
2
2
  require 'ramaze/spec/helper'
3
3
 
4
- # if these libraries are missing there is no sense in running the tests,
5
- # cause they won't work at all.
6
- testcase_requires 'bluecloth', 'hpricot', 'nagoro'
4
+ spec_require 'bluecloth', 'hpricot'
7
5
 
8
- $:.unshift 'examples/whywiki'
6
+ $LOAD_PATH.unshift base = __DIR__/'..'
9
7
 
10
- Db = Ramaze::YAMLStoreCache.new('testwiki.yaml')
8
+ Db = Ramaze::YAMLStoreCache.new("#{base}/testwiki.yaml")
11
9
  require 'start'
12
10
 
13
- class WikiController < Ramaze::Controller
14
- template_root __DIR__ / '../template'
15
- end
16
-
17
- describe WikiController do
18
- after :all do
19
- FileUtils.rm('testwiki.yaml')
20
- end
11
+ describe 'WikiController' do
12
+ behaves_like 'http'
21
13
 
22
14
  def page(name)
23
- page = get('/'+name)
15
+ page = get(name)
24
16
  page.status.should == 200
25
- page.body.should_not be_nil
17
+ page.body.should.not == nil
26
18
 
27
19
  doc = Hpricot(page.body)
28
20
  title = doc.at('title').inner_html
@@ -32,32 +24,35 @@ describe WikiController do
32
24
  end
33
25
 
34
26
  it 'should start' do
35
- ramaze :public_root => '.', :port => 7001
27
+ ramaze :public_root => base/:public,
28
+ :template_root => base/:template
36
29
  get('/').status.should == 303
37
30
  end
38
31
 
39
32
  it 'should have main page' do
40
33
  t,body = page('/show/Home')
41
- t.should match(/^MicroWiki Home$/)
34
+ t.should.match(/^MicroWiki Home$/)
42
35
  body.at('h1').inner_html.should == 'Home'
43
36
  body.at('a[@href=/edit/Home]').inner_html.should == 'Create Home'
44
37
  end
45
38
 
46
39
  it 'should have edit page' do
47
40
  t,body = page('/edit/Home')
48
- t.should match(/^MicroWiki Edit Home$/)
41
+ t.should.match(/^MicroWiki Edit Home$/)
49
42
 
50
43
  body.at('a[@href=/]').inner_html.should == '&lt; Home'
51
44
  body.at('h1').inner_html.should == 'Edit Home'
52
- body.at('form[@action=/save]>textarea[@name=text]').should_not be_nil
45
+ body.at('form[@action=/save]>textarea[@name=text]').should.not == nil
53
46
  end
54
47
 
55
48
  it 'should create pages' do
56
49
  post('/save','text'=>'the text','page'=>'ThePage').status.should == 303
57
50
  page = Hpricot(get('/show/ThePage').body)
58
51
  body = page.at('body>div')
59
- body.should_not be_nil
52
+ body.should.not == nil
60
53
  body.at('a[@href=/edit/ThePage]').inner_html.should =='Edit ThePage'
61
54
  body.at('p').inner_html.should == 'the text'
62
55
  end
56
+
57
+ FileUtils.rm("#{base}/testwiki.yaml")
63
58
  end
@@ -10,7 +10,6 @@ Db = Ramaze::YAMLStoreCache.new('wiki.yaml') unless defined?(Db)
10
10
 
11
11
  class WikiController < Ramaze::Controller
12
12
  map :/
13
- engine :Nagoro
14
13
 
15
14
  def index
16
15
  redirect R(:show, 'Home')
@@ -1,16 +1,17 @@
1
1
  require 'ramaze'
2
2
  require 'ramaze/spec/helper'
3
3
 
4
- # if these libraries are missing there is no sense in running the tests,
5
- # cause they won't work at all.
6
- testcase_requires 'hpricot'
7
- testcase_requires 'sequel'
4
+ spec_require 'hpricot', 'sequel'
8
5
 
9
- $:.unshift __DIR__/'../'
6
+ $LOAD_PATH.unshift base = __DIR__/'..'
10
7
  require 'start'
11
8
 
12
9
  describe 'Wikore' do
13
- def should_redirect to = '/'
10
+ behaves_like 'http'
11
+ ramaze :public_root => base/:public,
12
+ :template_root => base/:template
13
+
14
+ def check_redirect(to = '/')
14
15
  response = yield
15
16
  response.status.should == 303
16
17
  response.body.should =~ /<a href="#{to}">/
@@ -24,10 +25,6 @@ describe 'Wikore' do
24
25
  end
25
26
  end
26
27
 
27
- before :all do
28
- ramaze :template_root => (__DIR__/'../template')
29
- end
30
-
31
28
  it 'should have no Main page' do
32
29
  page = get('/Main')
33
30
  page.status.should == 200
@@ -35,7 +32,7 @@ describe 'Wikore' do
35
32
  end
36
33
 
37
34
  it 'should create a Main page' do
38
- should_redirect '/Main' do
35
+ check_redirect '/Main' do
39
36
  post('/page/create', 'title' => 'Main', 'text' => 'Newly created Main page')
40
37
  end
41
38
 
@@ -47,7 +44,7 @@ describe 'Wikore' do
47
44
  end
48
45
 
49
46
  it 'should update Main page' do
50
- should_redirect '/Main' do
47
+ check_redirect '/Main' do
51
48
  post('/page/save', 'title' => 'Main', 'text' => 'Newly updated Main page')
52
49
  end
53
50
 
@@ -87,10 +84,10 @@ describe 'Wikore' do
87
84
  end
88
85
 
89
86
  it 'should rename Main page to Other and back' do
90
- should_redirect '/Other' do
87
+ check_redirect '/Other' do
91
88
  get('/page/rename/Main/Other')
92
89
  end
93
- should_redirect '/Main' do
90
+ check_redirect '/Main' do
94
91
  get('/page/rename/Other/Main')
95
92
  end
96
93
  end
@@ -102,15 +99,13 @@ describe 'Wikore' do
102
99
  end
103
100
 
104
101
  it 'should fail if create/save is not POSTed to' do
105
- should_redirect '/' do
102
+ check_redirect '/' do
106
103
  get('/page/save', 'title' => 'Main', 'text' => 'Newly updated Main page')
107
104
  end
108
- should_redirect '/' do
105
+ check_redirect '/' do
109
106
  get('/page/create', 'title' => 'Main', 'text' => 'Newly updated Main page')
110
107
  end
111
108
  end
112
109
 
113
- after :all do
114
- FileUtils.rm('wikore.db')
115
- end
110
+ FileUtils.rm('wikore.db')
116
111
  end
@@ -1,27 +1,19 @@
1
1
  require 'ramaze'
2
2
  require 'ramaze/spec/helper'
3
3
 
4
- # if these libraries are missing there is no sense in running the tests,
5
- # cause they won't work at all.
6
- testcase_requires 'bluecloth'
7
- testcase_requires 'hpricot'
4
+ spec_require 'hpricot', 'bluecloth'
8
5
 
9
- $:.unshift 'examples/wiktacular'
6
+ $LOAD_PATH.unshift base = __DIR__/'..'
10
7
  require 'start'
11
8
 
12
- # fix the paths to template and public for the spec
13
- # this is not needed usually, but this tests are also part of ramaze's suite
14
- class MainController
15
- template_root __DIR__ / '../template'
16
- end
17
-
18
9
  describe 'wiktacular' do
10
+ behaves_like 'http'
19
11
  NEWPAGE = "newpagename"
20
12
 
21
13
  def check_page(name)
22
14
  page = get('/'+name)
23
15
  page.status.should == 200
24
- page.body.should_not be_nil
16
+ page.body.should.not == nil
25
17
 
26
18
  doc = Hpricot(page.body)
27
19
  doc.at('title').inner_html.should == 'Wiktacular'
@@ -32,7 +24,7 @@ describe 'wiktacular' do
32
24
 
33
25
  navigation = doc.search('div#navigation>div>a')
34
26
  %w[link main markdown testing].each do |link|
35
- navigation.map{|n| n.inner_html }.sort.should include(link)
27
+ navigation.map{|n| n.inner_html }.sort.should.include(link)
36
28
  end
37
29
 
38
30
  manipulate = doc.search('div#manipulate>a')
@@ -43,7 +35,8 @@ describe 'wiktacular' do
43
35
  end
44
36
 
45
37
  it 'should start' do
46
- ramaze :public_root => 'examples/wiktacular/public', :port => 7001
38
+ ramaze :public_root => base/:public,
39
+ :template_root => base/:template
47
40
  get('/').status.should == 200
48
41
  end
49
42
 
@@ -73,7 +66,7 @@ describe 'wiktacular' do
73
66
  doc = check_page('/edit/main')
74
67
  form = doc.at('div#content>form')
75
68
  form.at('input[@type=text]')['value'].should == 'main'
76
- form.at('textarea').inner_html.should match(/# Hello, World/)
69
+ form.at('textarea').inner_html.should.match(/# Hello, World/)
77
70
  form.at('a').inner_html.should == 'cancel'
78
71
  form.at('a')['href'].should == '/main'
79
72
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
1
+ # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2
2
  # All files in this distribution are subject to the terms of the Ruby license.
3
3
 
4
4
  # Default url mappings are:
@@ -9,17 +9,17 @@
9
9
  # this will force the controller to be mounted on: /otherurl
10
10
 
11
11
  class MainController < Ramaze::Controller
12
+ layout '/page'
12
13
 
13
14
  # the index action is called automatically when no other action is specified
14
15
  def index
15
- @welcome = "Welcome to Ramaze!"
16
+ @title = "Welcome to Ramaze!"
16
17
  end
17
18
 
18
19
  # the string returned at the end of the function is used as the html body
19
20
  # if there is no template for the action. if there is a template, the string
20
21
  # is silently ignored
21
22
  def notemplate
22
- "there is no template associated with this action"
23
+ "there is no 'notemplate.xhtml' associated with this action"
23
24
  end
24
-
25
25
  end
@@ -1,9 +1,26 @@
1
+ body {
2
+ font-family: sans-serif;
3
+ }
4
+
1
5
  h1.main {
2
6
  text-align: center;
3
7
  }
4
8
 
9
+ td {
10
+ padding: 4px;
11
+ }
12
+
5
13
  table.main {
6
- background: #000;
14
+ background: #444;
15
+ margin-left: 2em;
16
+ }
17
+
18
+ div.additional h3 {
19
+ cursor: pointer;
20
+ }
21
+
22
+ div.additional pre {
23
+ margin-left: 2em;
7
24
  }
8
25
 
9
26
  table.main tr.head {
@@ -11,10 +28,18 @@ table.main tr.head {
11
28
  width: 100%;
12
29
  }
13
30
 
31
+ table.main tr {
32
+ background: #fff;
33
+ }
34
+
14
35
  table.main tr.source_container {
15
36
  display: none;
16
37
  }
17
38
 
39
+ tr.source td {
40
+ padding: 0;
41
+ }
42
+
18
43
  tr.source_container div {
19
44
  width: 100%;
20
45
  overflow: auto;
@@ -35,6 +60,11 @@ tr.source_container div table tr.source {
35
60
 
36
61
  div.source {
37
62
  background: #fff;
63
+ padding: 6px;
64
+ }
65
+
66
+ div.source td.editor {
67
+ font-size: 0.8em;
38
68
  }
39
69
 
40
70
  tr.source {
@@ -42,9 +72,15 @@ tr.source {
42
72
  }
43
73
 
44
74
  tr.source td.lineno {
45
- font-size: 0.8em;
75
+ font-size: 0.9em;
76
+ font-family: monospace;
77
+ }
78
+
79
+ tr.source td.lineno, tr.line td.lineno {
80
+ text-align: right;
46
81
  }
47
82
 
48
83
  tr.source td.code pre {
49
- height: 0.1em;
84
+ margin: 0;
85
+ font-family: monospace;
50
86
  }
@@ -1,74 +1,118 @@
1
- // prevent execution of jQuery if included more than once
2
- if(typeof window.jQuery == "undefined") {
1
+ (function(){
3
2
  /*
4
- * jQuery 1.1.3.1 - New Wave Javascript
3
+ * jQuery 1.2.2b2 - New Wave Javascript
5
4
  *
6
5
  * Copyright (c) 2007 John Resig (jquery.com)
7
6
  * Dual licensed under the MIT (MIT-LICENSE.txt)
8
7
  * and GPL (GPL-LICENSE.txt) licenses.
9
8
  *
10
- * $Date: 2007-07-05 00:43:24 -0400 (Thu, 05 Jul 2007) $
11
- * $Rev: 2243 $
9
+ * $Date: 2007-12-20 10:14:13 -0500 (Thu, 20 Dec 2007) $
10
+ * $Rev: 4269 $
12
11
  */
13
12
 
14
- // Global undefined variable
15
- window.undefined = window.undefined;
16
- var jQuery = function(a,c) {
17
- // If the context is global, return a new object
18
- if ( window == this || !this.init )
19
- return new jQuery(a,c);
20
-
21
- return this.init(a,c);
13
+ // Map over jQuery in case of overwrite
14
+ if ( window.jQuery )
15
+ var _jQuery = window.jQuery;
16
+
17
+ var jQuery = window.jQuery = function( selector, context ) {
18
+ // The jQuery object is actually just the init constructor 'enhanced'
19
+ return new jQuery.prototype.init( selector, context );
22
20
  };
23
21
 
24
22
  // Map over the $ in case of overwrite
25
- if ( typeof $ != "undefined" )
26
- jQuery._$ = $;
23
+ if ( window.$ )
24
+ var _$ = window.$;
27
25
 
28
26
  // Map the jQuery namespace to the '$' one
29
- var $ = jQuery;
27
+ window.$ = jQuery;
28
+
29
+ // A simple way to check for HTML strings or ID strings
30
+ // (both of which we optimize for)
31
+ var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;
32
+
33
+ // Is it a simple selector
34
+ var isSimple = /^.[^:#\[\.]*$/;
30
35
 
31
36
  jQuery.fn = jQuery.prototype = {
32
- init: function(a,c) {
37
+ init: function( selector, context ) {
33
38
  // Make sure that a selection was provided
34
- a = a || document;
39
+ selector = selector || document;
35
40
 
36
- // HANDLE: $(function)
37
- // Shortcut for document ready
38
- if ( jQuery.isFunction(a) )
39
- return new jQuery(document)[ jQuery.fn.ready ? "ready" : "load" ]( a );
41
+ // Handle $(DOMElement)
42
+ if ( selector.nodeType ) {
43
+ this[0] = selector;
44
+ this.length = 1;
45
+ return this;
40
46
 
41
47
  // Handle HTML strings
42
- if ( typeof a == "string" ) {
43
- // HANDLE: $(html) -> $(array)
44
- var m = /^[^<]*(<(.|\s)+>)[^>]*$/.exec(a);
45
- if ( m )
46
- a = jQuery.clean( [ m[1] ] );
48
+ } else if ( typeof selector == "string" ) {
49
+ // Are we dealing with HTML string or an ID?
50
+ var match = quickExpr.exec( selector );
51
+
52
+ // Verify a match, and that no context was specified for #id
53
+ if ( match && (match[1] || !context) ) {
54
+
55
+ // HANDLE: $(html) -> $(array)
56
+ if ( match[1] )
57
+ selector = jQuery.clean( [ match[1] ], context );
58
+
59
+ // HANDLE: $("#id")
60
+ else {
61
+ var elem = document.getElementById( match[3] );
62
+
63
+ // Make sure an element was located
64
+ if ( elem )
65
+ // Handle the case where IE and Opera return items
66
+ // by name instead of ID
67
+ if ( elem.id != match[3] )
68
+ return jQuery().find( selector );
69
+
70
+ // Otherwise, we inject the element directly into the jQuery object
71
+ else {
72
+ this[0] = elem;
73
+ this.length = 1;
74
+ return this;
75
+ }
47
76
 
48
- // HANDLE: $(expr)
49
- else
50
- return new jQuery( c ).find( a );
51
- }
77
+ else
78
+ selector = [];
79
+ }
80
+
81
+ // HANDLE: $(expr, [context])
82
+ // (which is just equivalent to: $(content).find(expr)
83
+ } else
84
+ return new jQuery( context ).find( selector );
85
+
86
+ // HANDLE: $(function)
87
+ // Shortcut for document ready
88
+ } else if ( jQuery.isFunction( selector ) )
89
+ return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );
52
90
 
53
91
  return this.setArray(
54
92
  // HANDLE: $(array)
55
- a.constructor == Array && a ||
93
+ selector.constructor == Array && selector ||
56
94
 
57
95
  // HANDLE: $(arraylike)
58
- // Watch for when an array-like object is passed as the selector
59
- (a.jquery || a.length && a != window && !a.nodeType && a[0] != undefined && a[0].nodeType) && jQuery.makeArray( a ) ||
96
+ // Watch for when an array-like object, contains DOM nodes, is passed in as the selector
97
+ (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||
60
98
 
61
99
  // HANDLE: $(*)
62
- [ a ] );
100
+ [ selector ] );
63
101
  },
64
- jquery: "1.1.3.1",
102
+
103
+ // The current version of jQuery being used
104
+ jquery: "1.2.2b2",
65
105
 
106
+ // The number of elements contained in the matched element set
66
107
  size: function() {
67
108
  return this.length;
68
109
  },
69
110
 
111
+ // The number of elements contained in the matched element set
70
112
  length: 0,
71
113
 
114
+ // Get the Nth element in the matched element set OR
115
+ // Get the whole matched element set as a clean array
72
116
  get: function( num ) {
73
117
  return num == undefined ?
74
118
 
@@ -76,241 +120,481 @@ jQuery.fn = jQuery.prototype = {
76
120
  jQuery.makeArray( this ) :
77
121
 
78
122
  // Return just the object
79
- this[num];
123
+ this[ num ];
80
124
  },
81
- pushStack: function( a ) {
82
- var ret = jQuery(a);
125
+
126
+ // Take an array of elements and push it onto the stack
127
+ // (returning the new matched element set)
128
+ pushStack: function( elems ) {
129
+ // Build a new jQuery matched element set
130
+ var ret = jQuery( elems );
131
+
132
+ // Add the old object onto the stack (as a reference)
83
133
  ret.prevObject = this;
134
+
135
+ // Return the newly-formed element set
84
136
  return ret;
85
137
  },
86
- setArray: function( a ) {
138
+
139
+ // Force the current matched set of elements to become
140
+ // the specified array of elements (destroying the stack in the process)
141
+ // You should use pushStack() in order to do this, but maintain the stack
142
+ setArray: function( elems ) {
143
+ // Resetting the length to 0, then using the native Array push
144
+ // is a super-fast way to populate an object with array-like properties
87
145
  this.length = 0;
88
- [].push.apply( this, a );
146
+ Array.prototype.push.apply( this, elems );
147
+
89
148
  return this;
90
149
  },
91
- each: function( fn, args ) {
92
- return jQuery.each( this, fn, args );
150
+
151
+ // Execute a callback for every element in the matched set.
152
+ // (You can seed the arguments with an array of args, but this is
153
+ // only used internally.)
154
+ each: function( callback, args ) {
155
+ return jQuery.each( this, callback, args );
93
156
  },
94
- index: function( obj ) {
95
- var pos = -1;
157
+
158
+ // Determine the position of an element within
159
+ // the matched set of elements
160
+ index: function( elem ) {
161
+ var ret = -1;
162
+
163
+ // Locate the position of the desired element
96
164
  this.each(function(i){
97
- if ( this == obj ) pos = i;
165
+ if ( this == elem )
166
+ ret = i;
98
167
  });
99
- return pos;
168
+
169
+ return ret;
100
170
  },
101
171
 
102
- attr: function( key, value, type ) {
103
- var obj = key;
172
+ attr: function( name, value, type ) {
173
+ var options = name;
104
174
 
105
175
  // Look for the case where we're accessing a style value
106
- if ( key.constructor == String )
176
+ if ( name.constructor == String )
107
177
  if ( value == undefined )
108
- return this.length && jQuery[ type || "attr" ]( this[0], key ) || undefined;
178
+ return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;
179
+
109
180
  else {
110
- obj = {};
111
- obj[ key ] = value;
181
+ options = {};
182
+ options[ name ] = value;
112
183
  }
113
184
 
114
185
  // Check to see if we're setting style values
115
- return this.each(function(index){
186
+ return this.each(function(i){
116
187
  // Set all the styles
117
- for ( var prop in obj )
188
+ for ( name in options )
118
189
  jQuery.attr(
119
- type ? this.style : this,
120
- prop, jQuery.prop(this, obj[prop], type, index, prop)
190
+ type ?
191
+ this.style :
192
+ this,
193
+ name, jQuery.prop( this, options[ name ], type, i, name )
121
194
  );
122
195
  });
123
196
  },
124
197
 
125
198
  css: function( key, value ) {
199
+ // ignore negative width and height values
200
+ if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
201
+ value = undefined;
126
202
  return this.attr( key, value, "curCSS" );
127
203
  },
128
204
 
129
- text: function(e) {
130
- if ( typeof e == "string" )
131
- return this.empty().append( document.createTextNode( e ) );
205
+ text: function( text ) {
206
+ if ( typeof text != "object" && text != null )
207
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
208
+
209
+ var ret = "";
132
210
 
133
- var t = "";
134
- jQuery.each( e || this, function(){
211
+ jQuery.each( text || this, function(){
135
212
  jQuery.each( this.childNodes, function(){
136
213
  if ( this.nodeType != 8 )
137
- t += this.nodeType != 1 ?
138
- this.nodeValue : jQuery.fn.text([ this ]);
214
+ ret += this.nodeType != 1 ?
215
+ this.nodeValue :
216
+ jQuery.fn.text( [ this ] );
139
217
  });
140
218
  });
141
- return t;
219
+
220
+ return ret;
142
221
  },
143
222
 
144
- wrap: function() {
145
- // The elements to wrap the target around
146
- var a, args = arguments;
223
+ wrapAll: function( html ) {
224
+ if ( this[0] )
225
+ // The elements to wrap the target around
226
+ jQuery( html, this[0].ownerDocument )
227
+ .clone()
228
+ .insertBefore( this[0] )
229
+ .map(function(){
230
+ var elem = this;
147
231
 
148
- // Wrap each of the matched elements individually
149
- return this.each(function(){
150
- if ( !a )
151
- a = jQuery.clean(args, this.ownerDocument);
232
+ while ( elem.firstChild )
233
+ elem = elem.firstChild;
152
234
 
153
- // Clone the structure that we're using to wrap
154
- var b = a[0].cloneNode(true);
235
+ return elem;
236
+ })
237
+ .append(this);
155
238
 
156
- // Insert it before the element to be wrapped
157
- this.parentNode.insertBefore( b, this );
239
+ return this;
240
+ },
158
241
 
159
- // Find the deepest point in the wrap structure
160
- while ( b.firstChild )
161
- b = b.firstChild;
242
+ wrapInner: function( html ) {
243
+ return this.each(function(){
244
+ jQuery( this ).contents().wrapAll( html );
245
+ });
246
+ },
162
247
 
163
- // Move the matched element to within the wrap structure
164
- b.appendChild( this );
248
+ wrap: function( html ) {
249
+ return this.each(function(){
250
+ jQuery( this ).wrapAll( html );
165
251
  });
166
252
  },
253
+
167
254
  append: function() {
168
- return this.domManip(arguments, true, 1, function(a){
169
- this.appendChild( a );
255
+ return this.domManip(arguments, true, false, function(elem){
256
+ if (this.nodeType == 1)
257
+ this.appendChild( elem );
170
258
  });
171
259
  },
260
+
172
261
  prepend: function() {
173
- return this.domManip(arguments, true, -1, function(a){
174
- this.insertBefore( a, this.firstChild );
262
+ return this.domManip(arguments, true, true, function(elem){
263
+ if (this.nodeType == 1)
264
+ this.insertBefore( elem, this.firstChild );
175
265
  });
176
266
  },
267
+
177
268
  before: function() {
178
- return this.domManip(arguments, false, 1, function(a){
179
- this.parentNode.insertBefore( a, this );
269
+ return this.domManip(arguments, false, false, function(elem){
270
+ this.parentNode.insertBefore( elem, this );
180
271
  });
181
272
  },
273
+
182
274
  after: function() {
183
- return this.domManip(arguments, false, -1, function(a){
184
- this.parentNode.insertBefore( a, this.nextSibling );
275
+ return this.domManip(arguments, false, true, function(elem){
276
+ this.parentNode.insertBefore( elem, this.nextSibling );
185
277
  });
186
278
  },
279
+
187
280
  end: function() {
188
- return this.prevObject || jQuery([]);
189
- },
190
- find: function(t) {
191
- var data = jQuery.map(this, function(a){ return jQuery.find(t,a); });
192
- return this.pushStack( /[^+>] [^+>]/.test( t ) || t.indexOf("..") > -1 ?
193
- jQuery.unique( data ) : data );
194
- },
195
- clone: function(deep) {
196
- // Need to remove events on the element and its descendants
197
- var $this = this.add(this.find("*"));
198
- $this.each(function() {
199
- this._$events = {};
200
- for (var type in this.$events)
201
- this._$events[type] = jQuery.extend({},this.$events[type]);
202
- }).unbind();
281
+ return this.prevObject || jQuery( [] );
282
+ },
283
+
284
+ find: function( selector ) {
285
+ var elems = jQuery.map(this, function(elem){
286
+ return jQuery.find( selector, elem );
287
+ });
288
+
289
+ return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
290
+ jQuery.unique( elems ) :
291
+ elems );
292
+ },
203
293
 
294
+ clone: function( events ) {
204
295
  // Do the clone
205
- var r = this.pushStack( jQuery.map( this, function(a){
206
- return a.cloneNode( deep != undefined ? deep : true );
207
- }) );
208
-
209
- // Add the events back to the original and its descendants
210
- $this.each(function() {
211
- var events = this._$events;
212
- for (var type in events)
213
- for (var handler in events[type])
214
- jQuery.event.add(this, type, events[type][handler], events[type][handler].data);
215
- this._$events = null;
296
+ var ret = this.map(function(){
297
+ if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
298
+ // IE copies events bound via attachEvent when
299
+ // using cloneNode. Calling detachEvent on the
300
+ // clone will also remove the events from the orignal
301
+ // In order to get around this, we use innerHTML.
302
+ // Unfortunately, this means some modifications to
303
+ // attributes in IE that are actually only stored
304
+ // as properties will not be copied (such as the
305
+ // the name attribute on an input).
306
+ var clone = this.cloneNode(true),
307
+ container = document.createElement("div"),
308
+ container2 = document.createElement("div");
309
+ container.appendChild(clone);
310
+ container2.innerHTML = container.innerHTML;
311
+ return container2.firstChild;
312
+ } else
313
+ return this.cloneNode(true);
216
314
  });
217
315
 
316
+ // Need to set the expando to null on the cloned set if it exists
317
+ // removeData doesn't work here, IE removes it from the original as well
318
+ // this is primarily for IE but the data expando shouldn't be copied over in any browser
319
+ var clone = ret.find("*").andSelf().each(function(){
320
+ if ( this[ expando ] != undefined )
321
+ this[ expando ] = null;
322
+ });
323
+
324
+ // Copy the events from the original to the clone
325
+ if ( events === true )
326
+ this.find("*").andSelf().each(function(i){
327
+ var events = jQuery.data( this, "events" );
328
+
329
+ for ( var type in events )
330
+ for ( var handler in events[ type ] )
331
+ jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
332
+ });
333
+
218
334
  // Return the cloned set
219
- return r;
335
+ return ret;
220
336
  },
221
337
 
222
- filter: function(t) {
338
+ filter: function( selector ) {
223
339
  return this.pushStack(
224
- jQuery.isFunction( t ) &&
225
- jQuery.grep(this, function(el, index){
226
- return t.apply(el, [index])
340
+ jQuery.isFunction( selector ) &&
341
+ jQuery.grep(this, function(elem, i){
342
+ return selector.call( elem, i );
227
343
  }) ||
228
344
 
229
- jQuery.multiFilter(t,this) );
345
+ jQuery.multiFilter( selector, this ) );
230
346
  },
231
347
 
232
- not: function(t) {
233
- return this.pushStack(
234
- t.constructor == String &&
235
- jQuery.multiFilter(t, this, true) ||
348
+ not: function( selector ) {
349
+ if ( selector.constructor == String )
350
+ // test special case where just one selector is passed in
351
+ if ( isSimple.test( selector ) )
352
+ return this.pushStack( jQuery.multiFilter( selector, this, true ) );
353
+ else
354
+ selector = jQuery.multiFilter( selector, this );
236
355
 
237
- jQuery.grep(this, function(a) {
238
- return ( t.constructor == Array || t.jquery )
239
- ? jQuery.inArray( a, t ) < 0
240
- : a != t;
241
- })
242
- );
356
+ var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
357
+ return this.filter(function() {
358
+ return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
359
+ });
243
360
  },
244
361
 
245
- add: function(t) {
246
- return this.pushStack( jQuery.merge(
362
+ add: function( selector ) {
363
+ return !selector ? this : this.pushStack( jQuery.merge(
247
364
  this.get(),
248
- t.constructor == String ?
249
- jQuery(t).get() :
250
- t.length != undefined && (!t.nodeName || t.nodeName == "FORM") ?
251
- t : [t] )
252
- );
365
+ selector.constructor == String ?
366
+ jQuery( selector ).get() :
367
+ selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
368
+ selector : [selector] ) );
369
+ },
370
+
371
+ is: function( selector ) {
372
+ return selector ?
373
+ jQuery.multiFilter( selector, this ).length > 0 :
374
+ false;
375
+ },
376
+
377
+ hasClass: function( selector ) {
378
+ return this.is( "." + selector );
379
+ },
380
+
381
+ val: function( value ) {
382
+ if ( value == undefined ) {
383
+
384
+ if ( this.length ) {
385
+ var elem = this[0];
386
+
387
+ // We need to handle select boxes special
388
+ if ( jQuery.nodeName( elem, "select" ) ) {
389
+ var index = elem.selectedIndex,
390
+ values = [],
391
+ options = elem.options,
392
+ one = elem.type == "select-one";
393
+
394
+ // Nothing was selected
395
+ if ( index < 0 )
396
+ return null;
397
+
398
+ // Loop through all the selected options
399
+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
400
+ var option = options[ i ];
401
+
402
+ if ( option.selected ) {
403
+ // Get the specifc value for the option
404
+ value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
405
+
406
+ // We don't need an array for one selects
407
+ if ( one )
408
+ return value;
409
+
410
+ // Multi-Selects return an array
411
+ values.push( value );
412
+ }
413
+ }
414
+
415
+ return values;
416
+
417
+ // Everything else, we just grab the value
418
+ } else
419
+ return (this[0].value || "").replace(/\r/g, "");
420
+
421
+ }
422
+
423
+ return undefined;
424
+ }
425
+
426
+ return this.each(function(){
427
+ if ( this.nodeType != 1 )
428
+ return;
429
+
430
+ if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
431
+ this.checked = (jQuery.inArray(this.value, value) >= 0 ||
432
+ jQuery.inArray(this.name, value) >= 0);
433
+
434
+ else if ( jQuery.nodeName( this, "select" ) ) {
435
+ var values = value.constructor == Array ?
436
+ value :
437
+ [ value ];
438
+
439
+ jQuery( "option", this ).each(function(){
440
+ this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
441
+ jQuery.inArray( this.text, values ) >= 0);
442
+ });
443
+
444
+ if ( !values.length )
445
+ this.selectedIndex = -1;
446
+
447
+ } else
448
+ this.value = value;
449
+ });
450
+ },
451
+
452
+ html: function( value ) {
453
+ return value == undefined ?
454
+ (this.length ?
455
+ this[0].innerHTML :
456
+ null) :
457
+ this.empty().append( value );
253
458
  },
254
- is: function(expr) {
255
- return expr ? jQuery.multiFilter(expr,this).length > 0 : false;
459
+
460
+ replaceWith: function( value ) {
461
+ return this.after( value ).remove();
462
+ },
463
+
464
+ eq: function( i ) {
465
+ return this.slice( i, i + 1 );
466
+ },
467
+
468
+ slice: function() {
469
+ return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
256
470
  },
257
471
 
258
- val: function( val ) {
259
- return val == undefined ?
260
- ( this.length ? this[0].value : null ) :
261
- this.attr( "value", val );
472
+ map: function( callback ) {
473
+ return this.pushStack( jQuery.map(this, function(elem, i){
474
+ return callback.call( elem, i, elem );
475
+ }));
262
476
  },
263
477
 
264
- html: function( val ) {
265
- return val == undefined ?
266
- ( this.length ? this[0].innerHTML : null ) :
267
- this.empty().append( val );
478
+ andSelf: function() {
479
+ return this.add( this.prevObject );
268
480
  },
269
- domManip: function(args, table, dir, fn){
270
- var clone = this.length > 1, a;
481
+
482
+ domManip: function( args, table, reverse, callback ) {
483
+ var clone = this.length > 1, elems;
271
484
 
272
485
  return this.each(function(){
273
- if ( !a ) {
274
- a = jQuery.clean(args, this.ownerDocument);
275
- if ( dir < 0 )
276
- a.reverse();
486
+ if ( !elems ) {
487
+ elems = jQuery.clean( args, this.ownerDocument );
488
+
489
+ if ( reverse )
490
+ elems.reverse();
277
491
  }
278
492
 
279
493
  var obj = this;
280
494
 
281
- if ( table && jQuery.nodeName(this, "table") && jQuery.nodeName(a[0], "tr") )
282
- obj = this.getElementsByTagName("tbody")[0] || this.appendChild(document.createElement("tbody"));
495
+ if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
496
+ obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );
283
497
 
284
- jQuery.each( a, function(){
285
- fn.apply( obj, [ clone ? this.cloneNode(true) : this ] );
498
+ var scripts = jQuery( [] );
499
+
500
+ jQuery.each(elems, function(){
501
+ var elem = clone ?
502
+ jQuery( this ).clone( true )[0] :
503
+ this;
504
+
505
+ // execute all scripts after the elements have been injected
506
+ if ( jQuery.nodeName( elem, "script" ) ) {
507
+ scripts = scripts.add( elem );
508
+ } else {
509
+ // Remove any inner scripts for later evaluation
510
+ if ( elem.nodeType == 1 )
511
+ scripts = scripts.add( jQuery( "script", elem ).remove() );
512
+
513
+ // Inject the elements into the document
514
+ callback.call( obj, elem );
515
+ }
286
516
  });
287
517
 
518
+ scripts.each( evalScript );
288
519
  });
289
520
  }
290
521
  };
291
522
 
523
+ // Give the init function the jQuery prototype for later instantiation
524
+ jQuery.prototype.init.prototype = jQuery.prototype;
525
+
526
+ function evalScript( i, elem ) {
527
+ if ( elem.src )
528
+ jQuery.ajax({
529
+ url: elem.src,
530
+ async: false,
531
+ dataType: "script"
532
+ });
533
+
534
+ else
535
+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
536
+
537
+ if ( elem.parentNode )
538
+ elem.parentNode.removeChild( elem );
539
+ }
540
+
292
541
  jQuery.extend = jQuery.fn.extend = function() {
293
542
  // copy reference to target object
294
- var target = arguments[0], a = 1;
543
+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
544
+
545
+ // Handle a deep copy situation
546
+ if ( target.constructor == Boolean ) {
547
+ deep = target;
548
+ target = arguments[1] || {};
549
+ // skip the boolean and the target
550
+ i = 2;
551
+ }
552
+
553
+ // Handle case when target is a string or something (possible in deep copy)
554
+ if ( typeof target != "object" && typeof target != "function" )
555
+ target = {};
295
556
 
296
557
  // extend jQuery itself if only one argument is passed
297
- if ( arguments.length == 1 ) {
558
+ if ( length == 1 ) {
298
559
  target = this;
299
- a = 0;
560
+ i = 0;
300
561
  }
301
- var prop;
302
- while ( (prop = arguments[a++]) != null )
303
- // Extend the base object
304
- for ( var i in prop ) target[i] = prop[i];
562
+
563
+ for ( ; i < length; i++ )
564
+ // Only deal with non-null/undefined values
565
+ if ( (options = arguments[ i ]) != null )
566
+ // Extend the base object
567
+ for ( var name in options ) {
568
+ // Prevent never-ending loop
569
+ if ( target === options[ name ] )
570
+ continue;
571
+
572
+ // Recurse if we're merging object values
573
+ if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
574
+ target[ name ] = jQuery.extend( target[ name ], options[ name ] );
575
+
576
+ // Don't bring in undefined values
577
+ else if ( options[ name ] != undefined )
578
+ target[ name ] = options[ name ];
579
+
580
+ }
305
581
 
306
582
  // Return the modified object
307
583
  return target;
308
584
  };
309
585
 
586
+ var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};
587
+
588
+ // exclude the following css properties to add px
589
+ var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
590
+
310
591
  jQuery.extend({
311
- noConflict: function() {
312
- if ( jQuery._$ )
313
- $ = jQuery._$;
592
+ noConflict: function( deep ) {
593
+ window.$ = _$;
594
+
595
+ if ( deep )
596
+ window.jQuery = _jQuery;
597
+
314
598
  return jQuery;
315
599
  },
316
600
 
@@ -321,247 +605,457 @@ jQuery.extend({
321
605
  fn.constructor != Array && /function/i.test( fn + "" );
322
606
  },
323
607
 
324
- // check if an element is in a XML document
325
- isXMLDoc: function(elem) {
326
- return elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
608
+ // check if an element is in a (or is an) XML document
609
+ isXMLDoc: function( elem ) {
610
+ return elem.documentElement && !elem.body ||
611
+ elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
612
+ },
613
+
614
+ // Evalulates a script in a global context
615
+ globalEval: function( data ) {
616
+ data = jQuery.trim( data );
617
+
618
+ if ( data ) {
619
+ // Inspired by code by Andrea Giammarchi
620
+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
621
+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
622
+ script = document.createElement("script");
623
+
624
+ script.type = "text/javascript";
625
+ if ( jQuery.browser.msie )
626
+ script.text = data;
627
+ else
628
+ script.appendChild( document.createTextNode( data ) );
629
+
630
+ head.appendChild( script );
631
+ head.removeChild( script );
632
+ }
327
633
  },
328
634
 
329
635
  nodeName: function( elem, name ) {
330
636
  return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
331
637
  },
638
+
639
+ cache: {},
640
+
641
+ data: function( elem, name, data ) {
642
+ elem = elem == window ?
643
+ windowData :
644
+ elem;
645
+
646
+ var id = elem[ expando ];
647
+
648
+ // Compute a unique ID for the element
649
+ if ( !id )
650
+ id = elem[ expando ] = ++uuid;
651
+
652
+ // Only generate the data cache if we're
653
+ // trying to access or manipulate it
654
+ if ( name && !jQuery.cache[ id ] )
655
+ jQuery.cache[ id ] = {};
656
+
657
+ // Prevent overriding the named cache with undefined values
658
+ if ( data != undefined )
659
+ jQuery.cache[ id ][ name ] = data;
660
+
661
+ // Return the named cache data, or the ID for the element
662
+ return name ?
663
+ jQuery.cache[ id ][ name ] :
664
+ id;
665
+ },
666
+
667
+ removeData: function( elem, name ) {
668
+ elem = elem == window ?
669
+ windowData :
670
+ elem;
671
+
672
+ var id = elem[ expando ];
673
+
674
+ // If we want to remove a specific section of the element's data
675
+ if ( name ) {
676
+ if ( jQuery.cache[ id ] ) {
677
+ // Remove the section of cache data
678
+ delete jQuery.cache[ id ][ name ];
679
+
680
+ // If we've removed all the data, remove the element's cache
681
+ name = "";
682
+
683
+ for ( name in jQuery.cache[ id ] )
684
+ break;
685
+
686
+ if ( !name )
687
+ jQuery.removeData( elem );
688
+ }
689
+
690
+ // Otherwise, we want to remove all of the element's data
691
+ } else {
692
+ // Clean up the element expando
693
+ try {
694
+ delete elem[ expando ];
695
+ } catch(e){
696
+ // IE has trouble directly removing the expando
697
+ // but it's ok with using removeAttribute
698
+ if ( elem.removeAttribute )
699
+ elem.removeAttribute( expando );
700
+ }
701
+
702
+ // Completely remove the data cache
703
+ delete jQuery.cache[ id ];
704
+ }
705
+ },
706
+
332
707
  // args is for internal usage only
333
- each: function( obj, fn, args ) {
334
- if ( obj.length == undefined )
335
- for ( var i in obj )
336
- fn.apply( obj[i], args || [i, obj[i]] );
337
- else
338
- for ( var i = 0, ol = obj.length; i < ol; i++ )
339
- if ( fn.apply( obj[i], args || [i, obj[i]] ) === false ) break;
340
- return obj;
708
+ each: function( object, callback, args ) {
709
+ if ( args ) {
710
+ if ( object.length == undefined )
711
+ for ( var name in object )
712
+ callback.apply( object[ name ], args );
713
+ else
714
+ for ( var i = 0, length = object.length; i < length; i++ )
715
+ if ( callback.apply( object[ i ], args ) === false )
716
+ break;
717
+
718
+ // A special, fast, case for the most common use of each
719
+ } else {
720
+ if ( object.length == undefined )
721
+ for ( var name in object )
722
+ callback.call( object[ name ], name, object[ name ] );
723
+ else
724
+ for ( var i = 0, length = object.length, value = object[0];
725
+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
726
+ }
727
+
728
+ return object;
341
729
  },
342
730
 
343
- prop: function(elem, value, type, index, prop){
731
+ prop: function( elem, value, type, i, name ) {
344
732
  // Handle executable functions
345
733
  if ( jQuery.isFunction( value ) )
346
- value = value.call( elem, [index] );
734
+ value = value.call( elem, i );
347
735
 
348
- // exclude the following css properties to add px
349
- var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;
350
-
351
736
  // Handle passing in a number to a CSS property
352
- return value && value.constructor == Number && type == "curCSS" && !exclude.test(prop) ?
737
+ return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
353
738
  value + "px" :
354
739
  value;
355
740
  },
356
741
 
357
742
  className: {
358
743
  // internal only, use addClass("class")
359
- add: function( elem, c ){
360
- jQuery.each( c.split(/\s+/), function(i, cur){
361
- if ( !jQuery.className.has( elem.className, cur ) )
362
- elem.className += ( elem.className ? " " : "" ) + cur;
744
+ add: function( elem, classNames ) {
745
+ jQuery.each((classNames || "").split(/\s+/), function(i, className){
746
+ if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
747
+ elem.className += (elem.className ? " " : "") + className;
363
748
  });
364
749
  },
365
750
 
366
751
  // internal only, use removeClass("class")
367
- remove: function( elem, c ){
368
- elem.className = c != undefined ?
369
- jQuery.grep( elem.className.split(/\s+/), function(cur){
370
- return !jQuery.className.has( c, cur );
371
- }).join(" ") : "";
752
+ remove: function( elem, classNames ) {
753
+ if (elem.nodeType == 1)
754
+ elem.className = classNames != undefined ?
755
+ jQuery.grep(elem.className.split(/\s+/), function(className){
756
+ return !jQuery.className.has( classNames, className );
757
+ }).join(" ") :
758
+ "";
372
759
  },
373
760
 
374
761
  // internal only, use is(".class")
375
- has: function( t, c ) {
376
- return jQuery.inArray( c, (t.className || t).toString().split(/\s+/) ) > -1;
762
+ has: function( elem, className ) {
763
+ return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
377
764
  }
378
765
  },
379
- swap: function(e,o,f) {
380
- for ( var i in o ) {
381
- e.style["old"+i] = e.style[i];
382
- e.style[i] = o[i];
766
+
767
+ // A method for quickly swapping in/out CSS properties to get correct calculations
768
+ swap: function( elem, options, callback ) {
769
+ var old = {};
770
+ // Remember the old values, and insert the new ones
771
+ for ( var name in options ) {
772
+ old[ name ] = elem.style[ name ];
773
+ elem.style[ name ] = options[ name ];
383
774
  }
384
- f.apply( e, [] );
385
- for ( var i in o )
386
- e.style[i] = e.style["old"+i];
387
- },
388
775
 
389
- css: function(e,p) {
390
- if ( p == "height" || p == "width" ) {
391
- var old = {}, oHeight, oWidth, d = ["Top","Bottom","Right","Left"];
776
+ callback.call( elem );
392
777
 
393
- jQuery.each( d, function(){
394
- old["padding" + this] = 0;
395
- old["border" + this + "Width"] = 0;
396
- });
778
+ // Revert the old values
779
+ for ( var name in options )
780
+ elem.style[ name ] = old[ name ];
781
+ },
397
782
 
398
- jQuery.swap( e, old, function() {
399
- if ( jQuery(e).is(':visible') ) {
400
- oHeight = e.offsetHeight;
401
- oWidth = e.offsetWidth;
402
- } else {
403
- e = jQuery(e.cloneNode(true))
404
- .find(":radio").removeAttr("checked").end()
405
- .css({
406
- visibility: "hidden", position: "absolute", display: "block", right: "0", left: "0"
407
- }).appendTo(e.parentNode)[0];
783
+ css: function( elem, name, force ) {
784
+ if ( name == "width" || name == "height" ) {
785
+ var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
786
+
787
+ function getWH() {
788
+ val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
789
+ var padding = 0, border = 0;
790
+ jQuery.each( which, function() {
791
+ padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
792
+ border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
793
+ });
794
+ val -= Math.round(padding + border);
795
+ }
796
+
797
+ if ( jQuery(elem).is(":visible") )
798
+ getWH();
799
+ else
800
+ jQuery.swap( elem, props, getWH );
801
+
802
+ return Math.max(0, val);
803
+ }
804
+
805
+ return jQuery.curCSS( elem, name, force );
806
+ },
408
807
 
409
- var parPos = jQuery.css(e.parentNode,"position") || "static";
410
- if ( parPos == "static" )
411
- e.parentNode.style.position = "relative";
808
+ curCSS: function( elem, name, force ) {
809
+ var ret;
412
810
 
413
- oHeight = e.clientHeight;
414
- oWidth = e.clientWidth;
811
+ // A helper method for determining if an element's values are broken
812
+ function color( elem ) {
813
+ if ( !jQuery.browser.safari )
814
+ return false;
415
815
 
416
- if ( parPos == "static" )
417
- e.parentNode.style.position = "static";
816
+ var ret = document.defaultView.getComputedStyle( elem, null );
817
+ return !ret || ret.getPropertyValue("color") == "";
818
+ }
418
819
 
419
- e.parentNode.removeChild(e);
420
- }
421
- });
820
+ // We need to handle opacity special in IE
821
+ if ( name == "opacity" && jQuery.browser.msie ) {
822
+ ret = jQuery.attr( elem.style, "opacity" );
422
823
 
423
- return p == "height" ? oHeight : oWidth;
824
+ return ret == "" ?
825
+ "1" :
826
+ ret;
827
+ }
828
+ // Opera sometimes will give the wrong display answer, this fixes it, see #2037
829
+ if ( jQuery.browser.opera && name == "display" ) {
830
+ var save = elem.style.display;
831
+ elem.style.display = "block";
832
+ elem.style.display = save;
424
833
  }
834
+
835
+ // Make sure we're using the right name for getting the float value
836
+ if ( name.match( /float/i ) )
837
+ name = styleFloat;
425
838
 
426
- return jQuery.curCSS( e, p );
427
- },
839
+ if ( !force && elem.style[ name ] )
840
+ ret = elem.style[ name ];
428
841
 
429
- curCSS: function(elem, prop, force) {
430
- var ret;
842
+ else if ( document.defaultView && document.defaultView.getComputedStyle ) {
431
843
 
432
- if (prop == "opacity" && jQuery.browser.msie) {
433
- ret = jQuery.attr(elem.style, "opacity");
434
- return ret == "" ? "1" : ret;
435
- }
436
-
437
- if (prop.match(/float/i))
438
- prop = jQuery.styleFloat;
844
+ // Only "float" is needed here
845
+ if ( name.match( /float/i ) )
846
+ name = "float";
439
847
 
440
- if (!force && elem.style[prop])
441
- ret = elem.style[prop];
848
+ name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
442
849
 
443
- else if (document.defaultView && document.defaultView.getComputedStyle) {
850
+ var getComputedStyle = document.defaultView.getComputedStyle( elem, null );
444
851
 
445
- if (prop.match(/float/i))
446
- prop = "float";
852
+ if ( getComputedStyle && !color( elem ) )
853
+ ret = getComputedStyle.getPropertyValue( name );
447
854
 
448
- prop = prop.replace(/([A-Z])/g,"-$1").toLowerCase();
449
- var cur = document.defaultView.getComputedStyle(elem, null);
855
+ // If the element isn't reporting its values properly in Safari
856
+ // then some display: none elements are involved
857
+ else {
858
+ var swap = [], stack = [];
859
+
860
+ // Locate all of the parent display: none elements
861
+ for ( var a = elem; a && color(a); a = a.parentNode )
862
+ stack.unshift(a);
863
+
864
+ // Go through and make them visible, but in reverse
865
+ // (It would be better if we knew the exact display type that they had)
866
+ for ( var i = 0; i < stack.length; i++ )
867
+ if ( color( stack[ i ] ) ) {
868
+ swap[ i ] = stack[ i ].style.display;
869
+ stack[ i ].style.display = "block";
870
+ }
450
871
 
451
- if ( cur )
452
- ret = cur.getPropertyValue(prop);
453
- else if ( prop == "display" )
454
- ret = "none";
455
- else
456
- jQuery.swap(elem, { display: "block" }, function() {
457
- var c = document.defaultView.getComputedStyle(this, "");
458
- ret = c && c.getPropertyValue(prop) || "";
459
- });
872
+ // Since we flip the display style, we have to handle that
873
+ // one special, otherwise get the value
874
+ ret = name == "display" && swap[ stack.length - 1 ] != null ?
875
+ "none" :
876
+ ( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";
877
+
878
+ // Finally, revert the display styles back
879
+ for ( var i = 0; i < swap.length; i++ )
880
+ if ( swap[ i ] != null )
881
+ stack[ i ].style.display = swap[ i ];
882
+ }
883
+
884
+ // We should always get a number back from opacity
885
+ if ( name == "opacity" && ret == "" )
886
+ ret = "1";
887
+
888
+ } else if ( elem.currentStyle ) {
889
+ var camelCase = name.replace(/\-(\w)/g, function(all, letter){
890
+ return letter.toUpperCase();
891
+ });
460
892
 
461
- } else if (elem.currentStyle) {
462
- var newProp = prop.replace(/\-(\w)/g,function(m,c){return c.toUpperCase();});
463
- ret = elem.currentStyle[prop] || elem.currentStyle[newProp];
893
+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
894
+
895
+ // From the awesome hack by Dean Edwards
896
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
897
+
898
+ // If we're not dealing with a regular pixel number
899
+ // but a number that has a weird ending, we need to convert it to pixels
900
+ if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
901
+ // Remember the original values
902
+ var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;
903
+
904
+ // Put in the new values to get a computed value out
905
+ elem.runtimeStyle.left = elem.currentStyle.left;
906
+ elem.style.left = ret || 0;
907
+ ret = elem.style.pixelLeft + "px";
908
+
909
+ // Revert the changed values
910
+ elem.style.left = style;
911
+ elem.runtimeStyle.left = runtimeStyle;
912
+ }
464
913
  }
465
914
 
466
915
  return ret;
467
916
  },
468
917
 
469
- clean: function(a, doc) {
470
- var r = [];
471
- doc = doc || document;
918
+ clean: function( elems, context ) {
919
+ var ret = [];
920
+ context = context || document;
921
+ // !context.createElement fails in IE with an error but returns typeof 'object'
922
+ if (typeof context.createElement == 'undefined')
923
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
472
924
 
473
- jQuery.each( a, function(i,arg){
474
- if ( !arg ) return;
925
+ jQuery.each(elems, function(i, elem){
926
+ if ( !elem )
927
+ return;
475
928
 
476
- if ( arg.constructor == Number )
477
- arg = arg.toString();
929
+ if ( elem.constructor == Number )
930
+ elem = elem.toString();
478
931
 
479
932
  // Convert html string into DOM nodes
480
- if ( typeof arg == "string" ) {
933
+ if ( typeof elem == "string" ) {
934
+ // Fix "XHTML"-style tags in all browsers
935
+ elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
936
+ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area)$/i) ?
937
+ all :
938
+ front + "></" + tag + ">";
939
+ });
940
+
481
941
  // Trim whitespace, otherwise indexOf won't work as expected
482
- var s = jQuery.trim(arg).toLowerCase(), div = doc.createElement("div"), tb = [];
942
+ var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");
483
943
 
484
944
  var wrap =
485
945
  // option or optgroup
486
- !s.indexOf("<opt") &&
487
- [1, "<select>", "</select>"] ||
946
+ !tags.indexOf("<opt") &&
947
+ [ 1, "<select multiple='multiple'>", "</select>" ] ||
488
948
 
489
- !s.indexOf("<leg") &&
490
- [1, "<fieldset>", "</fieldset>"] ||
949
+ !tags.indexOf("<leg") &&
950
+ [ 1, "<fieldset>", "</fieldset>" ] ||
491
951
 
492
- (!s.indexOf("<thead") || !s.indexOf("<tbody") || !s.indexOf("<tfoot") || !s.indexOf("<colg")) &&
493
- [1, "<table>", "</table>"] ||
952
+ tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
953
+ [ 1, "<table>", "</table>" ] ||
494
954
 
495
- !s.indexOf("<tr") &&
496
- [2, "<table><tbody>", "</tbody></table>"] ||
955
+ !tags.indexOf("<tr") &&
956
+ [ 2, "<table><tbody>", "</tbody></table>" ] ||
497
957
 
498
958
  // <thead> matched above
499
- (!s.indexOf("<td") || !s.indexOf("<th")) &&
500
- [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
959
+ (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
960
+ [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
501
961
 
502
- !s.indexOf("<col") &&
503
- [2, "<table><colgroup>", "</colgroup></table>"] ||
962
+ !tags.indexOf("<col") &&
963
+ [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
964
+
965
+ // IE can't serialize <link> and <script> tags normally
966
+ jQuery.browser.msie &&
967
+ [ 1, "div<div>", "</div>" ] ||
504
968
 
505
- [0,"",""];
969
+ [ 0, "", "" ];
506
970
 
507
971
  // Go to html and back, then peel off extra wrappers
508
- div.innerHTML = wrap[1] + arg + wrap[2];
972
+ div.innerHTML = wrap[1] + elem + wrap[2];
509
973
 
510
974
  // Move to the right depth
511
975
  while ( wrap[0]-- )
512
- div = div.firstChild;
976
+ div = div.lastChild;
513
977
 
514
978
  // Remove IE's autoinserted <tbody> from table fragments
515
979
  if ( jQuery.browser.msie ) {
516
980
 
517
981
  // String was a <table>, *may* have spurious <tbody>
518
- if ( !s.indexOf("<table") && s.indexOf("<tbody") < 0 )
519
- tb = div.firstChild && div.firstChild.childNodes;
982
+ var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
983
+ div.firstChild && div.firstChild.childNodes :
520
984
 
521
- // String was a bare <thead> or <tfoot>
522
- else if ( wrap[1] == "<table>" && s.indexOf("<tbody") < 0 )
523
- tb = div.childNodes;
524
-
525
- for ( var n = tb.length-1; n >= 0 ; --n )
526
- if ( jQuery.nodeName(tb[n], "tbody") && !tb[n].childNodes.length )
527
- tb[n].parentNode.removeChild(tb[n]);
985
+ // String was a bare <thead> or <tfoot>
986
+ wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
987
+ div.childNodes :
988
+ [];
989
+
990
+ for ( var j = tbody.length - 1; j >= 0 ; --j )
991
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
992
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
528
993
 
994
+ // IE completely kills leading whitespace when innerHTML is used
995
+ if ( /^\s/.test( elem ) )
996
+ div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
997
+
529
998
  }
530
999
 
531
- arg = jQuery.makeArray( div.childNodes );
1000
+ elem = jQuery.makeArray( div.childNodes );
532
1001
  }
533
1002
 
534
- if ( 0 === arg.length && (!jQuery.nodeName(arg, "form") && !jQuery.nodeName(arg, "select")) )
1003
+ if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
535
1004
  return;
536
1005
 
537
- if ( arg[0] == undefined || jQuery.nodeName(arg, "form") || arg.options )
538
- r.push( arg );
1006
+ if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
1007
+ ret.push( elem );
1008
+
539
1009
  else
540
- r = jQuery.merge( r, arg );
1010
+ ret = jQuery.merge( ret, elem );
541
1011
 
542
1012
  });
543
1013
 
544
- return r;
1014
+ return ret;
545
1015
  },
546
1016
 
547
- attr: function(elem, name, value){
548
- var fix = jQuery.isXMLDoc(elem) ? {} : jQuery.props;
1017
+ attr: function( elem, name, value ) {
1018
+ // don't set attributes on text and comment nodes
1019
+ if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
1020
+ return undefined;
1021
+
1022
+ var fix = jQuery.isXMLDoc( elem ) ?
1023
+ {} :
1024
+ jQuery.props;
1025
+
1026
+ // Safari mis-reports the default selected property of a hidden option
1027
+ // Accessing the parent's selectedIndex property fixes it
1028
+ if ( name == "selected" && jQuery.browser.safari )
1029
+ elem.parentNode.selectedIndex;
549
1030
 
550
1031
  // Certain attributes only work when accessed via the old DOM 0 way
551
- if ( fix[name] ) {
552
- if ( value != undefined ) elem[fix[name]] = value;
553
- return elem[fix[name]];
1032
+ if ( fix[ name ] ) {
1033
+ if ( value != undefined )
1034
+ elem[ fix[ name ] ] = value;
554
1035
 
555
- } else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName(elem, "form") && (name == "action" || name == "method") )
556
- return elem.getAttributeNode(name).nodeValue;
1036
+ return elem[ fix[ name ] ];
1037
+
1038
+ } else if ( jQuery.browser.msie && name == "style" )
1039
+ return jQuery.attr( elem.style, "cssText", value );
1040
+
1041
+ else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
1042
+ return elem.getAttributeNode( name ).nodeValue;
557
1043
 
558
1044
  // IE elem.getAttribute passes even for style
559
1045
  else if ( elem.tagName ) {
560
-
561
1046
 
562
- if ( value != undefined ) elem.setAttribute( name, value );
563
- if ( jQuery.browser.msie && /href|src/.test(name) && !jQuery.isXMLDoc(elem) )
1047
+ if ( value != undefined ) {
1048
+ // We can't allow the type property to be changed (since it causes problems in IE)
1049
+ if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
1050
+ throw "type property can't be changed";
1051
+
1052
+ // convert the value to a string (all browsers do this but IE) see #1070
1053
+ elem.setAttribute( name, "" + value );
1054
+ }
1055
+
1056
+ if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) )
564
1057
  return elem.getAttribute( name, 2 );
1058
+
565
1059
  return elem.getAttribute( name );
566
1060
 
567
1061
  // elem is actually elem.style ... set the style
@@ -574,131 +1068,152 @@ jQuery.extend({
574
1068
  elem.zoom = 1;
575
1069
 
576
1070
  // Set the alpha filter to set the opacity
577
- elem.filter = (elem.filter || "").replace(/alpha\([^)]*\)/,"") +
578
- (parseFloat(value).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
1071
+ elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
1072
+ (parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
579
1073
  }
580
1074
 
581
- return elem.filter ?
582
- (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() : "";
1075
+ return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
1076
+ (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
1077
+ "";
583
1078
  }
584
- name = name.replace(/-([a-z])/ig,function(z,b){return b.toUpperCase();});
585
- if ( value != undefined ) elem[name] = value;
586
- return elem[name];
1079
+
1080
+ name = name.replace(/-([a-z])/ig, function(all, letter){
1081
+ return letter.toUpperCase();
1082
+ });
1083
+
1084
+ if ( value != undefined )
1085
+ elem[ name ] = value;
1086
+
1087
+ return elem[ name ];
587
1088
  }
588
1089
  },
589
- trim: function(t){
590
- return t.replace(/^\s+|\s+$/g, "");
1090
+
1091
+ trim: function( text ) {
1092
+ return (text || "").replace( /^\s+|\s+$/g, "" );
591
1093
  },
592
1094
 
593
- makeArray: function( a ) {
594
- var r = [];
1095
+ makeArray: function( array ) {
1096
+ var ret = [];
595
1097
 
596
1098
  // Need to use typeof to fight Safari childNodes crashes
597
- if ( typeof a != "array" )
598
- for ( var i = 0, al = a.length; i < al; i++ )
599
- r.push( a[i] );
1099
+ if ( typeof array != "array" )
1100
+ for ( var i = 0, length = array.length; i < length; i++ )
1101
+ ret.push( array[ i ] );
600
1102
  else
601
- r = a.slice( 0 );
1103
+ ret = array.slice( 0 );
602
1104
 
603
- return r;
1105
+ return ret;
604
1106
  },
605
1107
 
606
- inArray: function( b, a ) {
607
- for ( var i = 0, al = a.length; i < al; i++ )
608
- if ( a[i] == b )
1108
+ inArray: function( elem, array ) {
1109
+ for ( var i = 0, length = array.length; i < length; i++ )
1110
+ if ( array[ i ] == elem )
609
1111
  return i;
1112
+
610
1113
  return -1;
611
1114
  },
612
- merge: function(first, second) {
1115
+
1116
+ merge: function( first, second ) {
613
1117
  // We have to loop this way because IE & Opera overwrite the length
614
1118
  // expando of getElementsByTagName
615
- for ( var i = 0; second[i]; i++ )
616
- first.push(second[i]);
1119
+
1120
+ // Also, we need to make sure that the correct elements are being returned
1121
+ // (IE returns comment nodes in a '*' query)
1122
+ if ( jQuery.browser.msie ) {
1123
+ for ( var i = 0; second[ i ]; i++ )
1124
+ if ( second[ i ].nodeType != 8 )
1125
+ first.push( second[ i ] );
1126
+
1127
+ } else
1128
+ for ( var i = 0; second[ i ]; i++ )
1129
+ first.push( second[ i ] );
1130
+
617
1131
  return first;
618
1132
  },
619
- unique: function(first) {
620
- var r = [], num = jQuery.mergeNum++;
621
1133
 
622
- for ( var i = 0, fl = first.length; i < fl; i++ )
623
- if ( num != first[i].mergeNum ) {
624
- first[i].mergeNum = num;
625
- r.push(first[i]);
1134
+ unique: function( array ) {
1135
+ var ret = [], done = {};
1136
+
1137
+ try {
1138
+
1139
+ for ( var i = 0, length = array.length; i < length; i++ ) {
1140
+ var id = jQuery.data( array[ i ] );
1141
+
1142
+ if ( !done[ id ] ) {
1143
+ done[ id ] = true;
1144
+ ret.push( array[ i ] );
1145
+ }
626
1146
  }
627
1147
 
628
- return r;
1148
+ } catch( e ) {
1149
+ ret = array;
1150
+ }
1151
+
1152
+ return ret;
629
1153
  },
630
1154
 
631
- mergeNum: 0,
632
- grep: function(elems, fn, inv) {
1155
+ grep: function( elems, callback, inv ) {
633
1156
  // If a string is passed in for the function, make a function
634
1157
  // for it (a handy shortcut)
635
- if ( typeof fn == "string" )
636
- fn = new Function("a","i","return " + fn);
1158
+ if ( typeof callback == "string" )
1159
+ callback = eval("false||function(a,i){return " + callback + "}");
637
1160
 
638
- var result = [];
1161
+ var ret = [];
639
1162
 
640
1163
  // Go through the array, only saving the items
641
1164
  // that pass the validator function
642
- for ( var i = 0, el = elems.length; i < el; i++ )
643
- if ( !inv && fn(elems[i],i) || inv && !fn(elems[i],i) )
644
- result.push( elems[i] );
1165
+ for ( var i = 0, length = elems.length; i < length; i++ )
1166
+ if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
1167
+ ret.push( elems[ i ] );
645
1168
 
646
- return result;
1169
+ return ret;
647
1170
  },
648
- map: function(elems, fn) {
649
- // If a string is passed in for the function, make a function
650
- // for it (a handy shortcut)
651
- if ( typeof fn == "string" )
652
- fn = new Function("a","return " + fn);
653
1171
 
654
- var result = [];
1172
+ map: function( elems, callback ) {
1173
+ var ret = [];
655
1174
 
656
1175
  // Go through the array, translating each of the items to their
657
1176
  // new value (or values).
658
- for ( var i = 0, el = elems.length; i < el; i++ ) {
659
- var val = fn(elems[i],i);
1177
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
1178
+ var value = callback( elems[ i ], i );
1179
+
1180
+ if ( value !== null && value != undefined ) {
1181
+ if ( value.constructor != Array )
1182
+ value = [ value ];
660
1183
 
661
- if ( val !== null && val != undefined ) {
662
- if ( val.constructor != Array ) val = [val];
663
- result = result.concat( val );
1184
+ ret = ret.concat( value );
664
1185
  }
665
1186
  }
666
1187
 
667
- return result;
1188
+ return ret;
668
1189
  }
669
1190
  });
670
-
671
- /*
672
- * Whether the W3C compliant box model is being used.
673
- *
674
- * @property
675
- * @name $.boxModel
676
- * @type Boolean
677
- * @cat JavaScript
678
- */
679
- new function() {
680
- var b = navigator.userAgent.toLowerCase();
681
-
682
- // Figure out what browser is being used
683
- jQuery.browser = {
684
- version: (b.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
685
- safari: /webkit/.test(b),
686
- opera: /opera/.test(b),
687
- msie: /msie/.test(b) && !/opera/.test(b),
688
- mozilla: /mozilla/.test(b) && !/(compatible|webkit)/.test(b)
689
- };
690
1191
 
691
- // Check to see if the W3C box model is being used
692
- jQuery.boxModel = !jQuery.browser.msie || document.compatMode == "CSS1Compat";
1192
+ var userAgent = navigator.userAgent.toLowerCase();
693
1193
 
694
- jQuery.styleFloat = jQuery.browser.msie ? "styleFloat" : "cssFloat",
1194
+ // Figure out what browser is being used
1195
+ jQuery.browser = {
1196
+ version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
1197
+ safari: /webkit/.test( userAgent ),
1198
+ opera: /opera/.test( userAgent ),
1199
+ msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
1200
+ mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
1201
+ };
695
1202
 
696
- jQuery.props = {
1203
+ var styleFloat = jQuery.browser.msie ?
1204
+ "styleFloat" :
1205
+ "cssFloat";
1206
+
1207
+ jQuery.extend({
1208
+ // Check to see if the W3C box model is being used
1209
+ boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
1210
+
1211
+ props: {
697
1212
  "for": "htmlFor",
698
1213
  "class": "className",
699
- "float": jQuery.styleFloat,
700
- cssFloat: jQuery.styleFloat,
701
- styleFloat: jQuery.styleFloat,
1214
+ "float": styleFloat,
1215
+ cssFloat: styleFloat,
1216
+ styleFloat: styleFloat,
702
1217
  innerHTML: "innerHTML",
703
1218
  className: "className",
704
1219
  value: "value",
@@ -706,23 +1221,34 @@ new function() {
706
1221
  checked: "checked",
707
1222
  readonly: "readOnly",
708
1223
  selected: "selected",
709
- maxlength: "maxLength"
710
- };
711
- };
1224
+ maxlength: "maxLength",
1225
+ selectedIndex: "selectedIndex",
1226
+ defaultValue: "defaultValue",
1227
+ tagName: "tagName",
1228
+ nodeName: "nodeName"
1229
+ }
1230
+ });
712
1231
 
713
1232
  jQuery.each({
714
- parent: "a.parentNode",
715
- parents: "jQuery.parents(a)",
716
- next: "jQuery.nth(a,2,'nextSibling')",
717
- prev: "jQuery.nth(a,2,'previousSibling')",
718
- siblings: "jQuery.sibling(a.parentNode.firstChild,a)",
719
- children: "jQuery.sibling(a.firstChild)"
720
- }, function(i,n){
721
- jQuery.fn[ i ] = function(a) {
722
- var ret = jQuery.map(this,n);
723
- if ( a && typeof a == "string" )
724
- ret = jQuery.multiFilter(a,ret);
725
- return this.pushStack( ret );
1233
+ parent: "elem.parentNode",
1234
+ parents: "jQuery.dir(elem,'parentNode')",
1235
+ next: "jQuery.nth(elem,2,'nextSibling')",
1236
+ prev: "jQuery.nth(elem,2,'previousSibling')",
1237
+ nextAll: "jQuery.dir(elem,'nextSibling')",
1238
+ prevAll: "jQuery.dir(elem,'previousSibling')",
1239
+ siblings: "jQuery.sibling(elem.parentNode.firstChild,elem)",
1240
+ children: "jQuery.sibling(elem.firstChild)",
1241
+ contents: "jQuery.nodeName(elem,'iframe')?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes)"
1242
+ }, function(name, fn){
1243
+ fn = eval("false||function(elem){return " + fn + "}");
1244
+
1245
+ jQuery.fn[ name ] = function( selector ) {
1246
+ var ret = jQuery.map( this, fn );
1247
+
1248
+ if ( selector && typeof selector == "string" )
1249
+ ret = jQuery.multiFilter( selector, ret );
1250
+
1251
+ return this.pushStack( jQuery.unique( ret ) );
726
1252
  };
727
1253
  });
728
1254
 
@@ -730,58 +1256,104 @@ jQuery.each({
730
1256
  appendTo: "append",
731
1257
  prependTo: "prepend",
732
1258
  insertBefore: "before",
733
- insertAfter: "after"
734
- }, function(i,n){
735
- jQuery.fn[ i ] = function(){
736
- var a = arguments;
1259
+ insertAfter: "after",
1260
+ replaceAll: "replaceWith"
1261
+ }, function(name, original){
1262
+ jQuery.fn[ name ] = function() {
1263
+ var args = arguments;
1264
+
737
1265
  return this.each(function(){
738
- for ( var j = 0, al = a.length; j < al; j++ )
739
- jQuery(a[j])[n]( this );
1266
+ for ( var i = 0, length = args.length; i < length; i++ )
1267
+ jQuery( args[ i ] )[ original ]( this );
740
1268
  });
741
1269
  };
742
1270
  });
743
1271
 
744
- jQuery.each( {
745
- removeAttr: function( key ) {
746
- jQuery.attr( this, key, "" );
747
- this.removeAttribute( key );
1272
+ jQuery.each({
1273
+ removeAttr: function( name ) {
1274
+ jQuery.attr( this, name, "" );
1275
+ if (this.nodeType == 1)
1276
+ this.removeAttribute( name );
748
1277
  },
749
- addClass: function(c){
750
- jQuery.className.add(this,c);
1278
+
1279
+ addClass: function( classNames ) {
1280
+ jQuery.className.add( this, classNames );
751
1281
  },
752
- removeClass: function(c){
753
- jQuery.className.remove(this,c);
1282
+
1283
+ removeClass: function( classNames ) {
1284
+ jQuery.className.remove( this, classNames );
754
1285
  },
755
- toggleClass: function( c ){
756
- jQuery.className[ jQuery.className.has(this,c) ? "remove" : "add" ](this, c);
1286
+
1287
+ toggleClass: function( classNames ) {
1288
+ jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
757
1289
  },
758
- remove: function(a){
759
- if ( !a || jQuery.filter( a, [this] ).r.length )
760
- this.parentNode.removeChild( this );
1290
+
1291
+ remove: function( selector ) {
1292
+ if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
1293
+ // Prevent memory leaks
1294
+ jQuery( "*", this ).add(this).each(function(){
1295
+ jQuery.event.remove(this);
1296
+ jQuery.removeData(this);
1297
+ });
1298
+ if (this.parentNode)
1299
+ this.parentNode.removeChild( this );
1300
+ }
761
1301
  },
1302
+
762
1303
  empty: function() {
1304
+ // Remove element nodes and prevent memory leaks
1305
+ jQuery( ">*", this ).remove();
1306
+
1307
+ // Remove any remaining nodes
763
1308
  while ( this.firstChild )
764
1309
  this.removeChild( this.firstChild );
765
1310
  }
766
- }, function(i,n){
767
- jQuery.fn[ i ] = function() {
768
- return this.each( n, arguments );
1311
+ }, function(name, fn){
1312
+ jQuery.fn[ name ] = function(){
1313
+ return this.each( fn, arguments );
769
1314
  };
770
1315
  });
771
1316
 
772
- jQuery.each( [ "eq", "lt", "gt", "contains" ], function(i,n){
773
- jQuery.fn[ n ] = function(num,fn) {
774
- return this.filter( ":" + n + "(" + num + ")", fn );
1317
+ jQuery.each([ "Height", "Width" ], function(i, name){
1318
+ var type = name.toLowerCase();
1319
+
1320
+ jQuery.fn[ type ] = function( size ) {
1321
+ // Get window width or height
1322
+ return this[0] == window ?
1323
+ // Opera reports document.body.client[Width/Height] properly in both quirks and standards
1324
+ jQuery.browser.opera && document.body[ "client" + name ] ||
1325
+
1326
+ // Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
1327
+ jQuery.browser.safari && window[ "inner" + name ] ||
1328
+
1329
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
1330
+ document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
1331
+
1332
+ // Get document width or height
1333
+ this[0] == document ?
1334
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
1335
+ Math.max(
1336
+ Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
1337
+ Math.max(document.body["offset" + name], document.documentElement["offset" + name])
1338
+ ) :
1339
+
1340
+ // Get or set width or height on the element
1341
+ size == undefined ?
1342
+ // Get width or height on the element
1343
+ (this.length ? jQuery.css( this[0], type ) : null) :
1344
+
1345
+ // Set the width or height on the element (default to pixels if value is unitless)
1346
+ this.css( type, size.constructor == String ? size : size + "px" );
775
1347
  };
776
1348
  });
777
1349
 
778
- jQuery.each( [ "height", "width" ], function(i,n){
779
- jQuery.fn[ n ] = function(h) {
780
- return h == undefined ?
781
- ( this.length ? jQuery.css( this[0], n ) : null ) :
782
- this.css( n, h.constructor == String ? h : h + "px" );
783
- };
784
- });
1350
+ var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
1351
+ "(?:[\\w*_-]|\\\\.)" :
1352
+ "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
1353
+ quickChild = new RegExp("^>\\s*(" + chars + "+)"),
1354
+ quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
1355
+ quickClass = new RegExp("^([#.]?)(" + chars + "*)");
1356
+
785
1357
  jQuery.extend({
786
1358
  expr: {
787
1359
  "": "m[2]=='*'||jQuery.nodeName(a,m[2])",
@@ -807,7 +1379,7 @@ jQuery.extend({
807
1379
  empty: "!a.firstChild",
808
1380
 
809
1381
  // Text Check
810
- contains: "(a.textContent||a.innerText||'').indexOf(m[3])>=0",
1382
+ contains: "(a.textContent||a.innerText||jQuery(a).text()||'').indexOf(m[3])>=0",
811
1383
 
812
1384
  // Visibility
813
1385
  visible: '"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden"',
@@ -829,25 +1401,29 @@ jQuery.extend({
829
1401
  image: "'image'==a.type",
830
1402
  reset: "'reset'==a.type",
831
1403
  button: '"button"==a.type||jQuery.nodeName(a,"button")',
832
- input: "/input|select|textarea|button/i.test(a.nodeName)"
833
- },
834
- "[": "jQuery.find(m[2],a).length"
1404
+ input: "/input|select|textarea|button/i.test(a.nodeName)",
1405
+
1406
+ // :has()
1407
+ has: "jQuery.find(m[3],a).length",
1408
+
1409
+ // :header
1410
+ header: "/h\\d/i.test(a.nodeName)",
1411
+
1412
+ // :animated
1413
+ animated: "jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length"
1414
+ }
835
1415
  },
836
1416
 
837
1417
  // The regular expressions that power the parsing engine
838
1418
  parse: [
839
1419
  // Match: [@value='test'], [@foo]
840
- /^\[ *(@)([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
841
-
842
- // Match: [div], [div p]
843
- /^(\[)\s*(.*?(\[.*?\])?[^[]*?)\s*\]/,
1420
+ /^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,
844
1421
 
845
1422
  // Match: :contains('foo')
846
1423
  /^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,
847
1424
 
848
1425
  // Match: :even, :last-chlid, #id, .class
849
- new RegExp("^([:.#]*)(" +
850
- ( jQuery.chars = jQuery.browser.safari && jQuery.browser.version < "3.0.0" ? "\\w" : "(?:[\\w\u0128-\uFFFF*_-]|\\\\.)" ) + "+)")
1426
+ new RegExp("^([:.#]*)(" + chars + "+)")
851
1427
  ],
852
1428
 
853
1429
  multiFilter: function( expr, elems, not ) {
@@ -862,33 +1438,21 @@ jQuery.extend({
862
1438
 
863
1439
  return cur;
864
1440
  },
1441
+
865
1442
  find: function( t, context ) {
866
1443
  // Quickly handle non-string expressions
867
1444
  if ( typeof t != "string" )
868
1445
  return [ t ];
869
1446
 
870
- // Make sure that the context is a DOM Element
871
- if ( context && !context.nodeType )
872
- context = null;
1447
+ // check to make sure context is a DOM element or a document
1448
+ if ( context && context.nodeType != 1 && context.nodeType != 9)
1449
+ return [ ];
873
1450
 
874
1451
  // Set the correct context (if none is provided)
875
1452
  context = context || document;
876
1453
 
877
- // Handle the common XPath // expression
878
- if ( !t.indexOf("//") ) {
879
- context = context.documentElement;
880
- t = t.substr(2,t.length);
881
-
882
- // And the / root expression
883
- } else if ( !t.indexOf("/") && !context.ownerDocument ) {
884
- context = context.documentElement;
885
- t = t.substr(1,t.length);
886
- if ( t.indexOf("/") >= 1 )
887
- t = t.substr(t.indexOf("/"),t.length);
888
- }
889
-
890
1454
  // Initialize the search
891
- var ret = [context], done = [], last;
1455
+ var ret = [context], done = [], last, nodeName;
892
1456
 
893
1457
  // Continue while a selector expression exists, and while
894
1458
  // we're no longer looping upon ourselves
@@ -896,22 +1460,22 @@ jQuery.extend({
896
1460
  var r = [];
897
1461
  last = t;
898
1462
 
899
- t = jQuery.trim(t).replace( /^\/\//, "" );
1463
+ t = jQuery.trim(t);
900
1464
 
901
1465
  var foundToken = false;
902
1466
 
903
1467
  // An attempt at speeding up child selectors that
904
1468
  // point to a specific element tag
905
- var re = new RegExp("^[/>]\\s*(" + jQuery.chars + "+)");
1469
+ var re = quickChild;
906
1470
  var m = re.exec(t);
907
1471
 
908
1472
  if ( m ) {
909
- var nodeName = m[1].toUpperCase();
1473
+ nodeName = m[1].toUpperCase();
910
1474
 
911
1475
  // Perform our own iteration and filter
912
1476
  for ( var i = 0; ret[i]; i++ )
913
1477
  for ( var c = ret[i].firstChild; c; c = c.nextSibling )
914
- if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName.toUpperCase()) )
1478
+ if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
915
1479
  r.push( c );
916
1480
 
917
1481
  ret = r;
@@ -919,30 +1483,31 @@ jQuery.extend({
919
1483
  if ( t.indexOf(" ") == 0 ) continue;
920
1484
  foundToken = true;
921
1485
  } else {
922
- re = /^((\/?\.\.)|([>\/+~]))\s*([a-z]*)/i;
1486
+ re = /^([>+~])\s*(\w*)/i;
923
1487
 
924
1488
  if ( (m = re.exec(t)) != null ) {
925
1489
  r = [];
926
1490
 
927
- var nodeName = m[4], mergeNum = jQuery.mergeNum++;
1491
+ var merge = {};
1492
+ nodeName = m[2].toUpperCase();
928
1493
  m = m[1];
929
1494
 
930
- for ( var j = 0, rl = ret.length; j < rl; j++ )
931
- if ( m.indexOf("..") < 0 ) {
932
- var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
933
- for ( ; n; n = n.nextSibling )
934
- if ( n.nodeType == 1 ) {
935
- if ( m == "~" && n.mergeNum == mergeNum ) break;
936
-
937
- if (!nodeName || n.nodeName.toUpperCase() == nodeName.toUpperCase() ) {
938
- if ( m == "~" ) n.mergeNum = mergeNum;
939
- r.push( n );
940
- }
941
-
942
- if ( m == "+" ) break;
1495
+ for ( var j = 0, rl = ret.length; j < rl; j++ ) {
1496
+ var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
1497
+ for ( ; n; n = n.nextSibling )
1498
+ if ( n.nodeType == 1 ) {
1499
+ var id = jQuery.data(n);
1500
+
1501
+ if ( m == "~" && merge[id] ) break;
1502
+
1503
+ if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
1504
+ if ( m == "~" ) merge[id] = true;
1505
+ r.push( n );
943
1506
  }
944
- } else
945
- r.push( ret[j].parentNode );
1507
+
1508
+ if ( m == "+" ) break;
1509
+ }
1510
+ }
946
1511
 
947
1512
  ret = r;
948
1513
 
@@ -970,18 +1535,18 @@ jQuery.extend({
970
1535
  t = " " + t.substr(1,t.length);
971
1536
 
972
1537
  } else {
973
- // Optomize for the case nodeName#idName
974
- var re2 = new RegExp("^(" + jQuery.chars + "+)(#)(" + jQuery.chars + "+)");
1538
+ // Optimize for the case nodeName#idName
1539
+ var re2 = quickID;
975
1540
  var m = re2.exec(t);
976
1541
 
977
1542
  // Re-organize the results, so that they're consistent
978
1543
  if ( m ) {
979
- m = [ 0, m[2], m[3], m[1] ];
1544
+ m = [ 0, m[2], m[3], m[1] ];
980
1545
 
981
1546
  } else {
982
1547
  // Otherwise, do a traditional filter check for
983
1548
  // ID, class, and element selectors
984
- re2 = new RegExp("^([#.]?)(" + jQuery.chars + "*)");
1549
+ re2 = quickClass;
985
1550
  m = re2.exec(t);
986
1551
  }
987
1552
 
@@ -990,7 +1555,7 @@ jQuery.extend({
990
1555
  var elem = ret[ret.length-1];
991
1556
 
992
1557
  // Try to do a global search by ID, where we can
993
- if ( m[1] == "#" && elem && elem.getElementById ) {
1558
+ if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
994
1559
  // Optimization for HTML document case
995
1560
  var oid = elem.getElementById(m[2]);
996
1561
 
@@ -1007,7 +1572,7 @@ jQuery.extend({
1007
1572
  // We need to find all descendant elements
1008
1573
  for ( var i = 0; ret[i]; i++ ) {
1009
1574
  // Grab the tag name being searched for
1010
- var tag = m[1] != "" || m[0] == "" ? "*" : m[2];
1575
+ var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];
1011
1576
 
1012
1577
  // Handle IE7 being really dumb about <object>s
1013
1578
  if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
@@ -1081,7 +1646,7 @@ jQuery.extend({
1081
1646
  var last;
1082
1647
 
1083
1648
  // Look for common filter expressions
1084
- while ( t && t != last ) {
1649
+ while ( t && t != last ) {
1085
1650
  last = t;
1086
1651
 
1087
1652
  var p = jQuery.parse, m;
@@ -1104,19 +1669,22 @@ jQuery.extend({
1104
1669
  // :not() is a special case that can be optimized by
1105
1670
  // keeping it out of the expression list
1106
1671
  if ( m[1] == ":" && m[2] == "not" )
1107
- r = jQuery.filter(m[3], r, true).r;
1672
+ // optimize if only one selector found (most common case)
1673
+ r = isSimple.test( m[3] ) ?
1674
+ jQuery.filter(m[3], r, true).r :
1675
+ jQuery( r ).not( m[3] );
1108
1676
 
1109
1677
  // We can get a big speed boost by filtering by class here
1110
1678
  else if ( m[1] == "." )
1111
1679
  r = jQuery.classFilter(r, m[2], not);
1112
1680
 
1113
- else if ( m[1] == "@" ) {
1681
+ else if ( m[1] == "[" ) {
1114
1682
  var tmp = [], type = m[3];
1115
1683
 
1116
1684
  for ( var i = 0, rl = r.length; i < rl; i++ ) {
1117
1685
  var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
1118
1686
 
1119
- if ( z == null || /href|src/.test(m[2]) )
1687
+ if ( z == null || /href|src|selected/.test(m[2]) )
1120
1688
  z = jQuery.attr(a,m[2]) || '';
1121
1689
 
1122
1690
  if ( (type == "" && !!z ||
@@ -1132,31 +1700,34 @@ jQuery.extend({
1132
1700
 
1133
1701
  // We can get a speed boost by handling nth-child here
1134
1702
  } else if ( m[1] == ":" && m[2] == "nth-child" ) {
1135
- var num = jQuery.mergeNum++, tmp = [],
1136
- test = /(\d*)n\+?(\d*)/.exec(
1703
+ var merge = {}, tmp = [],
1704
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
1705
+ test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
1137
1706
  m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
1138
- !/\D/.test(m[3]) && "n+" + m[3] || m[3]),
1139
- first = (test[1] || 1) - 0, last = test[2] - 0;
1140
-
1707
+ !/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
1708
+ // calculate the numbers (first)n+(last) including if they are negative
1709
+ first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
1710
+
1711
+ // loop through all the elements left in the jQuery object
1141
1712
  for ( var i = 0, rl = r.length; i < rl; i++ ) {
1142
- var node = r[i], parentNode = node.parentNode;
1713
+ var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);
1143
1714
 
1144
- if ( num != parentNode.mergeNum ) {
1715
+ if ( !merge[id] ) {
1145
1716
  var c = 1;
1146
1717
 
1147
1718
  for ( var n = parentNode.firstChild; n; n = n.nextSibling )
1148
1719
  if ( n.nodeType == 1 )
1149
1720
  n.nodeIndex = c++;
1150
1721
 
1151
- parentNode.mergeNum = num;
1722
+ merge[id] = true;
1152
1723
  }
1153
1724
 
1154
1725
  var add = false;
1155
1726
 
1156
- if ( first == 1 ) {
1157
- if ( last == 0 || node.nodeIndex == last )
1727
+ if ( first == 0 ) {
1728
+ if ( node.nodeIndex == last )
1158
1729
  add = true;
1159
- } else if ( (node.nodeIndex + last) % first == 0 )
1730
+ } else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
1160
1731
  add = true;
1161
1732
 
1162
1733
  if ( add ^ not )
@@ -1172,7 +1743,7 @@ jQuery.extend({
1172
1743
  f = jQuery.expr[m[1]][m[2]];
1173
1744
 
1174
1745
  // Build a custom macro to enclose it
1175
- eval("f = function(a,i){return " + f + "}");
1746
+ f = eval("false||function(a,i){return " + f + "}");
1176
1747
 
1177
1748
  // Execute it against the current filter
1178
1749
  r = jQuery.grep( r, f, not );
@@ -1183,15 +1754,18 @@ jQuery.extend({
1183
1754
  // and the modified expression string (t)
1184
1755
  return { r: r, t: t };
1185
1756
  },
1186
- parents: function( elem ){
1757
+
1758
+ dir: function( elem, dir ){
1187
1759
  var matched = [];
1188
- var cur = elem.parentNode;
1760
+ var cur = elem[dir];
1189
1761
  while ( cur && cur != document ) {
1190
- matched.push( cur );
1191
- cur = cur.parentNode;
1762
+ if ( cur.nodeType == 1 )
1763
+ matched.push( cur );
1764
+ cur = cur[dir];
1192
1765
  }
1193
1766
  return matched;
1194
1767
  },
1768
+
1195
1769
  nth: function(cur,result,dir,elem){
1196
1770
  result = result || 1;
1197
1771
  var num = 0;
@@ -1202,6 +1776,7 @@ jQuery.extend({
1202
1776
 
1203
1777
  return cur;
1204
1778
  },
1779
+
1205
1780
  sibling: function( n, elem ) {
1206
1781
  var r = [];
1207
1782
 
@@ -1213,6 +1788,7 @@ jQuery.extend({
1213
1788
  return r;
1214
1789
  }
1215
1790
  });
1791
+
1216
1792
  /*
1217
1793
  * A number of helper functions used for managing events.
1218
1794
  * Many of the ideas behind this code orignated from
@@ -1222,19 +1798,22 @@ jQuery.event = {
1222
1798
 
1223
1799
  // Bind an event to an element
1224
1800
  // Original by Dean Edwards
1225
- add: function(element, type, handler, data) {
1801
+ add: function(elem, types, handler, data) {
1802
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
1803
+ return;
1804
+
1226
1805
  // For whatever reason, IE has trouble passing the window object
1227
1806
  // around, causing it to be cloned in the process
1228
- if ( jQuery.browser.msie && element.setInterval != undefined )
1229
- element = window;
1230
-
1807
+ if ( jQuery.browser.msie && elem.setInterval != undefined )
1808
+ elem = window;
1809
+
1231
1810
  // Make sure that the function being executed has a unique ID
1232
1811
  if ( !handler.guid )
1233
1812
  handler.guid = this.guid++;
1234
1813
 
1235
1814
  // if data is passed, bind to handler
1236
1815
  if( data != undefined ) {
1237
- // Create temporary function pointer to original handler
1816
+ // Create temporary function pointer to original handler
1238
1817
  var fn = handler;
1239
1818
 
1240
1819
  // Create unique handler function, wrapped around original handler
@@ -1251,126 +1830,184 @@ jQuery.event = {
1251
1830
  }
1252
1831
 
1253
1832
  // Init the element's event structure
1254
- if (!element.$events)
1255
- element.$events = {};
1256
-
1257
- if (!element.$handle)
1258
- element.$handle = function() {
1833
+ var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
1834
+ handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
1259
1835
  // returned undefined or false
1260
1836
  var val;
1261
1837
 
1262
1838
  // Handle the second event of a trigger and when
1263
1839
  // an event is called after a page has unloaded
1264
1840
  if ( typeof jQuery == "undefined" || jQuery.event.triggered )
1265
- return val;
1266
-
1267
- val = jQuery.event.handle.apply(element, arguments);
1268
-
1841
+ return val;
1842
+
1843
+ val = jQuery.event.handle.apply(elem, arguments);
1844
+
1269
1845
  return val;
1270
- };
1271
-
1272
- // Get the current list of functions bound to this event
1273
- var handlers = element.$events[type];
1274
-
1275
- // Init the event handler queue
1276
- if (!handlers) {
1277
- handlers = element.$events[type] = {};
1846
+ });
1278
1847
 
1279
- // And bind the global event handler to the element
1280
- if (element.addEventListener)
1281
- element.addEventListener(type, element.$handle, false);
1282
- else
1283
- element.attachEvent("on" + type, element.$handle);
1284
- }
1848
+ // Handle multiple events seperated by a space
1849
+ // jQuery(...).bind("mouseover mouseout", fn);
1850
+ jQuery.each(types.split(/\s+/), function(index, type) {
1851
+ // Namespaced event handlers
1852
+ var parts = type.split(".");
1853
+ type = parts[0];
1854
+ handler.type = parts[1];
1855
+
1856
+ // Get the current list of functions bound to this event
1857
+ var handlers = events[type];
1858
+
1859
+ // Init the event handler queue
1860
+ if (!handlers) {
1861
+ handlers = events[type] = {};
1862
+
1863
+ // Check for a special event handler
1864
+ // Only use addEventListener/attachEvent if the special
1865
+ // events handler returns false
1866
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
1867
+ // Bind the global event handler to the element
1868
+ if (elem.addEventListener)
1869
+ elem.addEventListener(type, handle, false);
1870
+ else if (elem.attachEvent)
1871
+ elem.attachEvent("on" + type, handle);
1872
+ }
1873
+ }
1285
1874
 
1286
- // Add the function to the element's handler list
1287
- handlers[handler.guid] = handler;
1875
+ // Add the function to the element's handler list
1876
+ handlers[handler.guid] = handler;
1288
1877
 
1289
- // Remember the function in a global list (for triggering)
1290
- if (!this.global[type])
1291
- this.global[type] = [];
1292
- // Only add the element to the global list once
1293
- if (jQuery.inArray(element, this.global[type]) == -1)
1294
- this.global[type].push( element );
1878
+ // Keep track of which events have been used, for global triggering
1879
+ jQuery.event.global[type] = true;
1880
+ });
1295
1881
  },
1296
1882
 
1297
1883
  guid: 1,
1298
1884
  global: {},
1299
1885
 
1300
1886
  // Detach an event or set of events from an element
1301
- remove: function(element, type, handler) {
1302
- var events = element.$events, ret, index;
1887
+ remove: function(elem, types, handler) {
1888
+ // don't do events on text and comment nodes
1889
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
1890
+ return;
1891
+
1892
+ var events = jQuery.data(elem, "events"), ret, index;
1303
1893
 
1304
1894
  if ( events ) {
1305
- // type is actually an event object here
1306
- if ( type && type.type ) {
1307
- handler = type.handler;
1308
- type = type.type;
1309
- }
1310
-
1311
- if ( !type ) {
1312
- for ( type in events )
1313
- this.remove( element, type );
1314
-
1315
- } else if ( events[type] ) {
1316
- // remove the given handler for the given type
1317
- if ( handler )
1318
- delete events[type][handler.guid];
1895
+ // Unbind all events for the element
1896
+ if ( types == undefined )
1897
+ for ( var type in events )
1898
+ this.remove( elem, type );
1899
+ else {
1900
+ // types is actually an event object here
1901
+ if ( types.type ) {
1902
+ handler = types.handler;
1903
+ types = types.type;
1904
+ }
1319
1905
 
1320
- // remove all handlers for the given type
1321
- else
1322
- for ( handler in element.$events[type] )
1323
- delete events[type][handler];
1324
-
1325
- // remove generic event handler if no more handlers exist
1326
- for ( ret in events[type] ) break;
1327
- if ( !ret ) {
1328
- if (element.removeEventListener)
1329
- element.removeEventListener(type, element.$handle, false);
1330
- else
1331
- element.detachEvent("on" + type, element.$handle);
1332
- ret = null;
1333
- delete events[type];
1906
+ // Handle multiple events seperated by a space
1907
+ // jQuery(...).unbind("mouseover mouseout", fn);
1908
+ jQuery.each(types.split(/\s+/), function(index, type){
1909
+ // Namespaced event handlers
1910
+ var parts = type.split(".");
1911
+ type = parts[0];
1334
1912
 
1335
- // Remove element from the global event type cache
1336
- while ( this.global[type] && ( (index = jQuery.inArray(element, this.global[type])) >= 0 ) )
1337
- delete this.global[type][index];
1338
- }
1913
+ if ( events[type] ) {
1914
+ // remove the given handler for the given type
1915
+ if ( handler )
1916
+ delete events[type][handler.guid];
1917
+
1918
+ // remove all handlers for the given type
1919
+ else
1920
+ for ( handler in events[type] )
1921
+ // Handle the removal of namespaced events
1922
+ if ( !parts[1] || events[type][handler].type == parts[1] )
1923
+ delete events[type][handler];
1924
+
1925
+ // remove generic event handler if no more handlers exist
1926
+ for ( ret in events[type] ) break;
1927
+ if ( !ret ) {
1928
+ if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
1929
+ if (elem.removeEventListener)
1930
+ elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
1931
+ else if (elem.detachEvent)
1932
+ elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
1933
+ }
1934
+ ret = null;
1935
+ delete events[type];
1936
+ }
1937
+ }
1938
+ });
1339
1939
  }
1340
1940
 
1341
1941
  // Remove the expando if it's no longer used
1342
1942
  for ( ret in events ) break;
1343
- if ( !ret )
1344
- element.$handle = element.$events = null;
1943
+ if ( !ret ) {
1944
+ jQuery.removeData( elem, "events" );
1945
+ jQuery.removeData( elem, "handle" );
1946
+ }
1345
1947
  }
1346
1948
  },
1347
1949
 
1348
- trigger: function(type, data, element) {
1950
+ trigger: function(type, data, elem, donative, extra) {
1349
1951
  // Clone the incoming data, if any
1350
1952
  data = jQuery.makeArray(data || []);
1351
1953
 
1352
1954
  // Handle a global trigger
1353
- if ( !element )
1354
- jQuery.each( this.global[type] || [], function(){
1355
- jQuery.event.trigger( type, data, this );
1356
- });
1955
+ if ( !elem ) {
1956
+ // Only trigger if we've ever bound an event for it
1957
+ if ( this.global[type] )
1958
+ jQuery("*").add([window, document]).trigger(type, data);
1357
1959
 
1358
1960
  // Handle triggering a single element
1359
- else {
1360
- var val, ret, fn = jQuery.isFunction( element[ type ] || null );
1961
+ } else {
1962
+ // don't do events on text and comment nodes
1963
+ if ( elem.nodeType == 3 || elem.nodeType == 8 )
1964
+ return undefined;
1965
+
1966
+ var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
1967
+ // Check to see if we need to provide a fake event, or not
1968
+ event = !data[0] || !data[0].preventDefault;
1361
1969
 
1362
1970
  // Pass along a fake event
1363
- data.unshift( this.fix({ type: type, target: element }) );
1971
+ if ( event )
1972
+ data.unshift( this.fix({ type: type, target: elem }) );
1973
+
1974
+ // Enforce the right trigger type
1975
+ data[0].type = type;
1364
1976
 
1365
1977
  // Trigger the event
1366
- if ( jQuery.isFunction(element.$handle) && (val = element.$handle.apply( element, data )) !== false )
1367
- this.triggered = true;
1978
+ if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
1979
+ val = jQuery.data(elem, "handle").apply( elem, data );
1368
1980
 
1369
- if ( fn && val !== false && !jQuery.nodeName(element, 'a') )
1370
- element[ type ]();
1981
+ // Handle triggering native .onfoo handlers
1982
+ if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
1983
+ val = false;
1984
+
1985
+ // Extra functions don't get the custom event object
1986
+ if ( event )
1987
+ data.shift();
1988
+
1989
+ // Handle triggering of extra function
1990
+ if ( extra && jQuery.isFunction( extra ) ) {
1991
+ // call the extra function and tack the current return value on the end for possible inspection
1992
+ var ret = extra.apply( elem, data.concat( val ) );
1993
+ // if anything is returned, give it precedence and have it overwrite the previous value
1994
+ if (ret !== undefined)
1995
+ val = ret;
1996
+ }
1997
+
1998
+ // Trigger the native events (except for clicks on links)
1999
+ if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
2000
+ this.triggered = true;
2001
+ try {
2002
+ elem[ type ]();
2003
+ // prevent IE from throwing an error for some hidden elements
2004
+ } catch (e) {}
2005
+ }
1371
2006
 
1372
2007
  this.triggered = false;
1373
2008
  }
2009
+
2010
+ return val;
1374
2011
  },
1375
2012
 
1376
2013
  handle: function(event) {
@@ -1380,19 +2017,31 @@ jQuery.event = {
1380
2017
  // Empty object is for triggered events with no data
1381
2018
  event = jQuery.event.fix( event || window.event || {} );
1382
2019
 
1383
- var c = this.$events && this.$events[event.type], args = [].slice.call( arguments, 1 );
2020
+ // Namespaced event handlers
2021
+ var parts = event.type.split(".");
2022
+ event.type = parts[0];
2023
+
2024
+ var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
1384
2025
  args.unshift( event );
1385
2026
 
1386
- for ( var j in c ) {
2027
+ for ( var j in handlers ) {
2028
+ var handler = handlers[j];
1387
2029
  // Pass in a reference to the handler function itself
1388
2030
  // So that we can later remove it
1389
- args[0].handler = c[j];
1390
- args[0].data = c[j].data;
2031
+ args[0].handler = handler;
2032
+ args[0].data = handler.data;
1391
2033
 
1392
- if ( c[j].apply( this, args ) === false ) {
1393
- event.preventDefault();
1394
- event.stopPropagation();
1395
- val = false;
2034
+ // Filter the functions by class
2035
+ if ( !parts[1] || handler.type == parts[1] ) {
2036
+ var ret = handler.apply( this, args );
2037
+
2038
+ if ( val !== false )
2039
+ val = ret;
2040
+
2041
+ if ( ret === false ) {
2042
+ event.preventDefault();
2043
+ event.stopPropagation();
2044
+ }
1396
2045
  }
1397
2046
  }
1398
2047
 
@@ -1405,34 +2054,41 @@ jQuery.event = {
1405
2054
  },
1406
2055
 
1407
2056
  fix: function(event) {
2057
+ // Short-circuit if the event has already been fixed by jQuery.event.fix
2058
+ if ( event[ expando ] )
2059
+ return event;
2060
+
1408
2061
  // store a copy of the original event object
1409
2062
  // and clone to set read-only properties
1410
2063
  var originalEvent = event;
1411
2064
  event = jQuery.extend({}, originalEvent);
1412
2065
 
2066
+ // Mark the event as fixed by jQuery.event.fix
2067
+ event[ expando ] = true;
2068
+
1413
2069
  // add preventDefault and stopPropagation since
1414
2070
  // they will not work on the clone
1415
2071
  event.preventDefault = function() {
1416
2072
  // if preventDefault exists run it on the original event
1417
2073
  if (originalEvent.preventDefault)
1418
- return originalEvent.preventDefault();
2074
+ originalEvent.preventDefault();
1419
2075
  // otherwise set the returnValue property of the original event to false (IE)
1420
2076
  originalEvent.returnValue = false;
1421
2077
  };
1422
2078
  event.stopPropagation = function() {
1423
2079
  // if stopPropagation exists run it on the original event
1424
2080
  if (originalEvent.stopPropagation)
1425
- return originalEvent.stopPropagation();
2081
+ originalEvent.stopPropagation();
1426
2082
  // otherwise set the cancelBubble property of the original event to true (IE)
1427
2083
  originalEvent.cancelBubble = true;
1428
2084
  };
1429
2085
 
1430
2086
  // Fix target property, if necessary
1431
- if ( !event.target && event.srcElement )
1432
- event.target = event.srcElement;
2087
+ if ( !event.target )
2088
+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
1433
2089
 
1434
2090
  // check if target is a textnode (safari)
1435
- if (jQuery.browser.safari && event.target.nodeType == 3)
2091
+ if ( event.target.nodeType == 3 )
1436
2092
  event.target = originalEvent.target.parentNode;
1437
2093
 
1438
2094
  // Add relatedTarget, if necessary
@@ -1441,9 +2097,9 @@ jQuery.event = {
1441
2097
 
1442
2098
  // Calculate pageX/Y if missing and clientX/Y available
1443
2099
  if ( event.pageX == null && event.clientX != null ) {
1444
- var e = document.documentElement, b = document.body;
1445
- event.pageX = event.clientX + (e && e.scrollLeft || b.scrollLeft);
1446
- event.pageY = event.clientY + (e && e.scrollTop || b.scrollTop);
2100
+ var doc = document.documentElement, body = document.body;
2101
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
2102
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
1447
2103
  }
1448
2104
 
1449
2105
  // Add which for key events
@@ -1460,6 +2116,62 @@ jQuery.event = {
1460
2116
  event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
1461
2117
 
1462
2118
  return event;
2119
+ },
2120
+
2121
+ special: {
2122
+ ready: {
2123
+ setup: function() {
2124
+ // Make sure the ready event is setup
2125
+ bindReady();
2126
+ return;
2127
+ },
2128
+
2129
+ teardown: function() { return; }
2130
+ },
2131
+
2132
+ mouseenter: {
2133
+ setup: function() {
2134
+ if ( jQuery.browser.msie ) return false;
2135
+ jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
2136
+ return true;
2137
+ },
2138
+
2139
+ teardown: function() {
2140
+ if ( jQuery.browser.msie ) return false;
2141
+ jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
2142
+ return true;
2143
+ },
2144
+
2145
+ handler: function(event) {
2146
+ // If we actually just moused on to a sub-element, ignore it
2147
+ if ( withinElement(event, this) ) return true;
2148
+ // Execute the right handlers by setting the event type to mouseenter
2149
+ arguments[0].type = "mouseenter";
2150
+ return jQuery.event.handle.apply(this, arguments);
2151
+ }
2152
+ },
2153
+
2154
+ mouseleave: {
2155
+ setup: function() {
2156
+ if ( jQuery.browser.msie ) return false;
2157
+ jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
2158
+ return true;
2159
+ },
2160
+
2161
+ teardown: function() {
2162
+ if ( jQuery.browser.msie ) return false;
2163
+ jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
2164
+ return true;
2165
+ },
2166
+
2167
+ handler: function(event) {
2168
+ // If we actually just moused on to a sub-element, ignore it
2169
+ if ( withinElement(event, this) ) return true;
2170
+ // Execute the right handlers by setting the event type to mouseleave
2171
+ arguments[0].type = "mouseleave";
2172
+ return jQuery.event.handle.apply(this, arguments);
2173
+ }
2174
+ }
1463
2175
  }
1464
2176
  };
1465
2177
 
@@ -1469,6 +2181,7 @@ jQuery.fn.extend({
1469
2181
  jQuery.event.add( this, type, fn || data, fn && data );
1470
2182
  });
1471
2183
  },
2184
+
1472
2185
  one: function( type, data, fn ) {
1473
2186
  return this.each(function(){
1474
2187
  jQuery.event.add( this, type, function(event) {
@@ -1477,73 +2190,66 @@ jQuery.fn.extend({
1477
2190
  }, fn && data);
1478
2191
  });
1479
2192
  },
2193
+
1480
2194
  unbind: function( type, fn ) {
1481
2195
  return this.each(function(){
1482
2196
  jQuery.event.remove( this, type, fn );
1483
2197
  });
1484
2198
  },
1485
- trigger: function( type, data ) {
2199
+
2200
+ trigger: function( type, data, fn ) {
1486
2201
  return this.each(function(){
1487
- jQuery.event.trigger( type, data, this );
2202
+ jQuery.event.trigger( type, data, this, true, fn );
1488
2203
  });
1489
2204
  },
2205
+
2206
+ triggerHandler: function( type, data, fn ) {
2207
+ if ( this[0] )
2208
+ return jQuery.event.trigger( type, data, this[0], false, fn );
2209
+ return undefined;
2210
+ },
2211
+
1490
2212
  toggle: function() {
1491
2213
  // Save reference to arguments for access in closure
1492
- var a = arguments;
2214
+ var args = arguments;
1493
2215
 
1494
- return this.click(function(e) {
2216
+ return this.click(function(event) {
1495
2217
  // Figure out which function to execute
1496
2218
  this.lastToggle = 0 == this.lastToggle ? 1 : 0;
1497
2219
 
1498
2220
  // Make sure that clicks stop
1499
- e.preventDefault();
2221
+ event.preventDefault();
1500
2222
 
1501
2223
  // and execute the function
1502
- return a[this.lastToggle].apply( this, [e] ) || false;
2224
+ return args[this.lastToggle].apply( this, arguments ) || false;
1503
2225
  });
1504
2226
  },
1505
- hover: function(f,g) {
1506
-
1507
- // A private function for handling mouse 'hovering'
1508
- function handleHover(e) {
1509
- // Check if mouse(over|out) are still within the same parent element
1510
- var p = e.relatedTarget;
1511
-
1512
- // Traverse up the tree
1513
- while ( p && p != this ) try { p = p.parentNode } catch(e) { p = this; };
1514
-
1515
- // If we actually just moused on to a sub-element, ignore it
1516
- if ( p == this ) return false;
1517
-
1518
- // Execute the right function
1519
- return (e.type == "mouseover" ? f : g).apply(this, [e]);
1520
- }
1521
-
1522
- // Bind the function to the two event listeners
1523
- return this.mouseover(handleHover).mouseout(handleHover);
2227
+
2228
+ hover: function(fnOver, fnOut) {
2229
+ return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
1524
2230
  },
1525
- ready: function(f) {
2231
+
2232
+ ready: function(fn) {
2233
+ // Attach the listeners
2234
+ bindReady();
2235
+
1526
2236
  // If the DOM is already ready
1527
2237
  if ( jQuery.isReady )
1528
2238
  // Execute the function immediately
1529
- f.apply( document, [jQuery] );
2239
+ fn.call( document, jQuery );
1530
2240
 
1531
2241
  // Otherwise, remember the function for later
1532
2242
  else
1533
2243
  // Add the function to the wait list
1534
- jQuery.readyList.push( function() { return f.apply(this, [jQuery]) } );
2244
+ jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
1535
2245
 
1536
2246
  return this;
1537
2247
  }
1538
2248
  });
1539
2249
 
1540
2250
  jQuery.extend({
1541
- /*
1542
- * All the code that makes DOM Ready work nicely.
1543
- */
1544
2251
  isReady: false,
1545
2252
  readyList: [],
1546
-
1547
2253
  // Handle when the DOM is ready
1548
2254
  ready: function() {
1549
2255
  // Make sure that the DOM is not already loaded
@@ -1561,98 +2267,113 @@ jQuery.extend({
1561
2267
  // Reset the list of functions
1562
2268
  jQuery.readyList = null;
1563
2269
  }
1564
- // Remove event listener to avoid memory leak
1565
- if ( jQuery.browser.mozilla || jQuery.browser.opera )
1566
- document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
1567
-
1568
- // Remove script element used by IE hack
1569
- if( !window.frames.length ) // don't remove if frames are present (#1187)
1570
- jQuery(window).load(function(){ jQuery("#__ie_init").remove(); });
2270
+
2271
+ // Trigger any bound ready events
2272
+ $(document).triggerHandler("ready");
1571
2273
  }
1572
2274
  }
1573
2275
  });
1574
2276
 
1575
- new function(){
2277
+ var readyBound = false;
1576
2278
 
1577
- jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
1578
- "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
1579
- "submit,keydown,keypress,keyup,error").split(","), function(i,o){
1580
-
1581
- // Handle event binding
1582
- jQuery.fn[o] = function(f){
1583
- return f ? this.bind(o, f) : this.trigger(o);
1584
- };
1585
-
1586
- });
1587
-
1588
- // If Mozilla is used
1589
- if ( jQuery.browser.mozilla || jQuery.browser.opera )
2279
+ function bindReady(){
2280
+ if ( readyBound ) return;
2281
+ readyBound = true;
2282
+
2283
+ // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
2284
+ if ( document.addEventListener && !jQuery.browser.opera)
1590
2285
  // Use the handy event callback
1591
2286
  document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
1592
2287
 
1593
- // If IE is used, use the excellent hack by Matthias Miller
1594
- // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
1595
- else if ( jQuery.browser.msie ) {
1596
-
1597
- // Only works if you document.write() it
1598
- document.write("<scr" + "ipt id=__ie_init defer=true " +
1599
- "src=//:><\/script>");
1600
-
1601
- // Use the defer script hack
1602
- var script = document.getElementById("__ie_init");
1603
-
1604
- // script does not exist if jQuery is loaded dynamically
1605
- if ( script )
1606
- script.onreadystatechange = function() {
1607
- if ( this.readyState != "complete" ) return;
1608
- jQuery.ready();
1609
- };
1610
-
1611
- // Clear from memory
1612
- script = null;
1613
-
1614
- // If Safari is used
1615
- } else if ( jQuery.browser.safari )
1616
- // Continually check to see if the document.readyState is valid
1617
- jQuery.safariTimer = setInterval(function(){
1618
- // loaded and complete are both valid states
1619
- if ( document.readyState == "loaded" ||
1620
- document.readyState == "complete" ) {
1621
-
1622
- // If either one are found, remove the timer
1623
- clearInterval( jQuery.safariTimer );
1624
- jQuery.safariTimer = null;
1625
-
1626
- // and execute any waiting functions
1627
- jQuery.ready();
2288
+ // If IE is used and is not in a frame
2289
+ // Continually check to see if the document is ready
2290
+ if ( jQuery.browser.msie && window == top ) (function(){
2291
+ if (jQuery.isReady) return;
2292
+ try {
2293
+ // If IE is used, use the trick by Diego Perini
2294
+ // http://javascript.nwbox.com/IEContentLoaded/
2295
+ document.documentElement.doScroll("left");
2296
+ } catch( error ) {
2297
+ setTimeout( arguments.callee, 0 );
2298
+ return;
2299
+ }
2300
+ // and execute any waiting functions
2301
+ jQuery.ready();
2302
+ })();
2303
+
2304
+ if ( jQuery.browser.opera )
2305
+ document.addEventListener( "DOMContentLoaded", function () {
2306
+ if (jQuery.isReady) return;
2307
+ for (var i = 0; i < document.styleSheets.length; i++)
2308
+ if (document.styleSheets[i].disabled) {
2309
+ setTimeout( arguments.callee, 0 );
2310
+ return;
2311
+ }
2312
+ // and execute any waiting functions
2313
+ jQuery.ready();
2314
+ }, false);
2315
+
2316
+ if ( jQuery.browser.safari ) {
2317
+ var numStyles;
2318
+ (function(){
2319
+ if (jQuery.isReady) return;
2320
+ if ( document.readyState != "loaded" && document.readyState != "complete" ) {
2321
+ setTimeout( arguments.callee, 0 );
2322
+ return;
2323
+ }
2324
+ if ( numStyles === undefined )
2325
+ numStyles = jQuery("style, link[rel=stylesheet]").length;
2326
+ if ( document.styleSheets.length != numStyles ) {
2327
+ setTimeout( arguments.callee, 0 );
2328
+ return;
1628
2329
  }
1629
- }, 10);
2330
+ // and execute any waiting functions
2331
+ jQuery.ready();
2332
+ })();
2333
+ }
1630
2334
 
1631
2335
  // A fallback to window.onload, that will always work
1632
2336
  jQuery.event.add( window, "load", jQuery.ready );
2337
+ }
2338
+
2339
+ jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
2340
+ "mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
2341
+ "submit,keydown,keypress,keyup,error").split(","), function(i, name){
1633
2342
 
2343
+ // Handle event binding
2344
+ jQuery.fn[name] = function(fn){
2345
+ return fn ? this.bind(name, fn) : this.trigger(name);
2346
+ };
2347
+ });
2348
+
2349
+ // Checks if an event happened on an element within another element
2350
+ // Used in jQuery.event.special.mouseenter and mouseleave handlers
2351
+ var withinElement = function(event, elem) {
2352
+ // Check if mouse(over|out) are still within the same parent element
2353
+ var parent = event.relatedTarget;
2354
+ // Traverse up the tree
2355
+ while ( parent && parent != elem ) try { parent = parent.parentNode } catch(error) { parent = elem; };
2356
+ // Return true if we actually just moused on to a sub-element
2357
+ return parent == elem;
1634
2358
  };
1635
2359
 
1636
- // Clean up after IE to avoid memory leaks
1637
- if (jQuery.browser.msie)
1638
- jQuery(window).one("unload", function() {
1639
- var global = jQuery.event.global;
1640
- for ( var type in global ) {
1641
- var els = global[type], i = els.length;
1642
- if ( i && type != 'unload' )
1643
- do
1644
- els[i-1] && jQuery.event.remove(els[i-1], type);
1645
- while (--i);
1646
- }
1647
- });
2360
+ // Prevent memory leaks in IE
2361
+ // And prevent errors on refresh with events like mouseover in other browsers
2362
+ // Window isn't included so as not to unbind existing unload events
2363
+ jQuery(window).bind("unload", function() {
2364
+ jQuery("*").add(document).unbind();
2365
+ });
1648
2366
  jQuery.fn.extend({
1649
- loadIfModified: function( url, params, callback ) {
1650
- this.load( url, params, callback, 1 );
1651
- },
1652
- load: function( url, params, callback, ifModified ) {
2367
+ load: function( url, params, callback ) {
1653
2368
  if ( jQuery.isFunction( url ) )
1654
2369
  return this.bind("load", url);
1655
2370
 
2371
+ var off = url.indexOf(" ");
2372
+ if ( off >= 0 ) {
2373
+ var selector = url.slice(off, url.length);
2374
+ url = url.slice(0, off);
2375
+ }
2376
+
1656
2377
  callback = callback || function(){};
1657
2378
 
1658
2379
  // Default to a GET request
@@ -1678,46 +2399,67 @@ jQuery.fn.extend({
1678
2399
  jQuery.ajax({
1679
2400
  url: url,
1680
2401
  type: type,
2402
+ dataType: "html",
1681
2403
  data: params,
1682
- ifModified: ifModified,
1683
2404
  complete: function(res, status){
1684
- if ( status == "success" || !ifModified && status == "notmodified" )
1685
- // Inject the HTML into all the matched elements
1686
- self.attr("innerHTML", res.responseText)
1687
- // Execute all the scripts inside of the newly-injected HTML
1688
- .evalScripts()
1689
- // Execute callback
1690
- .each( callback, [res.responseText, status, res] );
1691
- else
1692
- callback.apply( self, [res.responseText, status, res] );
2405
+ // If successful, inject the HTML into all the matched elements
2406
+ if ( status == "success" || status == "notmodified" )
2407
+ // See if a selector was specified
2408
+ self.html( selector ?
2409
+ // Create a dummy div to hold the results
2410
+ jQuery("<div/>")
2411
+ // inject the contents of the document in, removing the scripts
2412
+ // to avoid any 'Permission Denied' errors in IE
2413
+ .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
2414
+
2415
+ // Locate the specified elements
2416
+ .find(selector) :
2417
+
2418
+ // If not, just inject the full result
2419
+ res.responseText );
2420
+
2421
+ self.each( callback, [res.responseText, status, res] );
1693
2422
  }
1694
2423
  });
1695
2424
  return this;
1696
2425
  },
2426
+
1697
2427
  serialize: function() {
1698
- return jQuery.param( this );
1699
- },
1700
- evalScripts: function() {
1701
- return this.find("script").each(function(){
1702
- if ( this.src )
1703
- jQuery.getScript( this.src );
1704
- else
1705
- jQuery.globalEval( this.text || this.textContent || this.innerHTML || "" );
1706
- }).end();
2428
+ return jQuery.param(this.serializeArray());
2429
+ },
2430
+ serializeArray: function() {
2431
+ return this.map(function(){
2432
+ return jQuery.nodeName(this, "form") ?
2433
+ jQuery.makeArray(this.elements) : this;
2434
+ })
2435
+ .filter(function(){
2436
+ return this.name && !this.disabled &&
2437
+ (this.checked || /select|textarea/i.test(this.nodeName) ||
2438
+ /text|hidden|password/i.test(this.type));
2439
+ })
2440
+ .map(function(i, elem){
2441
+ var val = jQuery(this).val();
2442
+ return val == null ? null :
2443
+ val.constructor == Array ?
2444
+ jQuery.map( val, function(val, i){
2445
+ return {name: elem.name, value: val};
2446
+ }) :
2447
+ {name: elem.name, value: val};
2448
+ }).get();
1707
2449
  }
1708
-
1709
2450
  });
1710
2451
 
1711
2452
  // Attach a bunch of functions for handling common AJAX events
1712
-
1713
2453
  jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
1714
2454
  jQuery.fn[o] = function(f){
1715
2455
  return this.bind(o, f);
1716
2456
  };
1717
2457
  });
1718
2458
 
2459
+ var jsc = (new Date).getTime();
2460
+
1719
2461
  jQuery.extend({
1720
- get: function( url, data, callback, type, ifModified ) {
2462
+ get: function( url, data, callback, type ) {
1721
2463
  // shift arguments if data argument was ommited
1722
2464
  if ( jQuery.isFunction( data ) ) {
1723
2465
  callback = data;
@@ -1729,19 +2471,18 @@ jQuery.extend({
1729
2471
  url: url,
1730
2472
  data: data,
1731
2473
  success: callback,
1732
- dataType: type,
1733
- ifModified: ifModified
2474
+ dataType: type
1734
2475
  });
1735
2476
  },
1736
- getIfModified: function( url, data, callback, type ) {
1737
- return jQuery.get(url, data, callback, type, 1);
1738
- },
2477
+
1739
2478
  getScript: function( url, callback ) {
1740
2479
  return jQuery.get(url, null, callback, "script");
1741
2480
  },
2481
+
1742
2482
  getJSON: function( url, data, callback ) {
1743
2483
  return jQuery.get(url, data, callback, "json");
1744
2484
  },
2485
+
1745
2486
  post: function( url, data, callback, type ) {
1746
2487
  if ( jQuery.isFunction( data ) ) {
1747
2488
  callback = data;
@@ -1756,9 +2497,7 @@ jQuery.extend({
1756
2497
  dataType: type
1757
2498
  });
1758
2499
  },
1759
- ajaxTimeout: function( timeout ) {
1760
- jQuery.ajaxSettings.timeout = timeout;
1761
- },
2500
+
1762
2501
  ajaxSetup: function( settings ) {
1763
2502
  jQuery.extend( jQuery.ajaxSettings, settings );
1764
2503
  },
@@ -1775,28 +2514,108 @@ jQuery.extend({
1775
2514
 
1776
2515
  // Last-Modified header cache for next request
1777
2516
  lastModified: {},
2517
+
1778
2518
  ajax: function( s ) {
1779
- // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
1780
- s = jQuery.extend({}, jQuery.ajaxSettings, s);
1781
-
1782
- // if data available
1783
- if ( s.data ) {
1784
- // convert data if not already a string
1785
- if (s.processData && typeof s.data != "string")
1786
- s.data = jQuery.param(s.data);
1787
- // append data to url for get requests
1788
- if( s.type.toLowerCase() == "get" ) {
1789
- // "?" + data or "&" + data (in case there are already params)
1790
- s.url += ((s.url.indexOf("?") > -1) ? "&" : "?") + s.data;
1791
- // IE likes to send both get and post data, prevent this
1792
- s.data = null;
1793
- }
2519
+ var jsonp, jsre = /=\?(&|$)/g, status, data;
2520
+
2521
+ // Extend the settings, but re-extend 's' so that it can be
2522
+ // checked again later (in the test suite, specifically)
2523
+ s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
2524
+
2525
+ // convert data if not already a string
2526
+ if ( s.data && s.processData && typeof s.data != "string" )
2527
+ s.data = jQuery.param(s.data);
2528
+
2529
+ // Handle JSONP Parameter Callbacks
2530
+ if ( s.dataType == "jsonp" ) {
2531
+ if ( s.type.toLowerCase() == "get" ) {
2532
+ if ( !s.url.match(jsre) )
2533
+ s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
2534
+ } else if ( !s.data || !s.data.match(jsre) )
2535
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
2536
+ s.dataType = "json";
2537
+ }
2538
+
2539
+ // Build temporary JSONP function
2540
+ if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
2541
+ jsonp = "jsonp" + jsc++;
2542
+
2543
+ // Replace the =? sequence both in the query string and the data
2544
+ if ( s.data )
2545
+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
2546
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
2547
+
2548
+ // We need to make sure
2549
+ // that a JSONP style response is executed properly
2550
+ s.dataType = "script";
2551
+
2552
+ // Handle JSONP-style loading
2553
+ window[ jsonp ] = function(tmp){
2554
+ data = tmp;
2555
+ success();
2556
+ complete();
2557
+ // Garbage collect
2558
+ window[ jsonp ] = undefined;
2559
+ try{ delete window[ jsonp ]; } catch(e){}
2560
+ if ( head )
2561
+ head.removeChild( script );
2562
+ };
2563
+ }
2564
+
2565
+ if ( s.dataType == "script" && s.cache == null )
2566
+ s.cache = false;
2567
+
2568
+ if ( s.cache === false && s.type.toLowerCase() == "get" ) {
2569
+ var ts = (new Date()).getTime();
2570
+ // try replacing _= if it is there
2571
+ var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
2572
+ // if nothing was replaced, add timestamp to the end
2573
+ s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
2574
+ }
2575
+
2576
+ // If data is available, append data to url for get requests
2577
+ if ( s.data && s.type.toLowerCase() == "get" ) {
2578
+ s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
2579
+
2580
+ // IE likes to send both get and post data, prevent this
2581
+ s.data = null;
1794
2582
  }
1795
2583
 
1796
2584
  // Watch for a new set of requests
1797
2585
  if ( s.global && ! jQuery.active++ )
1798
2586
  jQuery.event.trigger( "ajaxStart" );
1799
2587
 
2588
+ // If we're requesting a remote document
2589
+ // and trying to load JSON or Script with a GET
2590
+ if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && ( s.dataType == "script" || s.dataType =="json" ) && s.type.toLowerCase() == "get" ) {
2591
+ var head = document.getElementsByTagName("head")[0];
2592
+ var script = document.createElement("script");
2593
+ script.src = s.url;
2594
+ if (s.scriptCharset)
2595
+ script.charset = s.scriptCharset;
2596
+
2597
+ // Handle Script loading
2598
+ if ( !jsonp ) {
2599
+ var done = false;
2600
+
2601
+ // Attach handlers for all browsers
2602
+ script.onload = script.onreadystatechange = function(){
2603
+ if ( !done && (!this.readyState ||
2604
+ this.readyState == "loaded" || this.readyState == "complete") ) {
2605
+ done = true;
2606
+ success();
2607
+ complete();
2608
+ head.removeChild( script );
2609
+ }
2610
+ };
2611
+ }
2612
+
2613
+ head.appendChild(script);
2614
+
2615
+ // We handle everything using the script element injection
2616
+ return undefined;
2617
+ }
2618
+
1800
2619
  var requestDone = false;
1801
2620
 
1802
2621
  // Create the request object; Microsoft failed to properly
@@ -1806,29 +2625,32 @@ jQuery.extend({
1806
2625
  // Open the socket
1807
2626
  xml.open(s.type, s.url, s.async);
1808
2627
 
1809
- // Set the correct header, if data is being sent
1810
- if ( s.data )
1811
- xml.setRequestHeader("Content-Type", s.contentType);
2628
+ // Need an extra try/catch for cross domain requests in Firefox 3
2629
+ try {
2630
+ // Set the correct header, if data is being sent
2631
+ if ( s.data )
2632
+ xml.setRequestHeader("Content-Type", s.contentType);
1812
2633
 
1813
- // Set the If-Modified-Since header, if ifModified mode.
1814
- if ( s.ifModified )
1815
- xml.setRequestHeader("If-Modified-Since",
1816
- jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
2634
+ // Set the If-Modified-Since header, if ifModified mode.
2635
+ if ( s.ifModified )
2636
+ xml.setRequestHeader("If-Modified-Since",
2637
+ jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
1817
2638
 
1818
- // Set header so the called script knows that it's an XMLHttpRequest
1819
- xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2639
+ // Set header so the called script knows that it's an XMLHttpRequest
2640
+ xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2641
+ } catch(e){}
1820
2642
 
1821
2643
  // Allow custom headers/mimetypes
1822
- if( s.beforeSend )
2644
+ if ( s.beforeSend )
1823
2645
  s.beforeSend(xml);
1824
2646
 
1825
2647
  if ( s.global )
1826
- jQuery.event.trigger("ajaxSend", [xml, s]);
2648
+ jQuery.event.trigger("ajaxSend", [xml, s]);
1827
2649
 
1828
2650
  // Wait for a response to come back
1829
2651
  var onreadystatechange = function(isTimeout){
1830
2652
  // The transfer is complete and the data is available, or the request timed out
1831
- if ( xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
2653
+ if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
1832
2654
  requestDone = true;
1833
2655
 
1834
2656
  // clear poll interval
@@ -1837,71 +2659,64 @@ jQuery.extend({
1837
2659
  ival = null;
1838
2660
  }
1839
2661
 
1840
- var status;
1841
- try {
1842
- status = jQuery.httpSuccess( xml ) && isTimeout != "timeout" ?
1843
- s.ifModified && jQuery.httpNotModified( xml, s.url ) ? "notmodified" : "success" : "error";
1844
- // Make sure that the request was successful or notmodified
1845
- if ( status != "error" ) {
1846
- // Cache Last-Modified header, if ifModified mode.
1847
- var modRes;
1848
- try {
1849
- modRes = xml.getResponseHeader("Last-Modified");
1850
- } catch(e) {} // swallow exception thrown by FF if header is not available
1851
-
1852
- if ( s.ifModified && modRes )
1853
- jQuery.lastModified[s.url] = modRes;
1854
-
2662
+ status = isTimeout == "timeout" && "timeout" ||
2663
+ !jQuery.httpSuccess( xml ) && "error" ||
2664
+ s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
2665
+ "success";
2666
+
2667
+ if ( status == "success" ) {
2668
+ // Watch for, and catch, XML document parse errors
2669
+ try {
1855
2670
  // process the data (runs the xml through httpData regardless of callback)
1856
- var data = jQuery.httpData( xml, s.dataType );
1857
-
1858
- // If a local callback was specified, fire it and pass it the data
1859
- if ( s.success )
1860
- s.success( data, status );
1861
-
1862
- // Fire the global callback
1863
- if( s.global )
1864
- jQuery.event.trigger( "ajaxSuccess", [xml, s] );
1865
- } else
1866
- jQuery.handleError(s, xml, status);
1867
- } catch(e) {
1868
- status = "error";
1869
- jQuery.handleError(s, xml, status, e);
2671
+ data = jQuery.httpData( xml, s.dataType );
2672
+ } catch(e) {
2673
+ status = "parsererror";
2674
+ }
1870
2675
  }
1871
2676
 
1872
- // The request was completed
1873
- if( s.global )
1874
- jQuery.event.trigger( "ajaxComplete", [xml, s] );
2677
+ // Make sure that the request was successful or notmodified
2678
+ if ( status == "success" ) {
2679
+ // Cache Last-Modified header, if ifModified mode.
2680
+ var modRes;
2681
+ try {
2682
+ modRes = xml.getResponseHeader("Last-Modified");
2683
+ } catch(e) {} // swallow exception thrown by FF if header is not available
2684
+
2685
+ if ( s.ifModified && modRes )
2686
+ jQuery.lastModified[s.url] = modRes;
1875
2687
 
1876
- // Handle the global AJAX counter
1877
- if ( s.global && ! --jQuery.active )
1878
- jQuery.event.trigger( "ajaxStop" );
2688
+ // JSONP handles its own success callback
2689
+ if ( !jsonp )
2690
+ success();
2691
+ } else
2692
+ jQuery.handleError(s, xml, status);
1879
2693
 
1880
- // Process result
1881
- if ( s.complete )
1882
- s.complete(xml, status);
2694
+ // Fire the complete handlers
2695
+ complete();
1883
2696
 
1884
2697
  // Stop memory leaks
1885
- if(s.async)
2698
+ if ( s.async )
1886
2699
  xml = null;
1887
2700
  }
1888
2701
  };
1889
2702
 
1890
- // don't attach the handler to the request, just poll it instead
1891
- var ival = setInterval(onreadystatechange, 13);
1892
-
1893
- // Timeout checker
1894
- if ( s.timeout > 0 )
1895
- setTimeout(function(){
1896
- // Check to see if the request is still happening
1897
- if ( xml ) {
1898
- // Cancel the request
1899
- xml.abort();
1900
-
1901
- if( !requestDone )
1902
- onreadystatechange( "timeout" );
1903
- }
1904
- }, s.timeout);
2703
+ if ( s.async ) {
2704
+ // don't attach the handler to the request, just poll it instead
2705
+ var ival = setInterval(onreadystatechange, 13);
2706
+
2707
+ // Timeout checker
2708
+ if ( s.timeout > 0 )
2709
+ setTimeout(function(){
2710
+ // Check to see if the request is still happening
2711
+ if ( xml ) {
2712
+ // Cancel the request
2713
+ xml.abort();
2714
+
2715
+ if( !requestDone )
2716
+ onreadystatechange( "timeout" );
2717
+ }
2718
+ }, s.timeout);
2719
+ }
1905
2720
 
1906
2721
  // Send the data
1907
2722
  try {
@@ -1913,6 +2728,30 @@ jQuery.extend({
1913
2728
  // firefox 1.5 doesn't fire statechange for sync requests
1914
2729
  if ( !s.async )
1915
2730
  onreadystatechange();
2731
+
2732
+ function success(){
2733
+ // If a local callback was specified, fire it and pass it the data
2734
+ if ( s.success )
2735
+ s.success( data, status );
2736
+
2737
+ // Fire the global callback
2738
+ if ( s.global )
2739
+ jQuery.event.trigger( "ajaxSuccess", [xml, s] );
2740
+ }
2741
+
2742
+ function complete(){
2743
+ // Process result
2744
+ if ( s.complete )
2745
+ s.complete(xml, status);
2746
+
2747
+ // The request was completed
2748
+ if ( s.global )
2749
+ jQuery.event.trigger( "ajaxComplete", [xml, s] );
2750
+
2751
+ // Handle the global AJAX counter
2752
+ if ( s.global && ! --jQuery.active )
2753
+ jQuery.event.trigger( "ajaxStop" );
2754
+ }
1916
2755
 
1917
2756
  // return XMLHttpRequest to allow aborting the request etc.
1918
2757
  return xml;
@@ -1933,8 +2772,9 @@ jQuery.extend({
1933
2772
  // Determines if an XMLHttpRequest was successful or not
1934
2773
  httpSuccess: function( r ) {
1935
2774
  try {
2775
+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
1936
2776
  return !r.status && location.protocol == "file:" ||
1937
- ( r.status >= 200 && r.status < 300 ) || r.status == 304 ||
2777
+ ( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
1938
2778
  jQuery.browser.safari && r.status == undefined;
1939
2779
  } catch(e){}
1940
2780
  return false;
@@ -1952,16 +2792,13 @@ jQuery.extend({
1952
2792
  return false;
1953
2793
  },
1954
2794
 
1955
- /* Get the data out of an XMLHttpRequest.
1956
- * Return parsed XML if content-type header is "xml" and type is "xml" or omitted,
1957
- * otherwise return plain text.
1958
- * (String) data - The type of data that you're expecting back,
1959
- * (e.g. "xml", "html", "script")
1960
- */
1961
2795
  httpData: function( r, type ) {
1962
2796
  var ct = r.getResponseHeader("content-type");
1963
- var data = !type && ct && ct.indexOf("xml") >= 0;
1964
- data = type == "xml" || data ? r.responseXML : r.responseText;
2797
+ var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
2798
+ var data = xml ? r.responseXML : r.responseText;
2799
+
2800
+ if ( xml && data.documentElement.tagName == "parsererror" )
2801
+ throw "parsererror";
1965
2802
 
1966
2803
  // If the type is "script", eval it in global context
1967
2804
  if ( type == "script" )
@@ -1971,10 +2808,6 @@ jQuery.extend({
1971
2808
  if ( type == "json" )
1972
2809
  data = eval("(" + data + ")");
1973
2810
 
1974
- // evaluate scripts within html
1975
- if ( type == "html" )
1976
- jQuery("<div>").html(data).evalScripts();
1977
-
1978
2811
  return data;
1979
2812
  },
1980
2813
 
@@ -2004,24 +2837,11 @@ jQuery.extend({
2004
2837
  s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
2005
2838
 
2006
2839
  // Return the resulting serialization
2007
- return s.join("&");
2008
- },
2009
-
2010
- // evalulates a script in global context
2011
- // not reliable for safari
2012
- globalEval: function( data ) {
2013
- if ( window.execScript )
2014
- window.execScript( data );
2015
- else if ( jQuery.browser.safari )
2016
- // safari doesn't provide a synchronous global eval
2017
- window.setTimeout( data, 0 );
2018
- else
2019
- eval.call( window, data );
2840
+ return s.join("&").replace(/%20/g, "+");
2020
2841
  }
2021
2842
 
2022
2843
  });
2023
2844
  jQuery.fn.extend({
2024
-
2025
2845
  show: function(speed,callback){
2026
2846
  return speed ?
2027
2847
  this.animate({
@@ -2029,12 +2849,15 @@ jQuery.fn.extend({
2029
2849
  }, speed, callback) :
2030
2850
 
2031
2851
  this.filter(":hidden").each(function(){
2032
- this.style.display = this.oldblock ? this.oldblock : "";
2033
- if ( jQuery.css(this,"display") == "none" )
2034
- this.style.display = "block";
2852
+ this.style.display = this.oldblock || "";
2853
+ if ( jQuery.css(this,"display") == "none" ) {
2854
+ var elem = jQuery("<" + this.tagName + " />").appendTo("body");
2855
+ this.style.display = elem.css("display");
2856
+ elem.remove();
2857
+ }
2035
2858
  }).end();
2036
2859
  },
2037
-
2860
+
2038
2861
  hide: function(speed,callback){
2039
2862
  return speed ?
2040
2863
  this.animate({
@@ -2043,14 +2866,13 @@ jQuery.fn.extend({
2043
2866
 
2044
2867
  this.filter(":visible").each(function(){
2045
2868
  this.oldblock = this.oldblock || jQuery.css(this,"display");
2046
- if ( this.oldblock == "none" )
2047
- this.oldblock = "block";
2048
2869
  this.style.display = "none";
2049
2870
  }).end();
2050
2871
  },
2051
2872
 
2052
2873
  // Save the old toggle function
2053
2874
  _toggle: jQuery.fn.toggle,
2875
+
2054
2876
  toggle: function( fn, fn2 ){
2055
2877
  return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
2056
2878
  this._toggle( fn, fn2 ) :
@@ -2062,29 +2884,40 @@ jQuery.fn.extend({
2062
2884
  jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
2063
2885
  });
2064
2886
  },
2887
+
2065
2888
  slideDown: function(speed,callback){
2066
2889
  return this.animate({height: "show"}, speed, callback);
2067
2890
  },
2891
+
2068
2892
  slideUp: function(speed,callback){
2069
2893
  return this.animate({height: "hide"}, speed, callback);
2070
2894
  },
2895
+
2071
2896
  slideToggle: function(speed, callback){
2072
2897
  return this.animate({height: "toggle"}, speed, callback);
2073
2898
  },
2899
+
2074
2900
  fadeIn: function(speed, callback){
2075
2901
  return this.animate({opacity: "show"}, speed, callback);
2076
2902
  },
2903
+
2077
2904
  fadeOut: function(speed, callback){
2078
2905
  return this.animate({opacity: "hide"}, speed, callback);
2079
2906
  },
2907
+
2080
2908
  fadeTo: function(speed,to,callback){
2081
2909
  return this.animate({opacity: to}, speed, callback);
2082
2910
  },
2911
+
2083
2912
  animate: function( prop, speed, easing, callback ) {
2084
- return this.queue(function(){
2085
- var hidden = jQuery(this).is(":hidden"),
2086
- opt = jQuery.speed(speed, easing, callback),
2087
- self = this;
2913
+ var optall = jQuery.speed(speed, easing, callback);
2914
+
2915
+ return this[ optall.queue === false ? "each" : "queue" ](function(){
2916
+ if ( this.nodeType != 1)
2917
+ return false;
2918
+
2919
+ var opt = jQuery.extend({}, optall);
2920
+ var hidden = jQuery(this).is(":hidden"), self = this;
2088
2921
 
2089
2922
  for ( var p in prop ) {
2090
2923
  if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
@@ -2102,39 +2935,121 @@ jQuery.fn.extend({
2102
2935
  if ( opt.overflow != null )
2103
2936
  this.style.overflow = "hidden";
2104
2937
 
2105
- this.curAnim = jQuery.extend({}, prop);
2938
+ opt.curAnim = jQuery.extend({}, prop);
2106
2939
 
2107
2940
  jQuery.each( prop, function(name, val){
2108
2941
  var e = new jQuery.fx( self, opt, name );
2109
- if ( val.constructor == Number )
2110
- e.custom( e.cur(), val );
2111
- else
2942
+
2943
+ if ( /toggle|show|hide/.test(val) )
2112
2944
  e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
2945
+ else {
2946
+ var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
2947
+ start = e.cur(true) || 0;
2948
+
2949
+ if ( parts ) {
2950
+ var end = parseFloat(parts[2]),
2951
+ unit = parts[3] || "px";
2952
+
2953
+ // We need to compute starting value
2954
+ if ( unit != "px" ) {
2955
+ self.style[ name ] = (end || 1) + unit;
2956
+ start = ((end || 1) / e.cur(true)) * start;
2957
+ self.style[ name ] = start + unit;
2958
+ }
2959
+
2960
+ // If a +=/-= token was provided, we're doing a relative animation
2961
+ if ( parts[1] )
2962
+ end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
2963
+
2964
+ e.custom( start, end, unit );
2965
+ } else
2966
+ e.custom( start, val, "" );
2967
+ }
2113
2968
  });
2969
+
2970
+ // For JS strict compliance
2971
+ return true;
2114
2972
  });
2115
2973
  },
2116
- queue: function(type,fn){
2117
- if ( !fn ) {
2974
+
2975
+ queue: function(type, fn){
2976
+ if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
2118
2977
  fn = type;
2119
2978
  type = "fx";
2120
2979
  }
2121
-
2980
+
2981
+ if ( !type || (typeof type == "string" && !fn) )
2982
+ return queue( this[0], type );
2983
+
2122
2984
  return this.each(function(){
2123
- if ( !this.queue )
2124
- this.queue = {};
2125
-
2126
- if ( !this.queue[type] )
2127
- this.queue[type] = [];
2128
-
2129
- this.queue[type].push( fn );
2130
-
2131
- if ( this.queue[type].length == 1 )
2132
- fn.apply(this);
2985
+ if ( this.nodeType != 1)
2986
+ return;
2987
+
2988
+ if ( fn.constructor == Array )
2989
+ queue(this, type, fn);
2990
+ else {
2991
+ queue(this, type).push( fn );
2992
+
2993
+ if ( queue(this, type).length == 1 )
2994
+ fn.apply(this);
2995
+ }
2996
+ });
2997
+ },
2998
+
2999
+ stop: function(clearQueue, gotoEnd){
3000
+ var timers = jQuery.timers;
3001
+
3002
+ if (clearQueue)
3003
+ this.queue([]);
3004
+
3005
+ this.each(function(){
3006
+ // go in reverse order so anything added to the queue during the loop is ignored
3007
+ for ( var i = timers.length - 1; i >= 0; i-- )
3008
+ if ( timers[i].elem == this ) {
3009
+ if (gotoEnd)
3010
+ // force the next step to be the last
3011
+ timers[i](true);
3012
+ timers.splice(i, 1);
3013
+ }
2133
3014
  });
3015
+
3016
+ // start the next in the queue if the last step wasn't forced
3017
+ if (!gotoEnd)
3018
+ this.dequeue();
3019
+
3020
+ return this;
2134
3021
  }
2135
3022
 
2136
3023
  });
2137
3024
 
3025
+ var queue = function( elem, type, array ) {
3026
+ if ( !elem )
3027
+ return undefined;
3028
+
3029
+ type = type || "fx";
3030
+
3031
+ var q = jQuery.data( elem, type + "queue" );
3032
+
3033
+ if ( !q || array )
3034
+ q = jQuery.data( elem, type + "queue",
3035
+ array ? jQuery.makeArray(array) : [] );
3036
+
3037
+ return q;
3038
+ };
3039
+
3040
+ jQuery.fn.dequeue = function(type){
3041
+ type = type || "fx";
3042
+
3043
+ return this.each(function(){
3044
+ var q = queue(this, type);
3045
+
3046
+ q.shift();
3047
+
3048
+ if ( q.length )
3049
+ q[0].apply( this );
3050
+ });
3051
+ };
3052
+
2138
3053
  jQuery.extend({
2139
3054
 
2140
3055
  speed: function(speed, easing, fn) {
@@ -2142,7 +3057,7 @@ jQuery.extend({
2142
3057
  complete: fn || !fn && easing ||
2143
3058
  jQuery.isFunction( speed ) && speed,
2144
3059
  duration: speed,
2145
- easing: fn && easing || easing && easing.constructor != Function && easing || (jQuery.easing.swing ? "swing" : "linear")
3060
+ easing: fn && easing || easing && easing.constructor != Function && easing
2146
3061
  };
2147
3062
 
2148
3063
  opt.duration = (opt.duration && opt.duration.constructor == Number ?
@@ -2152,7 +3067,8 @@ jQuery.extend({
2152
3067
  // Queueing
2153
3068
  opt.old = opt.complete;
2154
3069
  opt.complete = function(){
2155
- jQuery.dequeue(this, "fx");
3070
+ if ( opt.queue !== false )
3071
+ jQuery(this).dequeue();
2156
3072
  if ( jQuery.isFunction( opt.old ) )
2157
3073
  opt.old.apply( this );
2158
3074
  };
@@ -2169,176 +3085,279 @@ jQuery.extend({
2169
3085
  }
2170
3086
  },
2171
3087
 
2172
- queue: {},
2173
-
2174
- dequeue: function(elem,type){
2175
- type = type || "fx";
2176
-
2177
- if ( elem.queue && elem.queue[type] ) {
2178
- // Remove self
2179
- elem.queue[type].shift();
2180
-
2181
- // Get next function
2182
- var f = elem.queue[type][0];
2183
-
2184
- if ( f ) f.apply( elem );
2185
- }
2186
- },
2187
-
2188
3088
  timers: [],
3089
+ timerId: null,
2189
3090
 
2190
- /*
2191
- * I originally wrote fx() as a clone of moo.fx and in the process
2192
- * of making it small in size the code became illegible to sane
2193
- * people. You've been warned.
2194
- */
2195
-
2196
3091
  fx: function( elem, options, prop ){
3092
+ this.options = options;
3093
+ this.elem = elem;
3094
+ this.prop = prop;
2197
3095
 
2198
- var z = this;
2199
-
2200
- // The styles
2201
- var y = elem.style;
2202
-
2203
- // Simple function for setting a style value
2204
- z.a = function(){
2205
- if ( options.step )
2206
- options.step.apply( elem, [ z.now ] );
3096
+ if ( !options.orig )
3097
+ options.orig = {};
3098
+ }
2207
3099
 
2208
- if ( prop == "opacity" )
2209
- jQuery.attr(y, "opacity", z.now); // Let attr handle opacity
2210
- else {
2211
- y[prop] = parseInt(z.now) + "px";
2212
- y.display = "block"; // Set display property to block for animation
2213
- }
2214
- };
3100
+ });
2215
3101
 
2216
- // Figure out the maximum number to run to
2217
- z.max = function(){
2218
- return parseFloat( jQuery.css(elem,prop) );
2219
- };
3102
+ jQuery.fx.prototype = {
2220
3103
 
2221
- // Get the current size
2222
- z.cur = function(){
2223
- var r = parseFloat( jQuery.curCSS(elem, prop) );
2224
- return r && r > -10000 ? r : z.max();
2225
- };
3104
+ // Simple function for setting a style value
3105
+ update: function(){
3106
+ if ( this.options.step )
3107
+ this.options.step.apply( this.elem, [ this.now, this ] );
2226
3108
 
2227
- // Start an animation from one number to another
2228
- z.custom = function(from,to){
2229
- z.startTime = (new Date()).getTime();
2230
- z.now = from;
2231
- z.a();
3109
+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
2232
3110
 
2233
- jQuery.timers.push(function(){
2234
- return z.step(from, to);
2235
- });
3111
+ // Set display property to block for height/width animations
3112
+ if ( this.prop == "height" || this.prop == "width" )
3113
+ this.elem.style.display = "block";
3114
+ },
2236
3115
 
2237
- if ( jQuery.timers.length == 1 ) {
2238
- var timer = setInterval(function(){
2239
- var timers = jQuery.timers;
2240
-
2241
- for ( var i = 0; i < timers.length; i++ )
2242
- if ( !timers[i]() )
2243
- timers.splice(i--, 1);
3116
+ // Get the current size
3117
+ cur: function(force){
3118
+ if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
3119
+ return this.elem[ this.prop ];
2244
3120
 
2245
- if ( !timers.length )
2246
- clearInterval( timer );
2247
- }, 13);
2248
- }
2249
- };
3121
+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
3122
+ return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
3123
+ },
2250
3124
 
2251
- // Simple 'show' function
2252
- z.show = function(){
2253
- if ( !elem.orig ) elem.orig = {};
3125
+ // Start an animation from one number to another
3126
+ custom: function(from, to, unit){
3127
+ this.startTime = (new Date()).getTime();
3128
+ this.start = from;
3129
+ this.end = to;
3130
+ this.unit = unit || this.unit || "px";
3131
+ this.now = this.start;
3132
+ this.pos = this.state = 0;
3133
+ this.update();
2254
3134
 
2255
- // Remember where we started, so that we can go back to it later
2256
- elem.orig[prop] = jQuery.attr( elem.style, prop );
3135
+ var self = this;
3136
+ function t(gotoEnd){
3137
+ return self.step(gotoEnd);
3138
+ }
2257
3139
 
2258
- options.show = true;
3140
+ t.elem = this.elem;
2259
3141
 
2260
- // Begin the animation
2261
- z.custom(0, this.cur());
3142
+ jQuery.timers.push(t);
2262
3143
 
2263
- // Make sure that we start at a small width/height to avoid any
2264
- // flash of content
2265
- if ( prop != "opacity" )
2266
- y[prop] = "1px";
2267
-
2268
- // Start by showing the element
2269
- jQuery(elem).show();
2270
- };
3144
+ if ( jQuery.timerId == null ) {
3145
+ jQuery.timerId = setInterval(function(){
3146
+ var timers = jQuery.timers;
3147
+
3148
+ for ( var i = 0; i < timers.length; i++ )
3149
+ if ( !timers[i]() )
3150
+ timers.splice(i--, 1);
2271
3151
 
2272
- // Simple 'hide' function
2273
- z.hide = function(){
2274
- if ( !elem.orig ) elem.orig = {};
3152
+ if ( !timers.length ) {
3153
+ clearInterval( jQuery.timerId );
3154
+ jQuery.timerId = null;
3155
+ }
3156
+ }, 13);
3157
+ }
3158
+ },
2275
3159
 
2276
- // Remember where we started, so that we can go back to it later
2277
- elem.orig[prop] = jQuery.attr( elem.style, prop );
3160
+ // Simple 'show' function
3161
+ show: function(){
3162
+ // Remember where we started, so that we can go back to it later
3163
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3164
+ this.options.show = true;
2278
3165
 
2279
- options.hide = true;
3166
+ // Begin the animation
3167
+ this.custom(0, this.cur());
2280
3168
 
2281
- // Begin the animation
2282
- z.custom(this.cur(), 0);
2283
- };
3169
+ // Make sure that we start at a small width/height to avoid any
3170
+ // flash of content
3171
+ if ( this.prop == "width" || this.prop == "height" )
3172
+ this.elem.style[this.prop] = "1px";
3173
+
3174
+ // Start by showing the element
3175
+ jQuery(this.elem).show();
3176
+ },
2284
3177
 
2285
- // Each step of an animation
2286
- z.step = function(firstNum, lastNum){
2287
- var t = (new Date()).getTime();
3178
+ // Simple 'hide' function
3179
+ hide: function(){
3180
+ // Remember where we started, so that we can go back to it later
3181
+ this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
3182
+ this.options.hide = true;
2288
3183
 
2289
- if (t > options.duration + z.startTime) {
2290
- z.now = lastNum;
2291
- z.a();
3184
+ // Begin the animation
3185
+ this.custom(this.cur(), 0);
3186
+ },
2292
3187
 
2293
- if (elem.curAnim) elem.curAnim[ prop ] = true;
3188
+ // Each step of an animation
3189
+ step: function(gotoEnd){
3190
+ var t = (new Date()).getTime();
2294
3191
 
2295
- var done = true;
2296
- for ( var i in elem.curAnim )
2297
- if ( elem.curAnim[i] !== true )
2298
- done = false;
3192
+ if ( gotoEnd || t > this.options.duration + this.startTime ) {
3193
+ this.now = this.end;
3194
+ this.pos = this.state = 1;
3195
+ this.update();
2299
3196
 
2300
- if ( done ) {
2301
- if ( options.display != null ) {
2302
- // Reset the overflow
2303
- y.overflow = options.overflow;
2304
-
2305
- // Reset the display
2306
- y.display = options.display;
2307
- if ( jQuery.css(elem, "display") == "none" )
2308
- y.display = "block";
2309
- }
3197
+ this.options.curAnim[ this.prop ] = true;
2310
3198
 
2311
- // Hide the element if the "hide" operation was done
2312
- if ( options.hide )
2313
- y.display = "none";
3199
+ var done = true;
3200
+ for ( var i in this.options.curAnim )
3201
+ if ( this.options.curAnim[i] !== true )
3202
+ done = false;
2314
3203
 
2315
- // Reset the properties, if the item has been hidden or shown
2316
- if ( options.hide || options.show )
2317
- for ( var p in elem.curAnim )
2318
- jQuery.attr(y, p, elem.orig[p]);
3204
+ if ( done ) {
3205
+ if ( this.options.display != null ) {
3206
+ // Reset the overflow
3207
+ this.elem.style.overflow = this.options.overflow;
3208
+
3209
+ // Reset the display
3210
+ this.elem.style.display = this.options.display;
3211
+ if ( jQuery.css(this.elem, "display") == "none" )
3212
+ this.elem.style.display = "block";
2319
3213
  }
2320
3214
 
2321
- // If a callback was provided, execute it
2322
- if ( done && jQuery.isFunction( options.complete ) )
2323
- // Execute the complete function
2324
- options.complete.apply( elem );
2325
-
2326
- return false;
2327
- } else {
2328
- var n = t - this.startTime;
2329
- // Figure out where in the animation we are and set the number
2330
- var p = n / options.duration;
2331
-
2332
- // Perform the easing function, defaults to swing
2333
- z.now = jQuery.easing[options.easing](p, n, firstNum, (lastNum-firstNum), options.duration);
3215
+ // Hide the element if the "hide" operation was done
3216
+ if ( this.options.hide )
3217
+ this.elem.style.display = "none";
2334
3218
 
2335
- // Perform the next step of the animation
2336
- z.a();
3219
+ // Reset the properties, if the item has been hidden or shown
3220
+ if ( this.options.hide || this.options.show )
3221
+ for ( var p in this.options.curAnim )
3222
+ jQuery.attr(this.elem.style, p, this.options.orig[p]);
2337
3223
  }
2338
3224
 
2339
- return true;
2340
- };
3225
+ // If a callback was provided, execute it
3226
+ if ( done && jQuery.isFunction( this.options.complete ) )
3227
+ // Execute the complete function
3228
+ this.options.complete.apply( this.elem );
3229
+
3230
+ return false;
3231
+ } else {
3232
+ var n = t - this.startTime;
3233
+ this.state = n / this.options.duration;
3234
+
3235
+ // Perform the easing function, defaults to swing
3236
+ this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
3237
+ this.now = this.start + ((this.end - this.start) * this.pos);
3238
+
3239
+ // Perform the next step of the animation
3240
+ this.update();
3241
+ }
3242
+
3243
+ return true;
3244
+ }
3245
+
3246
+ };
3247
+
3248
+ jQuery.fx.step = {
3249
+ scrollLeft: function(fx){
3250
+ fx.elem.scrollLeft = fx.now;
3251
+ },
3252
+
3253
+ scrollTop: function(fx){
3254
+ fx.elem.scrollTop = fx.now;
3255
+ },
3256
+
3257
+ opacity: function(fx){
3258
+ jQuery.attr(fx.elem.style, "opacity", fx.now);
3259
+ },
3260
+
3261
+ _default: function(fx){
3262
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
3263
+ }
3264
+ };
3265
+ // The Offset Method
3266
+ // Originally By Brandon Aaron, part of the Dimension Plugin
3267
+ // http://jquery.com/plugins/project/dimensions
3268
+ jQuery.fn.offset = function() {
3269
+ var left = 0, top = 0, elem = this[0], results;
3270
+
3271
+ if ( elem ) with ( jQuery.browser ) {
3272
+ var parent = elem.parentNode,
3273
+ offsetChild = elem,
3274
+ offsetParent = elem.offsetParent,
3275
+ doc = elem.ownerDocument,
3276
+ safari2 = safari && parseInt(version) < 522,
3277
+ fixed = jQuery.css(elem, "position") == "fixed";
3278
+
3279
+ // Use getBoundingClientRect if available
3280
+ if ( elem.getBoundingClientRect ) {
3281
+ var box = elem.getBoundingClientRect();
3282
+
3283
+ // Add the document scroll offsets
3284
+ add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
3285
+ box.top + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
3286
+
3287
+ // IE adds the HTML element's border, by default it is medium which is 2px
3288
+ // IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
3289
+ // IE 7 standards mode, the border is always 2px
3290
+ // This border/offset is typically represented by the clientLeft and clientTop properties
3291
+ // However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
3292
+ // Therefore this method will be off by 2px in IE while in quirksmode
3293
+ add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
2341
3294
 
3295
+ // Otherwise loop through the offsetParents and parentNodes
3296
+ } else {
3297
+
3298
+ // Initial element offsets
3299
+ add( elem.offsetLeft, elem.offsetTop );
3300
+
3301
+ // Get parent offsets
3302
+ while ( offsetParent ) {
3303
+ // Add offsetParent offsets
3304
+ add( offsetParent.offsetLeft, offsetParent.offsetTop );
3305
+
3306
+ // Mozilla and Safari > 2 does not include the border on offset parents
3307
+ // However Mozilla adds the border for table or table cells
3308
+ if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
3309
+ border( offsetParent );
3310
+
3311
+ // Add the document scroll offsets if position is fixed on any offsetParent
3312
+ if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
3313
+ fixed = true;
3314
+
3315
+ // Set offsetChild to previous offsetParent unless it is the body element
3316
+ offsetChild = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
3317
+ // Get next offsetParent
3318
+ offsetParent = offsetParent.offsetParent;
3319
+ }
3320
+
3321
+ // Get parent scroll offsets
3322
+ while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
3323
+ // Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
3324
+ if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
3325
+ // Subtract parent scroll offsets
3326
+ add( -parent.scrollLeft, -parent.scrollTop );
3327
+
3328
+ // Mozilla does not add the border for a parent that has overflow != visible
3329
+ if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
3330
+ border( parent );
3331
+
3332
+ // Get next parent
3333
+ parent = parent.parentNode;
3334
+ }
3335
+
3336
+ // Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
3337
+ // Mozilla doubles body offsets with a non-absolutely positioned offsetChild
3338
+ if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) ||
3339
+ (mozilla && jQuery.css(offsetChild, "position") != "absolute") )
3340
+ add( -doc.body.offsetLeft, -doc.body.offsetTop );
3341
+
3342
+ // Add the document scroll offsets if position is fixed
3343
+ if ( fixed )
3344
+ add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
3345
+ Math.max(doc.documentElement.scrollTop, doc.body.scrollTop));
3346
+ }
3347
+
3348
+ // Return an object with top and left properties
3349
+ results = { top: top, left: left };
2342
3350
  }
2343
- });
2344
- }
3351
+
3352
+ function border(elem) {
3353
+ add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
3354
+ }
3355
+
3356
+ function add(l, t) {
3357
+ left += parseInt(l) || 0;
3358
+ top += parseInt(t) || 0;
3359
+ }
3360
+
3361
+ return results;
3362
+ };
3363
+ })();