SOW : Utils

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

Info

A collection of useful tools, as light as possible!

Main purpose: cut backend coding & processing!
Example: avatar initials would be parsed in a backend loop! Why not doing this on client side?


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

	:: Plugin Init
*/	$.SOW.core.utils.init();
									

Simple Background Slideshow

Simple background image slideshow (as cover) written from scratch (1.5Kb final size)! Mobile supported with different set of images!
Please note: Images are loaded on page load, so is not recommended to use too many images or too many slideshows on the same page! Depends on total size!

There are no controlls! Just a simple slideshow!

data-sow-slideshow-interval="3000"
data-sow-slideshow-fade-delay="1500"
data-sow-slideshow-interval="8000"
data-sow-slideshow-fade-delay="3000"
<!-- 
Please note, position-relative of main container, if something goes wrong 
Anjust overlay (darknes or lightness if .overlay-light used instead):	
	overlay-opacity-[0-9]

Also note: in this example, we have 300px width/height! 
Because is a background image, width/height should be set/known.

Real example of this script: niche.restaurant.html
-->
<div class="sow-util-slideshow position-relative w--300 h--300 overlay-dark overlay-opacity-3" 
	data-sow-slideshow-interval="3000" 
	data-sow-slideshow-fade-delay="1500" 
	data-sow-slideshow="
		demo.files/images/unsplash/restaurant/thumb_600/jade-wulfraat-sIzym-INcvk-unsplash-min-min.jpg,
		demo.files/images/unsplash/restaurant/thumb_600/jade-wulfraat-UaOPeqfdW1c-unsplash-min-min.jpg,
		.demo.files/images/unsplash/restaurant/thumb_600/jade-wulfraat-yXnPoTkkY94-unsplash-min-min.jpg
	">
</div>


<!-- 

	Using mobile attribute for smaller image size 
	(~768px is ok) 

-->
<div class="sow-util-slideshow position-relative w--300 h--300 overlay-dark overlay-opacity-3" 
	data-sow-slideshow-interval="3000" 
	data-sow-slideshow-fade-delay="1500" 
	data-sow-slideshow="
		demo.files/images/unsplash/restaurant/jade-wulfraat-sIzym-INcvk-unsplash-min-min.jpg,
		demo.files/images/unsplash/restaurant/jade-wulfraat-UaOPeqfdW1c-unsplash-min-min.jpg,
		demo.files/images/unsplash/restaurant/jade-wulfraat-yXnPoTkkY94-unsplash-min-min.jpg
	"
	data-sow-slideshow-xs="
		demo.files/images/unsplash/restaurant/thumb_600/jade-wulfraat-sIzym-INcvk-unsplash-min-min.jpg,
		demo.files/images/unsplash/restaurant/thumb_600/jade-wulfraat-UaOPeqfdW1c-unsplash-min-min.jpg,
		demo.files/images/unsplash/restaurant/thumb_600/jade-wulfraat-yXnPoTkkY94-unsplash-min-min.jpg
	"
	>
</div>
									

Initials by attribute

Extract the full name and inject the initials only.

Manual/static color

Asign color by name
Manual/static color

Asign color by name
<!-- circle elements: replace .rounded with .rounded-circle -->
<span data-initials="John Doe" class="sow-util-initials bg-danger-soft rounded h5 w--40 h--40 d-inline-flex justify-content-center align-items-center">
	<i class="fi fi-circle-spin fi-spin"></i>
</span>


<!-- 
	Assign color by name 

	by default we set .bg-light as a default background color!
	Is replaced by the plugin with actual name color!
-->
<span data-initials="John Doe" data-assign-color="true" class="sow-util-initials bg-light rounded h5 w--40 h--40 d-inline-flex justify-content-center align-items-center">
	<i class="fi fi-circle-spin fi-spin"></i>
</span>
									

Cookies by attribute

Add, delete and toggle cookies using a button/link

Set Cookie Set Delete Toggle
<!-- 
	data-cookie-val  		is set by defatul to "1" if not provided!
	data-cookie-expire 		(in days) is set by default to 7 if not pvided!
	data-cookie-path="/" 		(cookie path, default "/")

