SOW : Core Plugins

SOW = Step Of Web (Smarty author).
SOW plugins are part of Smarty Core, written from scratch!

SOW : Ajax Navigation

Plugin written to enable full ajax navigation, solving few common problems. This documentation is using it, all pages are served by ajax.
Works on link click, on "open link in new tab", on browser refresh, on sharing the link, like a non-ajax website.

Overview:
  • parsing the content and "catching" javascript files & inline js code.
  • serving content without parsing (dynamic websites)
  • URL update without page refresh & enableing back|forward history
  • able to reinit plugins
  • callback available for each link
  • scroll up when new content is loaded (optional)
  • able to add a class to a second container for each link/page (this documentation is adding .animate-bouncein class to top sidebar image - you might already noticed that "bounce" on each new page load).
  • Lightweight ~10Kb minified (~3.5Kb gzipped).

How the parser works:
Because this documentation is fully ajax, we can use it as a real example.
We have two important containers on each page:
A. #middle - main content of each page
B. #page_js_files bottom page container (a <div>) containing only SPECIFIC javascript files of each page. The main javascripts are outside of this container.
These two containers are set by default. You can change them but for now are our defaults.
When you click a link (let's say href="changelog.html"), the plugin is loading changelog.html page processing data:
1. extract #middle of changelog.html (this is basically the page content - this scrollable area)
2. extract specific page javascripts (files and/or inline code) from #page_js_files container (if there are any javascripts).
Why extracting javascripts? To solve this well known browser issue: "[Deprecation] Synchronous XMLHttpRequest".
3. The plugin will now push the #middle content and javascripts. All javascripts are pushed in the same order, are not shuffled/mixed because of async.
4. Your visitors are enjoying your content and instant loading!

Developer note: If debug is enabled in sow.config.js, you can watch live in your browser console all triggers and plugins inits/reinits. All SOW plugins are carefully written to serve the needed info. So you can see the reinits for ajax containers, what is fired, how is fired, etc. Debug is on now! Never forget to set the debug to false on production!

PRODUCTION : Without using the parser

The parser is usually needed for html websites only! On complex websites, the backend should serve only the content (middle), without header, navigation, etc. You can leave the parser enabled, of course, but on each request, the plugin will check the content for #middle container. There is no problem because of this, but... you know... developers! That's why we are not in Forbes! Now, because Forbes is far away, to disable that parser, GULP rebuild is required (because by default, parser is enabled - this documentation is using it).

1. open gulp.config__core.js and go down to sow_ajax_navigation section. Set: parser_extract_enable: false,
2. Because you are already there, you can also change page_404 to fit your real 404 default page/url. (indeed, there are more variables you can change if you need/want to - see below)!
3. Assuming that you didn't disabled the plugin (by default is enabled), you can rebuild using gulp.
Note: target_container: '#middle' – the target_container is set by default to '#middle' because the admin is using this unique id for the main content.
Is recommended to keep it as it is and use this id as main container, even if you plan to use ajax in frontend - just add to frontend: <div id="middle"></div> for the content (except header/footer, of course)

That's it!

Add .js-ajax class to any href/link (ONLY links because forms/divs/etc are handled by other SOW plugins) to enable ajax navigation. All included plugins/vendors (vensors are actually plugins, but called "vendors" because are third party files) are by default fully working in ajax mode - inside ajax content, inside modals, etc.
Plugins are deelply reinitialized for specific containers when/where/if needed! Everything is automatically handled by Smarty Controllers - each plugin you see in this documentation, has it's own controller.

If you add a new plugin to Smarty, you have to create your own Controller the same way all others are arelady created (there is also a boilerplate) or you can simply create a function in your custom javascript file:
function global_callback(ajax_container){ ... }
and from this function you can expand your project because this function is called on each .js-ajax call/click for all containers that require a check and plugin initialization. That param ajax_container is the container (string - like #mycontainer or .mycontainer) for, you should initialize your own plugins. You can test by creating the function and add inside: alert(ajax_container); or console.log(ajax_container);

SOW : Ajax Navigation is an optional plugin, can be removed if not needed/used!



/* 
	:: Plugin File
	src/js/sow.core/sow.ajax_navigation.js

	:: Plugin Init
*/	$.SOW.core.ajax_navigation.init('a.js-ajax');



/* 
	:: Plugin Options|Defaults

*/	$.SOW.core.ajax_navigation.init('a.js-ajax' {

		enable 						: true,
		method 						: 'GET',
		contentType 					: '', 	// jQuery params
		dataType 					: '', 	// jQuery params
		headers 					: '', 	// jQuery params
		crossDomain 					: '', 	// jQuery params
		data_params 					: {ajax:'true'}, // jQuery extra request optional params for your backend

		target_container 				: '#middle', // container to push data
		update_url 					: true,
		show_loading_icon				: true,

		/* 
			callback_example = function(el, data, target_container) {
				// el 			= link clicked 			$(this)
				// data 		= server response 		(html|string)
				// target_container 	= container to push data   	(string:#middle)
			}
		*/
		callback_function 				: '',

		// content (server response) is sent to your callback function only.
		callback_before_push				: false,

		/*
			#middle 	= main content to be extracted
			#page_js_files  = second container containing js files wrapped inside a div
		*/
		parser_extract_enable 				: true,
		parser_extract_element				: '#middle, #page_js_files',
		// in case #middle element not found in request, entire data/page is pushed/shown
		parser_force_push2target 			: false, 	

		autoscroll_to_content				: true, // scroll up to content after page loaded

		
		// Optional second container - add a class when page loaded
		container2_element				: '',
		container2_class				: '',

		// 404 error page
		page_404					: '404.html',


		// Reload page content on back/forward history button instead of loading from history cache
		onpopstate_reload 				: true,


		/*
			Different than callback, cannot be overwritten by params
			Call a custom function after each page load
			Condition: callback_before_push: false (else, call the function from your callback).

			Might be used to reinit custom scripts/plugins and/or process special data

			custom_function_example = function(el, target_container) {
				// el 			= link clicked 				$(this)
				// target_container 	= container where data is pushed   	(string:#middle)
			}
		*/
		custom_function_call 				: '',
});

								

/* 
	:: Overwriting the defaults:
*/

	data-ajax-method="GET" 
	data-ajax-target-container="#middle" 
	data-ajax-update-url="true" 
	data-ajax-show-loading-icon="true" 
	data-ajax-callback-function="" 
	data-ajax-callback-before-push="false" 
	data-ajax-parser-extract-element="#middle, #page_js_files"
	data-ajax-autoscroll-to-content="true" 

	data-ajax-container2-element="img.js-ajax-loaded-animate" 
	data-ajax-container2-class="animate-bouncein" 
									

/* 
	:: Ajax navigation - meta title & meta description

	  When page has no meta tags because page section is loaded via ajax
	  add these custom tags to each section/page (optional).

	  Pay attention when page is loaded directly (or by refresh)
	  these tags should be not displayed (backend script might be needed)
	  By hidden them is a 'black hat seo' - so do not hide them!

	  Useful if parser not used or page has no meta tags.
*/
	<meta-title>...</meta-title>
	<meta-description>...</meta-description>
	<meta-canonical>...</meta-canonical>
	<meta-robots>...</meta-robots>

									

Examples

CLICK AND GO TO A 404 PAGE! This link is going as a test to a non-existent page which redirects to 404.html

<!-- 

	This is how an ajax default link looks like.
	Only .js-ajax class needed!
-->
<a href="my-page.html" class="js-ajax">
	Regular ajax link nav link
</a>


<!-- 
	All navigation links of this documentation are like this.
	The #middle content is parsed/extracted from "my-page.html" and 
	pushed via ajax. 

	If javascript files and/or inline code is inside of 
	#page_js_files, are also extracted and pushed via ajax. 
	Smarty don't use eval() so is no security worry! 

	++++++++++++++++++++++++++++++++++++++++++++++++++++++
	Please note: when using the parser, all SPECIFIC page 
	javascripts (not the main js files) must be inside of 
	#page_js_files container. Else, the parser will 
	not use them! Please inspect any bottom page of this 
	documentation to see how it's used. It's nothing different
	than a normal page except that specific page js files
	are wrapped inside #page_js_files container. That's all!

	If parser not used, javascripts are automatically
	handled. No need of #page_js_files container.

	Why the plugin handle javascripts? To solve this well
	known issue: "[Deprecation] Synchronous XMLHttpRequest"
	++++++++++++++++++++++++++++++++++++++++++++++++++++++

	You can now add params to the link if you need 
	to overwrite something for this specific link.
-->
											

Click to load

	<!--
		Note: this particular example is using data-href instead of href.
		Link is not crawlable by search engines.
		Used just to load a small content, like this one!

		data-href is always used as primary, if present.
		Can be crawlable by using both:
			     href="url-to-full-page.html"
			data-href="url-to-partial.html"

		Of course, by using data-ajax-parser-extract-element 
		will extract a specific part/section. 
	-->
	<a 	href="#" 
		data-href="_ajax/demo_content.html" 
		data-ajax-target-container="#link_ajax_container" 
		data-ajax-update-url="false" 
		data-ajax-show-loading-icon="true" 
		data-ajax-callback-function="" 
		data-ajax-callback-before-push="false" 
		data-ajax-parser-extract-element="" 
		data-ajax-autoscroll-to-content="true" 

		data-ajax-container2-element="img.js-ajax-loaded-animate" 
		data-ajax-container2-class="animate-bouncein" 

		class="js-ajax btn btn-danger btn-lg">
		Click to load
	</a>


	<div id="link_ajax_container">
		<!-- ajax content is added here -->
	</div>