app.js 9.84 KB
// Set up global error handling
$().ready(function(){
	$.ajaxSetup({
		error:function(x,e){
			if(x.status==0){
				alert('You are offline!!\n Please Check Your Network.');
			} else if(x.status==404){
				alert('Requested URL not found.');
			}else if(x.status==500){
				alert('Internal Server Error.');
			}else if(e=='parsererror'){
				alert('Error.\nParsing JSON Request failed.');
			}else if(e=='timeout'){
				alert('Request Time out.');
			}else {
				alert('Unknown Error.\n'+x.responseText);
			}
		}
	});
});

// Global index that is incremented at each appAddRow operation
var addRowIndex = 0;

var uispinServlet = 'uispin';


/**
 * Called when the user clicks Add to add a new row to a widget.
 * This takes the prototype with the given id and clones it,
 * replacing the system Ids.
 * @param id  the id of the div containing the editor prototype
 * @param single  to hide the 
 */
function appAddRow(id, single) {
	var prototype = $('#' + id);
	var clone = prototype.clone();
	var uid = clone.find('.appEditorHiddenField').attr('name').substring(8);
	var newUid = 'addedRowUid' + addRowIndex;
	var initializer = null;
	clone.attr('id', clone.attr('id') + '-' + addRowIndex);
	clone.find('*').each(function(index, element) {
		if($(element).hasClass('appDeleteRowButton')) {
			$(element).removeAttr('onclick');
			$(element).click(function() {
				appDeleteRow(newUid);
			});
		}
		if($(element).hasClass('appWidgetInitializer')) {
			initializer = $(element);
		}
		$.each(this.attributes, function(i, attrib) {
			var name = attrib.name;
			var oldValue = attrib.value;
			if(oldValue.indexOf(uid) != -1) {
				var newValue = oldValue.replace(uid, newUid);
				$(element).attr(name, newValue);
			}
		});
	});
	addRowIndex++;
	clone.children().insertBefore(prototype.parent());
	if(initializer) {
		eval('(' + initializer.attr('content') + ')');
		initializer.remove();
	}
	if(single) {
		prototype.parent().parent().find('.appAddButtonDiv').each(function(i,item) {
			$(item).css('display', 'none');
		});
	}
}


/**
 * Called when the user clicks delete to delete a row from a widget.
 * This completely deletes the element with the given id.
 * The hidden fields to instruct the server that the given object
 * shall be deleted are kept, and moved under the parent of the row. 
 * The function also makes sure that the add button is visible.
 * @param id  the id of the element to delete
 */
function appDeleteRow(id) {
	var row = $('#' + id);
	
	row.parent().parent().find('.appAddButtonDiv').each(function(index, item) {
		$(item).css('display', '');
	});
	
	row.find('.appEditorHiddenField').appendTo(row.parent());
	row.remove();
}


/**
 * Turns an input element with a given id into a jQuery auto-complete.
 * The actually selected resource will be returned to the server with
 * a hidden field that needs to be passed into this function as well.
 * @param id  the id of the visible input element
 * @param hiddenId  the id of the hidden field
 * @param link  the link for the server callback 
 */
function appInitAutoComplete(id, hiddenId, link) {
	$('#' + id).autocomplete({
		dataType : 'json',
		source : link,
		formatItem : function(item) {
			return item.label;
		},
		select : function(event, ui) {
			$('#' + hiddenId).val(ui.item.resource);
		}
	});
}


/**
 * Turns an input element with a given widget id into a jQuery datepicker.
 * @param id  the uid of the widget
 */
function appInitDatePicker(id) {
	$('#dateEditor' + id).datepicker({ 
		altField: '#new-' + id, 
		altFormat: 'yy-mm-dd', 
		dateFormat: 'yy-mm-dd',
	});
}


/**
 * Replaces a form with another mode.
 * This is for example called as handler of the Edit and Cancel buttons.
 * @param formId  the id of the form to replace
 * @param mode  the name of the new mode
 * @param resourceURI  the URI of the resource
 * @param resourceTypeURI  the URI of the resource type (optional)
 * @param queryGraphURI  the URI of the query graph
 * @returns false to stop further processing
 */
function appLoadForm(formId, mode, resourceURI, resourceTypeURI, queryGraphURI) {
	var data = {
		formId: formId,
		modeName: mode,
		_viewClass: 'app:FormSelector',
		_snippet: true
	};
	if(resourceURI) {
		data.resource = '<' + resourceURI + '>';
	}
	if(resourceTypeURI) {
		data.resourceType = '<' + resourceTypeURI + '>';
	}
	if(queryGraphURI) {
		data._base = '<' + queryGraphURI + '>';
	}
	$.get(uispinServlet, data, function(data) {
		$('#' + formId).parent().html(data); 
	});
	return false;
}


/**
 * Loads an edit form into a given element.
 * @param parentId  the id of the element to load into
 * @param resourceType  the class to edit
 */
function appLoadEditForm(parentId, resourceType) {
	var data = {
		modeName: 'edit',
		resourceType: resourceType,
		_viewClass: 'app:FormSelector',
		_snippet: true
	};
	$.get(uispinServlet, data, function(data) {
		$('#' + parentId).html(data); 
	});
	return false;
}