Note: toast is optional!
	data-toast-msg-type-set="primary|success|warning|danger" (default: success)
	data-toast-msg-type-del="primary|success|warning|danger" (default: success)
-->



<!-- add cookie -->
<a href="#" class="sow-util-cookie"
	data-cookie-set="_test_" 
	data-cookie-val="1" 
	data-cookie-expire="1" 

	data-toast-msg-set="Set: _test_" 
	data-toast-msg-pos="top-center" 
	data-toast-msg-type-set="success-soft">
	Set Cookie
</a>

<!-- delete cookie -->
<a href="#" class="sow-util-cookie"
	data-cookie-del="_test_" 

	data-toast-msg-del="Deleted: _test_" 
	data-toast-msg-pos="top-center" 
	data-toast-msg-type-del="danger-soft">
	Set Delete
</a>

<!-- toggle cookie -->
<a href="#" class="sow-util-cookie"
	data-cookie-toggle="_test_" 
	data-cookie-val="1" 
	data-cookie-expire="1" 

	data-toast-msg-set="Set: _test_" 
	data-toast-msg-del="Deleted: _test_" 
	data-toast-msg-pos="top-center"
	data-toast-msg-type-set="success-soft" 
	data-toast-msg-type-del="danger-soft">
	Toggle
</a>
									


	/*
	programatically 
	Cookie Plugin is added as Core in Smarty:
	https://github.com/js-cookie/js-cookie
	So you can also use directly in your app:
	*/

	Cookies.set('key', 'val', { expires: 365, path: '/' });
	Cookies.get('key');
	Cookies.remove('key', { path: '/' });


	/*
		IMPORTANT! 'SameSite=None; secure'
		You can pass the Google params in path.
		And you can use the global variable:
		$.SOW.globals.cookie_secure
	*/

	Cookies.set('key', 'val', { expires: 365, path: $.SOW.globals.cookie_secure });
	Cookies.get('key', { path: $.SOW.globals.cookie_secure });
	Cookies.remove('key', { path: $.SOW.globals.cookie_secure });
									

Time ago






<!-- 
	WAYS TO SET THE LANGUAGE 
	(default is already english ; can be changed in gulp.config__core.js)

		1. by data attribute, as you can see the working example below (will overwrite anything)
		2. by javascript
			<script>
				var sow_util_timeago_lang = {
					seconds 		: "less than a minute ago",
					minute 			: "about a minute ago",
					minutes 		: "%d minutes ago",
					hour 			: "about an hour ago",
					hours 			: "about %d hours ago",
					day 			: "a day ago",
					days 			: "%d days ago",
					month 			: "about a month ago",
					months 			: "%d months ago",
					year 			: "about a year ago",
					years 			: "%d years ago"
				}
			</script>

		3. by empty span tag
				<span class="hide sow-util-timeago-lang" data-lang='{
					"seconds" 		: "less than a minute ago",
					"minute" 		: "about a minute ago",
					"minutes" 		: "%d minutes ago",
					"hour" 			: "about an hour ago",
					"hours" 		: "about %d hours ago",
					"day" 			: "a day ago",
					"days" 			: "%d days ago",
					"month" 		: "about a month ago",
					"months" 		: "%d months ago",
					"year" 			: "about a year ago",
					"years" 		: "%d years ago"
				}'>

		2 & 3 – used for multilanguage portal, if multiple timeago are used.
		Set it once anywhere, for each page that timeago is required!
		You can also change the default (english) in gulp.config__core.js and rebuild using GULP

	

	data-live="true" 	will update in realtime (1min. loop)

-->
<time class="sow-util-timeago" 
	datetime="2019-09-17T23:59:17" 
	data-live="true" 
	data-lang='{
		"seconds" 		: "less than a minute ago",
		"minute" 		: "about a minute ago",
		"minutes" 		: "%d minutes ago",
		"hour" 			: "about an hour ago",
		"hours" 		: "about %d hours ago",
		"day" 			: "a day ago",
		"days" 			: "%d days ago",
		"month" 		: "about a month ago",
		"months" 		: "%d months ago",
		"year" 			: "about a year ago",
		"years" 		: "%d years ago"
	}'></time>


<!-- using abbr -->
<abbr class="sow-util-timeago" data-time="December 17, 2012">December 17, 2012</abbr>
<abbr class="sow-util-timeago" data-time="2011-12-17T09:24:17Z"></abbr> 

<!-- using span (and timestamp example) -->
<span class="sow-util-timeago" data-time="1372218564"></span>

Note: any date format is working on any tag: span, abbr, etc.
Here are just few examples of using them!

									

Element Cloner Hint: create some clones and then drag to reorder

Self Cloning
Outside Cloning (hidden element as `template`)
Note: this example is simple, no buttons

ADD ELEMENT

<!-- 
	
	Attributes 

	data-clone-target="..."  				what to clone
	data-clone-destination="..."  		where to append the clone
	data-clone-sortable="true" 				true = reorder on drag/drop
	data-clone-limit="0"  				max no. of clones
	data-clone-method="append"  			append|prepend (default: append)

	.sow-util-cloner class is required on "+" button/link
	.btn-clone-remove class is required only for the second example (not for self cloning)


	IMPORTANT! (see example 2)
		If a field is datepicker, colorpicker (or anything else),
		the plugin should know what to reinit for each clone! Will not work for "self cloning"
		so the second example with a hidden element should be used instead.

		We can't add .datepicker class directly because will be initialized on
		page load and the clone will be wrong! So we add this attribute instead of a direct class:
	 		data-cloned-replace-class="datepicker"

	 Other examples:
	 	data-cloned-replace-class="bs-select"	(for selects)
	 	data-cloned-replace-class="rangepicker"
	 	data-cloned-replace-class="colorpicker"
	 	... and so on
-->





<!-- 1. Self Cloning -->
<div id="container_clone_example">

	<div class="input-group mb-3">
		<input type="text" class="form-control" placeholder="Recipient's username">

		<div class="input-group-append">
			<a href="#" 

				data-clone-target="#container_clone_example" 
				data-clone-destination="#container_clones"  
				data-clone-sortable="true" 
				data-clone-limit="0" 
			
				class="sow-util-cloner btn btn-outline-secondary">
				<!-- 
					note: icon class replaced when cloned
					attribute not limited to icon - can be added to any element inside clone
				 -->
				<i class="fi fi-plus m-0" data-cloned-replace-class="fi fi-close m-0"></i>
			</a>
		</div>
	</div>

</div>

<div id="container_clones"><!-- clones appended here --></div>
									

<!-- 2. Outside Cloning (hidden element as `template`) -->
<a href="#" 

	data-clone-target="#container_tpl_hidden>div" 
	data-clone-destination="#container_clones2"  
	data-clone-sortable="true" 
	data-clone-limit="5" 

	class="sow-util-cloner">
	ADD ELEMENT
</a>

<div id="container_clones2"><!-- clones appended here --></div>

<!-- hidden container containing the `template` to be cloned -->
<div id="container_tpl_hidden" class="hide">
	
	<!-- this will be cloned -->
	<div class="clearfix mb-3"><!-- always wrap elements inside a div/container -->
		<input type="text" class="form-control" data-cloned-replace-class="form-control rangepicker">
		<a href="#" class="btn-clone-remove">remove</a>
	</div>

</div>
									
<!-- PREADDED ITEMS 
Preadded items should be present inside the clone container and 
this is the strucuture (for the first example):
-->
<div id="container_clones">
	<div class="js-cloned">

		<input type="text" class="form-control">

		<a href="#" data-clone-target="#container_clone_example">remove</a>

	</div>
</div>
									

Advanced Group Cloner Hint: type min. 3 chars in "Product Search"

Example: Memory Upgrade
Example: Memory Upgrade
<!--

	NOTE

		Because clonned elements are arrays, fields are replaced (input, select, etc)!

			[$] is replaced with group number like this: [1], [2], etc
			according to group number (each box is a group)

			1. Replace form field name ; example:  name="group_on[1]"
				data-cloned-replace-name="group_on[$]"

			2. Replace data attribute (used by input-suggest in this example)
				this will replace the attribute (similar to previous example, but for data attributes)
				replaced attribute is used then to apply ajax rules - so is dynamically applied.
			data-name="product_id[]" 
			data-cloned-replace-attribute-name="data-name" 
			data-cloned-replace-attribute-value="product_id[$][]" 


		Please use inspect element to see it working.

		Dependencies in this demo:
			SOW : Input Suggest 
			Vendor : Sortable

