NIHVIVO-2810 NIHVIVO-2232 Added custom list view for display:hasElement and first go at menu item drag-n-drop for menu management. Also added new entry for Menu Management on site admin page under site configuration. Work in progress and not fully functional.
This commit is contained in:
parent
6fac9339d6
commit
44ee8c88bf
6 changed files with 255 additions and 9 deletions
37
webapp/web/config/listViewConfig-hasElement.xml
Normal file
37
webapp/web/config/listViewConfig-hasElement.xml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<!-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<!-- Custom list view config file for display:hasElement property (used for menu system)
|
||||||
|
|
||||||
|
See guidelines in vitro/doc/list_view_configuration_guidelines.txt -->
|
||||||
|
|
||||||
|
<list-view-config>
|
||||||
|
<query-select>
|
||||||
|
PREFIX display: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#>
|
||||||
|
PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#>
|
||||||
|
|
||||||
|
SELECT ?menuItem
|
||||||
|
(afn:localname(?menuItem) AS ?menuItemName)
|
||||||
|
?linkText
|
||||||
|
?menuPosition WHERE {
|
||||||
|
?subject ?property ?menuItem
|
||||||
|
OPTIONAL { ?menuItem display:linkText ?linkText }
|
||||||
|
OPTIONAL { ?menuItem display:menuPosition ?menuPosition }
|
||||||
|
} ORDER BY ?menuPosition
|
||||||
|
</query-select>
|
||||||
|
|
||||||
|
<query-construct>
|
||||||
|
CONSTRUCT {
|
||||||
|
?subject ?property ?menuItem .
|
||||||
|
?menuItem ?menuItemProp ?menuItemObj
|
||||||
|
} WHERE {
|
||||||
|
{ ?subject ?property ?menuItem }
|
||||||
|
UNION {
|
||||||
|
?subject ?property ?menuItem .
|
||||||
|
?menuItem ?menuItemProp ?menuItemObj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</query-construct>
|
||||||
|
|
||||||
|
<template>propStatement-hasElement.ftl</template>
|
||||||
|
</list-view-config>
|
20
webapp/web/css/individual/menuManagement.css
Normal file
20
webapp/web/css/individual/menuManagement.css
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
/* MENU ITEMS------> */
|
||||||
|
ul.menuItems {
|
||||||
|
width: 35%;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
}
|
||||||
|
ul.menuItems li {
|
||||||
|
margin: .2em 0;
|
||||||
|
padding: .5em;
|
||||||
|
background: #f3f3f0;
|
||||||
|
}
|
||||||
|
ul.menuItems.dragNdrop li {
|
||||||
|
padding-left: 1em;
|
||||||
|
background: url("../../edit/forms/images/sortable_icon.png") no-repeat .4em center #f3f3f0;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
span.controls {
|
||||||
|
float: right;
|
||||||
|
}
|
150
webapp/web/js/individual/menuManagement.js
Normal file
150
webapp/web/js/individual/menuManagement.js
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
var menuManagement = {
|
||||||
|
|
||||||
|
// Initial page setup
|
||||||
|
onLoad: function() {
|
||||||
|
this.mergeFromTemplate();
|
||||||
|
this.initMenuItemData();
|
||||||
|
this.initObjects();
|
||||||
|
this.initMenuItemsDD();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add variables from menupage template
|
||||||
|
mergeFromTemplate: function() {
|
||||||
|
$.extend(this, menuManagementData);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Create references to frequently used elements for convenience
|
||||||
|
initObjects: function() {
|
||||||
|
this.menuItemsList = $('ul.menuItems');
|
||||||
|
},
|
||||||
|
|
||||||
|
// Drag-and-drop
|
||||||
|
initMenuItemsDD: function() {
|
||||||
|
var menuItems = this.menuItemsList.children('li');
|
||||||
|
|
||||||
|
if (menuItems.length < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.menuItemsList.addClass('dragNdrop');
|
||||||
|
|
||||||
|
menuItems.attr('title', 'Drag and drop to reorder menu items');
|
||||||
|
|
||||||
|
this.menuItemsList.sortable({
|
||||||
|
cursor: 'move',
|
||||||
|
update: function(event, ui) {
|
||||||
|
alert("Congrats! You just reordered a menu item. (not really)");
|
||||||
|
// Once we figure out how the editing will work, we'll call reorderMenuItems
|
||||||
|
// and get rid of the debug alert.
|
||||||
|
// menuManagement.reorderMenutItems(event, ui);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Reorder menu items. Called after menu item drag-and-drop
|
||||||
|
// This is all make-believe at the moment. Just an example to demonstrate to Huda how this could work.
|
||||||
|
reorderMenuItems: function(event, ui) {
|
||||||
|
var menuItems = $('li.menuItem').map(function(index, el) {
|
||||||
|
return $(this).data('menuItemUri');
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: menuManagement.reorderUrl,
|
||||||
|
data: {
|
||||||
|
predicate: menuManagement.positionPredicate,
|
||||||
|
individuals: menuItems
|
||||||
|
},
|
||||||
|
traditional: true, // serialize the array of individuals for the server
|
||||||
|
dataType: 'json',
|
||||||
|
type: 'POST',
|
||||||
|
success: function(data, status, request) {
|
||||||
|
var pos;
|
||||||
|
$('.menuItem').each(function(index){
|
||||||
|
pos = index + 1;
|
||||||
|
// Set the new position for this element. The only function of this value
|
||||||
|
// is so we can reset an element to its original position in case reordering fails.
|
||||||
|
menuManagement.setPosition(this, pos);
|
||||||
|
});
|
||||||
|
// Set the form rank field value.
|
||||||
|
$('#rank').val(pos + 1);
|
||||||
|
},
|
||||||
|
error: function(request, status, error) {
|
||||||
|
// ui is undefined after removal of a menu item.
|
||||||
|
if (ui) {
|
||||||
|
// Put the moved item back to its original position.
|
||||||
|
// Seems we need to do this by hand. Can't see any way to do it with jQuery UI. ??
|
||||||
|
var pos = menuManagement.getPosition(ui.item),
|
||||||
|
nextpos = pos + 1,
|
||||||
|
menuItems = menuManagement.menuItemsList,
|
||||||
|
next = menuManagement.findMenuItem('position', nextpos);
|
||||||
|
|
||||||
|
if (next.length) {
|
||||||
|
ui.item.insertBefore(next);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.item.appendTo(menuItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
alert('Reordering of menu items failed.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// On page load, associate data with each menu item list element. Then we don't
|
||||||
|
// have to keep retrieving data from or modifying the DOM as we manipulate the
|
||||||
|
// menu items.
|
||||||
|
initMenuItemData: function() {
|
||||||
|
$('.menuItem').each(function(index) {
|
||||||
|
$(this).data(menuItemData[index]);
|
||||||
|
|
||||||
|
// RY We might still need position to put back an element after reordering
|
||||||
|
// failure. Position might already have been reset? Check.
|
||||||
|
// We also may need position to implement undo links: we want the removed menu item
|
||||||
|
// to show up in the list, but it has no position.
|
||||||
|
$(this).data('position', index+1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getPosition: function(menuItem) {
|
||||||
|
return $(menuItem).data('position');
|
||||||
|
},
|
||||||
|
|
||||||
|
setPosition: function(menuItem, pos) {
|
||||||
|
$(menuItem).data('position', pos);
|
||||||
|
},
|
||||||
|
|
||||||
|
findMenuItem: function(key, value) {
|
||||||
|
var matchingMenuItem = $(); // if we don't find one, return an empty jQuery set
|
||||||
|
|
||||||
|
$('.menuItem').each(function() {
|
||||||
|
var menuItem = $(this);
|
||||||
|
if ( menuItem.data(key) === value ) {
|
||||||
|
matchingMenuItem = menuItem;
|
||||||
|
return false; // stop the loop
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return matchingMenuItem;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Event listeners
|
||||||
|
|
||||||
|
// Disable drag-n-drop and associated cues if only one menu item remains
|
||||||
|
// Good chance we won't need this if Huda's able to hook into standard delete for n3 editing (loads confirmation in separate page)
|
||||||
|
disableMenuItemsDD: function() {
|
||||||
|
var menuItems = this.menuItemsList.children('li');
|
||||||
|
|
||||||
|
this.menuItemsList.sortable({ disable: true } );
|
||||||
|
|
||||||
|
this.menuItemsList.removeClass('dragNdrop');
|
||||||
|
|
||||||
|
menuItems.removeAttr('title');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
menuManagement.onLoad();
|
||||||
|
});
|
|
@ -4,16 +4,20 @@
|
||||||
|
|
||||||
<#include "individual-setup.ftl">
|
<#include "individual-setup.ftl">
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var menuItemData = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
<h3>Menu management</h3>
|
<h3>Menu management</h3>
|
||||||
|
|
||||||
<#assign hasElement = propertyGroups.pullProperty("${namespaces.display}hasElement")>
|
<#assign hasElement = propertyGroups.pullProperty("${namespaces.display}hasElement")>
|
||||||
|
|
||||||
<#-- List the menu items -->
|
<#-- List the menu items -->
|
||||||
|
<ul class="menuItems">
|
||||||
<#list hasElement.statements as statement>
|
<#list hasElement.statements as statement>
|
||||||
Position | <#include "${hasElement.template}"> | <@p.editingLinks "hasElement" statement editable /> <br />
|
<li class="menuItem"><#include "${hasElement.template}"> <span class="controls"><@p.editingLinks "hasElement" statement editable /></a></li>
|
||||||
</#list>
|
</#list>
|
||||||
|
</ul>
|
||||||
<br /> <#-- remove this once styles are applied -->
|
|
||||||
|
|
||||||
<#-- Link to add a new menu item -->
|
<#-- Link to add a new menu item -->
|
||||||
<#if editable>
|
<#if editable>
|
||||||
|
@ -23,6 +27,23 @@
|
||||||
</#if>
|
</#if>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/individual/individual.css" />')}
|
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/individual/individual.css" />',
|
||||||
|
'<link rel="stylesheet" href="${urls.base}/css/individual/menuManagement.css" />')}
|
||||||
|
|
||||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/individual/individualUtils.js"></script>')}
|
${headScripts.add('<script type="text/javascript" src="${urls.base}/js/jquery-ui/js/jquery-ui-1.8.9.custom.min.js"></script>')}
|
||||||
|
|
||||||
|
<#assign positionPredicate = "${namespaces.display}menuPosition" />
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
// <#-- We need the controller to provide ${reorderUrl}. This is where ajax request will be sent on drag-n-drop events. -->
|
||||||
|
var menuManagementData = {
|
||||||
|
// <#-- reorderUrl: '${reorderUrl}', -->
|
||||||
|
positionPredicate: '${positionPredicate}'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<#-- Since the individual page can currently be viewed by anonymous users, only invoke sortable if logged in for now
|
||||||
|
Jim is working on this (see NIHVIVO-2749) -->
|
||||||
|
<#if editable>
|
||||||
|
${scripts.add('<script type="text/javascript" src="${urls.base}/js/individual/menuManagement.js"></script>')}
|
||||||
|
</#if>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Template for display:hasElement (used for menu system).
|
||||||
|
|
||||||
|
This template must be self-contained and not rely on other variables set for the individual page, because it
|
||||||
|
is also used to generate the property statement during a deletion.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<#-- Anchor is here for convenience during development. Should be removed before release -->
|
||||||
|
<a href="${profileUrl(statement.menuItem)}">${statement.linkText}</a>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
menuItemData.push({
|
||||||
|
'menuItemUri': '${statement.menuItem}'
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -14,7 +14,9 @@
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if siteConfig.urls.menuN3Editor??>
|
<#if siteConfig.urls.menuN3Editor??>
|
||||||
<li><a href="${siteConfig.urls.menuN3Editor}">Menu management</a></li>
|
<#-- once new menu management is ready to go, we'll want to add a url for this to siteConfig.urls and remove menu.n3 editor -->
|
||||||
|
<li><a href="${urls.base}/individual?uri=http%3A%2F%2Fvitro.mannlib.cornell.edu%2Fontologies%2Fdisplay%2F1.1%23DefaultMenu&switchToDisplayModel=true">Menu Management</a> (in development)</li>
|
||||||
|
<li><a href="${siteConfig.urls.menuN3Editor}">menu.n3 editor</a></li>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if siteConfig.urls.userList??>
|
<#if siteConfig.urls.userList??>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue