text:
(function($) {

	function isOverAxis( x, reference, size ) {
		return ( x > reference ) && ( x < ( reference + size ) );
	}

	$.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {

		options: {
			doNotClear: false,
			expandOnHover: 700,
			isAllowed: function(placeholder, placeholderParent, originalItem) { return true; },
			isTree: false,
			listType: 'ol',
			maxLevels: 0,
			protectRoot: false,
			rootID: null,
			rtl: false,
			startCollapsed: false,
			tabSize: 20,

			branchClass: 'mjs-nestedSortable-branch',
			collapsedClass: 'mjs-nestedSortable-collapsed',
			disableNestingClass: 'mjs-nestedSortable-no-nesting',
			errorClass: 'mjs-nestedSortable-error',
			expandedClass: 'mjs-nestedSortable-expanded',
			hoveringClass: 'mjs-nestedSortable-hovering',
			leafClass: 'mjs-nestedSortable-leaf'
		},

		_create: function() {
			this.element.data('ui-sortable', this.element.data('mjs-nestedSortable'));

			// mjs - prevent browser from freezing if the HTML is not correct
			if (!this.element.is(this.options.listType))
				throw new Error('nestedSortable: Please check that the listType option is set to your actual list type');

			// mjs - force 'intersect' tolerance method if we have a tree with expanding/collapsing functionality
			if (this.options.isTree && this.options.expandOnHover) {
				this.options.tolerance = 'intersect';
			}

			$.ui.sortable.prototype._create.apply(this, arguments);

			// mjs - prepare the tree by applying the right classes (the CSS is responsible for actual hide/show functionality)
			if (this.options.isTree) {
				var self = this;
				$(this.items).each(function() {
					var $li = this.item;
					if ($li.children(self.options.listType).length) {
						$li.addClass(self.options.branchClass);
						// expand/collapse class only if they have children
						if (self.options.startCollapsed) $li.addClass(self.options.collapsedClass);
						else $li.addClass(self.options.expandedClass);
					} else {
						$li.addClass(self.options.leafClass);
					}
				})
			}
		},

		_destroy: function() {
			this.element
				.removeData("mjs-nestedSortable")
				.removeData("ui-sortable");
			return $.ui.sortable.prototype._destroy.apply(this, arguments);
		},

		_mouseDrag: function(event) {
			var i, item, itemElement, intersection,
				o = this.options,
				scrolled = false;

			//Compute the helpers position
			this.position = this._generatePosition(event);
			this.positionAbs = this._convertPositionTo("absolute");

			if (!this.lastPositionAbs) {
				this.lastPositionAbs = this.positionAbs;
			}

			//Do scrolling
			if(this.options.scroll) {
				if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {

					if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
					} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
					}

					if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
					} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
					}

				} else {

					if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
						scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
					} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
						scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
					}

					if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
						scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
					} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
						scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
					}

				}

				if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
					$.ui.ddmanager.prepareOffsets(this, event);
			}

			//Regenerate the absolute position used for position checks
			this.positionAbs = this._convertPositionTo("absolute");

			// mjs - find the top offset before rearrangement,
			var previousTopOffset = this.placeholder.offset().top;

			//Set the helper position
			if(!this.options.axis || this.options.axis !== "y") {
				this.helper[0].style.left = this.position.left+"px";
			}
			if(!this.options.axis || this.options.axis !== "x") {
				this.helper[0].style.top = this.position.top+"px";
			}

			// mjs - check and reset hovering state at each cycle
			this.hovering = this.hovering ? this.hovering : null;
			this.mouseentered = this.mouseentered ? this.mouseentered : false;

			// mjs - let's start caching some variables
			var parentItem = (this.placeholder[0].parentNode.parentNode &&
							 $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
				       			? $(this.placeholder[0].parentNode.parentNode)
				       			: null,
			    level = this._getLevel(this.placeholder),
			    childLevels = this._getChildLevels(this.helper);

			var newList = document.createElement(o.listType);

			//Rearrange
			for (i = this.items.length - 1; i >= 0; i--) {

				//Cache variables and intersection, continue if no intersection
				item = this.items[i];
				itemElement = item.item[0];
				intersection = this._intersectsWithPointer(item);
				if (!intersection) {
					continue;
				}

				// Only put the placeholder inside the current Container, skip all
				// items form other containers. This works because when moving
				// an item from one container to another the
				// currentContainer is switched before the placeholder is moved.
				//
				// Without this moving items in "sub-sortables" can cause the placeholder to jitter
				// beetween the outer and inner container.
				if (item.instance !== this.currentContainer) {
					continue;
				}

				// cannot intersect with itself
				// no useless actions that have been done before
				// no action if the item moved is the parent of the item checked
				if (itemElement !== this.currentItem[0] &&
					this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
					!$.contains(this.placeholder[0], itemElement) &&
					(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
				) {

					// mjs - we are intersecting an element: trigger the mouseenter event and store this state
					if (!this.mouseentered) {
						$(itemElement).mouseenter();
						this.mouseentered = true;
					}

					// mjs - if the element has children and they are hidden, show them after a delay (CSS responsible)
					if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) {
						if (!this.hovering) {
							$(itemElement).addClass(o.hoveringClass);
							var self = this;
							this.hovering = window.setTimeout(function() {
								$(itemElement).removeClass(o.collapsedClass).addClass(o.expandedClass);
								self.refreshPositions();
								self._trigger("expand", event, self._uiHash());
							}, o.expandOnHover);
						}
					}

					this.direction = intersection == 1 ? "down" : "up";

					// mjs - rearrange the elements and reset timeouts and hovering state
					if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
						$(itemElement).mouseleave();
						this.mouseentered = false;
						$(itemElement).removeClass(o.hoveringClass);
						this.hovering && window.clearTimeout(this.hovering);
						this.hovering = null;

						// mjs - do not switch container if it's a root item and 'protectRoot' is true
						// or if it's not a root item but we are trying to make it root
						if (o.protectRoot
							&& ! (this.currentItem[0].parentNode == this.element[0] // it's a root item
								  && itemElement.parentNode != this.element[0]) // it's intersecting a non-root item
						) {
							if (this.currentItem[0].parentNode != this.element[0]
							   	&& itemElement.parentNode == this.element[0]
							) {

								if ( ! $(itemElement).children(o.listType).length) {
									itemElement.appendChild(newList);
									o.isTree && $(itemElement).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
								}

								var a = this.direction === "down" ? $(itemElement).prev().children(o.listType) : $(itemElement).children(o.listType);
								if (a[0] !== undefined) {
									this._rearrange(event, null, a);
								}

							} else {
								this._rearrange(event, item);
							}
						} else if ( ! o.protectRoot) {
							this._rearrange(event, item);
						}
					} else {
						break;
					}

					// Clear emtpy ul's/ol's
					this._clearEmpty(itemElement);

					this._trigger("change", event, this._uiHash());
					break;
				}
			}

			// mjs - to find the previous sibling in the list, keep backtracking until we hit a valid list item.
			var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
			if (previousItem != null) {
				while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
					if (previousItem[0].previousSibling) {
						previousItem = $(previousItem[0].previousSibling);
					} else {
						previousItem = null;
						break;
					}
				}
			}

			// mjs - to find the next sibling in the list, keep stepping forward until we hit a valid list item.
			var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
			if (nextItem != null) {
				while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
					if (nextItem[0].nextSibling) {
						nextItem = $(nextItem[0].nextSibling);
					} else {
						nextItem = null;
						break;
					}
				}
			}

			this.beyondMaxLevels = 0;

			// mjs - if the item is moved to the left, send it one level up but only if it's at the bottom of the list
			if (parentItem != null
				&& nextItem == null
				&& ! (o.protectRoot && parentItem[0].parentNode == this.element[0])
				&&
					(o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth())
					 || ! o.rtl && (this.positionAbs.left < parentItem.offset().left))
			) {

				parentItem.after(this.placeholder[0]);
				if (o.isTree && parentItem.children(o.listItem).children('li:visible:not(.ui-sortable-helper)').length < 1) {
					parentItem.removeClass(this.options.branchClass + ' ' + this.options.expandedClass)
							  .addClass(this.options.leafClass);
				}
				this._clearEmpty(parentItem[0]);
				this._trigger("change", event, this._uiHash());
			}
			// mjs - if the item is below a sibling and is moved to the right, make it a child of that sibling
			else if (previousItem != null
					 && ! previousItem.hasClass(o.disableNestingClass)
					 &&
						(previousItem.children(o.listType).length && previousItem.children(o.listType).is(':visible')
						 || ! previousItem.children(o.listType).length)
					 && ! (o.protectRoot && this.currentItem[0].parentNode == this.element[0])
					 &&
						(o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize)
						 || ! o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))
			) {

				this._isAllowed(previousItem, level, level+childLevels+1);

				if (!previousItem.children(o.listType).length) {
					previousItem[0].appendChild(newList);
					o.isTree && previousItem.removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
				}

		        // mjs - if this item is being moved from the top, add it to the top of the list.
		        if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
		        	previousItem.children(o.listType).prepend(this.placeholder);
		        }
		        // mjs - otherwise, add it to the bottom of the list.
		        else {
					previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
				}

				this._trigger("change", event, this._uiHash());
			}
			else {
				this._isAllowed(parentItem, level, level+childLevels);
			}

			//Post events to containers
			this._contactContainers(event);

			//Interconnect with droppables
			if($.ui.ddmanager) {
				$.ui.ddmanager.drag(this, event);
			}

			//Call callbacks
			this._trigger('sort', event, this._uiHash());

			this.lastPositionAbs = this.positionAbs;
			return false;

		},

		_mouseStop: function(event, noPropagation) {

			// mjs - if the item is in a position not allowed, send it back
			if (this.beyondMaxLevels) {

				this.placeholder.removeClass(this.options.errorClass);

				if (this.domPosition.prev) {
					$(this.domPosition.prev).after(this.placeholder);
				} else {
					$(this.domPosition.parent).prepend(this.placeholder);
				}

				this._trigger("revert", event, this._uiHash());

			}

			// mjs - clear the hovering timeout, just to be sure
			$('.'+this.options.hoveringClass).mouseleave().removeClass(this.options.hoveringClass);
			this.mouseentered = false;
			this.hovering && window.clearTimeout(this.hovering);
			this.hovering = null;

			$.ui.sortable.prototype._mouseStop.apply(this, arguments);

		},

		// mjs - this function is slightly modified to make it easier to hover over a collapsed element and have it expand
		_intersectsWithSides: function(item) {

			var half = this.options.isTree ? .8 : .5;

			var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height*half), item.height),
				isOverTopHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top - (item.height*half), item.height),
				isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
				verticalDirection = this._getDragVerticalDirection(),
				horizontalDirection = this._getDragHorizontalDirection();

			if (this.floating && horizontalDirection) {
				return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
			} else {
				return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && isOverTopHalf));
			}

		},

		_contactContainers: function(event) {

			if (this.options.protectRoot && this.currentItem[0].parentNode == this.element[0] ) {
				return;
			}

			$.ui.sortable.prototype._contactContainers.apply(this, arguments);

		},

		_clear: function(event, noPropagation) {

			$.ui.sortable.prototype._clear.apply(this, arguments);

			// mjs - clean last empty ul/ol
			for (var i = this.items.length - 1; i >= 0; i--) {
				var item = this.items[i].item[0];
				this._clearEmpty(item);
			}

		},

		serialize: function(options) {

			var o = $.extend({}, this.options, options),
				items = this._getItemsAsjQuery(o && o.connected),
			    str = [];

			$(items).each(function() {
				var res = ($(o.item || this).attr(o.attribute || 'id') || '')
						.match(o.expression || (/(.+)[-=_](.+)/)),
				    pid = ($(o.item || this).parent(o.listType)
						.parent(o.items)
						.attr(o.attribute || 'id') || '')
						.match(o.expression || (/(.+)[-=_](.+)/));

				if (res) {
					str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
						+ '='
						+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
				}
			});

			if(!str.length && o.key) {
				str.push(o.key + '=');
			}

			return str.join('&');

		},

		toHierarchy: function(options) {

			var o = $.extend({}, this.options, options),
				sDepth = o.startDepthCount || 0,
			    ret = [];

			$(this.element).children(o.items).each(function () {
				var level = _recursiveItems(this);
				ret.push(level);
			});

			return ret;

			function _recursiveItems(item) {
				var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
				if (id) {
					var currentItem = {"id" : id[2]};
					if ($(item).children(o.listType).children(o.items).length > 0) {
						currentItem.children = [];
						$(item).children(o.listType).children(o.items).each(function() {
							var level = _recursiveItems(this);
							currentItem.children.push(level);
						});
					}
					return currentItem;
				}
			}
		},

		toArray: function(options) {

			var o = $.extend({}, this.options, options),
				sDepth = o.startDepthCount || 0,
			    ret = [],
			    left = 1;

			if (!o.excludeRoot) {
				ret.push({
					"item_id": o.rootID,
					"parent_id": null,
					"depth": sDepth,
					"left": left,
					"right": ($(o.items, this.element).length + 1) * 2
				});
				left++
			}

			$(this.element).children(o.items).each(function () {
				left = _recursiveArray(this, sDepth + 1, left);
			});

			ret = ret.sort(function(a,b){ return (a.left - b.left); });

			return ret;

			function _recursiveArray(item, depth, left) {

				var right = left + 1,
				    id,
				    pid;

				if ($(item).children(o.listType).children(o.items).length > 0) {
					depth ++;
					$(item).children(o.listType).children(o.items).each(function () {
						right = _recursiveArray($(this), depth, right);
					});
					depth --;
				}

				id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));

				if (depth === sDepth + 1) {
					pid = o.rootID;
				} else {
					var parentItem = ($(item).parent(o.listType)
											 .parent(o.items)
											 .attr(o.attribute || 'id'))
											 .match(o.expression || (/(.+)[-=_](.+)/));
					pid = parentItem[2];
				}

				if (id) {
						ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
				}

				left = right + 1;
				return left;
			}

		},

		_clearEmpty: function(item) {
			var o = this.options;

			var emptyList = $(item).children(o.listType);

			if (emptyList.length && !emptyList.children().length && !o.doNotClear) {
				o.isTree && $(item).removeClass(o.branchClass + ' ' + o.expandedClass).addClass(o.leafClass);
				emptyList.remove();
			} else if (o.isTree && emptyList.length && emptyList.children().length && emptyList.is(':visible')) {
				$(item).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
			} else if (o.isTree && emptyList.length && emptyList.children().length && !emptyList.is(':visible')) {
				$(item).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.collapsedClass);
			}

		},

		_getLevel: function(item) {

			var level = 1;

			if (this.options.listType) {
				var list = item.closest(this.options.listType);
				while (list && list.length > 0 &&
                    	!list.is('.ui-sortable')) {
					level++;
					list = list.parent().closest(this.options.listType);
				}
			}

			return level;
		},

		_getChildLevels: function(parent, depth) {
			var self = this,
			    o = this.options,
			    result = 0;
			depth = depth || 0;

			$(parent).children(o.listType).children(o.items).each(function (index, child) {
					result = Math.max(self._getChildLevels(child, depth + 1), result);
			});

			return depth ? result + 1 : result;
		},

		_isAllowed: function(parentItem, level, levels) {
			var o = this.options,
				maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list

			// mjs - is the root protected?
			// mjs - are we nesting too deep?
			if ( ! o.isAllowed(this.placeholder, parentItem, this.currentItem)) {
					this.placeholder.addClass(o.errorClass);
					if (maxLevels < levels && maxLevels != 0) {
						this.beyondMaxLevels = levels - maxLevels;
					} else {
						this.beyondMaxLevels = 1;
					}
			} else {
				if (maxLevels < levels && maxLevels != 0) {
					this.placeholder.addClass(o.errorClass);
					this.beyondMaxLevels = levels - maxLevels;
				} else {
					this.placeholder.removeClass(o.errorClass);
					this.beyondMaxLevels = 0;
				}
			}
		}

	}));

	$.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
})(jQuery);
/*********************************************************************************************
/**	* jQuery Sortable
* 	* @author	@mvdandrieux
**#******************************************************************************************/
$(function()
{
//	Zoom
	$('#section_tree').on('change', 'input[type="range"]', function()
	{
		console.log($(this).val());
		$('ol.tree').css('transform', 'scale('+$(this).val()+')');
	});

//	Expand
	$('ol.tree').on('click', '.expand', function()
	{
	//	Some vars
		$page = $(this).closest('.page');
		$children = $childrenContainer.find('li');

		$children.toggle('fast');
	});

//	Add new page
	$('ol.tree').on('click', '.add', function()
	{
	//	Some vars
		$page = $(this).closest('.page');
		$item = $(this).closest('[data-item]');
		$childrenContainer = $page.next('ol');

	//	And create a draft
		$.ajx(
		{
			app: 'content',
			template: '/master/workflow',
			mime:'json',
			item:'page',
			parent:$item.data('item'),
			status:'draft',
		}, {
		//	Done
			done:function(id)
			{
			//	Find & append the template
				template = $item.clone();
				template.data('item', '');
				template.find('.page').attr('data-type', 'new');
				template.attr('style', 'display:none');
				template.find('.action a').not('.edit').remove();
				template.find('.cc-badge').remove();
				template.find('.action a.edit').attr('href', 'edit?item=workflow&id='+id);
				template.find('ol').html('');
				template.find('.card').addClass('flipped');
				template.find('.add').remove('');
			//	Make some babies!
				$(template).appendTo($childrenContainer).show('fast');
			}
		});
	});

//	Revert on hover intent out
	$('.card').hoverIntent(
	{
		timeout: 500,
		over: function() {},
		out: function()
		{
			$(this).removeClass('flipped preview');
		}
	});

//	Preview
	$('ol.tree .action').on('click', '.preview', function()
	{
		$page = $(this).closest('.page');
		$card = $page.find('.card');
		$back = $card.find('.back');
		url = $page.data('url');

		$card.addClass('preview');
		$back.find('.preview iframe').attr('src', url);
	});

//	Asleep / live
	$('ol.tree .action').on('click', '.asleep, .live', function()
	{
	//	Some vars
		$item = $(this).closest('[data-item]');
		item = $item.data('item');
		$page = $item.find('.page');
	//	live = $page.data('live');/* #4.3 */
		status = $(this).attr('class');

	//	Change live status
		$.ajx(
		{
			app: 'content',
			template: '/master/live',
			mime:'json',
			item:item,
		//	live:live, /* #4.3 */
			status:status,
		}, {
		//	Done
			done:function(rep)
			{
			//	Change the display
			//	$page.attr('data-live', live).data('live', live); /* #4.3 */
				$page.attr('data-status', status).data('status', status);

			//	Asleep? Put all kids asleep as well
				if (status == 'false')
				{
				//	$item.find('[data-item]').each(function()
				//	{
				//		$(this).find('.asleep').click();
				//	});
				}

			}
		});
	});

/*********************************************************************************************
/**	* Focus on search engine
 	* @author	@mvdandrieux
**#******************************************************************************************/
	$('#refine input').focus();

/*********************************************************************************************
/**	* Site tree
* 	* @author	@mvdandrieux
**#******************************************************************************************/
//	Start nested sortable
	$(document).bind('unlock', function()
	{
	//	Kill draggable slick
		$('#sectiontray').slick("slickSetOption", "draggable", false, false);

	//	Make sortable
		$('ol.tree').nestedSortable(
		{
			handle: '.card',
			items: '> li li[data-item]',
            toleranceElement: '> .node',
			protectRoot:true,
			tabSize:600,

		//	On start
			start: function()
			{
			//	Show trash
				$('#trashbin').data('trashbin').show();
			//	Collapse

			},

		//	On stop
			stop: function()
			{
			//	Hide trash
				$('#trashbin').data('trashbin').hide();
			//	re-expand

			},

		});
	});

//	Save the current sitetree
	$(document).bind('lock', function()
	{
	//	Back to draggable
		$('#sectiontray').slick("slickSetOption", "draggable", true, true);

	//	Get the order
		pages = $('#section_tree ol.tree').find('li[data-item]');
		tree = new Object();
	//	Loop through the pages
		pages.each(function(i)
		{
		//	Kill the new pages that have not been created
			if ($(this).find('.page').data('type') == 'new') $(this).remove();
		//	Save the position of the other pages
			else
			{
			//	Get the nickname and the children
				item = $(this).data('item');
				children = new Array();
				$(this).find('>.node>ol>li[data-item]').each(function()
				{
					children.push($(this).data('item'));
				});
			//	Store the data
				tree[i] = {item:item, children:children}
			}
		});
	//	Send the new order to ajax
		$.ajx(
		{
			app:'content',
			template:'tree/order.routine',
			tree:tree,
		});
	});

});
/*
 * jQuery scrollsync Plugin
 * version: 1.0 (30 -Jun-2009)
 * Copyright (c) 2009 Miquel Herrera
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */
;(function($){ // secure $ jQuery alias

/**
 * Synchronizes scroll of one element (first matching targetSelector filter)
 * with all the rest meaning that the rest of elements scroll will follow the
 * matched one.
 *
 * options is composed of the following properties:
 *	------------------------------------------------------------------------
 *	targetSelector	| A jQuery selector applied to filter. The first element of
 *					| the resulting set will be the target all the rest scrolls
 *					| will be synchronised against. Defaults to ':first' which
 *					| selects the first element in the set.
 *	------------------------------------------------------------------------
 *	axis			| sets the scroll axis which will be synchronised, can be
 *					| x, y or xy. Defaults to xy which will synchronise both.
 *	------------------------------------------------------------------------
 */
$.fn.scrollsync = function( options ){
	var settings = $.extend(
			{
				targetSelector:':first',
				axis: 'xy'
			},options || {});

	function scrollHandler(event) {
		if (event.data.xaxis){
			event.data.followers.scrollLeft(event.data.target.scrollLeft());
		}
		if (event.data.yaxis){
			event.data.followers.scrollTop(event.data.target.scrollTop());
		}
	}

	// Find target to follow and separate from followers
	settings.target = this.filter(settings.targetSelector).filter(':first');
	settings.followers=this.not(settings.target); // the rest of elements

	// Parse axis
	settings.xaxis= (settings.axis=='xy' || settings.axis=='x') ? true : false;
	settings.yaxis= (settings.axis=='xy' || settings.axis=='y') ? true : false;
	if (!settings.xaxis && !settings.yaxis) return;  // No axis left

	// bind scroll event passing array of followers
	settings.target.bind('scroll', settings, scrollHandler);

}; // end plugin scrollsync

})( jQuery ); // confine scope