-->





<!--

	CLONE MAIN CONTAINER

-->
<div id="clone_group_list" class="row sortable">

	<!--

		PREADDED

	-->
	<div class="col-12 col-lg-6 mt-3 py-3 rounded js-cloned">

		<div class="border border-primary rounded border-dashed p--15">

			<!-- header -->
			<div class="clearfix mb-2 sortable-handle">

				<!-- on/off -->
				<label class="form-switch form-switch-pill form-switch-primary">
					<input type="checkbox" value="1" checked="" name="group_on[0]">
					<i data-on="✔" data-off="✕"></i>
					Enable
				</label>

				<!-- remove button -->
				<a href="#" class="sow-util-cloner close mt--n8 float-end" data-clone-target="#clone_group_list" tabindex="-1">
					<i class="fi fi-close m-0"></i>
				</a>

			</div>

			<!-- group name -->
			<div class="form-label-group mb-3">
				<input type="text" placeholder="Group Name" class="form-control" name="group_name[0]" value="">
				<label>Group Name</label>
				<small class="d-block text-gray-500">Example: <span class="font-weight-medium">Memory Upgrade</span></small>
			</div>

			<!-- 
				See the console for Ajax request 

				Params sent to URL:
					{ajax: "true", action: "input_search", key: "_USER_KEYWORDS_", limit: 20}

				Note: in this demo, there are always the same results
				because the active search is done by the backend!

			-->
			<div class="input-suggest-group">
				<div class="form-label-group">

					<!--
						
						NOTE:
							data-name="product_id[]"
							Is used to generate hidden input fields for each item added to the list
							If not provided, name="..." attribute is used!
							If none of them found, "item[]" is used by default for input hidden fields!
					-->
					<input type="text" class="form-control input-suggest" value="" 
						data-cloned-replace-class="form-control input-suggest" 
						placeholder="Product Search..." 
						data-name="product_id[0][]" 
						data-input-suggest-mode="append" 
						data-input-suggest-typing-delay="300" 
						data-input-suggest-typing-min-char="3" 
						data-input-suggest-append-container="parent:group" 
						data-input-suggest-max-items="2" 
						data-input-suggest-ajax-url="_ajax/input_suggest_append.json" 
						data-input-suggest-ajax-method="GET" 
						data-input-suggest-ajax-limit="10">
					<label>Product Search...</label>
				</div>

				<!-- append data -->
				<div class="input-suggest-container sortable hide-empty mt-3"></div>
			</div>

		</div>
	</div>

</div>




<!--

	CLONE TPL

-->
<div id="configurator_tpl" class="hide">

	<div class="col-12 col-lg-6 mt-3 py-3 rounded">

		<div class="border border-primary rounded border-dashed p--15">

			<!-- header -->
			<div class="clearfix mb-2 sortable-handle">

				<!-- on/off -->
				<label class="form-switch form-switch-pill form-switch-primary">
					<input type="checkbox" value="1" checked="" name="group_on[]" data-cloned-replace-name="group_on[$]">
					<i data-on="✔" data-off="✕"></i>
					Enable
				</label>

				<!-- remove button -->
				<a href="#" class="sow-util-cloner close mt--n8 float-end" data-clone-target="#clone_group_list" tabindex="-1">
					<i class="fi fi-close m-0"></i>
				</a>

			</div>

			<!-- group name -->
			<div class="form-label-group mb-3">
				<input type="text" placeholder="Group Name" class="form-control" id="group_name" name="group_name[]" data-cloned-replace-name="group_name[$]" value="">
				<label for="group_name">Group Name</label>
				<small class="d-block text-gray-500">Example: <span class="font-weight-medium">Memory Upgrade</span></small>
			</div>

			<!-- 
				See the console for Ajax request 

				Params sent to URL:
					{ajax: "true", action: "input_search", key: "_USER_KEYWORDS_", limit: 20}

				Note: in this demo, there are always the same results
				because the active search is done by the backend!

			-->
			<div class="input-suggest-group">
				<div class="form-label-group">

					<!--
						
						NOTE:
							data-name="product_id[]"
							Is used to generate hidden input fields for each item added to the list
							If not provided, name="..." attribute is used!
							If none of them found, "item[]" is used by default for input hidden fields!
					-->
					<input type="text" class="form-control" value="" 
						data-cloned-replace-class="form-control input-suggest" 
						placeholder="Product Search..." 
						data-name="product_id[]" 
						data-cloned-replace-attribute-name="data-name" 
						data-cloned-replace-attribute-value="product_id[$][]" 
						data-input-suggest-mode="append" 
						data-input-suggest-typing-delay="300" 
						data-input-suggest-typing-min-char="3" 
						data-input-suggest-append-container="parent:group" 
						data-input-suggest-max-items="2" 
						data-input-suggest-ajax-url="_ajax/input_suggest_append.json" 
						data-input-suggest-ajax-method="GET" 
						data-input-suggest-ajax-limit="10">
					<label>Product Search...</label>
				</div>

				<!-- append data -->
				<div class="input-suggest-container hide-empty mt-3" data-cloned-replace-class="input-suggest-container sortable hide-empty mt-3"></div>
			</div>

		</div>
	</div>

