<!DOCTYPE html>
<html>

  <head>
    <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/themes/ui-darkness/jquery-ui.css" />
    <script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/jquery-ui.js"></script>
    <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <link rel="stylesheet" href="demo.css" />
    <script src="checkedUI.js"></script>
    <script src="script.js"></script>
  </head>

<body class="ui-widget">
	<h1>Pretty demo </h1>
	<div id="ThemeRoller"></div>
	<p>
		Just a quick demo of what checked-ui does, with a few common scenarios to make sure everything is hanging
		together correctly.
	</p>

	<fieldset>
		<legend>Checkbox Examples</legend>
 
		<!-- tables .. urg ... didn't they die out last century ;-) -->
		<table class="x-large">
			<thead>
				<tr>
					<th>Scenario</th>
					<th>prettyCheck</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>
						Initially check is <strong>off</strong>
					</td>
					<td>
						<label for="chkUI1">Check 1</label>					
						<input type="checkbox" class="prettyCheck" id="chkUI1" />
					</td>
				</tr>
				<tr>
					<td>
						Initially check is <strong>on</strong>
					</td>
					<td>
						<label for="chkUI2">Check 2</label>					
						<input type="checkbox" class="prettyCheck" id="chkUI2" checked="checked" />
					</td>
				</tr>
				<tr>
					<td>
						Initially check is <strong>on</strong> and <strong>disabled</strong>
					</td>
					<td>
						<label for="chkUI3">Check 3</label>					
						<input type="checkbox" class="prettyCheck" id="chkUI3" checked="checked" disabled="disabled" />
					</td>
				</tr>
				<tr>
					<td>
						Initially check is <strong>off</strong> and <strong>disabled</strong>
					</td>
					<td>
						<label for="chkUI4">Check 4</label>					
						<input type="checkbox" class="prettyCheck" id="chkUI4" disabled="disabled" />
					</td>
				</tr>
			</tbody>
		</table>
	</fieldset>

	<fieldset>
		<legend>Radiobutton Examples</legend>

		<!-- tables .. urg ... didn't they die out last century ;-) -->
		<table class="x-large">
			<col class="large" />
			<col class="small" />
			<thead>
				<tr>
					<th>Scenario</th>
					<th>Pretty Rad</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>
						Initially none active
					</td>
					<td>
						<label for="radUI2_Yes">Yes</label>
						<input class="prettyRad" type="radio" name="chkUI2" id="radUI2_Yes" value="Yes" />
						<label for="radUI2_No">No</label>  
						<input class="prettyRad" type="radio" name="chkUI2" id="radUI2_No" value="No" />
					</td>
				</tr>
				<tr>
					<td>
						Disabled
					</td>
					<td>
						<label for="radUI3_Yes">Yes</label>
						<input class="prettyRad" type="radio" name="chkUI3" id="radUI3_Yes" value="Yes" checked="checked" disabled="disabled" />
						<label for="radUI3_No">No</label>  
						<input class="prettyRad" type="radio" name="chkUI3" id="radUI3_No" value="No" disabled="disabled" />
					</td>
				</tr>
				<tr><td colspan="3"><hr /></td></tr>
				<tr>					
					<td>
						Not grouped (no <strong>name</strong> attribute)
					</td>
					<td>
						<label for="radUI1_Yes">Yes</label>
						<input class="prettyRad" type="radio" id="radUI1_Yes" value="Yes" />
						<label for="radUI1_No">No</label>  
						<input class="prettyRad" type="radio" id="radUI1_No" value="No" />
					</td>
				</tr>
				
			</tbody>
		</table>
	</fieldset>
  </body>

</html>
$(document).ready(function() {
  var debugMode = false;
  $("input:checkbox.prettyCheck").checkedUI({
    debug: debugMode
  });
  $("input:radio.prettyRad").checkedUI({
    debug: debugMode
  });
  $('#ThemeRoller').themeswitcher();
});

body {
	margin: 5%;
	font-size: 80% !important;
}

fieldset {
	margin-bottom: 1em;
}

h1 {
	font-size: x-large;
}

ul {
	list-style: none;
	margin-left: -1em;
}

th {
	text-align: left;
}

.x-large {
	width: 100%;
}

.small {
	width: 30%;
}

.large {
	width: 40%;
}