/*
 * jQuery dragscrollable Plugin
 * version: 1.0 (25-Jun-2009)
 * Copyright (c) 2009 Miquel Herrera
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */
;(function($){ // secure $ jQuery alias

/**
 * Adds the ability to manage elements scroll by dragging
 * one or more of its descendant elements. Options parameter
 * allow to specifically select which inner elements will
 * respond to the drag events.
 *
 * options properties:
 * ------------------------------------------------------------------------
 *  dragSelector         | jquery selector to apply to each wrapped element
 *                       | to find which will be the dragging elements.
 *                       | Defaults to '>:first' which is the first child of
 *                       | scrollable element
 * ------------------------------------------------------------------------
 *  acceptPropagatedEvent| Will the dragging element accept propagated
 *	                     | events? default is yes, a propagated mouse event
 *	                     | on a inner element will be accepted and processed.
 *	                     | If set to false, only events originated on the
 *	                     | draggable elements will be processed.
 * ------------------------------------------------------------------------
 *  preventDefault       | Prevents the event to propagate further effectivey
 *                       | dissabling other default actions. Defaults to true
 * ------------------------------------------------------------------------
 *
 *  usage examples:
 *
 *  To add the scroll by drag to the element id=viewport when dragging its
 *  first child accepting any propagated events
 *	$('#viewport').dragscrollable();
 *
 *  To add the scroll by drag ability to any element div of class viewport
 *  when dragging its first descendant of class dragMe responding only to
 *  evcents originated on the '.dragMe' elements.
 *	$('div.viewport').dragscrollable({dragSelector:'.dragMe:first',
 *									  acceptPropagatedEvent: false});
 *
 *  Notice that some 'viewports' could be nested within others but events
 *  would not interfere as acceptPropagatedEvent is set to false.
 *
 */
$.fn.dragscrollable = function( options ){

	var settings = $.extend(
		{
			dragSelector:'>:first',
			acceptPropagatedEvent: true,
            preventDefault: true
		},options || {});

	var dragscroll =
	{
		mouseDownHandler : function(event)
		{
			// mousedown, left click, check propagation
			if (event.which!=1 ||
				(!event.data.acceptPropagatedEvent && event.target != this)){
				return false;
			}

			// Initial coordinates will be the last when dragging
			event.data.lastCoord = {left: event.clientX, top: event.clientY};

			$.event.add( document, "mouseup",
						 dragscroll.mouseUpHandler, event.data );
			$.event.add( document, "mousemove",
						 dragscroll.mouseMoveHandler, event.data );
			if (event.data.preventDefault) {
                event.preventDefault();
                return false;
            }
		},
	 // User is dragging
		mouseMoveHandler : function(event)
		{
		//	Grabbing
			$('ol.tree').addClass('grabbing');
			// How much did the mouse move?
			var delta = {left: (event.clientX - event.data.lastCoord.left),
						 top: (event.clientY - event.data.lastCoord.top)};

			// Set the scroll position relative to what ever the scroll is now
			event.data.scrollable.scrollLeft(
							event.data.scrollable.scrollLeft() - delta.left);
			event.data.scrollable.scrollTop(
							event.data.scrollable.scrollTop() - delta.top);

			// Save where the cursor is
			event.data.lastCoord={left: event.clientX, top: event.clientY}
			if (event.data.preventDefault) {
                event.preventDefault();
                return false;
            }

		},
	 // Stop scrolling
		mouseUpHandler : function(event)
		{
		//	Grabbing
			$('ol.tree').removeClass('grabbing');
			$.event.remove( document, "mousemove", dragscroll.mouseMoveHandler);
			$.event.remove( document, "mouseup", dragscroll.mouseUpHandler);
			if (event.data.preventDefault) {
                event.preventDefault();
                return false;
            }
		}
	}

	// set up the initial events
	this.each(function()
	{
		// closure object data for each scrollable element
		var data = {scrollable : $(this),
					acceptPropagatedEvent : settings.acceptPropagatedEvent,
                    preventDefault : settings.preventDefault }
		// Set mouse initiating event on the desired descendant
		$(this).find(settings.dragSelector).
						bind('mousedown', data, dragscroll.mouseDownHandler);
	});
}; //end plugin dragscrollable

})( jQuery ); // confine scope

$(function() {

	// Set header viewport to follow viewport scroll on x axis
//	$('#viewport, #header_viewport').
//		scrollsync({targetSelector: '#viewport', axis : 'x'});

	// Set drag scroll on first descendant of class dragger on both selected elements
//	$('section#section_tree').dragscrollable({dragSelector: 'ol.tree'});

  });


text:
import os
import sys
sys.path.insert(0, os.path.realpath(os.path.join(__file__, '../../')))
for p in os.environ.get('PYTHONPATH', '').split(';'):
    sys.path.append(p)

from asserts import *
from ckstyle.browsers.BinaryRule import *
from ckstyle.browsers.Hacks import *

redpajama_set_name: RedPajamaGithub


text:
id: 587d778c367417b2b2512aa9
title: Standardize Times with the HTML5 datetime Attribute
challengeType: 0
videoUrl: 'https://scrimba.com/c/cmzMgtz'
forumTopicId: 301025
localeTitle: 使用 HTML5 的 datatime 属性标准化时间
---

## Description

继续日期主题。HTML5 还引入了time标签与datetime属性来标准化时间。time是一个行内标签,用于在页面中呈现日期或时间,而datetime属性保存了日期的有效格式,辅助设备可以访问这个值。通过标准化时间格式,即使时间在文本中是以非正式的或口语化的形式编写,辅助设备依然可以获取准确的时间和日期。
举个例子:
<p>Master Camper Cat officiated the cage match between Goro and Scorpion <time datetime="2013-02-13">last Wednesday</time>, which ended in a draw.</p>

## Instructions

Camper Cat 的比武大会的时间确定了!请使用time标签包含文本 "Thursday, September 15<sup>th</sup>",并将datetime属性设置为 "2016-09-15"。

## Tests

```yml
tests:
  - text: '<code>time</code>标签应该包含文本"Thursday, September 15<sup>th</sup>"。'
    testString: assert(timeElement.length);
  - text: '<code>time</code>标签应该有 1 个非空的<code>datetime</code>属性。'
    testString: assert(timeElement.length && $(timeElement).html().trim() === "Thursday, September 15<sup>th</sup>");
  - text: '<code>datetime</code>属性的值应该为 2016-09-15。'
    testString: assert(datetimeAttr && datetimeAttr.length);
  - text: '确保<code>time</code>标签是闭合的。'
    testString: assert(datetimeAttr === "2016-09-15");
```

## Challenge Seed

```html
<body>
  <header>
    <h1>Tournaments</h1>
  </header>
  <article>
    <h2>Mortal Kombat Tournament Survey Results</h2>

    <!-- Add your code below this line -->

    <p>Thank you to everyone for responding to Master Camper Cat's survey. The best day to host the vaunted Mortal Kombat tournament is Thursday, September 15<sup>th</sup>. May the best ninja win!</p>

    <!-- Add your code above this line -->

    <section>
      <h3>Comments:</h3>
      <article>
        <p>Posted by: Sub-Zero on <time datetime="2016-08-13T20:01Z">August 13<sup>th</sup></time></p>
        <p>Johnny Cage better be there, I'll finish him!</p>
      </article>
      <article>
        <p>Posted by: Doge on <time datetime="2016-08-15T08:12Z">August 15<sup>th</sup></time></p>
        <p>Wow, much combat, so mortal.</p>
      </article>
      <article>
        <p>Posted by: The Grim Reaper on <time datetime="2016-08-16T00:00Z">August 16<sup>th</sup></time></p>
        <p>Looks like I'll be busy that day.</p>
      </article>
    </section>
  </article>
  <footer>© 2018 Camper Cat</footer>
</body>
```

```html
<script>
const pElement = $("article > p")
  .filter((_, elem) => $(elem).text().includes("Thank you to everyone for responding to Master Camper Cat's survey."));
const timeElement = pElement[0] ? $(pElement[0]).find("time") : null;
const datetimeAttr = $(timeElement).attr("datetime");
</script>
```

## Solution

```html
// solution required
```


text:
package org.keycloak.authentication;