</div>


<!--

	CLONE TRIGGER

-->
<div class="mt-3">
	<a href="#" 
		data-clone-target="#configurator_tpl>div" 
		data-clone-destination="#clone_group_list"	
		data-clone-limit="5" 
		class="sow-util-cloner btn btn-sm btn-secondary">
		ADD GROUP
	</a>
</div>
									

Action Util

Many util functions for a single button/checkbox/etc. Slightly similar with SOW : Button Toggle plugin but extended, more options and more flexible.


<!-- EMAIL ADDRESS -->
<div class="input-group-over">

	<div class="form-label-group">
		<input required readonly placeholder="Email Address" id="account_email" name="account[email]" type="email" class="form-control" value="john.doe@gmail.com">
		<label for="account_email"><span class="text-danger">Email</span> Address</label>
	</div>

	<a id="email_edit_show" href="#!" class="btn transition-none sow-util-action" 
		data-util-self-ignore="true" 
		data-util-target-hide="#email_edit_show" 
		data-util-target-show="#email_edit_hide, #email_edit_password_request" 
		data-util-target-readonly-off="#account_email" 

		data-util-target-input="#account_email" 
		data-util-target-input-val="" 

		data-util-target-focus="#account_email">
		<i class="fi fi-pencil m-0"></i>
	</a>

	<a id="email_edit_hide" href="#!" class="btn transition-none sow-util-action hide" 
		data-util-self-ignore="true" 
		data-util-target-hide="#email_edit_hide, #email_edit_password_request" 
		data-util-target-show="#email_edit_show" 
		data-util-target-readonly-on="#account_email" 

		data-util-target-input="#account_email" 
		data-util-target-input-val="john.doe@gmail.com">
		<i class="fi fi-close m-0"></i>
	</a>

</div>


<div id="email_edit_password_request" class="mt-3 hide">

	<!-- password -->
	<div class="input-group-over">
		<div class="form-label-group mb-3">
			<input placeholder="Account Password" id="account_password" name="account[current_password]" type="password" class="form-control">
			<label for="account_password">Account Password</label>
		</div>

		<!-- Show Password -->
		<a href="#" class="btn btn-password-type-toggle" data-target="#account_password">
			<span class="group-icon">
				<i class="fi fi-eye m-0"></i>
				<i class="fi fi-close m-0"></i>
			</span>
		</a>
	</div>
	<!-- /password -->

</div>
											
<!-- AVAILABLE OPTIONS -->


<!-- Do not toggle self "active" class : on button click -->
data-util-self-ignore="true"

<!-- Show/Hide -->
data-util-target-hide="#container" 
data-util-target-show="#container" 

<!-- Add Class -->
data-util-target-class-add="#container" 
data-util-target-class-add-val="someclass" 

<!-- Remove Class -->
data-util-target-class-remove="#container" 
data-util-target-class-remove-val="someclass" 