/**
 * Replaces a given element (specified by oldElementId) with a search form
 * for a given resource type, using a specified query graph.
 * @param oldElementId  the id of the element to replace - this will be the id of the new form.
 * @param resultsId  the id of the element to display the search results
 * @param resourceTypeURI  the type of resources to search for
 * @param queryGraphURI  the query graph URI
 * @param schemaGraphURI  (optional) the URI of the schema graph
 * @param noBorder  (optional) to suppress the border
 */
function appLoadSearchForm(oldElementId, resultsId, resourceTypeURI, queryGraphURI, schemaGraphURI, noBorder) {
	var data = {
		formId: oldElementId,
		resourceType: '<' + resourceTypeURI + '>',
		resultsId: resultsId,
		_base : '<' + queryGraphURI + '>',
		_viewClass : 'app:SearchForm',
		_snippet : true
	};
	if(schemaGraphURI) {
		data.schemaGraph = '<' + schemaGraphURI + '>';
	}
	if(noBorder) {
		data.noBorder = true;
	}
	$.get(uispinServlet, data, function(data) {
		$('#' + oldElementId).parent().html(data); 
	});
}


/**
 * Loads a SearchResultsGrid based on the selections in a form with
 * a given id.  Will replace the content of a given target element.
 * @param formId  the form id
 * @param targetId  the target id
 * @param queryGraphURI  the current query graph
 * @returns false
 */
function appLoadSearchResultsGrid(formId, targetId, queryGraphURI) {
	var params = $('#' + formId).serialize();
	var escaped = '&params=' + escape(params);
	$.get(uispinServlet + '?_viewClass=app:SearchResultsGrid&_snippet=true&' + 
			'_base=' + escape('<' + queryGraphURI + '>') +
			'&' + params + escaped, function(data) {
		$('#' + targetId).html(data);
	});
	return false;
}


/**
 * Changes the location (URL) of the current browser window to the
 * URL of the uispin servlet with the default view of a given resource
 * and a given context graph
 * @param resourceURI  the URI of the resource to navigate to
 * @param queryGraphURI  the URI of the current query graph
 * @return false
 */
function appNavigateTo(resourceURI, queryGraphURI) {
	window.location = uispinServlet + '?_base=' + escape(queryGraphURI) + 
		'&_resource=' + escape(resourceURI);
}


/**
 * Opens a new tab or browser window with the URL of the uispin servlet
 * with the default view of a given resource and a given context graph
 * @param resourceURI  the URI of the resource to navigate to
 * @param queryGraphURI  the URI of the current query graph
 */
function appNavigateToInTab(resourceURI, queryGraphURI) {
	window.open('uispinServlet' + '?_base=' + escape(queryGraphURI) + 
		'&_resource=' + escape(resourceURI));
}


/**
 * Walks up the parents of a 'link' element with a given id until it
 * finds a form. Then it replaces that form with a new form displaying
 * a given resource.
 * @param resourceURI  the URI of the resource to load
 * @param queryGraphURI  the current query graph
 * @param linkElement  an element that is contained within the form
 */
function appReloadForm(resourceURI, queryGraphURI, linkElementId) {
	var form = $('#' + linkElementId).closest('.appForm');
	if(!form) {
		alert('appReloadForm can only be called within an .appForm');
		return;
	}
	var id = form.attr('id');
	appLoadForm(id, 'view', resourceURI, null, queryGraphURI);
}


/**
 * Submits a form and switches it to viewing mode when done.
 * @param form  the id of the form
 * @param servlet  the optional name of the servlet
 * @returns false to stop further processing
 */
function appSubmitForm(form, servlet) {
	if(!servlet) {
		servlet = 'swpEdit';
	}
	var params = $(form).serialize();
	$.getJSON(servlet + '?' + params, function(data) {
		if(data.errors) {
			var msg = data.errors.length + ' Constraint violations:';
			$.each(data.errors, function(index, item) {
				msg += '\n - ' + item.message;
			});
			appUpdateFormErrors(form, data.errors);
			alert(msg);
		}
		else {
			var root = data.rootResource;
			appLoadForm(form, 'view', root);
		}
	});
	return false;
}


/**
 * Displays or clears the error indicators on a given form, based
 * on an array of errors (as produced by the SPIN constraint validation)
 * @param form  the id of the form containing the indicators 
 * @param errors  the errors to display
 */
function appUpdateFormErrors(form, errors) {
	$(form).find('.appErrorIndicator').each(function(index, itemElement) {
		var item = $(itemElement);
		var e = false;
		$.each(errors, function(i, error) {
			if(item.attr('id') == 'error-' + error.path) {
				e = true;
				item.addClass('ui-icon');
				item.addClass('ui-icon-alert');
				item.attr('title', error.message);
			}
		});
		if(!e) {
			item.removeClass('ui-icon');
			item.removeClass('ui-icon-alert');
			item.removeAttr('title');
		}
	});
}


/**
 * Validates a form and updates the errors.
 * @param form  the id of the form
 * @returns false to stop further processing
 */
function appValidateForm(form) {
	var params = $(form).serialize();
	$.getJSON('swpEdit?validateOnly=true&' + params, function(data) {
		if(data.errors) {
			appUpdateFormErrors(form, data.errors);
		}
		else {
			appUpdateFormErrors(form, []);
		}
	});
	return false;
}