import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.ClientConnection;
import org.keycloak.OAuth2Constants;
import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
import org.keycloak.authentication.authenticators.client.ClientAuthUtil;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.login.LoginFormsProvider;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.BruteForceProtector;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.LoginActionsService;
import org.keycloak.util.Time;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Bill Burke
 * @version $Revision: 1 $
 */
public class AuthenticationProcessor {
    public static final String CURRENT_AUTHENTICATION_EXECUTION = "current.authentication.execution";
    protected static Logger logger = Logger.getLogger(AuthenticationProcessor.class);
    protected RealmModel realm;
    protected UserSessionModel userSession;
    protected ClientSessionModel clientSession;
    protected ClientConnection connection;
    protected UriInfo uriInfo;
    protected KeycloakSession session;
    protected BruteForceProtector protector;
    protected EventBuilder event;
    protected HttpRequest request;
    protected String flowId;
    protected String flowPath;
    /**
     * This could be an error message forwarded from another authenticator
     */
    protected FormMessage forwardedErrorMessage;

    /**
     * This could be an success message forwarded from another authenticator
     */
    protected FormMessage forwardedSuccessMessage;
    protected boolean userSessionCreated;

    // Used for client authentication
    protected ClientModel client;
    protected Map<String, String> clientAuthAttributes = new HashMap<>();

    public AuthenticationProcessor() {
    }

    public RealmModel getRealm() {
        return realm;
    }

    public ClientModel getClient() {
        return client;
    }

    public void setClient(ClientModel client) {
        this.client = client;
    }

    public Map<String, String> getClientAuthAttributes() {
        return clientAuthAttributes;
    }

    public ClientSessionModel getClientSession() {
        return clientSession;
    }

    public ClientConnection getConnection() {
        return connection;
    }

    public UriInfo getUriInfo() {
        return uriInfo;
    }

    public KeycloakSession getSession() {
        return session;
    }

    public UserSessionModel getUserSession() {
        return userSession;
    }

    public boolean isUserSessionCreated() {
        return userSessionCreated;
    }

    public AuthenticationProcessor setRealm(RealmModel realm) {
        this.realm = realm;
        return this;
    }

    public AuthenticationProcessor setClientSession(ClientSessionModel clientSession) {
        this.clientSession = clientSession;
        return this;
    }

    public AuthenticationProcessor setConnection(ClientConnection connection) {
        this.connection = connection;
        return this;
    }

    public AuthenticationProcessor setUriInfo(UriInfo uriInfo) {
        this.uriInfo = uriInfo;
        return this;
    }

    public AuthenticationProcessor setSession(KeycloakSession session) {
        this.session = session;
        return this;
    }

    public AuthenticationProcessor setProtector(BruteForceProtector protector) {
        this.protector = protector;
        return this;
    }

    public AuthenticationProcessor setEventBuilder(EventBuilder eventBuilder) {
        this.event = eventBuilder;
        return this;
    }

    public AuthenticationProcessor setRequest(HttpRequest request) {
        this.request = request;
        return this;
    }

    public AuthenticationProcessor setFlowId(String flowId) {
        this.flowId = flowId;
        return this;
    }

    /**
     * This is the path segment to append when generating an action URL.
     *
     * @param flowPath
     */
    public AuthenticationProcessor setFlowPath(String flowPath) {
        this.flowPath = flowPath;
        return this;
    }

    public AuthenticationProcessor setForwardedErrorMessage(FormMessage forwardedErrorMessage) {
        this.forwardedErrorMessage = forwardedErrorMessage;
        return this;
    }

    public AuthenticationProcessor setForwardedSuccessMessage(FormMessage forwardedSuccessMessage) {
        this.forwardedSuccessMessage = forwardedSuccessMessage;
        return this;
    }

    public String generateCode() {
        ClientSessionCode accessCode = new ClientSessionCode(getRealm(), getClientSession());
        clientSession.setTimestamp(Time.currentTime());
        return accessCode.getCode();
    }

    public EventBuilder newEvent() {
        this.event = new EventBuilder(realm, session, connection);
        return this.event;
    }

    public EventBuilder getEvent() {
        return event;
    }

    public HttpRequest getRequest() {
        return request;
    }

    public void setAutheticatedUser(UserModel user) {
        UserModel previousUser = clientSession.getAuthenticatedUser();
        if (previousUser != null && !user.getId().equals(previousUser.getId()))
            throw new AuthenticationFlowException(AuthenticationFlowError.USER_CONFLICT);
        validateUser(user);
        getClientSession().setAuthenticatedUser(user);
    }

    public class Result implements AuthenticationFlowContext, ClientAuthenticationFlowContext {
        AuthenticatorConfigModel authenticatorConfig;
        AuthenticationExecutionModel execution;
        Authenticator authenticator;
        FlowStatus status;
        ClientAuthenticator clientAuthenticator;
        Response challenge;
        AuthenticationFlowError error;
        List<AuthenticationExecutionModel> currentExecutions;
        FormMessage errorMessage;
        FormMessage successMessage;

        private Result(AuthenticationExecutionModel execution, Authenticator authenticator, List<AuthenticationExecutionModel> currentExecutions) {
            this.execution = execution;
            this.authenticator = authenticator;
            this.currentExecutions = currentExecutions;
        }

        private Result(AuthenticationExecutionModel execution, ClientAuthenticator clientAuthenticator, List<AuthenticationExecutionModel> currentExecutions) {
            this.execution = execution;
            this.clientAuthenticator = clientAuthenticator;
            this.currentExecutions = currentExecutions;
        }

        @Override
        public EventBuilder newEvent() {
            return AuthenticationProcessor.this.newEvent();
        }

        @Override
        public AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory) {
            List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(execution.getParentFlow());
            for (AuthenticationExecutionModel exe : executions) {
                AuthenticatorFactory factory = (AuthenticatorFactory) getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, exe.getAuthenticator());
                if (factory != null && factory.getReferenceCategory().equals(authenticatorCategory)) {
                    return exe.getRequirement();
                }

            }
            return null;
        }

        @Override
        public AuthenticationExecutionModel getExecution() {
            return execution;
        }

        @Override
        public AuthenticatorConfigModel getAuthenticatorConfig() {
            if (execution.getAuthenticatorConfig() == null) return null;
            if (authenticatorConfig != null) return authenticatorConfig;
            authenticatorConfig = realm.getAuthenticatorConfigById(execution.getAuthenticatorConfig());
            return authenticatorConfig;
        }

        public Authenticator getAuthenticator() {
            return authenticator;
        }

        @Override
        public FlowStatus getStatus() {
            return status;
        }

        public ClientAuthenticator getClientAuthenticator() {
            return clientAuthenticator;
        }

        @Override
        public void success() {
            this.status = FlowStatus.SUCCESS;
        }

        @Override
        public void failure(AuthenticationFlowError error) {
            status = FlowStatus.FAILED;
            this.error = error;

        }

        @Override
        public void challenge(Response challenge) {
            this.status = FlowStatus.CHALLENGE;
            this.challenge = challenge;

        }

        @Override
        public void forceChallenge(Response challenge) {
            this.status = FlowStatus.FORCE_CHALLENGE;
            this.challenge = challenge;

        }

        @Override
        public void failureChallenge(AuthenticationFlowError error, Response challenge) {
            this.error = error;
            this.status = FlowStatus.FAILURE_CHALLENGE;
            this.challenge = challenge;

        }

        @Override
        public void failure(AuthenticationFlowError error, Response challenge) {
            this.error = error;
            this.status = FlowStatus.FAILED;
            this.challenge = challenge;

        }

        @Override
        public void attempted() {
            this.status = FlowStatus.ATTEMPTED;

        }

        @Override
        public UserModel getUser() {
            return getClientSession().getAuthenticatedUser();
        }

        @Override
        public void setUser(UserModel user) {
            setAutheticatedUser(user);
        }

        @Override
        public RealmModel getRealm() {
            return AuthenticationProcessor.this.getRealm();
        }

        @Override
        public ClientModel getClient() {
            return AuthenticationProcessor.this.getClient();
        }

        @Override
        public void setClient(ClientModel client) {
            AuthenticationProcessor.this.setClient(client);
        }

        @Override
        public Map<String, String> getClientAuthAttributes() {
            return AuthenticationProcessor.this.getClientAuthAttributes();
        }

        @Override
        public ClientSessionModel getClientSession() {
            return AuthenticationProcessor.this.getClientSession();
        }

        @Override
        public ClientConnection getConnection() {
            return AuthenticationProcessor.this.getConnection();
        }

        @Override
        public UriInfo getUriInfo() {
            return AuthenticationProcessor.this.getUriInfo();
        }

        @Override
        public KeycloakSession getSession() {
            return AuthenticationProcessor.this.getSession();
        }

        @Override
        public HttpRequest getHttpRequest() {
            return AuthenticationProcessor.this.request;
        }

        @Override
        public void attachUserSession(UserSessionModel userSession) {
            AuthenticationProcessor.this.userSession = userSession;
        }

        @Override
        public BruteForceProtector getProtector() {
            return AuthenticationProcessor.this.protector;
        }

        @Override
        public EventBuilder getEvent() {
            return AuthenticationProcessor.this.event;
        }

        @Override
        public FormMessage getForwardedErrorMessage() {
            return AuthenticationProcessor.this.forwardedErrorMessage;
        }

        @Override
        public String generateAccessCode() {
            return generateCode();
        }

        public Response getChallenge() {
            return challenge;
        }

        @Override
        public AuthenticationFlowError getError() {
            return error;
        }

        @Override
        public LoginFormsProvider form() {
            String accessCode = generateAccessCode();
            URI action = getActionUrl(accessCode);
            LoginFormsProvider provider = getSession().getProvider(LoginFormsProvider.class)
                    .setUser(getUser())
                    .setActionUri(action)
                    .setClientSessionCode(accessCode);
            if (getForwardedErrorMessage() != null) {
                provider.addError(getForwardedErrorMessage());
            } else if (getForwardedSuccessMessage() != null) {
                provider.addSuccess(getForwardedSuccessMessage());
            }
            return provider;
        }

        @Override
        public URI getActionUrl(String code) {
            return LoginActionsService.loginActionsBaseUrl(getUriInfo())
                    .path(AuthenticationProcessor.this.flowPath)
                    .queryParam(OAuth2Constants.CODE, code)
                    .queryParam("execution", getExecution().getId())
                    .build(getRealm().getName());
        }

        @Override
        public URI getActionUrl() {
            return getActionUrl(generateAccessCode());
        }

        @Override
        public void cancelLogin() {
            getEvent().error(Errors.REJECTED_BY_USER);
            LoginProtocol protocol = getSession().getProvider(LoginProtocol.class, getClientSession().getAuthMethod());
            protocol.setRealm(getRealm())
                    .setHttpHeaders(getHttpRequest().getHttpHeaders())
                    .setUriInfo(getUriInfo());
            Response response = protocol.cancelLogin(getClientSession());
            forceChallenge(response);
        }

        @Override
        public void fork() {
            this.status = FlowStatus.FORK;
        }

        @Override
        public void forkWithSuccessMessage(FormMessage message) {
            this.status = FlowStatus.FORK;
            this.successMessage = message;

        }

        @Override
        public void forkWithErrorMessage(FormMessage message) {
            this.status = FlowStatus.FORK;
            this.errorMessage = message;

        }

        @Override
        public FormMessage getForwardedSuccessMessage() {
            return AuthenticationProcessor.this.forwardedSuccessMessage;
        }

        public FormMessage getErrorMessage() {
            return errorMessage;
        }

        public FormMessage getSuccessMessage() {
            return successMessage;
        }
    }

    public void logFailure() {
        if (realm.isBruteForceProtected()) {
            String username = clientSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
            // todo need to handle non form failures
            if (username == null) {

            } else {
                protector.failedLogin(realm, username, connection);

            }
        }
    }

    public boolean isSuccessful(AuthenticationExecutionModel model) {
        ClientSessionModel.ExecutionStatus status = clientSession.getExecutionStatus().get(model.getId());
        if (status == null) return false;
        return status == ClientSessionModel.ExecutionStatus.SUCCESS;
    }

    public Response handleBrowserException(Exception failure) {
        if (failure instanceof AuthenticationFlowException) {
            AuthenticationFlowException e = (AuthenticationFlowException) failure;
            if (e.getError() == AuthenticationFlowError.INVALID_USER) {
                logger.error("failed authentication: " + e.getError().toString(), e);
                event.error(Errors.USER_NOT_FOUND);
                return ErrorPage.error(session, Messages.INVALID_USER);
            } else if (e.getError() == AuthenticationFlowError.USER_DISABLED) {
                logger.error("failed authentication: " + e.getError().toString(), e);
                event.error(Errors.USER_DISABLED);
                return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
            } else if (e.getError() == AuthenticationFlowError.USER_TEMPORARILY_DISABLED) {
                logger.error("failed authentication: " + e.getError().toString(), e);
                event.error(Errors.USER_TEMPORARILY_DISABLED);
                return ErrorPage.error(session, Messages.ACCOUNT_TEMPORARILY_DISABLED);

            } else if (e.getError() == AuthenticationFlowError.INVALID_CLIENT_SESSION) {
                logger.error("failed authentication: " + e.getError().toString(), e);
                event.error(Errors.INVALID_CODE);
                return ErrorPage.error(session, Messages.INVALID_CODE);

            } else if (e.getError() == AuthenticationFlowError.EXPIRED_CODE) {
                logger.error("failed authentication: " + e.getError().toString(), e);
                event.error(Errors.EXPIRED_CODE);
                return ErrorPage.error(session, Messages.EXPIRED_CODE);

            } else if (e.getError() == AuthenticationFlowError.FORK_FLOW) {
                ForkFlowException reset = (ForkFlowException)e;
                ClientSessionModel clone = clone(session, clientSession);
                clone.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
                AuthenticationProcessor processor = new AuthenticationProcessor();
                processor.setClientSession(clone)
                        .setFlowPath(LoginActionsService.AUTHENTICATE_PATH)
                        .setFlowId(realm.getBrowserFlow().getId())
                        .setForwardedErrorMessage(reset.getErrorMessage())
                        .setForwardedSuccessMessage(reset.getSuccessMessage())
                        .setConnection(connection)
                        .setEventBuilder(event)
                        .setProtector(protector)
                        .setRealm(realm)
                        .setSession(session)
                        .setUriInfo(uriInfo)
                        .setRequest(request);
                return processor.authenticate();

            } else {
                logger.error("failed authentication: " + e.getError().toString(), e);
                event.error(Errors.INVALID_USER_CREDENTIALS);
                return ErrorPage.error(session, Messages.INVALID_USER);
            }

        } else {
            logger.error("failed authentication", failure);
            event.error(Errors.INVALID_USER_CREDENTIALS);
            return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
        }

    }

    public Response handleClientAuthException(Exception failure) {
        if (failure instanceof AuthenticationFlowException) {
            AuthenticationFlowException e = (AuthenticationFlowException) failure;
            logger.error("Failed client authentication: " + e.getError().toString(), e);
            if (e.getError() == AuthenticationFlowError.CLIENT_NOT_FOUND) {
                event.error(Errors.CLIENT_NOT_FOUND);
                return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "Could not find client");
            } else if (e.getError() == AuthenticationFlowError.CLIENT_DISABLED) {
                event.error(Errors.CLIENT_DISABLED);
                return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "Client is not enabled");
            } else if (e.getError() == AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED) {
                event.error(Errors.INVALID_CLIENT_CREDENTIALS);
                return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", e.getMessage());
            } else {
                event.error(Errors.INVALID_CLIENT_CREDENTIALS);
                return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", e.getError().toString() + ": " + e.getMessage());
            }
        } else {
            logger.error("Unexpected error when authenticating client", failure);
            event.error(Errors.INVALID_CLIENT_CREDENTIALS);
            return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unexpected error when authenticating client: " + failure.getMessage());
        }
    }

    public AuthenticationFlow createFlowExecution(String flowId, AuthenticationExecutionModel execution) {
        AuthenticationFlowModel flow = realm.getAuthenticationFlowById(flowId);
        if (flow == null) {
            logger.error("Unknown flow to execute with");
            throw new AuthenticationFlowException(AuthenticationFlowError.INTERNAL_ERROR);
        }
        if (flow.getProviderId() == null || flow.getProviderId().equals(AuthenticationFlow.BASIC_FLOW)) {
            DefaultAuthenticationFlow flowExecution = new DefaultAuthenticationFlow(this, flow);
            return flowExecution;

        } else if (flow.getProviderId().equals(AuthenticationFlow.FORM_FLOW)) {
            FormAuthenticationFlow flowExecution = new FormAuthenticationFlow(this, execution);
            return flowExecution;
        } else if (flow.getProviderId().equals(AuthenticationFlow.CLIENT_FLOW)) {
            ClientAuthenticationFlow flowExecution = new ClientAuthenticationFlow(this, flow);
            return flowExecution;
        }
        throw new AuthenticationFlowException("Unknown flow provider type", AuthenticationFlowError.INTERNAL_ERROR);
    }

    public Response authenticate() throws AuthenticationFlowException {
        checkClientSession();
        logger.debug("AUTHENTICATE");
        event.client(clientSession.getClient().getClientId())
                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
        String authType = clientSession.getNote(Details.AUTH_TYPE);
        if (authType != null) {
            event.detail(Details.AUTH_TYPE, authType);
        }
        UserModel authUser = clientSession.getAuthenticatedUser();
        validateUser(authUser);
        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
        Response challenge = authenticationFlow.processFlow();
        if (challenge != null) return challenge;
        if (clientSession.getAuthenticatedUser() == null) {
            throw new AuthenticationFlowException(AuthenticationFlowError.UNKNOWN_USER);
        }
        return authenticationComplete();
    }

    public Response authenticateClient() throws AuthenticationFlowException {
        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
        try {
            Response challenge = authenticationFlow.processFlow();
            return challenge;
        } catch (Exception e) {
            return handleClientAuthException(e);
        }
    }

    public static void resetFlow(ClientSessionModel clientSession) {
        clientSession.setTimestamp(Time.currentTime());
        clientSession.setAuthenticatedUser(null);
        clientSession.clearExecutionStatus();
        clientSession.clearUserSessionNotes();
        clientSession.removeNote(CURRENT_AUTHENTICATION_EXECUTION);
    }

    public static ClientSessionModel clone(KeycloakSession session, ClientSessionModel clientSession) {
        ClientSessionModel clone = session.sessions().createClientSession(clientSession.getRealm(), clientSession.getClient());
        for (Map.Entry<String, String> entry : clientSession.getNotes().entrySet()) {
            clone.setNote(entry.getKey(), entry.getValue());
        }
        clone.setRedirectUri(clientSession.getRedirectUri());
        clone.setAuthMethod(clientSession.getAuthMethod());
        clone.setTimestamp(Time.currentTime());
        clone.removeNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
        return clone;

    }

    public Response authenticationAction(String execution) {
        checkClientSession();
        String current = clientSession.getNote(CURRENT_AUTHENTICATION_EXECUTION);
        if (!execution.equals(current)) {
            logger.debug("Current execution does not equal executed execution.  Might be a page refresh");
            logFailure();
            resetFlow(clientSession);
            return authenticate();
        }
        UserModel authUser = clientSession.getAuthenticatedUser();
        validateUser(authUser);
        AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
        if (model == null) {
            logger.debug("Cannot find execution, reseting flow");
            logFailure();
            resetFlow(clientSession);
            return authenticate();
        }
        event.client(clientSession.getClient().getClientId())
                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
        String authType = clientSession.getNote(Details.AUTH_TYPE);
        if (authType != null) {
            event.detail(Details.AUTH_TYPE, authType);
        }

        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, model);
        Response challenge = authenticationFlow.processAction(execution);
        if (challenge != null) return challenge;
        if (clientSession.getAuthenticatedUser() == null) {
            throw new AuthenticationFlowException(AuthenticationFlowError.UNKNOWN_USER);
        }
        return authenticationComplete();
    }

    public void checkClientSession() {
        ClientSessionCode code = new ClientSessionCode(realm, clientSession);
        String action = ClientSessionModel.Action.AUTHENTICATE.name();
        if (!code.isValidAction(action)) {
            throw new AuthenticationFlowException(AuthenticationFlowError.INVALID_CLIENT_SESSION);
        }
        if (!code.isActionActive(action)) {
            throw new AuthenticationFlowException(AuthenticationFlowError.EXPIRED_CODE);
        }
        clientSession.setTimestamp(Time.currentTime());
    }

    public Response authenticateOnly() throws AuthenticationFlowException {
        checkClientSession();
        event.client(clientSession.getClient().getClientId())
                .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
                .detail(Details.AUTH_METHOD, clientSession.getAuthMethod());
        String authType = clientSession.getNote(Details.AUTH_TYPE);
        if (authType != null) {
            event.detail(Details.AUTH_TYPE, authType);
        }
        UserModel authUser = clientSession.getAuthenticatedUser();
        validateUser(authUser);
        AuthenticationFlow authenticationFlow = createFlowExecution(this.flowId, null);
        Response challenge = authenticationFlow.processFlow();
        return challenge;
    }

    public Response attachSessionExecutionRequiredActions() {
        attachSession();
        return AuthenticationManager.actionRequired(session, userSession, clientSession, connection, request, uriInfo, event);
    }

    public void attachSession() {
        String username = clientSession.getAuthenticatedUser().getUsername();
        String attemptedUsername = clientSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME);
        if (attemptedUsername != null) username = attemptedUsername;
        String rememberMe = clientSession.getNote(Details.REMEMBER_ME);
        boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("true");
        if (userSession == null) { // if no authenticator attached a usersession
            userSession = session.sessions().createUserSession(realm, clientSession.getAuthenticatedUser(), username, connection.getRemoteAddr(), clientSession.getAuthMethod(), remember, null, null);
            userSession.setState(UserSessionModel.State.LOGGING_IN);
            userSessionCreated = true;
        }
        if (remember) {
            event.detail(Details.REMEMBER_ME, "true");
        }
        TokenManager.attachClientSession(userSession, clientSession);
        event.user(userSession.getUser())
                .detail(Details.USERNAME, username)
                .session(userSession);
    }

    public void evaluateRequiredActionTriggers() {
        AuthenticationManager.evaluateRequiredActionTriggers(session, userSession, clientSession, connection, request, uriInfo, event, realm, clientSession.getAuthenticatedUser());
    }

    public Response finishAuthentication() {
        event.success();
        RealmModel realm = clientSession.getRealm();
        return AuthenticationManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, connection);

    }

    public void validateUser(UserModel authenticatedUser) {
        if (authenticatedUser == null) return;
        if (!authenticatedUser.isEnabled()) throw new AuthenticationFlowException(AuthenticationFlowError.USER_DISABLED);
        if (realm.isBruteForceProtected()) {
            if (protector.isTemporarilyDisabled(session, realm, authenticatedUser.getUsername())) {
                throw new AuthenticationFlowException(AuthenticationFlowError.USER_TEMPORARILY_DISABLED);
            }
        }
    }

    protected Response authenticationComplete() {
        attachSession();
        return AuthenticationManager.nextActionAfterAuthentication(session, userSession, clientSession, connection, request, uriInfo, event);

    }

    public AuthenticationProcessor.Result createAuthenticatorContext(AuthenticationExecutionModel model, Authenticator authenticator, List<AuthenticationExecutionModel> executions) {
        return new Result(model, authenticator, executions);
    }

    public AuthenticationProcessor.Result createClientAuthenticatorContext(AuthenticationExecutionModel model, ClientAuthenticator clientAuthenticator, List<AuthenticationExecutionModel> executions) {
        return new Result(model, clientAuthenticator, executions);
    }

}