<!-- Toggle Class -->
data-util-target-class-toggle="#container" 
data-util-target-class-toggle-val="someclass" 

<!-- Input/Textarea Value -->
data-util-target-input="#inputElement" 
data-util-target-input-val="someValue" 

<!-- Input/Textarea Placeholder -->
data-util-target-placeholder="#inputElement" 
data-util-target-placeholder-val="someValue" 

<!-- Readonly Attribute -->
data-util-target-readonly-on="#inputElement" 
data-util-target-readonly-off="#inputElement" 
data-util-target-readonly-toggle="#inputElement" 

<!-- Disabled Attribute -->
data-util-target-disable-on="#element" 
data-util-target-disable-off="#element" 
data-util-target-disable-toggle="#element" 

<!-- Remove Container -->
data-util-target-remove="#container" 

<!-- Focus Input/Textarea -->
data-util-target-focus="#inputElement" 

<!-- Toast Message on click (different then ajax toast) -->
data-util-toast-msg="Item Changed" 
data-util-toast-position="top-center" 
data-util-toast-type="success" 
data-util-toast-timeout="2500" 

<!-- Ajax Request -->
data-util-ajax-request="URL_HERE" 
data-util-ajax-method="GET" 
data-util-ajax-params="['param1','value1']['param2','value2']" 
data-util-ajax-toast-success="Successfully Updated!" 
data-util-ajax-toast-position="top-center" 
data-util-ajax-toast-timeout="2500" 
data-util-ajax-append-response="#container" 

Group Util

Links acting like checkboxes/radio! Can be used in various places, by manipulating a class.



<!-- checkbox like -->
<div id="group_checkbox">

	<a href="#!" class="form-checkbox form-checkbox-primary clearfix d-block mb-2 sow-util-action" 
		data-util-group-active="#group_checkbox>a.form-checkbox" 
		data-util-group-active-class="active">
		<i></i> Option 1
	</a>

	<a href="#!" class="form-checkbox form-checkbox-primary clearfix d-block mb-2 sow-util-action" 
		data-util-group-active="#group_checkbox>a.form-checkbox" 
		data-util-group-active-class="active">
		<i></i> Option 2
	</a>

</div>

<!-- radio like -->
<div id="group_radio">

	<a href="#!" class="form-radio form-radio-primary clearfix d-block mb-2 sow-util-action" 
		data-util-group-active="#group_radio>a.form-radio" 
		data-util-group-active-class="active">
		<i></i> Option 1
	</a>

	<a href="#!" class="form-radio form-radio-primary clearfix d-block mb-2 sow-util-action" 
		data-util-group-active="#group_radio>a.form-radio" 
		data-util-group-active-class="active">
		<i></i> Option 2
	</a>

</div>

Ghost Ajax Form

Without using form tags!

In rare situations when we can't use form inside form.

Price: $23.99
Sale Price: $18.99
Inventory: 100 items
Submit

<div class="mb-5">
	<div>
		Price: $<span id="price_info">23.99</span>
	</div>
	<div>
		Sale Price: $<span id="price_sale_info">18.99</span>
	</div>
	<div>
		Inventory: <span id="product_inventory_info">100</span> items
	</div>
</div>



<div class="sow-util-form position-relative" 
	 data-util-form-action="../demo.files/php/demo.ajax_request.php" 
	 data-util-form-method="post" 
	 data-util-form-params="['param1','value1'],['param2','value2']" 
	 data-util-form-toast-success="Successfully Saved!" 
	 data-util-form-toast-error="Unexpected Internal error!" 
	 data-util-form-toast-position="top-center">
	
	<!-- price -->
	<div class="form-label-group mb-1">
		<input placeholder="Price" id="price" name="price" type="number" value="23.99" class="form-control form-control-sm" data-util-update="#price_info">
		<label for="price">Price</label>
	</div>

	<!-- sale price -->
	<div class="form-label-group mb-1">
		<input placeholder="Sale Price" id="price_sale" name="price_sale" type="number" value="18.99" class="form-control form-control-sm" data-util-update="#price_sale_info">
		<label for="price_sale">Sale Price</label>
	</div>

	<!-- inventory -->
	<div class="form-label-group mb-1">
		<input placeholder="Inventory" id="inventory" name="inventory" type="number" value="100" class="form-control form-control-sm" data-util-update="#product_inventory_info">
		<label for="inventory">Inventory</label>
	</div>

	<!-- submit -->
	<a href="#!" class="sow-util-form-submit btn btn-block btn-warning btn-sm">Submit</a>
	
	<!-- loading (optional) -->
	<span class="sow-util-loader absolute-full z-index-1 bg-white opacity-3 d-middle hide">
		<i class="fi fi-orbit fi-spin fs--30"></i>
	</span>