(function ($) {

	$.fn.checkedUI = function (settings) {
		this.version = "1.0.0";
		this.plugInName = "checkedUI";

		/// <summary>
		/// Set of overrides for configing how the plug-in works
		/// </summary>
		var config = {
			// Possible variations
			//   onChkClass              offChkClass
			//   "ui-icon-check"           "ui-icon-close"
			//   "ui-icon-circle-check"    "ui-icon-circle-close"
			//                             "ui-icon-closethick"
			//   onRadClass              offRadClass
			//   ui-icon-radio-on        ui-icon-radio-off
			//   ui-icon-bullet          
			//   
			onChkClass: "ui-icon-check",
			offChkClass: "ui-icon-closethick",
			onRadClass: "ui-icon-bullet",
			offRadClass: "ui-icon-radio-off"
		}; // config

		if (settings)
		// add overrides from default settings
			$.extend(config, settings);



		/// <summary>
		/// Builds up the HTML to surround the checkbox or radio button
		/// </summary>
		function getIconHtml(chk, opts) {
			// is the checkbox currently ticked and/or disabled? 
			var isChecked = chk.is(':checked');
			var isDisabled = chk.prop("disabled");

			// locals for referencing the correct initial class state
			var startIcon = (isChecked ? opts.onClass : opts.offClass);
			var startState = "";
			if (isDisabled) {
				// disabled appearance takes precendence over checked
				startState = "ui-state-disabled";
			} else {
				startState = (isChecked ? " ui-state-active " : "");
			}

			// build up the mark up for the pseudo icon
			// ... basically we have a surrounding "inline-block" span around the icon span so we can have the background icon appear
			var icoHtml = "<span class='ui-icon " + startIcon + "' />";
			var wrapper =
				"<span " +
					"class='ui-state-default " + startState + " ui-corner-all ui-button' " +
					"style='display: inline-block; margin-right: 5px;'>" +
				icoHtml + "</span>";

			return wrapper;

		}; // getIconHtml



		/// <summary>
		/// Kind of what it says on the tin ... takes the status of the control and amends the styling
		/// of the icon and container as appropriate
		/// </summary>
		function updateUI(chk, opts) {
			var isChecked = chk.prop("checked");
			var isDisabled = chk.prop("disabled");

			opts._icon
				.toggleClass(opts.onClass, isChecked)
				.toggleClass(opts.offClass, !isChecked)
			;
			opts._box
				.toggleClass("ui-state-active", (!isDisabled && isChecked))
				.toggleClass("ui-state-disabled", isDisabled);
			;

		}; // updateUI

		
		function hideElement(chk) {
			if (chk.prop("disabled")) {
				// For disabled elements, just hide the underlying control, as the 
				// z-index version doesn't look good.  Besides for disabled elements
				// you can't select it with the mouse OR keyboard anyway ...
				chk.addClass("ui-helper-hidden");
			} else {
				// We don't want to physically hide the checkbox/rad as we'll lose keyboard
				// access (you won't be able to hit "space" to toggle a checkbox for instance)
				// so we just disguise it by placing it directly under our pretty span
				chk
					.css("position", "relative")
					.css("left", "-25px")
					.css("z-index", "-1000")
				;
			}
		}; // hideElement


		/// <summary>
		/// Preps the checkbox/radio button as appropriate and wires up all events required to function
		/// </summary>
		function checkedUI(chk, opts) {
			var isRadio = chk.is(":radio");

			// wire up the correct icons to use
			opts.onClass = (isRadio ? config.onRadClass : config.onChkClass);
			opts.offClass = (isRadio ? config.offRadClass : config.offChkClass);

			// Build up the HTML to mimic the control
			var wrapper = getIconHtml(chk, opts);

			// Put the HTML just before the actual checkbox/radio button 
			// ... doesn't have to be before, could be after it's not required I just like it checkbox being afterwards :)
			chk.before(wrapper);

			// get a reference back to the inline-block span which allows the background-image to be visible
			opts._box = chk.prev();
			// ... and a reference to the icon itself (i.e. the jQuery UI "ui-icon" span)
			opts._icon = opts._box.find("span");

			if (!config.debug) {
				// hide the original checkbox (this will only exist behind the scenes)
				// ... this is configurable, purely to make future development easier
				hideElement(chk);
			}

			var changeSelector = chk;
			if (isRadio) {
				// The incoming control, "chk" only points to a single racio/checkbox.  This is fine for checkboxes which
				// run in isolation, but radio buttons can be grouped.  So changing the value of one radio button, will
				// actually un-select others in the group.  But we won't get a "change" event for them becuase our "chk" filter
				// is only looking at one of the radio buttons in the group.
				// To fix this expand the "change" selector to include all radio buttons in the group, that way we'll get 
				// [radio button] notifications for both select and de-select scenarios.
				// Not ideal to search teh full dom, but other than _guessing_ where they are in the hierarchy there's no a great
				// deal we can do.
				changeSelector = "input[name='" + chk.attr("name") + "']";
			}
			chk.add(changeSelector).change(function () {
				updateUI(chk, opts);
			});

			// hover behaviour, note this is against the container element
			opts._box.hover(
				function () {
					if (chk.prop("disabled"))
					// shouldn't have any indication on disabled elements
						return;
					opts._box.removeClass("ui-state-active");
					opts._box.addClass("ui-state-hover");
				},
				function () {
					opts._box.removeClass("ui-state-hover");
					updateUI(chk, opts);
				}
			);

			// ... and wire up when the user clicks on the container
			opts._box.click(
				function () {
					// change the appearance of the widget given the container has been clicked
					updateUI(chk, opts);
					// propagate the click through to the underlying checkbox 
					// ... the handles any other events that have latched onto the click event of the checkbox
					// ... and honours them
					chk.click();
				}
			);

		}; // checkedUI


		// iterate over in match in the selector
		this.each(function (index) {
			var options = {};
			var me = $(this);

			checkedUI(me, options);
		});

		// maintain chainability
		return this;
	};

})(jQuery);