text:
require 'test_helper'
require 'json'

class InstanceMetadataTest < InstanceAgentTestCase

  def self.should_check_status_code(&blk)
    should 'raise unless status code is 200' do
      @response.stubs(:code).returns(503)
      assert_raise(&blk)
    end
  end

  context 'The instance metadata service' do
    setup do
      region = 'us-east-1'
      account_id = '123456789012'
      instance_id = 'i-deadbeef'
      @host_identifier = "arn:aws:ec2:#{region}:#{account_id}:instance/#{instance_id}"
      @instance_document = JSON.dump({"accountId" => account_id, "region" => region, "instanceId" => instance_id})
      @http = mock()
      @response = mock()
      @response.stubs(:code).returns("200")
      @http.stubs(:get).returns(@response)
      Net::HTTP.stubs(:start).yields(@http)
    end

    context 'getting the host identifier' do

      setup do
        @response.stubs(:body).returns(@instance_document)
      end

      should 'connect to the right host' do
        Net::HTTP.expects(:start).with('169.254.169.254', 80).yields(@http)
        InstanceMetadata.host_identifier
      end

      should 'call the correct URL' do
        @http.expects(:get).
          with("/latest/dynamic/instance-identity/document").
          returns(@response)
        InstanceMetadata.host_identifier
      end

      should 'return the body' do
        assert_equal(@host_identifier, InstanceMetadata.host_identifier)
      end

      should 'strip whitesace in the body' do
        @response.stubs(:body).returns(" \t#{@instance_document}   ")
        assert_equal(@host_identifier, InstanceMetadata.host_identifier)
      end

      should_check_status_code { InstanceMetadata.host_identifier }

    end

    context 'getting the region' do

      setup do
        @response.stubs(:body).returns("us-east-1a")
      end

      should 'connect to the right host' do
        Net::HTTP.expects(:start).with('169.254.169.254', 80).yields(@http)
        InstanceMetadata.region
      end

      should 'call the correct URL' do
        @http.expects(:get).
          with("/latest/meta-data/placement/availability-zone").
          returns(@response)
        InstanceMetadata.region
      end

      should 'return the region part of the AZ' do
        @response.stubs(:body).returns("us-east-1a")
        assert_equal("us-east-1", InstanceMetadata.region)
      end

      should 'raise an error if the response is not an AZ' do
        @response.stubs(:body).returns("foobar")
        assert_raise { InstanceMetadata.region }
      end

      should 'ignore whitespace in the body' do
        @response.stubs(:body).returns(" \tus-east-1a   ")
        assert_equal("us-east-1", InstanceMetadata.region)
      end

      should_check_status_code { InstanceMetadata.region }

    end

  end

end


text:
package com.fincatto.documentofiscal.utils;

import com.fincatto.documentofiscal.DFConfig;
import com.fincatto.documentofiscal.DFLog;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.naming.ldap.LdapName;
import javax.xml.crypto.*;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.*;

public class DFAssinaturaDigital implements DFLog {

    private static final String C14N_TRANSFORM_METHOD = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
    private static final String[] ELEMENTOS_ASSINAVEIS = new String[]{"infEvento", "infCanc", "infNFe", "infInut", "infMDFe", "infCte"};
    private final DFConfig config;

    public DFAssinaturaDigital(final DFConfig config) {
        this.config = config;
    }

    public boolean isValida(final InputStream xmlStream) throws Exception {
        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);

        final Document document = dbf.newDocumentBuilder().parse(xmlStream);
        final NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
        if (nodeList.getLength() == 0) {
            throw new IllegalStateException("Nao foi encontrada a assinatura do XML.");
        }

        final String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
        final XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).getDeclaredConstructor().newInstance());
        final DOMValidateContext validateContext = new DOMValidateContext(new DFKeySelector(), nodeList.item(0));
        for (final String tag : DFAssinaturaDigital.ELEMENTOS_ASSINAVEIS) {
            final NodeList elements = document.getElementsByTagName(tag);
            if (elements.getLength() > 0) {
                validateContext.setIdAttributeNS((Element) elements.item(0), null, "Id");
            }
        }
        return signatureFactory.unmarshalXMLSignature(validateContext).validate(validateContext);
    }

    public String assinarDocumento(final String conteudoXml) throws Exception {
        return this.assinarDocumento(conteudoXml, DFAssinaturaDigital.ELEMENTOS_ASSINAVEIS);
    }

    public String assinarDocumento(final String conteudoXml, final String... elementosAssinaveis) throws Exception {
        try (StringReader reader = new StringReader(conteudoXml)) {
            try (StringWriter writer = new StringWriter()) {
                this.assinarDocumento(reader, writer, elementosAssinaveis);
                return writer.toString();
            }
        }
    }

    public void assinarDocumento(final Reader xmlReader, final Writer xmlAssinado, final String... elementosAssinaveis) throws Exception {
        final KeyStore.PrivateKeyEntry keyEntry = getPrivateKeyEntry();

        final String dn = ((X509Certificate) keyEntry.getCertificate()).getSubjectX500Principal().getName();
        this.getLogger().debug("DN: {}", dn);

        final String cn = new LdapName(dn).getRdns().stream()
                .filter(rdn -> StringUtils.equalsIgnoreCase(rdn.getType(), "CN"))
                .map(val -> String.valueOf(val.getValue()))
                .findFirst()
                .orElse("");
        this.getLogger().debug("CN: {}", cn);

        final XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
        final List<Transform> transforms = new ArrayList<>(2);
        transforms.add(signatureFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
        transforms.add(signatureFactory.newTransform(DFAssinaturaDigital.C14N_TRANSFORM_METHOD, (TransformParameterSpec) null));

        final KeyInfoFactory keyInfoFactory = signatureFactory.getKeyInfoFactory();
        final X509Data x509Data = keyInfoFactory.newX509Data(Collections.singletonList((X509Certificate) keyEntry.getCertificate()));
        final KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));
        final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);

        final Document document = documentBuilderFactory.newDocumentBuilder().parse(new InputSource(xmlReader));
        for (final String elementoAssinavel : elementosAssinaveis) {
            final NodeList elements = document.getElementsByTagName(elementoAssinavel);
            for (int i = 0; i < elements.getLength(); i++) {
                final Element element = (Element) elements.item(i);
                final String id = element.getAttribute("Id");
                element.setIdAttribute("Id", true);

                final Reference reference = signatureFactory.newReference("#" + id, signatureFactory.newDigestMethod(DigestMethod.SHA1, null), transforms, null, null);
                final SignedInfo signedInfo = signatureFactory.newSignedInfo(signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null), signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null), Collections.singletonList(reference));
                final XMLSignature signature = signatureFactory.newXMLSignature(signedInfo, keyInfo);
                signature.sign(new DOMSignContext(keyEntry.getPrivateKey(), element.getParentNode()));
            }
        }

        final Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.transform(new DOMSource(document), new StreamResult(xmlAssinado));
    }

    private KeyStore.PrivateKeyEntry getPrivateKeyEntry() throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
        final KeyStore.PasswordProtection passwordProtection = new KeyStore.PasswordProtection(this.config.getCertificadoSenha().toCharArray());
        if (StringUtils.isNotBlank(config.getCertificadoAlias())) {
            this.getLogger().debug("Usando alias informado: '{}'", config.getCertificadoAlias());
            return (KeyStore.PrivateKeyEntry) config.getCertificadoKeyStore().getEntry(config.getCertificadoAlias(), passwordProtection);
        } else {
            final KeyStore ks = config.getCertificadoKeyStore();
            for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
                final String alias = e.nextElement();
                if (ks.isKeyEntry(alias)) {
                    this.getLogger().debug("Usando alias descoberto: '{}'", alias);
                    return (KeyStore.PrivateKeyEntry) ks.getEntry(alias, passwordProtection);
                }
            }
            throw new KeyStoreException("N\u00E3o foi poss\u00EDvel encontrar a chave privada do certificado!");
        }
    }

    public String assinarString(final String string) throws Exception {
        final byte[] buffer = string.getBytes();
        final Signature signatureProvider = Signature.getInstance("SHA1withRSA");
        signatureProvider.initSign(getPrivateKeyEntry().getPrivateKey());
        signatureProvider.update(buffer, 0, buffer.length);
        return Base64.getEncoder().encodeToString(signatureProvider.sign());
    }

    static class DFKeySelector extends KeySelector {
        @Override
        public KeySelectorResult select(final KeyInfo keyInfo, final KeySelector.Purpose purpose, final AlgorithmMethod method, final XMLCryptoContext context) throws KeySelectorException {
            for (final Object object : keyInfo.getContent()) {
                final XMLStructure info = (XMLStructure) object;
                if (info instanceof X509Data) {
                    final X509Data x509Data = (X509Data) info;
                    for (final Object certificado : x509Data.getContent()) {
                        if (certificado instanceof X509Certificate) {
                            final X509Certificate x509Certificate = (X509Certificate) certificado;
                            if (this.algEquals(method.getAlgorithm(), x509Certificate.getPublicKey().getAlgorithm())) {
                                return x509Certificate::getPublicKey;
                            }
                        }
                    }
                }
            }
            throw new KeySelectorException("Nao foi localizada a chave do certificado.");
        }

        private boolean algEquals(final String algURI, final String algName) {
            return ((algName.equalsIgnoreCase("DSA") && algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) || (algName.equalsIgnoreCase("RSA") && algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1)));
        }
    }
}