</div>
											

Ajax Form : Live Monintor

Monitor any change and send data to the server via ajax.

<!--
	Two ways to monitor form changes using 
	`data-util-live-monitor-elements` attribute:

	--

	1. 	Monitor all elements inside form
		.js-ignore = a class useful to ignore/exclude specific elements
	data-util-live-monitor-elements="*" 
	

	2. 	Monitor only specific elements
	data-util-live-monitor-elements="#first_name, #select_options" 


	--

	User action delay (in milliseconds 1000 = 1s)
	data-util-live-monitor-user-delay="1000" 

	Append server response to container
	data-util-live-monitor-append-response="#container" 

-->
<form class="sow-util-form-live-monitor" 
		data-util-live-ajax-url="../demo.files/php/demo.ajax_request.php" 
		data-util-live-ajax-method="GET" 
		data-util-live-ajax-params="['param1','value1']['param2','value2']" 
		data-util-live-monitor="true" 
		data-util-live-monitor-elements="*" 
		data-util-live-monitor-append-response="" 
		data-util-live-monitor-user-delay="3000" 

		data-util-live-toast-msg="Data Saved" 
		data-util-live-toast-position="top-center" 
		data-util-live-toast-type="success" 
		data-util-live-toast-timeout="2500">
	
	<div class="form-label-group mb-3">
		<input type="text" placeholder="First Name" class="form-control" id="first_name" name="first_name" value="">
		<label for="first_name">First Name</label>
	</div>

	<div class="form-label-group mb-3">
		<select id="select_options" name="select_options" class="form-control bs-select">
			<option value="1">Option 1</option>
			<option value="2">Option 2</option>
			<option value="3">Option 3</option>
		</select>
		<label for="select_options">Select</label>
	</div>

	<label class="form-checkbox form-checkbox-primary">
		<input type="checkbox" name="checkbox" id="checkbox" checked>
		<i></i> <span>Checkbox</span>
	</label>

	<!-- submit -->
	<!-- <a href="#!" class="sow-util-form-submit btn btn-block btn-warning btn-sm">Submit</a> -->

</form>
											

Ajax : Live Container Reload

Reload containers by ajax on change/click/keyup




Lorem Ipsum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Ajax link inside ajax content
<!--

Each element should have: 
class: .sow-util-live-reload
param: data-util-live-reload-target="#reloadTargetContainer"

Supported elements: 
input, select, checkboxe, radio, textarea, link, button

Can be used together with
Ajax Form : Live Monintor
-->
<div class="form-label-group mb-3">
	<input type="text" placeholder="First Name" class="form-control sow-util-live-reload" name="first_name" value="" data-util-live-reload-target="#reloadTargetContainer">
	<label>First Name</label>
</div>

<label class="form-checkbox form-checkbox-primary">
	<input type="checkbox" name="checkbox" class="sow-util-live-reload" data-util-live-reload-target="#reloadTargetContainer">
	<i></i> <span>Checkbox</span>
</label>

<div class="form-label-group mb-3">
	<select id="select_options" name="select_options" class="form-control bs-select sow-util-live-reload" data-util-live-reload-target="#reloadTargetContainer">
		<option value="1">Option 1</option>
		<option value="2">Option 2</option>
		<option value="3">Option 3</option>
	</select>
	<label for="select_options">Select</label>
</div>

<!-- Container (ajax params) -->
<div id="reloadTargetContainer" 
	data-reload-ajax-url="_ajax/dummy_text.html" 
	data-reload-ajax-method="GET" 
	data-reload-ajax-params="['param1','value1']['param2','value2']" 
	data-reload-ajax-delay="500">

	<!-- content here -->

</div>