├── .gitignore ├── CHECKLIST.txt ├── History.md ├── LICENSE.txt ├── Makefile ├── README.md ├── demo ├── index.html ├── pages │ ├── apricots.html │ ├── bananas.html │ ├── coconuts.html │ ├── durians.html │ └── eggplants.php ├── scripts │ └── modernizr-1.5.min.js └── styles │ ├── generic.css │ ├── style.css │ └── yui-reset-3.1.1-min.css └── scripts ├── closure.map ├── jquery-1.4.2.js ├── jquery-1.4.2.min.js ├── jquery.ajaxy.js ├── jquery.ajaxy.min.js └── resources ├── core.console.js ├── core.string.js ├── jquery.ajaxy.js ├── jquery.events.js ├── jquery.extra.js ├── jquery.history.js ├── jquery.scrollto.js └── jquery.utilities.js /.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | .DS_Store -------------------------------------------------------------------------------- /CHECKLIST.txt: -------------------------------------------------------------------------------- 1 | Benjamin "balupton" Lupton's Project Checklist v0.1.1 (July 09, 2010) 2 | 3 | All Projects: 4 | - Have you run all the unit tests for the project? 5 | - Have you remembered to remake the project? [make all] 6 | - Have you tested in all major browsers? 7 | - Have you ensured all documentation dates are correct? 8 | - Have you ensured all documentation project links are current? 9 | - Have you ensured version changelog entries have been added to appropriate file? 10 | - If yes; then you are good to tag this release if you like [git tag -s "v..."] 11 | - To push; use [git push --all] then [git push --tags] 12 | 13 | Project Specific: 14 | - Have you remembered to set it back to the minified version in the demo? 15 | - Do root urls work? 16 | - Do postponed anchors work? 17 | - Do postponed anchors work with back and forward buttons? (scrolling) 18 | - Do ajaxy anchors work? -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | ## History 2 | 3 | v1.6.1, December 28, 2012 4 | - Fixed `
` elements being stripped 5 | - Thanks to [exocom](https://github.com/exocom) for [pull request #7](https://github.com/balupton/jquery-ajaxy/pull/7) 6 | 7 | v1.6.0-beta, August 31, 2010 8 | - Added Ajaxy form demo. 9 | - Added Ajaxy.onReady, Ajaxy.onDocumentReady and Ajaxy.onConfigured promises 10 | - Controllers should now use classname instead of selector. B/C Break. 11 | - $.fn.addAjaxy now supports passing a controller so we can add the Controller.classname to the element(s) 12 | - Added $.fn.addAjaxy and $.fn.removeAjaxy 13 | - State.actionCompleted callback now supports options. 14 | - Added Refresh Action, this is triggered when we click the same Ajaxy link twice. If the refresh action does not exist a log will be outputted, and the Response action will be used instead. B/C Partial Break. 15 | - Improvements to the anchor handling, page tracking and scrolling. 16 | - While in postponed mode, and a anchor is clicked, we will treat the anchor as normal and not perform a redirect. 17 | - Added postpone and disable redirect option values. Postpone will postpone ajaxy functionality until the page is changed. Disable will disable ajaxy functionality all together. 18 | - Made Ajaxy.bind alias Ajaxy.addControllers, and add Ajaxy.addController 19 | - Fixed issue with jQuery UI AutoComplete. Fix due to update of sparkle dependencies. 20 | - We now use jQuery ScrollTo [v1.0.1-beta, August 31, 2010] as our ScrollTo Plugin: http://www.balupton.com/projects/jquery-scrollto 21 | - Updated jQuery History dependencies to [v1.5.0-final, August 31, 2010] 22 | - Updated jQuery Sparkle dependencies to [v1.5.2-beta, August 31, 2010] 23 | 24 | v1.5.8-beta, August 23, 2010 25 | - Added root_url to internal link checks 26 | - Improved internal links adding 27 | 28 | v1.5.7-beta, August 22, 2010 29 | - Added demo for Ajaxy Forms 30 | - Fixed Ajaxy Forms when used with Controller Selectors 31 | 32 | v1.5.6-beta, August 21, 2010 33 | - Updated jQuery Sparkle dependencies to [v1.4.17-final, August 21, 2010] 34 | - Updated jQuery History dependencies to [v1.4.4-final, August 21, 2010] 35 | 36 | v1.5.5-beta, August 19, 2010 37 | - Fixed issue with external links. http://getsatisfaction.com/balupton/topics/external_links_dont_work 38 | - Improved installation instructions to make more clear. 39 | - Updated Syntax Highlighter include and initialisation. We use http://www.balupton.com/projects/jquery-syntaxhighlighter 40 | - Code blocks within the demo are now using PRE instead of CODE elements due to an IE bug 41 | - Updated jQuery Sparkle dependencies to [v1.4.13-final, August 19, 2010]. 42 | - Updated jQuery History dependencies to [v1.4.3-final, August 19, 2010]. 43 | 44 | v1.5.4-beta, August 12, 2010 45 | - Updated jQuery History dependencies to [v1.4.2-final, August 12, 2010]. 46 | - This is a recommended update for all users. 47 | 48 | v1.5.3-beta, August 07, 2010 49 | - The Response.data returned on normal html ajaxy links is now as follows: 50 | { 51 | "controller": controller, 52 | "responseText": responseText, /* raw result */ 53 | "html": html, /* raw result put through Ajaxy.htmlCompat */ 54 | "title": title, /* the text of the title/#ajaxy-title element */ 55 | "head": head, /* the outerHTML of the head/#ajaxy-head element */ 56 | "body": body, /* the outerHTML of the body/#ajaxy-body element */ 57 | "content": content /* the innerHTML of the body/#ajaxy-body element or the html value */ 58 | } 59 | - Updated jQuery Sparkle dependencies to [v1.4.10-beta, August 07, 2010] 60 | 61 | v1.5.2-beta, August 07, 2010 62 | - Added the Ajaxy.htmlCompat function which will convert a html document into a jQuery compatible document. 63 | This is based on old functionality and includes fixes. 64 | The Response.data returned on normal html ajaxy links is now as follows: 65 | { 66 | "controller": controller, 67 | "responseText": responseText, /* raw result */ 68 | "html": html, /* raw result put through Ajaxy.htmlCompat */ 69 | "title": title, /* the value of the title element, or #ajaxy-title */ 70 | "head": head, /* the value of the head element, or #ajaxy-head */ 71 | "body": body, /* the value of the body element, or #ajaxy-body */ 72 | "content": content /* the value of the body element, or #ajaxy-body, or the html */ 73 | } 74 | - It is a backwards compatible release 75 | - Changed the demo to always use the unminified version, and included the minified version in a HTML comment 76 | - Added the HTML5 doctype and the utf8 meta element to the demo pages 77 | 78 | v1.5.1-beta, August 05, 2010 79 | - Fixed a redirection issue 80 | - Support for anchors is now complete. We can now detect all types of anchors and adjust the page and state accordingly. 81 | - Able to detect the severity of the page change, and if it is not considerable (such as only an anchor change) then do not both performing the request. 82 | - $.fn.SrollTo can now take the options argument. We also have a $.Ajaxy.options.scrollto_options for this. 83 | - Added the options [track_all_anchors] and [track_all_internal_links] to keep your Ajaxy website in sync; these are set to false by default. 84 | - A few more options added, should refer to the documentation about these. 85 | - Introduces a minor known issue that the ScrollTo plugin does no always scroll with animation. 86 | - Updated jQuery History dependencies to [v1.4.1-beta, August 05, 2010] 87 | 88 | v1.5.0-beta, August 03, 2010 89 | - Renamed format to extractHash. This change may break backwards compatibility in advanced cases. 90 | - Added support for anchors. This now requires a call to [var Action = this; this.documentReady()] once the content has updated to inform Ajaxy that it can take care of anchors now. See the updated JavaScript in the demo for more information. To do this we have included Ariel Flesler's $.fn.scrollTo with Balupton's $.fn.ScrollTo extension. 91 | - Added auto_ajaxify_documentReady option 92 | - Added auto_sparkle_documentReady option 93 | - Removed dependency on JSON2, instead we use jQuery's parseJSON 94 | - Fixed track providing 3 slashes issue 95 | - Fixed redirect issue 96 | - History requirement is now bundled into built jQuery Ajaxy script, so no need to include both anymore. This saves space as History and Ajax share some dependencies. 97 | - Updated jQuery History dependencies to [v1.4.0-beta, August 03, 2010] 98 | - This release may be a final release if no bugs are found. 99 | 100 | v1.4.0-beta, August 01, 2010 101 | - Updated licensing information. Still using the same license, as it is the best there is, but just provided some more information on it to make life simpler. 102 | - A very large redo and IS NOT backwards compatible 103 | - Added Controller.matches feature 104 | - Changed naming convention to Google's Javascript Standards for everything but options 105 | - Added #current to demo, to be similar to the jQuery History demo 106 | - Fixed SEO in the demo by using [./] on the pages instead of [/] 107 | - Added support for relative Ajaxy links 108 | - The Controller, State and Action are now separate entities. Instead of doing [this.response_data] or [this.data.response] you now do [this.State.Response.data] 109 | - All references to Hash have been renamed to State appropriately 110 | - We now support loading in complete HTML documents. Will find content and title automatically. 111 | - Updated jQuery Sparkle dependencies to [v1.4.8-beta, August 01, 2010] 112 | - Updated jQuery History dependencies to [v1.3.0-beta, August 01, 2010] 113 | - Quite close to a final release 114 | 115 | v1.3.2-dev, July 28, 2010 116 | - Track now includes base_url - this is a fix for certain circumstances. 117 | 118 | v1.3.1-dev, July 22, 2010 119 | - Updated demo to go into great detail 120 | 121 | v1.3.0-dev, July 22, 2010 122 | - Added demo 123 | - Added [redirect, relative_as_base, no_history_class, no_history_class, support_text] options 124 | - Added support for text responses 125 | - Added support for default controllers 126 | - Fixed an issue where request would fire twice for ajaxified controllers 127 | - Cleaned and now uses sparkle dependencies with makefile 128 | 129 | v1.2.0-beta, August 3, 2009 130 | - Moved base/root/relative url functionality inside 131 | - Fixed issue with A elements continuing link 132 | - Improvements to form submission 133 | - Debug improvements 134 | 135 | v1.1.0-beta, July 25, 2009 136 | - Added support for hash callbacks 137 | 138 | v1.0.1-final, July 11, 2009 139 | - Restructured a little bit 140 | - Documented 141 | - Added get and set functions for misc 142 | - Added support for Ajaxy error headers 143 | - Cleaned go/request 144 | 145 | v1.0.0-final, June 19, 2009 146 | - Been stable for over a year now, pushing live. 147 | 148 | v0.1.0-dev, July 24, 2008 149 | - Initial Release 150 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2008-2010 Benjamin Lupton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Javascript/CSS Compressor Makefile - By Benjamin "balupton" Lupton (MIT Licenced) 2 | 3 | MAKEFLAGS = --no-print-directory --always-make 4 | MAKE = make $(MAKEFLAGS) 5 | 6 | BUILDDIR = ./.build 7 | 8 | CLOSUREURL = http://closure-compiler.googlecode.com/files/compiler-latest.zip 9 | CLOSUREDIR = $(BUILDDIR)/closure 10 | CLOSUREFILE = $(CLOSUREDIR)/compiler.jar 11 | YUIURL = http://yui.zenfs.com/releases/yuicompressor/yuicompressor-2.4.7.zip 12 | YUIDIR = $(BUILDDIR)/yui 13 | YUIFILE = $(YUIDIR)/yuicompressor-2.4.7/build/yuicompressor-2.4.7.jar 14 | 15 | 16 | all: 17 | $(MAKE) build; 18 | $(MAKE) add; 19 | 20 | 21 | demo: 22 | open ./demo/index.html 23 | 24 | add: 25 | git add .gitignore CHECKLIST.* COPYING.* demo Makefile README.* scripts 26 | 27 | push: 28 | git push --all ; git push --tags ; 29 | 30 | edithooks: 31 | mate .git/hooks/pre-commit 32 | 33 | 34 | refresh: 35 | wget -q http://balupton.github.com/jquery-sparkle/scripts/resources/core.console.js -O scripts/resources/core.console.js ; 36 | wget -q http://balupton.github.com/jquery-sparkle/scripts/resources/core.string.js -O scripts/resources/core.string.js ; 37 | wget -q http://balupton.github.com/jquery-sparkle/scripts/resources/jquery.events.js -O scripts/resources/jquery.events.js ; 38 | wget -q http://balupton.github.com/jquery-sparkle/scripts/resources/jquery.extra.js -O scripts/resources/jquery.extra.js ; 39 | wget -q http://balupton.github.com/jquery-sparkle/scripts/resources/jquery.utilities.js -O scripts/resources/jquery.utilities.js ; 40 | wget -q http://balupton.github.com/jquery-scrollto/scripts/resources/jquery.scrollto.js -O scripts/resources/jquery.scrollto.js ; 41 | wget -q http://balupton.github.com/jquery-history/scripts/resources/jquery.history.js -O scripts/resources/jquery.history.js ; 42 | wget -q http://balupton.github.com/jquery-history/demo/styles/generic.css -O demo/styles/generic.css ; 43 | 44 | 45 | pack: 46 | cat \ 47 | ./scripts/resources/core.console.js \ 48 | ./scripts/resources/core.string.js \ 49 | ./scripts/resources/jquery.events.js \ 50 | ./scripts/resources/jquery.extra.js \ 51 | ./scripts/resources/jquery.utilities.js \ 52 | ./scripts/resources/jquery.scrollto.js \ 53 | ./scripts/resources/jquery.history.js \ 54 | ./scripts/resources/jquery.ajaxy.js \ 55 | > ./scripts/jquery.ajaxy.js; 56 | 57 | compress: 58 | java -jar $(CLOSUREFILE) --create_source_map ./scripts/closure.map --js_output_file=./scripts/jquery.ajaxy.min.js --js=./scripts/jquery.ajaxy.js; 59 | 60 | build: 61 | $(MAKE) pack; 62 | $(MAKE) compress; 63 | 64 | build-update: 65 | $(MAKE) clean; 66 | mkdir $(BUILDDIR) $(CLOSUREDIR) $(YUIDIR); 67 | cd $(CLOSUREDIR); wget $(CLOSUREURL) -O file.zip; tar -xf file.zip; 68 | cd $(YUIDIR); wget $(YUIURL) -O file.zip; tar -xf file.zip; 69 | 70 | clean: 71 | rm -Rf $(BUILDDIR); 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## jQuery Ajaxy 2 | 3 | jQuery Ajaxy aims at solving complicated AJAX Paradigms by providing you with a easy managed solution to bind into page state (URL Hash) changes, AJAX form submits, and support AJAX links. 4 | 5 | 6 | ## Usage 7 | 8 | Refer to the [demo](http://balupton.github.com/jquery-ajaxy/demo/) and the [source code](https://github.com/balupton/jquery-ajaxy/tree/master/scripts/resources) 9 | 10 | To discover available configuration options, refer to [lines 36 to 156 in the `scripts/resources/jquery.ajaxy.js` file](https://github.com/balupton/jquery-ajaxy/blob/master/scripts/resources/jquery.ajaxy.js#L36-156) 11 | 12 | 13 | ## History 14 | 15 | You can discover the history inside the [History.md](https://github.com/balupton/jquery-ajaxy/blob/master/History.md#files) file 16 | 17 | 18 | ## License 19 | 20 | Licensed under the [MIT License](http://creativecommons.org/licenses/MIT/) 21 |
Copyright © 2008-2010 [Benjamin Arthur Lupton](http://balupton.com) 22 | 23 | 24 | ## Thanks 25 | 26 | - [jQuery](http://jquery.com/) 27 | - [jQuery UI History - Klaus Hartl](http://www.stilbuero.de/jquery/ui_history/) 28 | - [Really Simple History - Brian Dillard and Brad Neuberg](http://code.google.com/p/reallysimplehistory/) 29 | - [jQuery History Plugin - Taku Sano (Mikage Sawatari)](http://www.mikage.to/jquery/jquery_history.html) 30 | - [jQuery History Remote Plugin - Klaus Hartl](http://stilbuero.de/jquery/history/) 31 | - [Content With Style: Fixing the back button and enabling bookmarking for ajax apps - Mike Stenhouse](http://www.contentwithstyle.co.uk/Articles/38/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps) 32 | - [Bookmarks and Back Buttons](http://ajax.howtosetup.info/options-and-efficiencies/bookmarks-and-back-buttons/) 33 | - [Ajax: How to handle bookmarks and back buttons - Brad Neuberg](http://dev.aol.com/ajax-handling-bookmarks-and-back-button) 34 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | jQuery Ajaxy 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 | 42 | 43 |
44 |

About

45 | 46 |

47 | jQuery Ajaxy allows you to easily upgrade your web site into a full featured Ajax web application. Anyone who has tried to do this themselves would no doubt have spent countless hours debugging tedious javascript ajax requests, trying to figure out how to get ajax pages bookmarkable and working with back and forward buttons, or even struggled to add javascript effects to help manage your pages. jQuery Ajaxy was developed to solve all these problems, as well as some you may have never encountered such as; How do I keep my page indexable by Search Engines while making it an Ajax Application, How do I keep my site accessible to those who have javascript disabled? How I ensure I send the correct page back to the browser? 48 |

49 | 50 |

All of those problems are extremely difficult to solve, which is why we've solved them for you. We've made it so:

51 | 52 |
    53 |
  • It's unbelievably simple to upgrade your ordinary links and forms into Ajax requests by just adding a CSS classname.
  • 54 |
  • You already have automatic support for tracking state changes in your now web application so you don't have to worry about this at all - we do it for you. This allows it so the user can still use those back and forward buttons, or even send the page URL to a friend and see the same thing!
  • 55 |
  • You can even submit forms via Ajax with confidence, without having to do any extra server side code.
  • 56 |
  • You will also have the ability to control your web applications state manually through your code for advanced circumstances.
  • 57 |
  • You will still have support for classical anchors despite us using hashes for our web application states! This means you can still direct your users to particular content on a webpage using a link like: my/web/page.html#the-content-to-scroll-to
  • 58 |
59 | 60 |

We've included a nice demo below so you can see all of this in action.

61 |
62 | 63 |
64 |

Using jQuery Ajaxy

65 | 66 |

Seeing it work

67 | 68 |

The following demo is perhaps overly simplistic, but we know the simpler something is; the simpler it is to understand what is going on. So let's get started by clicking through the tabs/links to change the content and update our state.

69 | 70 | 83 | 84 |

85 | As you clicked through these, you would have noticed the content kept changing. If you have a eye for detail, you may have noticed that the page's URL hash also kept changing - this is how we track the state of our application. And if you are really really keen, you may have even noticed the page's title was also changing appropriately for each click. 86 |

87 | 88 |

89 | Now let's mix it up a bit. Click the forward and back buttons in your browser. Watch as it correctly recreates the states of your browsing history. Isn't that cool! Now refresh the page, and notice how the correct state was again recreated. Or even copy the URL, open a new tab, and stick the URL in there and go. Again the state was created. This is soo important, as it allows you to keep track of the state of you application, and the best thing is that it all happens automatically for you - Ajaxy handles it all leaving you to focus on what is important. 90 |

91 | 92 |

The code responsible

93 | 94 |

95 | All of these changes happen because we have upgraded those normal a elements into full featured rich Ajax links. We did this by simple adding the following CSS classes to the links: ajaxy and ajaxy-page. The first CSS class tells Ajaxy that this link is one to be upgraded, and the second is defined by our demo page to say we should use the page controller. Let's see the complete HTML before we move on: 96 |

97 | 98 |

The HTML:

99 |
100 | 			<ul id="menu">
101 | 				<li><a href="./pages/apricots.html" class="ajaxy ajaxy-page">Learn about Apricots</a></li>
102 | 				<li><a href="./pages/bananas.html" class="ajaxy ajaxy-page">Lean about Bananas</a></li>
103 | 				<li><a href="./pages/coconuts.html" class="ajaxy ajaxy-page">Learn about Coconuts</a></li>
104 | 				<li><a href="./pages/durians.html#yummy" class="ajaxy ajaxy-page">Learn about Durians</a></li>
105 | 			</ul>
106 | 			<div id="result">
107 | 				<div id="content" style="max-height:100px;overflow:auto;"></div>
108 | 				<div id="current"></div>
109 | 			</div>
110 | 		
111 | 112 |

113 | Pretty simple isn't it. So let's explain what each element is. 114 | The div#demo is the container for our demo, such that we can separate it from this text explaining what it is. 115 | The ul#menu contains all our links which effectively act as tabs. 116 | Each li.ajaxy.ajaxy-page are all our tab links, they are all linked to the actual Ajax content we would like to load in - such that a search engine can still index our website, and we can be as graceful as possible in upgrading our site. 117 | The div#result is the container for the two result elements we will be using. 118 | The div#content is where our tab content will be loaded into. 119 | The div#current is where we display what the current state is of our web application. 120 |

121 | 122 |

123 | So it pretty much looks just like how you would code it up without Ajax doesn't it? With the exception of the CSS classnames we added. 124 | So what will this code do? Well when our page loads, Ajaxy will look for all elements with the ajaxy class name, and upgrade them into a Ajax link. 125 | Once that link is then clicked, Ajaxy will perform a Ajax request and let us know it's sent off a request such that we can do any fadeOuts or loading animations we would like. 126 | Once Ajaxy has received the response from our server, it'll then try and figure out what we received - did we received a 404 not found? invalid data? text or JSON? - Ajaxy will handle it all for us. 127 | It'll then inform us of a valid response or a error occurred and pass us all the data we need to display our fetched content in our page. 128 | - It may sound a bit complicated, but all of that complicated stuff is happening in the background and being handled by Ajaxy and not us! Youhou! So that means we can focus on what matters - telling Ajaxy which links we want to use with Ajax, and animating and populating our content when requests or responses are performed. 129 |

130 | 131 |

So now we got that out the way, let's get into the javascript. We've documented the code inline as detailed as we can, rather than splitting the code up into segments. As at least for me, reading comments inline is a lot better than detached segments of code as you can't see the big picture. So here you are the big picture with lots of comments. 132 | 133 |

The JavaScript:

134 |
135 | 		/**
136 | 		 * Create a local noconflict scope.
137 | 		 * This is important as perhaps we are running in an noConflict environment so $ is not defined, but jQuery is.
138 | 		 * What this will do is alias $ to jQuery, such that we can still write our code exactly the same as if we weren't in a noConflict environment.
139 | 		 * Another important thing is that this allows us to create a local scope.
140 | 		 * Local scopes are important they avoid variable overwrites and keeps our code nice and tidy.
141 | 		 */
142 | 		(function($){
143 | 			/**
144 | 			 * Fetch the element we will be using.
145 | 			 * We assign them to variables as that way they are cached in our local scope.
146 | 			 * This is good as say if we do $('#menu') three times, that is 3 times that jQuery has to find the #menu element. Causing unecessary load.
147 | 			 */
148 | 			var $body = $(document.body),
149 | 				$menu = $('#menu'),
150 | 				$content = $('#content'),
151 | 				$current = $('#current');
152 | 			
153 | 			/**
154 | 			 * Configure Ajaxy
155 | 			 * We now proceed to configure Ajaxy.
156 | 			 * We have to do this as otherwise, Ajaxy wouldn't know what to do with our Ajax data!
157 | 			 * It would just perform a request, receive a response, and then go... well what do I do now?
158 | 			 * So here we tell Ajaxy how to handle the different types of states we will have in our application.
159 | 			 */
160 | 			$.Ajaxy.configure({
161 | 				/**
162 | 				 * Ajaxy supports a whole bunch of different configuration options.
163 | 				 * By default some things are enabled such as "debug" etc - these should be turned turned off in production environments.
164 | 				 * We don't cover any of the options in this demo as they are outside the demo's scope.
165 | 				 * You can however learn about the options by reading the README.txt attached within the Ajaxy project.
166 | 				 */
167 | 				
168 | 				/**
169 | 				 * For this demo, it may be hosted on a server which does not support AJAX POST requests, so let's use AJAX GET requests instead
170 | 				 * For production you'll want to use POST which is the default - as this will allow you to send forms via ajaxy too.
171 | 				 */
172 | 				'method': 'get',
173 | 				
174 | 				/**
175 | 				 * Define our Ajaxy Controllers.
176 | 				 * If you have ever done some work with the Model View Controller architecture for applications, then this should be quite familiar to you.
177 | 				 * If not I'll explain it anyway :-)
178 | 				 * Controllers are what handles our application states, so if a state has changed we will rely on the appropriate controller to tell us what to do.
179 | 				 * We'll explain this more as we go along. But this is the core of building an Ajaxy application.
180 | 				 */
181 | 				'Controllers': {
182 | 					/**
183 | 					 * The Essential Generic Controller
184 | 				 	 * In jQuery Ajaxy, we will always have a "_generic" controller, hence why it is deemed essential.
185 | 				 	 * This controller is called for every single request and response Ajaxy recieves.
186 | 				 	 * You can use it to (and probably should) use it to display loading animations so our user knows something is happening when a Ajax request is performing, as well as using it to update the document.title with the current states title, and displaying error information.
187 | 				 	 */
188 | 					'_generic': {
189 | 						/**
190 | 						 * The Request Action
191 | 						 * As this is part of our Generic Controller, this will be called for every Ajax request that is performed.
192 | 						 * It allows us to do such things as display the loading animation, and debug requests.
193 | 						 */
194 | 						request: function(){
195 | 							// Prepare
196 | 							var Ajaxy = $.Ajaxy;
197 | 							// Log what is happening
198 | 							if ( Ajaxy.options.debug ) window.console.debug('$.Ajaxy.Controllers._generic.request', [this,arguments]);
199 | 							// Loading
200 | 							$body.addClass('loading');
201 | 							// Done
202 | 							return true;
203 | 						},
204 | 						
205 | 						/**
206 | 						 * The Response Action
207 | 						 * This one will fire when a Ajax request receives a successful response, and as it is part of the Generic Controller it'll fire for every response.
208 | 						 * It allows us to do such things as hide the loading animation, update the document.title with the current state's title, and debug responses.
209 | 						 */
210 | 						response: function(){
211 | 							// Prepare
212 | 							var Ajaxy = $.Ajaxy; var data = this.State.Response.data; var state = this.state||'unknown';
213 | 							// Log what is happening
214 | 							if ( Ajaxy.options.debug ) window.console.debug('$.Ajaxy.Controllers._generic.response', [this,arguments], data, state);
215 | 							// Title
216 | 							var title = data.title||false; // if we have a title in the response JSON
217 | 							if ( !title && this.state||false ) title = 'jQuery Ajaxy - '+this.state; // if not use the state as the title
218 | 							if ( title ) document.title = title; // if we have a new title use it
219 | 							// Loaded
220 | 							$body.removeClass('loading');
221 | 							// Display State
222 | 							$('#current').text('Our current state is: ['+state+']');
223 | 							// Return true
224 | 							return true;
225 | 						},
226 | 						
227 | 						/**
228 | 						 * The Error Action
229 | 						 * This one will fire when a Ajax request fails (be it we got a 404, invalid data, or whatever).
230 | 						 * It's important as it allows us to display a error message to the user.
231 | 						 * If an error occurs, only the Error action will be called and not the Response action, as such we should still do generic things like remove the loading animation.
232 | 						 */
233 | 						error: function(){
234 | 							// Prepare
235 | 							var Ajaxy = $.Ajaxy; var data = this.State.Error.data||this.State.Response.data; var state = this.state||'unknown';
236 | 							// Error
237 | 							var error = data.error||data.responseText||'Unknown Error.';
238 | 							var error_message = data.content||error;
239 | 							// Log what is happening
240 | 							window.console.error('$.Ajaxy.Controllers._generic.error', [this, arguments], error_message);
241 | 							// Loaded
242 | 							$body.removeClass('loading');
243 | 							// Display State
244 | 							$('#current').text('Our current state is: ['+state+']');
245 | 							// Done
246 | 							return true;
247 | 						}
248 | 					},
249 | 					
250 | 					/**
251 | 					 * Our Page Controller
252 | 					 * This is what makes the example in this demo come alive.
253 | 					 * It handles our page requests to do with the three fruits (apricots,bananas and coconuts).
254 | 					 * We can call this whatever we like.
255 | 					 */
256 | 					'page': {
257 | 						/**
258 | 						 * Our Page Controller's Classname [optional]
259 | 						 * This associates our controller with the particular elements which match this classname.
260 | 						 * It allows for when one of our Ajax links to be clicked, Ajaxy will know to fire the Page Controller's Request action.
261 | 						 * This is important as without this there would be no possible way for us to know that the Ajax Request is for our Controller.
262 | 						 */
263 | 						classname: 'ajaxy-page',
264 | 						
265 | 						/**
266 | 						 * Our Page Controller's Matches [optional]
267 | 						 * This can be a string, an array of strings, or a regular expression which is used to match the applications state.
268 | 						 * For this demo, we have chosen to use a regular expression that will match against anything which starts with "/pages"
269 | 						 * This variable follows the same reasoning as providing a selector, as it covers some more uses cases which the selector does not and vice versa.
270 | 						 * To provide ane example of such a use case. Consider our page was bookmarked with the following state active: "/pages/apricots.html"
271 | 						 * This would cause Ajaxy to perform the Ajax request necessary to recreate that state when the page has loaded.
272 | 						 * However, as this request has not come from a link, we cannot use the Controller's selector to associate the request with a particular controller.
273 | 						 * Instead we use this to match against the proposed state, and if it does then we know that this is the controller that should be used.
274 | 						 */
275 | 						matches: /^\/pages\/?/,
276 | 						
277 | 						/**
278 | 						 * Our Page Controller's Request Action
279 | 						 * This just like our Request Action in the Generic Controller will be fired for all Ajaxy requests.
280 | 						 * However this will only be fired for those Ajaxy requests which are known to be for the Page controller.
281 | 						 * For instance, we could have another Controller called "Subpage", if a request is determined to be for that controller, their request action will fire and not this one.
282 | 						 * We use this to prepare our tab area for incoming content, so we deselect all items in the tab menu, and fade out the content.
283 | 						 */
284 | 						request: function(){
285 | 							// Prepare
286 | 							var Ajaxy = $.Ajaxy;
287 | 							// Log what is happening
288 | 							if ( Ajaxy.options.debug ) window.console.debug('$.Ajaxy.Controllers.page.request', [this,arguments]);
289 | 							// Adjust Menu
290 | 							$menu.find('.active').removeClass('active');
291 | 							// Hide Content
292 | 							$content.stop(true,true).fadeOut(400);
293 | 							// Return true
294 | 							return true;
295 | 						},
296 | 						
297 | 						/**
298 | 						 * Our Page Controller's Response Action
299 | 						 * This is just like our Page Controller's Request Action, however for responses instead.
300 | 						 * We will use this to mark the appropriate item in the tab menu as active, to load the content into the tab area, and fade it in.
301 | 						 * This is all we have to do :-)
302 | 						 */
303 | 						response: function(){
304 | 							// Prepare
305 | 							var Ajaxy = $.Ajaxy; var data = this.State.Response.data; var state = this.state; var State = this.State;
306 | 							// Log what is happening
307 | 							if ( Ajaxy.options.debug ) window.console.debug('$.Ajaxy.Controllers.page.response', [this,arguments], data, state);
308 | 							// Adjust Menu
309 | 							$menu.children(':has(a[href*="'+State.raw.state+'"])').addClass('active').siblings('.active').removeClass('active');
310 | 							// Show Content
311 | 							var Action = this;
312 | 							$content.html(data.content).fadeIn(400,function(){
313 | 								Action.documentReady($content);
314 | 								/**
315 | 								 * The above line calls our Action's documentReady function.
316 | 								 * This is a special function which is always there as it is automaticly provided by Ajaxy.
317 | 								 * We assign this to the variable Action, as inside the callback function for our jQuery effect the variable this will be point to somewhere else then!
318 | 								 * 
319 | 								 * So what does this function do?
320 | 								 * 1. It tells Ajaxy that the document is now ready for post processing.
321 | 								 * 2. Ajaxy will then determine if the state included a anchor that we want to scroll to and initiate, and do that.
322 | 								 * 3. Ajaxy will ajaxify the new content (provided the option [auto_ajaxify_documentReady] is true).
323 | 								 * 4. Ajaxy will sparkle the new contnet (provided the option [auto_sparkle_documentReady] is true, and jQuery Sparkle exists).
324 | 								 *    This is optional as there are no dependencies with jQuery Sparkle, but it is a nifty project which is worth a look:
325 | 								 *    http://www.balupton.com/projects/jquery-sparkle/
326 | 								 */
327 | 							});
328 | 							// Return true
329 | 							return true;
330 | 						}
331 | 					}
332 | 				}
333 | 			});
334 | 			
335 | 			// All done
336 | 		})(jQuery);
337 | 		// Back to global scope
338 | 		
339 | 340 |

341 | Now that is quite long, but only because we have so many comments. Let's kill the comments, and let's see how long the entire demo is with the HTML and Javascript. 342 |

343 | 344 | 345 |

The HTML:

346 |
347 | 			<ul id="menu">
348 | 				<li><a href="./pages/apricots.html" class="ajaxy ajaxy-page">Learn about Apricots</a></li>
349 | 				<li><a href="./pages/bananas.html" class="ajaxy ajaxy-page">Lean about Bananas</a></li>
350 | 				<li><a href="./pages/coconuts.html" class="ajaxy ajaxy-page">Learn about Coconuts</a></li>
351 | 				<li><a href="./pages/durians.html#yummy" class="ajaxy ajaxy-page">Learn about Durians</a></li>
352 | 			</ul>
353 | 			<div id="result">
354 | 				<div id="content" style="max-height:100px;overflow:auto;"></div>
355 | 				<div id="current"></div>
356 | 			</div>
357 | 		
358 | 359 |

The JavaScript:

360 |
361 | 		(function($){
362 | 			var $body = $(document.body),
363 | 				$menu = $('#menu'),
364 | 				$content = $('#content'),
365 | 				$current = $('#current');
366 | 			$.Ajaxy.configure({
367 | 				'Controllers': {
368 | 					'_generic': {
369 | 						request: function(){
370 | 						request: function(){
371 | 							// Loading
372 | 							$body.addClass('loading');
373 | 							// Done
374 | 							return true;
375 | 						},
376 | 						response: function(){
377 | 							// Prepare
378 | 							var Ajaxy = $.Ajaxy; var data = this.State.Response.data; var state = this.state||'unknown';
379 | 							// Title
380 | 							var title = data.title||false; // if we have a title in the response JSON
381 | 							if ( !title && this.state||false ) title = 'jQuery Ajaxy - '+this.state; // if not use the state as the title
382 | 							if ( title ) document.title = title; // if we have a new title use it
383 | 							// Loaded
384 | 							$body.removeClass('loading');
385 | 							// Display State
386 | 							$('#current').text('Our current state is: ['+state+']');
387 | 							// Return true
388 | 							return true;
389 | 						},
390 | 						error: function(){
391 | 							// Prepare
392 | 							var Ajaxy = $.Ajaxy; var data = this.State.Error.data||this.State.Response.data; var state = this.state||'unknown';
393 | 							// Error
394 | 							var error = data.error||data.responseText||'Unknown Error.';
395 | 							var error_message = data.content||error;
396 | 							// Log what is happening
397 | 							window.console.error('$.Ajaxy.Controllers._generic.error', [this, arguments], error_message);
398 | 							// Loaded
399 | 							$body.removeClass('loading');
400 | 							// Display State
401 | 							$('#current').text('Our current state is: ['+state+']');
402 | 							// Done
403 | 							return true;
404 | 						}
405 | 					},
406 | 					'page': {
407 | 						classname: 'ajaxy-page',
408 | 						matches: /^\/pages\/?/,
409 | 						request: function(){
410 | 							// Prepare
411 | 							var Ajaxy = $.Ajaxy;
412 | 							// Adjust Menu
413 | 							$menu.find('.active').removeClass('active');
414 | 							// Hide Content
415 | 							$content.stop(true,true).fadeOut(400);
416 | 							// Return true
417 | 							return true;
418 | 						},
419 | 						response: function(){
420 | 							// Prepare
421 | 							var Ajaxy = $.Ajaxy; var data = this.State.Response.data; var state = this.state; var State = this.State;
422 | 							// Adjust Menu
423 | 							$menu.children(':has(a[href*="'+State.raw.state+'"])').addClass('active').siblings('.active').removeClass('active');
424 | 							// Show Content
425 | 							var Action = this;
426 | 							$content.html(data.content).fadeIn(400,function(){
427 | 								Action.documentReady($content);
428 | 							});
429 | 							// Return true
430 | 							return true;
431 | 						}
432 | 					}
433 | 				}
434 | 			});
435 | 			// All done
436 | 		})(jQuery);
437 | 		// Back to global scope
438 | 		
439 | 440 | 441 |

442 | See that is tiny considering what we have just accomplished. And especially considering the power and magnitude of what we have just unleashed into your web application. Now compare that to how many hundreds upon hundreds lines of codes it would have taken to write everything we did today from scratch, and then imagine just how messy that alternative could be! I've been there, it can be hideous! So just sit back right now, and just think of what is now accomplishable right there at your finger tips. And think of all the great fantastic new projects you can make. Or even think just how nice your code will be. You'll be the envy of everyone! Woohoo. 443 |

444 | 445 |

446 | So I do hope that you can truly see the awesomeness of what you have just gone through. You are now prepared with everything you need to get cracking on your own Web 2.0 applications. You can see installation details below. And you can always send us questions and feedback about this project and how you can use it, by clicking the support link up the top or the feedback button on the right. Happy coding! :-) 447 |

448 | 449 |
450 | 451 |
452 |

Installation

453 | 454 |

Step 1. Download jQuery Ajaxy, and extract it to your hard drive

455 |
456 | As everyones extraction process is a little bit different be sure of the following: 457 |
    458 |
  • If the archive was extracted and you have a whole bunch of files and directories (folders), then you must create a new directory called jquery-ajaxy and move all the files and directories into that to continue.
  • 459 |
  • If the archive was extracted and you have only one directory called jquery-ajaxy which has a whole bunch of stuff in it, then that is fine and you can continue onto the next step.
  • 460 |
  • If the archive was extracted and you have only one directory and it is not called jquery-ajaxy then you must rename it to jquery-ajaxy to continue.
  • 461 |
462 |
463 | 464 |

Step 2. Move the jquery-ajaxy directory to somewhere on your webserver

465 |

Be sure to always keep the entire jquery-ajaxy directory intact; this means if you were to only move some of the files instead of moving the entire directory, then you would run into problems due to the cross directory references would no longer be working.

466 | 467 |

Step 3. Include jQuery (insert into your page's head tag)

468 |

If your page already has jQuery included then you can skip this step.

469 |
470 | 			<!-- Include jQuery (Ajaxy Requirement) -->
471 | 			<script type="text/javascript" src="http://www.yoursite.com/somewhere/on/your/webserver/jquery-ajaxy/scripts/jquery-1.4.2.min.js"></script>
472 | 		
473 | 474 |

Step 4. Include jQuery Ajaxy (insert into your page's head tag)

475 |
476 | 			<!-- Include jQuery Ajaxy -->
477 | 			<script type="text/javascript" src="http://www.yoursite.com/somewhere/on/your/webserver/jquery-ajaxy/scripts/jquery.ajaxy.min.js"></script>
478 | 		
479 |
480 | 481 |
482 |

Enjoy!!!

483 |

484 | If anything isn't working the way you want it to, or if you would like to request a feature or provide praise or general feedback then be sure to click the feedback button to the right, or the "Get Support" link up the top of this page. 485 |

486 |

487 | This work is powered by coffee and distributed for free. Donations are how we afford our coffee. Coffee is how we stay awake after our day job hours to work on things like this free open-source project which you're looking at. So go ahead, and get that warm fuzzy feeling knowing you just helped some poor fellow working after hours for free to buy his coffee. You only need to spare a few dollars, or as much as you feel this piece of work is worth. Thanks so much. Alternatively; if you are not in a donating mood, then spreading the word about this project on twitter, your blog, or whatever is just as good. You can also give praise by clicking the feedback button or visiting our "Get Support" link. Thanks a bunch, we appreciate the help deeply. 488 |

489 |
490 | 491 | 492 | 493 | 494 | 495 | 496 |

497 | 498 | 499 |

500 |
501 |

502 | This work is licensed under a GNU Affero General Public License. 503 |

504 |
505 |
506 | 507 | 712 | 713 | 714 | 720 | 721 | 737 | 738 | 739 | -------------------------------------------------------------------------------- /demo/pages/apricots.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery Ajaxy - Apricots 6 | 7 | 8 |
9 | Apricots are small and orange. 10 |
11 | 12 | -------------------------------------------------------------------------------- /demo/pages/bananas.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery Ajaxy - Bananas 6 | 7 | 8 |
9 | Bananas are long and yellow. 10 |
11 | 12 | -------------------------------------------------------------------------------- /demo/pages/coconuts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery Ajaxy - Coconuts 6 | 7 | 8 |
9 | Coconuts are round and hairy. 10 |
11 | 12 | -------------------------------------------------------------------------------- /demo/pages/durians.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery Ajaxy - Durians 6 | 7 | 8 |
9 |

The durian (pronounced /ˈdʊəriən/)[2] is the fruit of several tree species belonging to the genus Durio and the Malvaceae family[1][3] (although some taxonomists place Durio in a distinct family, Durionaceae[1]). Widely known and revered in southeast Asia as the "king of fruits", the durian is distinctive for its large size, unique odour, and formidable thorn-covered husk. The fruit can grow as large as 30 centimetres (12 in) long and 15 centimetres (6 in) in diameter, and it typically weighs one to three kilograms (2 to 7 lb). Its shape ranges from oblong to round, the colour of its husk green to brown, and its flesh pale yellow to red, depending on the species.

10 |

The edible flesh emits a distinctive odour, strong and penetrating even when the husk is intact. Some people regard the durian as fragrant; others find the aroma overpowering and offensive. The smell evokes reactions from deep appreciation to intense disgust. The odour has led to the fruit's banishment from certain hotels and public transportation in southeast Asia.

11 |

The durian, native to Brunei, Indonesia and Malaysia, has been known to the Western world for about 600 years. The 19th-century British naturalist Alfred Russel Wallace famously described its flesh as "a rich custard highly flavoured with almonds". The flesh can be consumed at various stages of ripeness, and it is used to flavour a wide variety of savoury and sweet edibles in Southeast Asian cuisines. The seeds can also be eaten when cooked.

12 |

There are 30 recognised Durio species, at least nine of which produce edible fruit. Durio zibethinus is the only species available in the international market: other species are sold in their local regions. There are hundreds of durian cultivars; many consumers express preferences for specific cultivars, which fetch higher prices in the market.

13 |
14 |

They are soo yummy.

15 |

As you just saw when you clicked the durians link; the browser would have automatically just scrolled to the sentence "They are soo yummy" and highlighted it yellow. This is because on the durians link we clicked, there is an anchor which points to that sentence. This is done with:
16 | <a href="./pages/durians.html#yummy" class="ajaxy ajaxy-page">Learn about Durians</a>
17 | Ajaxy will automatically convert the #yummy anchor into part of our querystring and use that. This is pretty awesome as it allows us to still have full support for anchor functionality despite us hijacking the hash to use for ajax states!
18 | The yellow background color is specified using the CSS3 :target,.target selector.

19 |
20 | 21 | -------------------------------------------------------------------------------- /demo/pages/eggplants.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jQuery Ajaxy - Eggplants 6 | 7 | 8 | 9 |
10 | 11 | 12 | :-O you know eggplant is a vegetable right? 13 | 14 | You sure know your stuff ;-) 15 | 16 | 17 |
18 | Would you say that eggplants came from eggs?
19 |
20 |
21 | 22 |
23 | 24 | If this form does not submit properly, it is because the server this is hosted on does not support AJAX POST requests. 25 |
26 | 27 | -------------------------------------------------------------------------------- /demo/scripts/modernizr-1.5.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Modernizr JavaScript library 1.5 3 | * http://www.modernizr.com/ 4 | * 5 | * Copyright (c) 2009-2010 Faruk Ates - http://farukat.es/ 6 | * Dual-licensed under the BSD and MIT licenses. 7 | * http://www.modernizr.com/license/ 8 | * 9 | * Featuring major contributions by 10 | * Paul Irish - http://paulirish.com 11 | */ 12 | window.Modernizr=function(i,e,I){function C(a,b){for(var c in a)if(m[a[c]]!==I&&(!b||b(a[c],D)))return true}function r(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1);return!!C([a,"Webkit"+c,"Moz"+c,"O"+c,"ms"+c,"Khtml"+c],b)}function P(){j[E]=function(a){for(var b=0,c=a.length;b7)};d.historymanagement=function(){return!!(i.history&&history.pushState)};d.draganddrop=function(){return u("drag")&&u("dragstart")&&u("dragenter")&&u("dragover")&&u("dragleave")&&u("dragend")&&u("drop")};d.websockets=function(){return"WebSocket"in i};d.rgba=function(){m.cssText="background-color:rgba(150,255,150,.5)";return(""+m.backgroundColor).indexOf("rgba")!==-1};d.hsla=function(){m.cssText="background-color:hsla(120,40%,100%,.5)";return(""+ 17 | m.backgroundColor).indexOf("rgba")!==-1};d.multiplebgs=function(){m.cssText="background:url(//:),url(//:),red url(//:)";return/(url\s*\(.*?){3}/.test(m.background)};d.backgroundsize=function(){return r("backgroundSize")};d.borderimage=function(){return r("borderImage")};d.borderradius=function(){return r("borderRadius","",function(a){return(""+a).indexOf("orderRadius")!==-1})};d.boxshadow=function(){return r("boxShadow")};d.opacity=function(){var a=y.join("opacity:.5;")+"";m.cssText=a;return(""+m.opacity).indexOf("0.5")!== 18 | -1};d.cssanimations=function(){return r("animationName")};d.csscolumns=function(){return r("columnCount")};d.cssgradients=function(){var a=("background-image:"+y.join("gradient(linear,left top,right bottom,from(#9f9),to(white));background-image:")+y.join("linear-gradient(left top,#9f9, white);background-image:")).slice(0,-17);m.cssText=a;return(""+m.backgroundImage).indexOf("gradient")!==-1};d.cssreflections=function(){return r("boxReflect")};d.csstransforms=function(){return!!C(["transformProperty", 19 | "WebkitTransform","MozTransform","OTransform","msTransform"])};d.csstransforms3d=function(){var a=!!C(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);if(a){var b=document.createElement("style"),c=e.createElement("div");b.textContent="@media ("+y.join("transform-3d),(")+"modernizr){#modernizr{height:3px}}";e.getElementsByTagName("head")[0].appendChild(b);c.id="modernizr";s.appendChild(c);a=c.offsetHeight===3;b.parentNode.removeChild(b);c.parentNode.removeChild(c)}return a}; 20 | d.csstransitions=function(){return r("transitionProperty")};d.fontface=function(){var a;if(/*@cc_on@if(@_jscript_version>=5)!@end@*/0)a=true;else{var b=e.createElement("style"),c=e.createElement("span"),h,t=false,g=e.body,o,w;b.textContent="@font-face{font-family:testfont;src:url('data:font/ttf;base64,AAEAAAAMAIAAAwBAT1MvMliohmwAAADMAAAAVmNtYXCp5qrBAAABJAAAANhjdnQgACICiAAAAfwAAAAEZ2FzcP//AAMAAAIAAAAACGdseWYv5OZoAAACCAAAANxoZWFk69bnvwAAAuQAAAA2aGhlYQUJAt8AAAMcAAAAJGhtdHgGDgC4AAADQAAAABRsb2NhAIQAwgAAA1QAAAAMbWF4cABVANgAAANgAAAAIG5hbWUgXduAAAADgAAABPVwb3N03NkzmgAACHgAAAA4AAECBAEsAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAACAAMDAAAAAAAAgAACbwAAAAoAAAAAAAAAAFBmRWQAAAAgqS8DM/8zAFwDMwDNAAAABQAAAAAAAAAAAAMAAAADAAAAHAABAAAAAABGAAMAAQAAAK4ABAAqAAAABgAEAAEAAgAuqQD//wAAAC6pAP///9ZXAwAAAAAAAAACAAAABgBoAAAAAAAvAAEAAAAAAAAAAAAAAAAAAAABAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEACoAAAAGAAQAAQACAC6pAP//AAAALqkA////1lcDAAAAAAAAAAIAAAAiAogAAAAB//8AAgACACIAAAEyAqoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8sgECAO0yMxEhESczESMiARDuzMwCqv1WIgJmAAACAFUAAAIRAc0ADwAfAAATFRQWOwEyNj0BNCYrASIGARQGKwEiJj0BNDY7ATIWFX8aIvAiGhoi8CIaAZIoN/43KCg3/jcoAWD0JB4eJPQkHh7++EY2NkbVRjY2RgAAAAABAEH/+QCdAEEACQAANjQ2MzIWFAYjIkEeEA8fHw8QDxwWFhwWAAAAAQAAAAIAAIuYbWpfDzz1AAsEAAAAAADFn9IuAAAAAMWf0i797/8zA4gDMwAAAAgAAgAAAAAAAAABAAADM/8zAFwDx/3v/98DiAABAAAAAAAAAAAAAAAAAAAABQF2ACIAAAAAAVUAAAJmAFUA3QBBAAAAKgAqACoAWgBuAAEAAAAFAFAABwBUAAQAAgAAAAEAAQAAAEAALgADAAMAAAAQAMYAAQAAAAAAAACLAAAAAQAAAAAAAQAhAIsAAQAAAAAAAgAFAKwAAQAAAAAAAwBDALEAAQAAAAAABAAnAPQAAQAAAAAABQAKARsAAQAAAAAABgAmASUAAQAAAAAADgAaAUsAAwABBAkAAAEWAWUAAwABBAkAAQBCAnsAAwABBAkAAgAKAr0AAwABBAkAAwCGAscAAwABBAkABABOA00AAwABBAkABQAUA5sAAwABBAkABgBMA68AAwABBAkADgA0A/tDb3B5cmlnaHQgMjAwOSBieSBEYW5pZWwgSm9obnNvbi4gIFJlbGVhc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgT3BlbiBGb250IExpY2Vuc2UuIEtheWFoIExpIGdseXBocyBhcmUgcmVsZWFzZWQgdW5kZXIgdGhlIEdQTCB2ZXJzaW9uIDMuYmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhTGlnaHRiYWVjMmE5MmJmZmU1MDMyIC0gc3Vic2V0IG9mIEZvbnRGb3JnZSAyLjAgOiBKdXJhIExpZ2h0IDogMjMtMS0yMDA5YmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhIExpZ2h0VmVyc2lvbiAyIGJhZWMyYTkyYmZmZTUwMzIgLSBzdWJzZXQgb2YgSnVyYUxpZ2h0aHR0cDovL3NjcmlwdHMuc2lsLm9yZy9PRkwAQwBvAHAAeQByAGkAZwBoAHQAIAAyADAAMAA5ACAAYgB5ACAARABhAG4AaQBlAGwAIABKAG8AaABuAHMAbwBuAC4AIAAgAFIAZQBsAGUAYQBzAGUAZAAgAHUAbgBkAGUAcgAgAHQAaABlACAAdABlAHIAbQBzACAAbwBmACAAdABoAGUAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBzAGUALgAgAEsAYQB5AGEAaAAgAEwAaQAgAGcAbAB5AHAAaABzACAAYQByAGUAIAByAGUAbABlAGEAcwBlAGQAIAB1AG4AZABlAHIAIAB0AGgAZQAgAEcAUABMACAAdgBlAHIAcwBpAG8AbgAgADMALgBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQBMAGkAZwBoAHQAYgBhAGUAYwAyAGEAOQAyAGIAZgBmAGUANQAwADMAMgAgAC0AIABzAHUAYgBzAGUAdAAgAG8AZgAgAEYAbwBuAHQARgBvAHIAZwBlACAAMgAuADAAIAA6ACAASgB1AHIAYQAgAEwAaQBnAGgAdAAgADoAIAAyADMALQAxAC0AMgAwADAAOQBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQAgAEwAaQBnAGgAdABWAGUAcgBzAGkAbwBuACAAMgAgAGIAYQBlAGMAMgBhADkAMgBiAGYAZgBlADUAMAAzADIAIAAtACAAcwB1AGIAcwBlAHQAIABvAGYAIABKAHUAcgBhAEwAaQBnAGgAdABoAHQAdABwADoALwAvAHMAYwByAGkAcAB0AHMALgBzAGkAbAAuAG8AcgBnAC8ATwBGAEwAAAAAAgAAAAAAAP+BADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQACAQIAEQt6ZXJva2F5YWhsaQ==')}"; 21 | e.getElementsByTagName("head")[0].appendChild(b);c.setAttribute("style","font:99px _,arial,helvetica;position:absolute;visibility:hidden");if(!g){g=s.appendChild(e.createElement("fontface"));t=true}c.innerHTML="........";c.id="fonttest";g.appendChild(c);h=c.offsetWidth*c.offsetHeight;c.style.font="99px testfont,_,arial,helvetica";a=h!==c.offsetWidth*c.offsetHeight;var v=function(){if(g.parentNode){a=j.fontface=h!==c.offsetWidth*c.offsetHeight;s.className=s.className.replace(/(no-)?fontface\b/,"")+ 22 | (a?" ":" no-")+"fontface"}};setTimeout(v,75);setTimeout(v,150);addEventListener("load",function(){v();(w=true)&&o&&o(a);setTimeout(function(){t||(g=c);g.parentNode.removeChild(g);b.parentNode.removeChild(b)},50)},false)}j._fontfaceready=function(p){w||a?p(a):(o=p)};return a||h!==c.offsetWidth};d.video=function(){var a=e.createElement("video"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('video/ogg; codecs="theora"');b.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"');b.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}return b}; 23 | d.audio=function(){var a=e.createElement("audio"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('audio/ogg; codecs="vorbis"');b.mp3=a.canPlayType("audio/mpeg;");b.wav=a.canPlayType('audio/wav; codecs="1"');b.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}return b};d.localStorage=function(){return"localStorage"in i&&i.localStorage!==null};d.sessionStorage=function(){try{return"sessionStorage"in i&&i.sessionStorage!==null}catch(a){return false}};d.webworkers=function(){return!!i.Worker}; 24 | d.applicationCache=function(){var a=i.applicationCache;return!!(a&&typeof a.status!="undefined"&&typeof a.update=="function"&&typeof a.swapCache=="function")};d.svg=function(){return!!e.createElementNS&&!!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect};d.smil=function(){return!!e.createElementNS&&/SVG/.test(M.call(e.createElementNS("http://www.w3.org/2000/svg","animate")))};d.svgclippaths=function(){return!!e.createElementNS&&/SVG/.test(M.call(e.createElementNS("http://www.w3.org/2000/svg", 25 | "clipPath")))};for(var z in d)if(O(d,z))N.push(((j[z.toLowerCase()]=d[z]())?"":"no-")+z.toLowerCase());j[E]||P();j.addTest=function(a,b){a=a.toLowerCase();if(!j[a]){b=!!b();s.className+=" "+(b?"":"no-")+a;j[a]=b;return j}};m.cssText="";D=n=null;(function(){var a=e.createElement("div");a.innerHTML="";return a.childNodes.length!==1})()&&function(a,b){function c(f,k){if(o[f])o[f].styleSheet.cssText+=k;else{var l=t[G],q=b[A]("style");q.media=f;l.insertBefore(q,l[G]);o[f]=q;c(f,k)}}function h(f, 26 | k){for(var l=new RegExp("\\b("+w+")\\b(?!.*[;}])","gi"),q=function(B){return".iepp_"+B},x=-1;++x\\s*$","i");g.innerHTML=f.outerHTML.replace(/\r|\n/g," ").replace(l,f.currentStyle.display=="block"?"":"");l=g.childNodes[0];l.className+=" iepp_"+q;l=p[p.length]=[f,l];f.parentNode.replaceChild(l[1],l[0])}h(b.styleSheets,"all")});a.attachEvent("onafterprint", 28 | function(){for(var f=-1,k;++f").css({position:"absolute",top:"0px",left:"0px"}),h=f.css("position");f.css("position","relative");e.appendTo(f);var i=e.offset().top,g=g.offset().top-i;e.remove();f.css("position", 71 | h);f.animate({scrollTop:g+"px"},b.duration,b.easing,function(c){a.length===0?typeof b.callback==="function"&&b.callback.apply(this,[c]):d.scroll(a,b);return true});return true},fn:function(a){var b=c.ScrollTo,d=c(this);if(d.length===0)return this;var e=d.parent(),f=[];for(config=c.extend({},b.config,a);e.length===1&&!e.is("body")&&e.get(0)!==document;){a=e.get(0);if(e.css("overflow-y")!=="visible"&&a.scrollHeight!==a.clientHeight){f.push({$container:e,$target:d});d=e}e=e.parent()}f.push({$container:c(c.browser.msie? 72 | "html":"body"),$target:d});if(config.durationMode==="all")config.duration=config.duration/f.length;b.scroll(f,config);return this},construct:function(a){var b=c.ScrollTo;c.fn.ScrollTo=b.fn;b.config=c.extend(b.config,a);return this}};c.ScrollTo.construct()}})(jQuery); 73 | (function(c){if(c.History)window.console.warn("$.History has already been defined...");else{c.History={options:{debug:false},state:"",$window:null,$iframe:null,handlers:{generic:[],specific:{}},extractHash:function(a){return a.replace(/^[^#]*#/,"").replace(/^#+|#+$/,"")},getState:function(){return c.History.state},setState:function(a){var b=c.History,a=b.extractHash(a);b.state=a;return b.state},getHash:function(){return c.History.extractHash(window.location.hash||location.hash)},setHash:function(a){a= 74 | c.History.extractHash(a);if(typeof window.location.hash!=="undefined"){if(window.location.hash!==a)window.location.hash=a}else if(location.hash!==a)location.hash=a;return a},go:function(a){var b=c.History,a=b.extractHash(a),d=b.getHash(),e=b.getState();if(a!==d)b.setHash(a);else{a!==e&&b.setState(a);b.trigger()}return true},hashchange:function(){var a=c.History,b=a.getHash();a.go(b);return true},bind:function(a,b){var d=c.History;if(b){typeof d.handlers.specific[a]==="undefined"&&(d.handlers.specific[a]= 75 | []);d.handlers.specific[a].push(b)}else d.handlers.generic.push(a);return true},trigger:function(a){var b=c.History;typeof a==="undefined"&&(a=b.getState());var d,e,f,g;if(typeof b.handlers.specific[a]!=="undefined"){g=b.handlers.specific[a];d=0;for(e=g.length;d=8?g=true:a.webkit&&d>=528?g=true:a.mozilla?b>1?g=true:b===1&&(f>9?g=true:f===9&&e>=2&&(g=true)):a.opera&&(b>10? 77 | g=true:b===10&&f>=60&&(g=true));return g},hashchangeLoader:function(){var a=c.History;if(a.nativeSupport())a.getHash()&&a.$window.trigger("hashchange");else{var b;if(c.browser.msie){a.$iframe=c('