text:
using namespace foundation;

namespace renderer
{

namespace
{
    //
    // Uniform pixel renderer.
    //

    class UniformPixelRenderer
      : public PixelRendererBase
    {
      public:
        UniformPixelRenderer(
            const Frame&                frame,
            ISampleRendererFactory*     factory,
            const ParamArray&           params,
            const size_t                thread_index)
          : PixelRendererBase(frame, thread_index, params)
          , m_params(params)
          , m_sample_renderer(factory->create(thread_index))
          , m_sample_count(m_params.m_samples)
          , m_sqrt_sample_count(round<int>(sqrt(static_cast<double>(m_params.m_samples))))
        {
            if (!m_params.m_decorrelate)
            {
                m_pixel_sampler.initialize(m_sqrt_sample_count);

                if (thread_index == 0)
                {
                    if (params.get_optional<size_t>("passes", 1) > 1)
                        RENDERER_LOG_WARNING("doing multipass rendering with pixel decorrelation off.");

                    RENDERER_LOG_INFO(
                        "effective max subpixel grid size: %d x %d",
                        m_sqrt_sample_count,
                        m_sqrt_sample_count);
                }
            }
        }

        void release() override
        {
            delete this;
        }

        void print_settings() const override
        {
            RENDERER_LOG_INFO(
                "uniform pixel renderer settings:\n"
                "  samples                       %s\n"
                "  force antialiasing            %s\n"
                "  decorrelate pixels            %s\n"
                "  diagnostics                   %s",
                pretty_uint(m_params.m_samples).c_str(),
                m_params.m_force_aa ? "on" : "off",
                m_params.m_decorrelate ? "on" : "off",
                are_diagnostics_enabled() ? "on" : "off");

            m_sample_renderer->print_settings();
        }

        void render_pixel(
            const Frame&                frame,
            Tile&                       tile,
            TileStack&                  aov_tiles,
            const AABB2i&               tile_bbox,
            const size_t                pass_hash,
            const Vector2i&             pi,
            const Vector2i&             pt,
            AOVAccumulatorContainer&    aov_accumulators,
            ShadingResultFrameBuffer&   framebuffer) override
        {
            const size_t aov_count = frame.aov_images().size();

            on_pixel_begin(pi, pt, tile_bbox, aov_accumulators);

            if (m_params.m_decorrelate)
            {
                // Create a sampling context.
                const size_t frame_width = frame.image().properties().m_canvas_width;
                const size_t pixel_index = pi.y * frame_width + pi.x;
                const size_t instance = hash_uint32(static_cast<uint32>(pass_hash + pixel_index));
                SamplingContext::RNGType rng(pass_hash, instance);
                SamplingContext sampling_context(
                    rng,
                    m_params.m_sampling_mode,
                    2,                          // number of dimensions
                    0,                          // number of samples -- unknown
                    instance);                  // initial instance number

                for (size_t i = 0; i < m_sample_count; ++i)
                {
                    // Generate a uniform sample in [0,1)^2.
                    const Vector2d s =
                        m_sample_count > 1 || m_params.m_force_aa
                            ? sampling_context.next2<Vector2d>()
                            : Vector2d(0.5);

                    // Compute the sample position in NDC.
                    const Vector2d sample_position = frame.get_sample_position(pi.x + s.x, pi.y + s.y);

                    // Create a pixel context that identifies the pixel and sample currently being rendered.
                    const PixelContext pixel_context(pi, sample_position);

                    // Render the sample.
                    ShadingResult shading_result(aov_count);
                    SamplingContext child_sampling_context(sampling_context);
                    m_sample_renderer->render_sample(
                        child_sampling_context,
                        pixel_context,
                        sample_position,
                        aov_accumulators,
                        shading_result);

                    // Update sampling statistics.
                    m_total_sampling_dim.insert(child_sampling_context.get_total_dimension());

                    // Merge the sample into the framebuffer.
                    if (shading_result.is_valid())
                    {
                        framebuffer.add(
                            static_cast<float>(pt.x + s.x),
                            static_cast<float>(pt.y + s.y),
                            shading_result);
                    }
                    else signal_invalid_sample();
                }
            }
            else
            {
                const size_t frame_width = frame.image().properties().m_canvas_width;
                const size_t pixel_index = pi.y * frame_width + pi.x;
                const size_t instance = hash_uint32(static_cast<uint32>(pass_hash + pixel_index));
                SamplingContext::RNGType rng(pass_hash, instance);

                const int base_sx = pi.x * m_sqrt_sample_count;
                const int base_sy = pi.y * m_sqrt_sample_count;

                for (int sy = 0; sy < m_sqrt_sample_count; ++sy)
                {
                    for (int sx = 0; sx < m_sqrt_sample_count; ++sx)
                    {
                        // Compute the sample position (in continuous image space) and the instance number.
                        Vector2d s;
                        size_t instance;
                        m_pixel_sampler.sample(base_sx + sx, base_sy + sy, s, instance);

                        // Compute the sample position in NDC.
                        const Vector2d sample_position = frame.get_sample_position(s.x, s.y);

                        // Create a pixel context that identifies the pixel and sample currently being rendered.
                        const PixelContext pixel_context(pi, sample_position);

                        // Create a sampling context. We start with an initial dimension of 1,
                        // as this seems to give less correlation artifacts than when the
                        // initial dimension is set to 0 or 2.
                        SamplingContext sampling_context(
                            rng,
                            m_params.m_sampling_mode,
                            1,                          // number of dimensions
                            instance,                   // number of samples
                            instance);                  // initial instance number -- end of sequence

                        // Render the sample.
                        ShadingResult shading_result(aov_count);
                        m_sample_renderer->render_sample(
                            sampling_context,
                            pixel_context,
                            sample_position,
                            aov_accumulators,
                            shading_result);

                        // Update sampling statistics.
                        m_total_sampling_dim.insert(sampling_context.get_total_dimension());

                        // Merge the sample into the framebuffer.
                        if (shading_result.is_valid())
                        {
                            framebuffer.add(
                                static_cast<float>(s.x - pi.x + pt.x),
                                static_cast<float>(s.y - pi.y + pt.y),
                                shading_result);
                        }
                        else signal_invalid_sample();
                    }
                }
            }

            on_pixel_end(pi, pt, tile_bbox, aov_accumulators);
        }

        StatisticsVector get_statistics() const override
        {
            Statistics stats;
            stats.insert("max sampling dimension", m_total_sampling_dim);

            StatisticsVector vec;
            vec.insert("generic sample generator statistics", stats);
            vec.merge(m_sample_renderer->get_statistics());

            return vec;
        }

        size_t get_max_samples_per_pixel() const override
        {
            return m_sample_count;
        }

      private:
        struct Parameters
        {
            const SamplingContext::Mode     m_sampling_mode;
            const size_t                    m_samples;
            const bool                      m_force_aa;
            const bool                      m_decorrelate;

            explicit Parameters(const ParamArray& params)
              : m_sampling_mode(get_sampling_context_mode(params))
              , m_samples(params.get_required<size_t>("samples", 64))
              , m_force_aa(params.get_optional<bool>("force_antialiasing", false))
              , m_decorrelate(params.get_optional<bool>("decorrelate_pixels", true))
            {
            }
        };

        const Parameters                    m_params;
        auto_release_ptr<ISampleRenderer>   m_sample_renderer;
        const size_t                        m_sample_count;
        const int                           m_sqrt_sample_count;
        PixelSampler                        m_pixel_sampler;
        Population<uint64>                  m_total_sampling_dim;
    };
}

//
// UniformPixelRendererFactory class implementation.
//

UniformPixelRendererFactory::UniformPixelRendererFactory(
    const Frame&                frame,
    ISampleRendererFactory*     factory,
    const ParamArray&           params)
  : m_frame(frame)
  , m_factory(factory)
  , m_params(params)
{
}

void UniformPixelRendererFactory::release()
{
    delete this;
}

IPixelRenderer* UniformPixelRendererFactory::create(
    const size_t                thread_index)
{
    return new UniformPixelRenderer(m_frame, m_factory, m_params, thread_index);
}

Dictionary UniformPixelRendererFactory::get_params_metadata()
{
    Dictionary metadata = PixelRendererBaseFactory::get_params_metadata();

    metadata.dictionaries().insert(
        "samples",
        Dictionary()
            .insert("type", "int")
            .insert("default", "64")
            .insert("label", "Samples")
            .insert("help", "Number of anti-aliasing samples"));

    metadata.dictionaries().insert(
        "force_antialiasing",
        Dictionary()
            .insert("type", "bool")
            .insert("default", "false")
            .insert("label", "Force Anti-Aliasing")
            .insert(
                "help",
                "When using 1 sample/pixel and Force Anti-Aliasing is disabled, samples are placed at the center of pixels"));

    metadata.dictionaries().insert(
        "decorrelate_pixels",
        Dictionary()
            .insert("type", "bool")
            .insert("default", "true")
            .insert("label", "Decorrelate Pixels")
            .insert(
                "help",
                "Avoid correlation patterns at the expense of slightly more sampling noise"));

    return metadata;
}

}   // namespace renderer


