(function($){
	$(document).ready(function(){

		var currentLayout,
			pageEditorTabs,
			$radioThumbnail,
			sectionCount = [],
			$mainChannelSortable,
			$subChannelSortable,
			hasCanvasChanged = false,
			hasConfigChanged = false,
			templatesLoaded = false,
			modulesLoaded = false,
			moduleInstancesLoaded = false,
			templateChanged = false,
			moduleDragStart = false;

		function initPage(){

			$('#btnAdminCP').click(function(){
				location.href = pageData.baseurl + '/' + pageData.admincpdir + '/index.php/';
			});

			//page editor dialog
			$('#page-editor-dialog').dialog({
				title:'Page Editor',
				autoOpen:false,
				modal:true,
				resizable:false,
				closeOnEscape:false,
				width:1000,
				dialogClass:'sb-dialog-container page-editor-dialog-container shadow-dark',
				close:function(){
					//show module without animation
					$('#content .youtube-widget .toggle-icon').trigger('click', [true]);

					//reset flags
					hasCanvasChanged = false;
					hasConfigChanged = false;
					templateChanged = false;
				},
				create:function(){
					//initialize tabs
					$pageEditorTabs = $('.tabs').tabs({
						show:function(event, ui){
							if (ui.index > 0){ //Change Layout tab and Select Templates tab
								//.outerWidth() doesn't work when element is hidden, so we need to do this on 'show' event
								resizeListWidth(ui.index);
							}
						},
						select:function(event, ui){

							if (ui.index == 1){ //Change Layout tab
								//the template might have changed so we need to always highlight (not click) the appropriate layout
								$('#page-editor-dialog .layout-list .layout-border.selected').removeClass('selected');
								var $selectedRadio = $('#page-editor-dialog .layout-list input[type=radio][value={0}]'.format($('#page-editor-dialog .canvas-layout.show').attr('layout-id')));
								$selectedRadio.prev().addClass('selected');
								currentLayout = 'canvas-' + $selectedRadio.attr('id');
							}
						}
					});

					//show corresponding canvas
					$('#page-editor-dialog #' + $('.canvas-layout-container .canvas-layout').attr('id')).removeClass('hide').addClass('show');

					//select associated screen layout
					$('#page-editor-dialog .layout-list input[type=radio][value={0}]'.format($('#page-editor-dialog .canvas-layout.show').attr('layout-id'))).attr('checked', 'checked');
					currentLayout = 'canvas-' + $('#page-editor-dialog .layout-list input[type=radio]:checked').attr('id');

					$('#page-editor-dialog .add-modules-link').click(function(){
						$pageEditorTabs.tabs('select', 0);
						return false;
					});

					//transform screen layout radio buttons to thumbnails
					var $screenLayoutThumbnails = $('#page-editor-dialog .layout-list input[type=radio]').thumbnailRadioCheckbox({
						thumbnailClass:'radio-checkbox-thumbnail layout-border',
					});

					//set the 'select' event handler after initializing the thumbnailRadioCheckbox plugin object to prevent the 'select' event to fire immediately
					$screenLayoutThumbnails.thumbnailRadioCheckbox('option', 'select', function($thumbnail, $radio){
						$('#page-editor-dialog .canvas-layout').removeClass('show').addClass('hide');
						$('#page-editor-dialog #canvas-' + $radio.attr('id')).removeClass('hide').addClass('show');
						selectLayout('canvas-' + $radio.attr('id'));
						hasCanvasChanged = true;
					});

					//widget close button click
					$('#page-editor-dialog .canvas-widget .canvas-widget-item .close-button').live('click', function(){
						var $this = $(this);
						openConfirmDialog({
							'title': 'Remove Module?',
							'content': '<p>Do you really want to remove the <strong>{0}</strong> module?</p><p>Warning! This action cannot be undone.</p>'.format($(this).prev().text()),
							'data': {
								'yes-callback': function(){
									$this.parent().parent().remove();
									hasCanvasChanged = true;
								}
							}
						});
					});

					//Add subchannel button click
					$('#channel-config-dialog .channel-list .channel-item .add-subchannel-button a').live('click', function(){
						var $addedChannel = addSubChannel('', 'New Channel', $(this).closest('.channel-item-container'));
						$('.channel-title div', $addedChannel).click();
						$('.channel-title input', $addedChannel).get(0).scrollIntoView(false);
						return false;

					});

					//channel widget close button click
					$('#channel-config-dialog .channel-list .channel-item .close-button').live('click', function(){
						var $this = $(this);
						var hasSubChannels = $('> .sub-channel-container > .channel-item-container', $this.closest('.channel-item-container')).length > 0;
						openConfirmDialog({
							'title': 'Remove Channel?',
							'content': '<p>Do you really want to remove the <strong>{0}</strong> channel?{1}</p><p>Warning! This action cannot be undone.</p>'.format(
									$(this).prev().text(),
									(hasSubChannels) ? ' All its subchannels will also be deleted.' : ''),
							'data': {
								'yes-callback': function(){
									var $channelItemContainer = $this.closest('.channel-item-container');
									var $channelContainer = $channelItemContainer.parent();

									//delete channel/subchannel item container which also includes all its subchannels, if any
									$channelItemContainer.remove();

									//if we are deleting the main channel, we should remove the whole thing
									if ($channelContainer.hasClass('main-channel-container')){
										$channelContainer.slideUp('fast', function(){
											$(this).remove();
										});
									}
								}
							}
						});
					});

					//channel widget Edit button click
					$('#page-editor-dialog .channel-widget .canvas-widget-item .edit-button').live('click', function(){
						var $widgetContainer = $(this).parent().parent();
						$('#channel-config-dialog').data('channel-widget', $(this).closest('.channel-widget')); //remember corresponding channel widget
						$('#channel-config-dialog').dialog('open');
						return false;
					});

					//make page canvas widget items draggable-n-droppable
					$('#page-editor-dialog .canvas-widget-list').sortable({
						revert:true,
						connectWith: ".connectedSortable",
						placeholder: "canvas-widget-highlight drag-highlight round-corner5 clear",
						update: function(event, ui){//console.debug('sortable update');
							ui.item.css('z-index', ui.item.css('z-index')-1); //for IE7
							adjustDivider();
							hasCanvasChanged = true;
						},
						sort:function(event, ui){
							if (moduleDragStart){
								//console.debug('sortable sort-'+ui.placeholder.height()+'x'+ui.item.height());
								//ui.item.width(66);
								ui.placeholder.height(32);
							}
							ui.item.addClass('shadow');
							adjustDivider();
						},
						start:function(event, ui){
							ui.item.removeClass('shadow');
							if ($.browser.msie && parseInt($.browser.version, 10) == 8){ //IE8 widget height is bigger
								ui.item.height(ui.item.height()-4);
							}
							ui.item.css('z-index', ui.item.css('z-index')+1); //for IE7
							ui.placeholder.height(ui.item.height());
							ui.placeholder.html('Drag and drop module here');
						},
						over:function(event, ui){//console.debug('sortable over');
							//console.debug('i:'+ui.item);
							//console.debug(ui.placeholder.width());
							$.each(ui.placeholder.parent().attr('className').split(' '), function(index, className){
								if (className.indexOf('section-') == 0){
									ui.item.addClass(className);
									return false;
								}
							});
						},
						stop:function(event, ui){//console.debug('sortable stop');
							ui.item.get(0).className = ui.item.get(0).className.replace(/\bsection-\d?\b/g, '');
						},
						handle:'.canvas-widget-item > .grip-icon',
						items:'.canvas-widget'
					});

					//get column counts for each layout
					$('#page-editor-dialog .canvas-layout-container .canvas-layout').each(function(){
						sectionCount[this.id] = $('#page-editor-dialog #' + this.id + ' div[class*="section-"]').length;
					});

					//add channel button
					$('#channel-config-dialog .add-channel-fieldset .add-button, #channel-config-dialog .add-channel-fieldset input').live('click keydown', function(event){
						if (((event.type == 'click' || event.which != 13) && this.type == 'text') || (event.type == 'keydown' && this.type == 'button' && event.which != 13)){
							return true;
						}
						var $channelTitleField = (this.type == 'text') ? $(this):$(this).prev();
						var channelTitle = $.trim($channelTitleField.val());
						if (channelTitle && channelTitle != $channelTitleField.attr('defaultValue')){
							addMainChannel('', channelTitle, true);

							//reset channel title field
							$channelTitleField.val('');

							if (this.type == 'button') $channelTitleField.focus();
						}
						else {
							showErrorDialog('<span>Please enter Channel Title.</span>', function(){
								$channelTitleField.focus();
							});
						}

					});

					//channel title click handler
					$('#channel-config-dialog .main-channel-container .channel-item .channel-title div').live('click', function(){
						$(this).hide();
						var $channelTitle = $(this).next();
						$channelTitle.show();
						$channelTitle.select();
						$channelTitle.focus();
					});

					//channel title textbox event handlers
					$('#channel-config-dialog .main-channel-container .channel-item .channel-title input').live('keydown blur', function(event){
						if (event.type == 'focusout' || (event.type == 'keydown' && event.which == 13)){
							if (!$.trim(this.value) && event.type == 'focusout'){
								this.value = this.defaultValue;
							}
							if ($.trim(this.value)) {
								$(this).hide();
								$(this).prev().html(this.value);
								$(this).prev().show();
							}
						}
					});

				},
				open:function(){
					$('#edit-content').show();
					$('#save-content').hide();

					//show first tab by default
					$pageEditorTabs.tabs('select', 0);
					if (!modulesLoaded){
						loadModules();
					}
					if (!templatesLoaded){
						loadTemplates();
					}
					else {
						//click default checked template
						//var $checkedTemplate = $('#page-editor-dialog .template-list .template-item input[type=radio]:checked');//the form has been reset at this time, so the checked item is the default checked item
						//$radioThumbnail.thumbnailRadioCheckbox('check', $checkedTemplate, true);
					}
				}
			});

			$('.lnkPageEditor').click(function(){
				//collapse YouTube modules as videos obscure the Page Editor overlay (overlays are problematic with flash WITHIN iframe - iframe shim technique doesn't work)
				if (!$('#content .youtube-widget .widget-content').is(':hidden')){
					$('#content .youtube-widget .toggle-icon').trigger('click', [true]); //hide module without animation
				}
				$('#page-editor-dialog').dialog('open');
				return false;
			});

			//populate the corresponding displaysections[] hidden textbox with the added widgets when Save button is clicked
			$('#btnSaveEditPage').click(function(){
				//validate inputs
				if (!$.trim(this.form.pagetitle.value)){
					showErrorDialog('<span>Please enter the Page Name.</span>', function(){
						$('#save-page-form #pagetitle').focus();
					});
					return false;
				}
				if (!this.form.pagetemplateid[0].checked && !this.form.pagetemplateid[1].checked){
					showErrorDialog('<span>Please select the template option.</span>', function(){
						$('#save-page-form #pagetemplateid').focus();
					});
					return false;
				}
				if (this.form.pagetemplateid[1].checked && this.form.templatetitle.value == this.form.templatetitle.defaultValue){
					showErrorDialog('<span>Please enter the new template name.</span>', function(){
						$('#save-page-form #templatetitle').focus();
					});
					return false;
				}

				var $currentLayout = $('#page-editor-dialog #' + currentLayout);

				//update screenlayoutid with selected layout
				this.form.screenlayoutid.value = $currentLayout.attr('layout-id');

				//prepare module instances data
				$('input[type=hidden][name*="displaysections"]', $currentLayout).clone().appendTo($('#moduleData').empty());
				for (var i=0; i<sectionCount[currentLayout]; i++) {
					var arr = [];
					$('> div.section-' + i + ' > div.canvas-widget', $currentLayout).each(function(index){
						arr.push($(this).attr('widget-id') + '=' + ($(this).attr('widget-instance-id')||'0'));
					});
					this.form.elements['displaysections[' + i + ']'].value = arr.join(',');
				}

				return true;

			});

			$('#btnSavePage').click(function(){
				$('#edit-content').hide();
				$('#save-content').show();
			});

			$('#btnCancelPage').click(function(){
				if (hasCanvasChanged || hasConfigChanged || templateChanged) {
					openConfirmDialog({
						'title': 'Cancel Saving Page?',
						'content': '<p>All changes to the page will be lost.</p><p>Do you want to continue?</p>',
						'data': {
							'yes-callback': function(){
								$('#page-editor-dialog').dialog('close');
								$('#select-template').trigger('reset');
								$('#change-layout').trigger('reset');
							}
						}
					});
				}
				else {
					$('#page-editor-dialog').dialog('close');
				}
			});

			$('#btnAddModules').click(function(){
				$('#edit-content').show();
				$('#save-content').hide();
				$pageEditorTabs.tabs('select', 0);
			});
			$('#btnChangeLayout').click(function(){
				$('#edit-content').show();
				$('#save-content').hide();
				$pageEditorTabs.tabs('select', 1);
			});
			$('#btnSelectTemplate').click(function(){
				$('#edit-content').show();
				$('#save-content').hide();
				$pageEditorTabs.tabs('select', 2);
			});
			$('#btnExit').click(function(){
				//prompt confirmation dialog if form has changed
				if (this.form.pagetitle.value != this.form.pagetitle.defaultValue
						|| this.form.pageurl.value != this.form.pageurl.defaultValue
						|| (this.form.pagetemplateid[0].defaultChecked && !this.form.pagetemplateid[0].checked)
						|| (this.form.pagetemplateid[1].defaultChecked && !this.form.pagetemplateid[1].checked)){
					openConfirmDialog({
						'title': 'Exit Without Saving?',
						'content': '<p>Do you really want to exit without saving the page?</p><p>Warning! All changes will be lost.</p>',
						'data': {'yes-callback': function(){
							$('#edit-content').show();
							$('#save-content').hide();
							$('#save-page-form').trigger('reset');
						}}
					});
				}
				else {
					$('#edit-content').show();
					$('#save-content').hide();
				}
			});
			$('#templatetitle').focus(function(){
				$('#newpagetemplateid').attr('checked', 'checked');
			});

			//initialize widget config dialog
			$('#config-dialog').dialog({
				title:'Widget Configuration',
				autoOpen:false,
				modal:true,
				resizable:false,
				closeOnEscape:false,
				height:500,
				width:800,
				dialogClass:'sb-dialog-container config-dialog-container shadow-dark',
				create:function(){
					//submit form handler to save config
					$('#sitebuilder-widget-form').submit(function() {

			  		  $('body').css('cursor', 'wait');
			  		  $('#config-dialog .action-buttons button').attr('disabled', 'disabled');

					  $.ajax({
				  			url:this.action,
				  			type:this.method,
				  			data:($(this).serializeArray()),
				  			dataType: 'json',
				  			success:function(result){
				  				$('body').css('cursor', 'auto');

				  				//@todo:check for validation errors returned by the server here

				  				$('#config-dialog').dialog('close');
				  			},
				  			error:function(xhr, statusText, error){
				  				$('body').css('cursor', 'auto');
				  				showErrorDialog('<span>Error saving the configuration for "' + $('#config-dialog .widget-name h1').text() + '" widget.<br /><br />Please try again later.</span>', function(){
				  					$('#config-dialog .action-buttons button').removeAttr('disabled');
								});
								$('#config-dialog .widget-loader').hide();
				  			}
				  		});

					  	return false;
					});
					$('#btnCloseConfig').click(function(){
						$('#config-dialog').dialog('close');
					});
				},
				close:function(){
					$('#config-dialog .action-buttons button').removeAttr('disabled');
				}
			});

			//initialize channel widget config dialog
			$('#channel-config-dialog').dialog({
				title:'Edit Channel Module',
				autoOpen:false,
				modal:true,
				resizable:false,
				closeOnEscape:false,
				width:1000,
				dialogClass:'sb-dialog-container channel-config-dialog-container shadow-dark',
				close:function(){
					$mainChannelSortable.sortable('destroy');
					$subChannelSortable.sortable('destroy');
				},
				open:function(){

					//add existing channels
					$('.widget-channel-list > li', $('#channel-config-dialog').data('channel-widget')).each(function(){
						var $channel = addMainChannel($(this).attr('data-channel-id'), $('>span', this).html(), false);
						addSubChannels($('> .widget-subchannel-list > li', this), $channel);
					});

					$('.main-channel-container > .channel-item-container > .channel-item .grip-icon').live('mousedown', function(){
						$(this).closest('.main-channel-container').height($(this).closest('.main-channel-container').height());
					});
					$('.sub-channel-container > .channel-item-container > .channel-item .grip-icon').live('mousedown', function(){
						$(this).closest('.sub-channel-container').height($(this).closest('.sub-channel-container').height());
					});

					hasConfigChanged = false;
				},
				create:function(){

					//make channel-list draggable-n-droppable
					makeSortableChannels();

					$('#btnSaveChannelConfig').click(function(){
						$('body').css('cursor', 'wait');
						//$('#loadingIcon').show();

						var $channelWidgetInstance = $('#channel-config-dialog').data('channel-widget');
						var widgetData = {id: $channelWidgetInstance.attr('widget-id'), instanceid: $channelWidgetInstance.attr('widget-instance-id')};

						var channelData = {
								widgetid: widgetData.id,
								widgetinstanceid: widgetData.instanceid,
								pagetemplateid: $('#select-template input[type=radio]:checked').val(),
								channels: []
						};

						function populateSubChannelData($subChannelContainer, channelObj, parentChannelId){
							var $subChannelItemContainers = $('> .channel-item-container', $subChannelContainer);
							if ($subChannelItemContainers.length > 0){
								$subChannelItemContainers.each(function(index){
									var $subChannelItem = $('> .channel-item', this);
									var subChannelId = $subChannelItem.attr('data-channel-id');
									//add sub channel data
									channelObj.subchannels.push({
										nodeid: subChannelId || '0',
										title: $('.channel-title div', $subChannelItem).text(),
										displayorder:index,
										parentid: parentChannelId || '0',
										subchannels : []
									});
									populateSubChannelData($subChannelItem.next('.sub-channel-container'), channelObj.subchannels[index], subChannelId);
								});
							}
						}

						//populate 'channels' property
						$('#channel-config-dialog .channel-list .main-channel-container').each(function(index){
							var $channel = $('> .channel-item-container > .channel-item', this);
							var mainChannelId = $channel.attr('data-channel-id');

							var channelObj = {
								nodeid: mainChannelId,
								title: $('.channel-title div', $channel).text(),
								displayorder:index,
								subchannels : []
							}
							//populate 'subchannels' property recursively
							populateSubChannelData($channel.next('.sub-channel-container'), channelObj, mainChannelId);

							//add main channel data
							channelData.channels.push(channelObj);
						});
						//console.debug(JSON.stringify(channelData));
						//return false;

						//submit the channel data
						$.ajax({
							url:pageData.baseurl + '/index.php/ajax/api/widget/saveChannelWidgetConfig',
							data: {data: JSON.stringify(channelData)}, //@todo: older browsers don't have JSON object, jQuery doesn't have equivalent method; use https://github.com/douglascrockford/JSON-js
				  			type:'POST',
				  			dataType: 'json',
				  			complete:function(){
								$('body').css('cursor', 'auto');
								//$('#loadingIcon').hide();
							},
				  			success:function(result){
								//check results
								if (result && result.widgetinstanceid > 0 && result.channels && result.channels.length > 0){
									//update the channel widget instance on the main page
									var $widgetChannelList = $('.widget-channel-list', $channelWidgetInstance).empty();
									$.each(result.channels, function(i, mainChannel){
										var $parentChannel = $('<li data-channel-id="{0}">Main Channel: <span>{1}</span><ul class="widget-subchannel-list"></ul></li>'.format(mainChannel.nodeid, mainChannel.title)).appendTo($widgetChannelList);
										displaySubChannels(mainChannel.subchannels, $parentChannel);
									});

									$channelWidgetInstance.attr('widget-instance-id', result.widgetinstanceid);
									$('.canvas-widget-content', $channelWidgetInstance).removeClass('hide');

									//empty the channel list
									$('#channel-config-dialog .channel-list').empty();

									//close channel config overlay
									$('#channel-config-dialog').dialog('close');

									hasConfigChanged = true;
								}
								else {
									showErrorDialog('<span>Error saving the channels.<br /><br />Please try again.</span>');
								}
							},
							error:function(xhr){
								showErrorDialog('<span>Error saving the channels.<br />(Error code {0})<br /><br />Please try again.</span>'.format(xhr.status));
							}
						});
					});

					$('#btnCancelChannelConfig').click(function(){
						function closeChannelConfigDialog(){
							$('#channel-config-dialog .channel-list').empty();
							$('#channel-config-dialog').dialog('close');
						}
						if (hasConfigChanged){
							var $this = $(this);
							openConfirmDialog({
								'title': 'Cancel Edit?',
								'content': '<p>Do you really want to cancel editing this Channel Module?</p><p>Warning! All changes will be lost.</p>',
								'data': {'yes-callback': closeChannelConfigDialog}
							});
						}
						else {
							closeChannelConfigDialog();
						}
					});
				}
			});
		}

		function selectLayout(targetLayout){
			if (!currentLayout) { //initialize current layout

				//only enable target layout's displaysections[] fields
				$('#page-editor-dialog .canvas-layout.hide input[type=hidden]').attr('disabled', 'disabled');
				$('#page-editor-dialog #' + targetLayout + ' input[type=hidden]').removeAttr('disabled');

				currentLayout = targetLayout;
				return;
			}
			else if (currentLayout == targetLayout) { //do nothing if the same layout is already selected
				return;
			}
			else { //put widgets to the target layout in the same sections as the current layout

				//only enable target layout's displaysections[] fields
				$('#page-editor-dialog .canvas-layout.hide input[type=hidden]').attr('disabled', 'disabled');
				$('#page-editor-dialog #' + targetLayout + ' input[type=hidden]').removeAttr('disabled');

				var targetLayoutSectionCount = sectionCount[targetLayout];
				var currentLayoutSectionCount = sectionCount[currentLayout];
				if (currentLayoutSectionCount > targetLayoutSectionCount) { //current layout has more sections than the target layout
					//put the widgets to the available target layout sections
					for (var i=0; i<targetLayoutSectionCount; i++) {
						$('#page-editor-dialog #' + currentLayout + ' > div.section-' + i +' > div.canvas-widget').appendTo('#' + targetLayout + ' > div.section-' + i);
					}
					//put the widgets from the excess section(s) of the current layout to the bottom of the last section of the target layout
					var targetLayoutLastSection = targetLayoutSectionCount - 1;
					for (i=targetLayoutSectionCount; i<currentLayoutSectionCount; i++) {
						//if ($('#page-editor-dialog #' + currentLayout + ' > div.section-' + i +' > div.canvas-widget').length > 0) {
							//$('#page-editor-dialog #' + currentLayout + ' > div.section-' + i +' > div.canvas-widget').insertBefore($('.unassigned-widget-list div.clear:last'));
							$('#page-editor-dialog #' + currentLayout + ' > div.section-' + i +' > div.canvas-widget').appendTo('#' + targetLayout + ' > div.section-' + targetLayoutLastSection);
							//showUnassignedWidgets = true;
						//}
					}
					//if (showUnassignedWidgets) {
					//	$('#page-editor-dialog .unassigned-widget-list').show();
					//}
				}
				else { //number of sections in the current layout is <= to that of the target layout
					for (var i=0; i<currentLayoutSectionCount; i++) {
						$('#page-editor-dialog #' + currentLayout + ' > div.section-' + i +' > div.canvas-widget').appendTo('#' + targetLayout + ' > div.section-' + i);
					}
				}
				adjustDivider();
			}
			currentLayout = targetLayout;
		};

		function addWidgets(widgets) {
			//validate widgets array
			if (!$.isArray(widgets) || widgets.length == 0) {
				return;
			}

			$('#loading-dialog').dialog('open');
			$('body').css('cursor', 'wait');


			//get widget templates via AJAX
			$.ajax({
				url:pageData.baseurl + '/index.php/ajax/admin-template/widget',
				data:({
					'widgets': widgets,
	  				'pagetemplateid': $('#txtPageTemplateId').val()
	  			}),
	  			type:'POST',
	  			dataType: 'json',
	  			complete:function(){
					if (modulesLoaded) $('#loading-dialog').dialog('close');
					$('body').css('cursor', 'auto');
				},
	  			success:function(result){
					moduleInstancesLoaded = true;
					if (result && $.isArray(result.widgets)){
						$.each(result.widgets, function(index, widget){
							if (!widget.widgetid || Number(widget.widgetid) < 1 || !widget.template) return true; //skip
							var section = (widget.displaysection && Number(widget.displaysection) > 0) ? widget.displaysection : 0;

							//append widget template to the DOM
							var $addedModule = $(widget.template).appendTo($('#page-editor-dialog .canvas-layout.show .canvas-widget-list.section-' + section).height('auto'));
							if (!$addedModule.hasClass('channel-widget')) {
								$('#page-editor-dialog .canvas-widget:not(.channel-widget) .edit-button a').live('click', function(){
							  		$('body').css('cursor', 'wait');
							  		var $widgetContainer = $(this).closest('.canvas-widget');
							  		var widgetId = $widgetContainer.attr('widget-id');
							  		var widgetName = $('.canvas-widget-title', $widgetContainer).html();

							  		$('#config-dialog .widget-loader').show();
							  		$('#config-dialog .widget-name h1').html(widgetName);
							  		$('#config-dialog .dialog-content .widget-config-container').hide().empty().removeClass('error');
							  		$('#config-dialog').dialog('open');

							  		//get config items of the selected widget
							  		$.ajax({
							  			url:pageData.baseurl + '/index.php/ajax/api/widget/fetchConfigSchema',
							  			data:({
							  				widgetid: widgetId,
							  				widgetinstanceid: $widgetContainer.attr('widget-instance-id')||'', //if this widget instance has been configured before, its widget instance id exists, so use it
							  				pagetemplateid: $('#select-template input[type=radio]:checked').val(),
							  				configtype: 'admin'
							  			}),
							  			type:'POST',
							  			dataType: 'json',
							  			complete:function(){
							  				$('body').css('cursor', 'auto');
							  			},
							  			success:function(result){
							  				if (result) {
							  					//set hidden fields
							  					$('#config_widgetid').val(result.widgetid);
							  					$('#config_widgetinstanceid').val(result.widgetinstanceid);
							  					$('#config_pagetemplateid, #txtPageTemplateId').val(result.pagetemplateid);

							  					//remember id of this widget instance for subsequent requests
							  					$widgetContainer.attr('widget-instance-id', result.widgetinstanceid);
												if (!result.configs || result.configs.length == 0) {
													$('.widget-config-container').html('No configurations found.').addClass('error');
													$('#btnSaveConfig').attr('disabled', 'disabled');
													$('#btnCloseConfig').focus();
												}
												else {
								  					//loop through all the config items
								  					var idx = 0; //result.configs is an object literal and not an indexed array so we cannot use $.each index for math operations.
								  					$.each(result.configs, function(index, config){
								  						var $configValue;
								  						//convert config item to corresponding UI control
								  						switch(config.type){
								  							case 'Text':
								  								$configValue = $('<input type="text" />')
								  												.attr({
								  													name: 'data[' + config.name + ']'
								  												})
								  												.css('width', '100%')
								  												.val(config['default']);
								  								break;
								  							case 'LongText':
								  								$configValue = $('<textarea />')
								  												.attr({
								  													rows:3,
								  													name: 'data[' + config.name + ']'
								  												})
								  												.css('width', '100%')
								  												.text(config['default']);
								  								break;
								  							case 'YesNo':
								  								var $options = {
								  									'option_1' : $('<input type="radio" value="1" />')
								  												.attr({
							  														name: 'data[' + config.name + ']',
							  														id: config.name + '_1'
							  													}),
							  										'label_1': $('<label />')
								  													.attr({'for': config.name + '_1'})
								  													.text('Yes'),
								  									'option_0' : $('<input type="radio" value="0" />')
								  												.attr({
							  														name: 'data[' + config.name + ']',
							  														id: config.name + '_0'
							  													}),
							  										'label_0': $('<label />')
								  													.attr({'for': config.name + '_0'})
								  													.text('No')
								  								}

								  								$options['option_'+config['default']].attr('checked', 'checked');
								  								$configValue = $('<div />')
								  									.append(
								  										$options['option_1'], $options['label_1'],
								  										$options['option_0'], $options['label_0']
								  									);
								  								break;
								  						}

								  						//put * if field is required
								  						$requiredMark = $('<div />')
								  										.addClass('config-required-mark left')
								  										.append(function(){
								  											return (config.isRequired==1) ? '*':'&nbsp;'
								  										});

								  						//disable field if config is not editable
								  						if (config.isEditable==0) {
								  							if (config.type=='YesNo') {
								  								$configValue.find('input').attr('disabled', 'disabled');
								  							}
								  							else {
								  								$configValue.attr('disabled', 'disabled');
								  							}
								  						}

														//append the config row
								  						$('#config-dialog .dialog-content .widget-config-container').append(
								  							$('<div></div>')
								  								.addClass(function(){
								  									return "config-row" + (((++idx) % 2 != 0) ? ' odd':'');
								  								})
								  								.append(
									  								$('<div></div>').addClass('config-label left').html(config.label),
									  								$requiredMark,
									  								$('<div></div>').addClass('config-value left').append($configValue),
									  								$('<div></div>').addClass('clear')
								  							)
								  						);
													});
								  				}
								  			}
							  				$('#config-dialog .dialog-content .widget-config-container').show();
											$('#config-dialog .widget-loader').hide();
							  			},
							  			error:function(xhr, statusText, error){
							  				showErrorDialog('<span>Error retrieving the configuration for \'{0}\' widget.<br /><br />Please try again.</span>'.format(widgetName), function(){
							  					$('#config-dialog').dialog('close');
											});
											$('#config-dialog .widget-loader').hide();
							  			}
									});
							  		return false;
								});
							}
						});

						adjustDivider();
					}
					else { //widgets in the ajax response is not an array - unlikely to occur but let's catch it for safety
						showErrorDialog('<span>Invalid server response.<br /><br />Please try again.</span>');
					}
				},
				error:function(xhr){
					showErrorDialog('<span>Error adding the widget(s).<br />(Error code {0})<br /><br />Please try again.</span>'.format(xhr.status));
				}
			});

			return false;
		}

		function adjustDivider(){
			var $rightCol = $('#page-editor-dialog .canvas-layout.show > div.has-adjacent-left-col');
			var $leftCol = $('#page-editor-dialog .canvas-layout.show > div.has-adjacent-right-col');
			if ($rightCol.length > 0 && $leftCol.length > 0) {

				if ($rightCol.height() > $leftCol.height()) {
					$leftCol.height($rightCol.height());
				}
				else if ($rightCol.height() < $leftCol.height()) {
					$leftCol.height('auto');
				}
			}
		}

		function makeSortableChannels(){
			$('#channel-config-dialog .channel-list').sortable({
				placeholder: "main-channel-container-highlight drag-highlight clear",
				update: function(event, ui){
					ui.item.css('z-index', '0'); //for IE7
					hasConfigChanged = true;
				},
				sort:function(event, ui){
					ui.item.addClass('shadow');
					//adjustDivider();
				},
				start:function(event, ui){
					ui.item.removeClass('shadow');
					if ($.browser.msie && parseInt($.browser.version, 10) == 8){ //IE8 widget height is bigger
						ui.item.height(ui.item.height()-4);
					}
					ui.item.css('z-index', '99999'); //for IE7
					ui.placeholder.height(ui.item.height());
				},
				over:function(event, ui){
					//console.debug('list over');
				},
				receive:function(event, ui){
					//console.debug('list receive');
				},
				out:function(event, ui){
					//console.debug('list out');
				},
				handle:'.grip-icon-main',
				items:'.main-channel-container'
			});
		}

		function makeSortableMainChannel(){
			$mainChannelSortable = $('.main-channel-container').sortable({
				connectWith: ".sub-channel-container",
				placeholder: "channel-item-highlight drag-highlight round-corner5",
				revert:true,
				update: function(event, ui){//console.debug('main update');
					//ui.item.css('z-index', '0'); //for IE7

					var $mainChannelContainer = ui.item.closest('.main-channel-container');

					//check the main channel container from where the item was dragged from
					if (ui.sender && ui.sender.hasClass('main-channel-container')){
						//remove the main channel container where the channel item came from if it has no sub channel items
						if ($('> .channel-item-container', ui.sender).length == 0){
							ui.sender.slideUp('fast', function(){$(this).remove()});
						}
					}

					hasConfigChanged = true;
				},
				sort:function(event, ui){
					//ui.item.addClass('shadow');
				},
				activate:function(event, ui){
					//console.debug('main activate');
				},
				start:function(event, ui){//console.debug('main start');
					/*ui.item.removeClass('shadow');
					if ($.browser.msie && parseInt($.browser.version, 10) == 8){ //IE8 widget height is bigger
						ui.item.height(ui.item.height()-4);
					}*/
					//ui.item.css('z-index', '99999'); //for IE7
					//ui.placeholder.height(ui.item.height());
				},
				stop:function(event, ui){
					$('.main-channel-container, .sub-channel-container').height('auto');
					//$('.sub-channel-container', ui.item).show();
				},
				over:function(event, ui){
					//console.debug('main over');
				},
				receive:function(event, ui){
					//console.debug('main receive');
				},
				out:function(event, ui){
					//console.debug('main out');
				},
				handle:'.channel-item-inner > .grip-icon-item',
				items:'.channel-item-container'
			});
		}

		function makeSortableSubChannel(){
			$subChannelSortable = $('.sub-channel-container').sortable({
				connectWith: ".sub-channel-container",
				revert:true,
				placeholder: "channel-item-highlight drag-highlight round-corner5",
				update: function(event, ui){//console.debug('sub update');
					//ui.item.css('z-index', '0'); //for IE7
					//check the main channel container from where the item was dragged from
					if (ui.sender && ui.sender.hasClass('main-channel-container')){
						//remove the main channel container where the channel item came from if it has no sub channel items
						if ($('> .channel-item-container', ui.sender).length == 0){
							ui.sender.slideUp('fast', function(){$(this).remove()});
						}
					}
					hasConfigChanged = true;
				},
				sort:function(event, ui){
					//ui.item.addClass('shadow');
				},
				start:function(event, ui){
					/*ui.item.removeClass('shadow');
					if ($.browser.msie && parseInt($.browser.version, 10) == 8){ //IE8 widget height is bigger
						ui.item.height(ui.item.height()-4);
					}*/
					//ui.item.css('z-index', '99999'); //for IE7
					//ui.placeholder.height(ui.item.height());
				},
				stop:function(event, ui){
					$('.main-channel-container, .sub-channel-container').height('auto');
				},
				over:function(event, ui){
					//console.debug('sub over');
				},
				receive:function(event, ui){
					//console.debug('sub receive');
				},
				out:function(event, ui){
					//console.debug('sub out');
				},
				handle:'.channel-item-inner > .grip-icon-item',
				items:'.channel-item-container'
			});
		}

		function addMainChannel(channelId, channelTitle, scrollToBottom){
			var $addedChannel =
				$('<div class="main-channel-container shadow">\
					<div class="grip-icon grip-icon-main left"><div>&uml;</div><div>&uml;</div><div>&uml;</div><div>&uml;</div><div>&uml;</div></div>\
					<div class="channel-item-container">\
						<div class="channel-item round-corner5 shadow" data-channel-id="{0}">\
							<div class="channel-item-inner">\
								<div class="grip-icon grip-icon-item left"><div>&uml;</div><div>&uml;</div><div>&uml;</div><div>&uml;</div><div>&uml;</div></div>\
								<div class="channel-title"><div title="Click text to edit title">{1}</div><input type="text" name="channeltitle" value="{1}" /></div>\
								<div class="close-button" title="Remove channel">x</div>\
								<div class="add-subchannel-button right" title="Add sub-channel"><a href="#">+</a></div>\
								<div class="clear"></div>\
							</div>\
						</div>\
						<div class="sub-channel-container"></div>\
					</div>\
			  </div>'.format(channelId, channelTitle))
			.appendTo($('.channel-list'));

			//scroll to the bottom
			if (scrollToBottom){
				var channelList = $('#channel-config-dialog .channel-list').get(0);
				$(channelList).animate({scrollTop: channelList.scrollHeight - channelList.clientHeight}, 'fast');
			}

			//enable drag n drop to the added channel
			makeSortableMainChannel();
			makeSortableSubChannel();

			hasConfigChanged = true;

			return $addedChannel;
		}

		function addSubChannel(channelId, channelTitle, $parentChannel){
			var $subChannelContainer = $parentChannel.hasClass('main-channel-container') ? $('> .channel-item-container > .sub-channel-container', $parentChannel) : $('> .sub-channel-container', $parentChannel)
			var $subChannel = $('<div class="channel-item-container">\
			       <div class="channel-item round-corner5 shadow" data-channel-id="{0}">\
					   <div class="channel-item-inner">\
						   <div class="grip-icon grip-icon-item left"><div>&uml;</div><div>&uml;</div><div>&uml;</div><div>&uml;</div><div>&uml;</div></div>\
						   <div class="channel-title"><div title="Click text to edit title">{1}</div><input type="text" name="channeltitle" value="{1}" /></div>\
						   <div class="close-button" title="Remove channel">x</div>\
						   <div class="add-subchannel-button right" title="Add sub-channel"><a href="#">+</a></div>\
						   <div class="clear"></div>\
					   </div>\
			      </div>\
			      <div class="sub-channel-container"></div>\
			   </div>'.format(channelId, channelTitle))
			.appendTo($subChannelContainer);

			makeSortableSubChannel($subChannel);

			hasConfigChanged = true;
			return $subChannel;
		}

		function loadModules(){
			$('#loading-dialog').dialog('open');
			$('body').css('cursor', 'wait');

			//retrieve modules via AJAX
			$.ajax({
				url:pageData.baseurl + '/index.php/ajax/fetch-widget-admin-template-list',
				dataType: 'json',
	  			complete:function(){
					if (templatesLoaded && moduleInstancesLoaded) $('#loading-dialog').dialog('close');
					$('body').css('cursor', 'auto');
				},
				success:function(result){
					modulesLoaded = true;
					if ($.isArray(result)){
						if (result.length > 0){
							//append 'All' and 'Search Result' categories
							$('<div class="category-arrow-left left" title="Previous">&lsaquo;</div>\
							   <div class="scroller category left">\
							       <div class="categories left">\
							           <div id="category-all" class="category selected round-corner7">All ({0})</div>\
							           <div id="category-result" class="category round-corner7 hide">Search Result (<span></span>)</div>\
							       </div>\
							   </div>\
							   <div class="category-arrow-right left" title="Next">&rsaquo;</div>\
							   <div class="clear"></div>'.format(result.length)
							  ).insertBefore('#page-editor-dialog .module-list-container .scroller');

							var categories = {};
							$.each(result, function(index, widget){
								if (!widget.widgetid || Number(widget.widgetid) < 1 || !widget.template) return true; //skip

								if (!categories[widget.category]){
									categories[widget.category] = {count:1, title: widget.category_title};
								}
								else {
									categories[widget.category].count++;
								}

								//append widget to the list using the exact template markup and put additional info
								$(widget.template)
									.attr('data-title', $('.canvas-widget-title', $(widget.template)).text().toLowerCase())
									.addClass('module-item list-item category-{0}'.format(widget.category))
									.appendTo('#page-editor-dialog .module-list');
							});

							//append the categories
							var totalWidth = 0;
							$.each(categories, function(index, category){
								var $category = $('<div id="category-{0}" class="category round-corner7">{1} ({2})</div>'.format(index, category.title, category.count)).insertBefore('#category-result');
								totalWidth += $category.outerWidth(true);
							});

							//resize categories list width
							$('.categories').width(totalWidth + $('#category-all').outerWidth(true));
							if ($('.categories').width() <= $('.scroller.category').width()){
								$('.category-arrow-left, .category-arrow-right').css('visibility', 'hidden');
							}
							else {
								$('.category-arrow-right').css('visibility', 'visible');
							}

							//resize module list width
							resizeListWidth(0);

							//make each module item draggable to the canvas
                            $('#page-editor-dialog .module-list .module-item').draggable({
								connectToSortable: "#page-editor-dialog .canvas-widget-list",
								helper: "clone",
								revert: "invalid",
								zIndex:2000,
								start: function(event, ui){
									moduleDragStart = true;
								},
								stop: function(event, ui){
									moduleDragStart = false;
								}
							}).disableSelection();

                            $('#page-editor-dialog .canvas-widget-list').sortable('refresh');

                            //search module autocomplete
                            var searchStarted = false;
        					$('#search-module-keyword').bind('keyup', function(event, manuallyTriggered){
        						var $addModules = $('#add-modules');
        						var $resultCategory = $('#category-result');
        						var $categories = $('.categories', $addModules);
        						var $scroller = $('.scroller.category', $addModules);

        						$('.module-item', $addModules).hide();
        						if (!manuallyTriggered){
	        						$('.category.selected', $addModules).removeClass('selected');
        						}

        						//search module title on the data-title attribute
        						//if search keyword is blank, no modules should be displayed
        						//but for IE, jQuery attributeContains selector ([attribute*="value"]) retrieves all elements if attribute is empty
        						//so we only search the attribute if search keyword is not empty
        						var keyword = $.trim(this.value.toLowerCase());
        						if (keyword){
        							$('.module-item[data-title*="{0}"]'.format(keyword)).show();
        						}

        						var visibleModuleCount = $('.module-item:visible', $addModules).length;
        						$('span', $resultCategory).text(visibleModuleCount);

        						resizeListWidth(0);

        						//show message when there are no modules in the search result
        						if (visibleModuleCount == 0){
        							$('.empty-module', $addModules).show();
        						}
        						else {
        							$('.empty-module', $addModules).hide();
        						}

        						$resultCategory.removeClass('hide').addClass('selected');
        						if (!searchStarted){
        							$categories.width($categories.width() + $resultCategory.outerWidth(true));
        						}
        						if ($categories.width() <= $scroller.width()){
    								$('.category-arrow-left, .category-arrow-right', $addModules).css('visibility', 'hidden');
    							}
    							else {
    								$('.category-arrow-left', $addModules).css('visibility', 'visible');
    								$('.category-arrow-right', $addModules).css('visibility', 'hidden');
    								var scrollerDom = $scroller.get(0);
    								$scroller.scrollLeft(scrollerDom.scrollWidth - scrollerDom.clientWidth);
    							}
        						searchStarted = true;

        						return true;
        					});

							//category click event handler
							$('#add-modules .category').click(function(){
								if ($(this).hasClass('selected')) return false;

								var $addModules = $('#add-modules');
								var $moduleItems = $('.module-item', $addModules);

								$('.category.selected', $addModules).removeClass('selected');
								$(this).addClass('selected');

								$moduleItems.hide();
								$('.empty-module', $addModules).hide();

								var categoryId = this.id;
								if (categoryId == 'category-all'){
									$moduleItems.show();
									resizeListWidth(0);
								}
								else if (categoryId == 'category-result'){
									$('#search-module-keyword').triggerHandler('keyup', [true]);

								}
								else {
									$('.module-item.{0}'.format(categoryId), $addModules).show();
									resizeListWidth(0);
								}
								return false;
							});

							//category left and right arrows click event handler
							var scrollTimer;
							$('.category-arrow-left').bind({
								mousedown: function(){
									$('.category-arrow-right').css('visibility', 'visible');
									scrollTimer = setInterval(function(){
										var $scroller = $('.scroller.category');
										$scroller.scrollLeft($scroller.scrollLeft() - 20);
										if ($scroller.scrollLeft() == 0 ){
											$('.category-arrow-left').css('visibility', 'hidden');
											clearInterval(scrollTimer);
										}
									}, 50);
								},
								mouseup: function(){
									clearInterval(scrollTimer);
								}
							}).disableSelection();

							$('.category-arrow-right').bind({
								mousedown: function(){
									$('.category-arrow-left').css('visibility', 'visible');
									scrollTimer = setInterval(function(){
										var $scroller = $('.scroller.category');
										$scroller.scrollLeft($scroller.scrollLeft() + 20);
										var scrollerDom = $scroller.get(0);
										if ($scroller.scrollLeft() == scrollerDom.scrollWidth - scrollerDom.clientWidth){
											$('.category-arrow-right').css('visibility', 'hidden');
											clearInterval(scrollTimer);
										}
									}, 50);
								},
								mouseup: function(){
									clearInterval(scrollTimer);
								}
							}).disableSelection();
						}
						else { //no modules retrieved
							$('<div class="empty-module">No modules found.</div>').appendTo('#page-editor-dialog .module-list');
						}
					}
					else { //widgets in the ajax response is not an array - unlikely to occur but let's catch it for safety
						showErrorDialog('<span>Invalid server response.<br /><br />Please try again.</span>');
					}
				},
				error:function(xhr){
					$('#loading-dialog').dialog('close');
					showErrorDialog('<span>Error retrieving modules. (Error code {0})</span>'.format(xhr.status));
				}
			});
		}

		function loadTemplates(){
			$('#loading-dialog').dialog('open');
			$('body').css('cursor', 'wait');

			//reset template list
			$('#page-editor-dialog .template-list').empty();

			$.ajax({
				url:pageData.baseurl + '/index.php/ajax/api/pagetemplate/fetchPageTemplateList',
				dataType: 'json',
	  			complete:function(){
					$('body').css('cursor', 'auto');
				},
	  			success:function(templates){
					templatesLoaded = true;
					//check results
					if ($.isArray(templates) && templates.length > 0) {
						$.each(templates, function(index, template) {
							$('<div class="template-item list-item left">\
									<input type="radio" name="pagetemplateid" value="{0}" data-thumbnail="{1}/{2}/img/template-icon-default.png"{3} />\
									<label class="label">{4}</label>\
							   </div>'.format(
									template.pagetemplateid,
									pageData.baseurl,
									pageData.admincpdir,
									($('#pagetemplateid').val() == template.pagetemplateid) ? ' checked="checked"' : '',
									template.title)
							).appendTo('#page-editor-dialog .template-list')
							 .data({
								 'screenlayoutid': template.screenlayoutid,
								 'widgetinstances': template.widgetinstances
							 });
						});

						//transform template radio buttons as thumbnails
						$radioThumbnail = $('#page-editor-dialog .template-list .template-item input[type=radio]').thumbnailRadioCheckbox({
							thumbnailClass:'radio-checkbox-thumbnail template-border shadow',
							preselect:function($thumbnail, $radio){
								if ($radio.is(':checked')) {
									return false;
								}
								if (hasCanvasChanged || hasConfigChanged){
									openConfirmDialog({
										'title': 'Switch Template?',
										'content': '<p>All layout and module changes you made to the template including the changes in the Module configuration will be lost.</p><p>Do you want to continue?</p>',
										'data': {
											'yes-callback': function(){
												$radioThumbnail.thumbnailRadioCheckbox('check', $radio, true);
												hasCanvasChanged = false;
												hasConfigChanged = false;
												templateChanged = true;
											}
										}
									});
									return false;
								}
								templateChanged = true;
								return true;
							},
							select:function($thumbnail, $radio){
							 	$thumbnail.css({'border-style':'inset', 'border-color':'#FFF'});
								$thumbnail.parent().removeClass('shadow');
								$('#page-editor-dialog .canvas-layout.show').removeClass('show').addClass('hide');

								var screenlayoutid = $radio.closest('.template-item').data('screenlayoutid');

								//show associated screen layout
								$('#page-editor-dialog .canvas-layout[layout-id=' + screenlayoutid + ']').removeClass('hide').addClass('show');

								//reset modules
								$('#page-editor-dialog .canvas-widget-list').empty();

								//load associated modules
								var widgetInstances = $radio.closest('.template-item').data('widgetinstances');
								if ($.isArray(widgetInstances) && widgetInstances.length > 0){
									moduleInstancesLoaded = false;
									var widgets = [];
									$.each(widgetInstances, function(index, widget){
										widgets.push({widgetid: widget.widgetid, widgetinstanceid: widget.widgetinstanceid});
									});
									addWidgets(widgets, true);
								}
								else {
									$('#loading-dialog').dialog('close');
								}

								//update 'Overwrite existing template' radio button value with the new selected template id
								//$('#save-page-form #pagetemplateid').val($radio.val());

								templateChanged = true;
							},
							unselect:function(){
								$('#page-editor-dialog .template-list .template-border img').css('border-style', 'solid');
								$('#page-editor-dialog .template-list .template-border').addClass('shadow');
							}
						});

						//set the minimum height of the scroller's parent
						if ($('#page-editor-dialog .template-list').height() > parseFloat($('#page-editor-dialog .template-list').css('min-height'))){
							$('#page-editor-dialog .tabs .tab .right').css('min-height', $('#page-editor-dialog .template-list').height() + 'px')
						}
					}
					else {
						$('#loading-dialog').dialog('close');
						showErrorDialog('<span>Error retrieving templates.</span>');
					}
				},
				error:function(xhr){
					$('#loading-dialog').dialog('close');
					showErrorDialog('<span>Error retrieving templates. (Error code {0})</span>'.format(xhr.status));
				}
			});
		}

		function displaySubChannels(subchannels, $parentChannel){
			$.each(subchannels, function(j, subChannel){
				var $parentSubChannel = $('<li data-channel-id="{0}">Sub-Channel: <span>{1}</span><ul class="widget-subchannel-list"></ul></li>'.format(subChannel.nodeid, subChannel.title)).appendTo($('> .widget-subchannel-list', $parentChannel));
				displaySubChannels(subchannels[j].subchannels, $parentSubChannel.eq(0));
			});
		}

		function addSubChannels($subchannels, $parentChannel){
			$subchannels.each(function(index){
				var $subChannel = $(this);
				var $parentSubChannel = addSubChannel($subChannel.attr('data-channel-id'), $('>span', $subChannel).html(), $parentChannel);
				addSubChannels($('> .widget-subchannel-list > li', $subChannel), $parentSubChannel);
			});
		}

		function resizeListWidth(tabIndex){
			//resize the width of the templates, layouts or modules list in order for its parent (scroller div) to have horizontal scrollbar
			//the contents of these lists are floating elements, so we have to manually resize the width
			var $moduleItem = $('#page-editor-dialog .tabs .tab:eq({0}) .list-item'.format(tabIndex));
			$moduleItem.parent().width(
				Math.max(
					$moduleItem.outerWidth(true) * $moduleItem.filter(':visible').length),
					parseFloat($moduleItem.parent().css('min-width')
				)
			);
		}

		initPage();
	});
})(jQuery);