text:
/**
 * File menu plugin for IRuby notebook
 * This adds a menu items to the File menu: open...(IRuby), that loads IRuby notebook and
 * convert it to a Beaker noteboook
 */
define(function(require, exports, module) {
  'use strict';
  var notebookConverter = (function() {
    var convertCodeCell = function(ipyCodeCell) {
      var bkrCodeCell = {
        "id": "code" + bkHelper.generateId(6),
        "evaluator": "IRuby",
        "class": ["code"],
        "input": {
          "body": ""
        },
        "output": {
        }
      };
      if (ipyCodeCell.input && ipyCodeCell.input.length > 0) {
        bkrCodeCell.input.body = ipyCodeCell.input.join('\n');
      }
      if (ipyCodeCell.outputs && ipyCodeCell.outputs.length > 0) {
        var ipyOutput = ipyCodeCell.outputs[0];
        if (ipyOutput.output_type === "pyout" && ipyOutput.text) {
          bkrCodeCell.output.selectedType = "Text";
          bkrCodeCell.output.result = ipyOutput.text[0];
        } else if (ipyOutput.output_type === "display_data" && ipyOutput.png) {
          bkrCodeCell.output.selectedType = "Image";
          bkrCodeCell.output.result = {
            "type": "ImageIcon",
            "imageData": ipyOutput.png
          };
        }
      } else {
        bkrCodeCell.output.result = "";
      }

      return bkrCodeCell;
    };

    var convertMarkDownCell = function(ipyMDCell) {
      var bkrMDCell = {
        "id": "markdown" + bkHelper.generateId(6),
        "class": ["markdown"],
        "body": "",
        "mode": "preview"
      };
      if (ipyMDCell.source && ipyMDCell.source.length > 0) {
        bkrMDCell.body = ipyMDCell.source.join("\n");
      }

      return bkrMDCell;
    };

    var convertRawCell = function(ipyRawCell) {
      var bkrTextCell = {
        "id": "text" + bkHelper.generateId(6),
        "class": ["text"],
        "body": ""
      };
      if (ipyRawCell.source && ipyRawCell.source.length > 0) {
        bkrTextCell.body = ipyRawCell.source.join("\n");
      }
      return bkrTextCell;
    };

    var convertHeadingCell = function(ipyHeadingCell) {
      var bkrTextCell = {
        "id": "text" + bkHelper.generateId(6),
        "class": ["text"],
        "body": ""
      };
      if (ipyHeadingCell.source && ipyHeadingCell.source.length > 0) {
        bkrTextCell.body = ipyHeadingCell.source.join("\n");
      }
      bkrTextCell.body = "<h" + ipyHeadingCell.level + ">" + bkrTextCell.body +
          "</h" + ipyHeadingCell.level + ">";
      return bkrTextCell;
    };

    var newBeakerNotebook = function() {
      return {
        "beaker": "1",
        "evaluators": [
          {
            "name": "Html",
            "plugin": "Html"
          },
          {
            "name": "Latex",
            "plugin": "Latex"
          },
          {
            "name": "IRuby",
            "plugin": "IRuby",
            "imports": "",
            "supplementalClassPath": ""
          }
        ],
        cells: [
          {
            "id": "root",
            "class": ["notebook", "container"]
          }
        ],
        tagMap: {
          "root": []
        },
        tagMap2: {
          "initialization": [],
          "IRuby": []
        }
      };
    };

    return {
      convert: function(ipyNb) {
//                if (ipyNb.nbformat !== 3 || ipyNb.nbformat_minor !== 0) {
//                    throw "unrecognized iPython notebook format version"
//                }

        var bkrNb = newBeakerNotebook();
        ipyNb.worksheets[0].cells.forEach(function(cell) {
          var bkrCell;
          if (cell.cell_type === "code") {
            bkrCell = convertCodeCell(cell);
          } else if (cell.cell_type === "markdown") {
            bkrCell = convertMarkDownCell(cell);
          } else if (cell.cell_type === "raw") {
            bkrCell = convertRawCell(cell);
          } else if (cell.cell_type === "heading") {
            bkrCell = convertHeadingCell(cell);
          } else {
            console.warn("unrecognized cell type: ", cell.cell_type, cell);
          }
          if (bkrCell) {
            bkrNb.cells.push(bkrCell);
            bkrNb.tagMap.root.push(bkrCell.id);
            bkrNb.tagMap2.IRuby.push(bkrCell.id);
          }
        });
        return bkrNb;
      }
    };
  })();

  var IRUBY_PATH_PREFIX = "iruby";
  bkHelper.setNotebookImporter(IRUBY_PATH_PREFIX, {
    open: function(fileContentAsString) {
      var ipyNbJson = fileContentAsString;
      var ipyNb = JSON.parse(ipyNbJson);
      var bkrNb = notebookConverter.convert(ipyNb);
      return bkrNb;
    }
  });

  var menuItemsDeferred = bkHelper.newDeferred();
  bkHelper.getHomeDirectory().then(function(homeDir) {
    var strategy = bkHelper.getFileSystemFileChooserStrategy();
    strategy.treeViewfs.extFilter = ['ipynb'];
    var toAdd = [
      {
        parent: "File",
        id: "file-menu",
        submenu: "Open",
        items: [
          {
            name: "Open... IRuby (.ipynb)",
            id: "open-iruby-menuitem",
            reducedName: "Open...",
            tooltip: "Open a IRuby notebook from file system and convert it to Beaker notebook",
            sortorder: 120,
            action: function() {
              bkHelper.openWithDialog('ipynb', null, true, IRUBY_PATH_PREFIX);
            }
          }
        ]
      }
    ];
    menuItemsDeferred.resolve(toAdd);
  });

  exports.getMenuItems = function() {
    return menuItemsDeferred.promise;
  };
});


text:
<md-toolbar class="md-mainColor md-hue-2 top-nav" layout="row" layout-align="start center">

		<md-button href="#/">Zenit Service</md-button>

			<md-button class="number" href="tel:18475555555" hide-sm show-gt-sm>888-888-8888</md-button>
			<md-button class="md-fab md-mini" aria-label="Call" href="tel:18475555555">
				<md-icon class="material-icons md-mainColor md-hue-4 icon">phone</md-icon>
			</md-button>
			<md-button class="md-fab md-mini side-nav" ng-click="vm.toggle()" aria-label="Menu">
	        	<md-icon class="material-icons md-mainColor md-hue-4 icon">menu</md-icon>
	        </md-button>

</md-toolbar>

<md-toolbar class="md-menu-toolbar dropdowns" layout="row" layout-align="center center">

		<md-menu-bar>
			<md-button class="" href="#/about">
				About
			</md-button>
			<md-button class="" href="#/contact">
				Contact
			</md-button>

			<md-menu>
				<md-button class="" ng-click="$mdOpenMenu()" href="">

					Residential
				</md-button>
				<md-menu-content ng-mouseleave="vm.mouseOut()" ng-mouseenter="vm.mouseIn()">
					<md-menu-item>
						<md-button href="#/residential/service">
							Service
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/residential/installation">
							Installation
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/residential/repairs">
							Repairs
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/residential/contracts">
							Maint. Contracts
						</md-button>
					</md-menu-item>
				</md-menu-content>
			</md-menu>

			<md-menu>
				<md-button class="" ng-click="$mdOpenMenu()" href="">
					Commercial
				</md-button>
				<md-menu-content ng-mouseleave="vm.mouseOut()" ng-mouseenter="vm.mouseIn()">
					<md-menu-item>
						<md-button href="#/commercial/contracts">
							Maint. Contracts
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/commercial/controls">
							Controls
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/commercial/iaq">
							IAQ
						</md-button>
					</md-menu-item>
				</md-menu-content>
			</md-menu>

			<md-menu>
				<md-button class="" ng-click="$mdOpenMenu()" href="">
					Mini Splits
				</md-button>
				<md-menu-content ng-mouseleave="vm.mouseOut()" ng-mouseenter="vm.mouseIn()">
					<md-menu-item>
						<md-button href="#/commercial/contracts">
							Maint. Contracts
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/commercial/controls">
							Controls
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/commercial/iaq">
							IAQ
						</md-button>
					</md-menu-item>
				</md-menu-content>
			</md-menu>

			<md-menu>
				<md-button class="" ng-click="$mdOpenMenu()" href="">
					Kitchen Services
				</md-button>
				<md-menu-content ng-mouseleave="vm.mouseOut()" ng-mouseenter="vm.mouseIn()">
					<md-menu-item>
						<md-button href="#/commercial/contracts">
							Hood Cleaning
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/commercial/controls">
							Refrigeration
						</md-button>
					</md-menu-item>
				</md-menu-content>
			</md-menu>

			<md-menu>
				<md-button class="" ng-click="$mdOpenMenu()" href="">
					Indoor Air Quality
				</md-button>
				<md-menu-content ng-mouseleave="vm.mouseOut()" ng-mouseenter="vm.mouseIn()">
					<md-menu-item>
						<md-button href="#/commercial/contracts">
							Air Cleaners
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/commercial/controls">
							UV Lights
						</md-button>
					</md-menu-item>
					<md-menu-item>
						<md-button href="#/commercial/controls">
							Duct Cleaning
						</md-button>
					</md-menu-item>
				</md-menu-content>
			</md-menu>

		</md-menu-bar>

</md-toolbar>

<ng-include src="'app/components/navbar/sidenav.html'"></ng-include>