Integration between science map widget and data table widget

This commit is contained in:
kongchinhua 2011-05-26 23:31:39 +00:00
parent 80fc455b9d
commit d07238287e
12 changed files with 459 additions and 166 deletions

View file

@ -0,0 +1,97 @@
var ControlPanel = Class.extend({
init: function(options) {
this.options = $.extend({}, this.options, options);
this.initDiv();
},
options: {
divClass: null, // use this to set absolute position and style
controlPositions: google.maps.ControlPosition.RIGHT_TOP, // Refer to API for alternative value
map: null, // map to be add to
jQueryDiv: null // add custom div
},
initDiv: function() {
var opt = this.options;
if (opt.jQueryDiv == null) {
opt.jQueryDiv = $(document.createElement('div'));
}
if (opt.divClass) {
opt.jQueryDiv.addClass(opt.divClass);
}
this.div = opt.jQueryDiv[0];
opt.map.controls[opt.controlPositions].push(this.div);
},
getDiv: function() {
/* Allow to edit everything start from div level by returning div jquery object */
return this.options.jQueryDiv;
},
hide: function() {
var div = this.div;
if (div) {
div.style.display = "none";
}
},
show: function() {
var div = this.div;
if (div) {
div.style.display = "block";
}
}
});
var SliderControlPanel = ControlPanel.extend({
init: function(options) {
this._super(options);
this.initSlider();
},
initSlider: function() {
var me = this;
var label = $("<div />").width(20).css("font-size", "60%").css("float", "right").text("0");
var slider = $("<div />").width(150).css("font-size","60%");
slider.slider({
slide: function(event, ui) {
me._setLabel(ui.value);
}
});
this.sliderDiv = slider;
this.labelDiv = label;
var div = me.getDiv();
div.css("margin-right", "10px");
div.append(slider);
div.append(label);
},
getValue: function () {
return this.sliderDiv.slider( "option", "value" );
},
setMin: function(min) {
this.sliderDiv.slider({
min: min
});
},
setMax: function(max) {
this.sliderDiv.slider({
max: max
});
},
setValue: function(value) {
this.sliderDiv.slider({
value: value
});
this._setLabel(value);
},
_setLabel: function(value) {
if (value < 1) {
this.labelDiv.text("0");
} else {
this.labelDiv.text(value);
}
},
setChangeEventHandler: function(handlerFunc) {
this.sliderDiv.slider({
change: handlerFunc
});
}
});

View file

@ -13,6 +13,30 @@ var ScinodePolygon = Polygon.extend({
setSize: function(size) {
this.polygon.setRadius(size);
this.setZIndex(-size);
},
focus: function() {
this.setOptions({strokeWeight: 2.0});
},
unfocus: function() {
this.setOptions({strokeWeight: 1.0});
},
registerEvents : function() {
var me = this;
var polygon = me.polygon;
this.registerEvent(addClickListener(polygon, function() {
INFO_WINDOW.setPosition(this.center);
var content = '<div style="font-size: 80%; padding: 5px; text-align: left;"><b>' + this.label +'</b><br />' + this.value + ' publications </div>';
INFO_WINDOW.setContent(content);
INFO_WINDOW.open(this.map);
}));
this.registerEvent(addMouseOverListener(polygon, function() {
me.focus();
}));
this.registerEvent(addMouseOutListener(polygon, function() {
me.unfocus();
}));
}
});

File diff suppressed because one or more lines are too long

View file

@ -4,7 +4,7 @@ var DataTableWidget = Class.extend({
widgetType: "MAIN_SCIENCE_AREAS",
currentSelectedFilter: "DISCIPLINE",
currentSelectedFilter: SCIMAP_TYPE.DISCIPLINE,
dom: {
searchBarParentContainerClass : "searchbar",
@ -67,7 +67,8 @@ var DataTableWidget = Class.extend({
}
});
});
me.setupView();
},
hasKey: function(key) {
return (this.keyToMarkerManagers.hasOwnProperty(key));
@ -78,8 +79,9 @@ var DataTableWidget = Class.extend({
},
cleanUp: function() {
},
initView: function() {
},
setupView: function() {
var me = this;
@ -95,7 +97,7 @@ var DataTableWidget = Class.extend({
var scienceAreasTH = $('<th>');
scienceAreasTH.attr("id", "science-areas-th");
if (this.currentSelectedFilter === 'SUBDISCIPLINE' ) {
if (this.currentSelectedFilter === SCIMAP_TYPE.SUBDISCIPLINE ) {
scienceAreasTH.html('Sub-Disciplines');
} else {
scienceAreasTH.html('Disciplines');
@ -123,18 +125,18 @@ var DataTableWidget = Class.extend({
var i = 0;
$.each(me.disciplineInfo, function(index, item) {
rowsToInsert[i++]  = '<tr><td>DISCIPLINE</td>';
    rowsToInsert[i++]  = '<td>' + item.label + '</td>';
    rowsToInsert[i++]  = '<td>' + item.publicationCount.toFixed(1) + '</td>';
    rowsToInsert[i++]  = '<td>' + (100 * (item.publicationCount / me.pubsMapped)).toFixed(1) + '</td></tr>';
rowsToInsert[i++] = '<tr><td>' + SCIMAP_TYPE.DISCIPLINE + '</td>';
rowsToInsert[i++] = '<td>' + item.label + '</td>';
rowsToInsert[i++] = '<td>' + item.publicationCount.toFixed(1) + '</td>';
rowsToInsert[i++] = '<td>' + (100 * (item.publicationCount / me.pubsMapped)).toFixed(1) + '</td></tr>';
});
$.each(me.subdisciplineInfo, function(index, item) {
rowsToInsert[i++]  = '<tr><td>SUBDISCIPLINE</td>';
    rowsToInsert[i++]  = '<td>' + item.label + '</td>';
    rowsToInsert[i++]  = '<td>' + item.publicationCount.toFixed(1) + '</td>';
    rowsToInsert[i++]  = '<td>' + (100 * (item.publicationCount / me.pubsMapped)).toFixed(1) + '</td></tr>';
rowsToInsert[i++] = '<tr><td>' + SCIMAP_TYPE.SUBDISCIPLINE + '</td>';
rowsToInsert[i++] = '<td>' + item.label + '</td>';
rowsToInsert[i++] = '<td>' + item.publicationCount.toFixed(1) + '</td>';
rowsToInsert[i++] = '<td>' + (100 * (item.publicationCount / me.pubsMapped)).toFixed(1) + '</td></tr>';
});
tbody.append(rowsToInsert.join(''));
@ -193,37 +195,62 @@ var DataTableWidget = Class.extend({
me.widget.fnFilter("");
});
$("." + me.dom.filterOptionClass).live('click', function() {
/* $("." + me.dom.filterOptionClass).live('click', function() {
if (!$(this).hasClass(me.dom.activeFilterClass)) {
if ($(this).attr('id') === me.dom.subdisciplinesFilterID) {
$("#" + me.dom.disciplineFilterID).removeClass(me.dom.activeFilterClass);
////
$("#science-areas-th").html("Sub-Disciplines");
me.widget.fnSettings()._iDisplayLength = 10;
me.currentSelectedFilter = "SUBDISCIPLINE";
me.currentSelectedFilter = SCIMAP_TYPE.SUBDISCIPLINE;
$("a#csv").attr("href", entityMapOfScienceSubDisciplineCSVURL);
////
} else if ($(this).attr('id') === me.dom.disciplineFilterID) {
$("#" + me.dom.subdisciplinesFilterID).removeClass(me.dom.activeFilterClass);
////
$("#science-areas-th").html("Disciplines");
me.currentSelectedFilter = "DISCIPLINE";
me.currentSelectedFilter = SCIMAP_TYPE.DISCIPLINE;
me.widget.fnSettings()._iDisplayLength = 13;
$("a#csv").attr("href", entityMapOfScienceDisciplineCSVURL);
////
}
$(this).addClass('active-filter');
////
ACTIVE_DISCIPLINE_SUBDISCIPLINE_FILTER = me.currentSelectedFilter;
me.widget.fnDraw();
////
}
});
});*/
},
changeFilter: function(filterType) {
if (filterType === SCIMAP_TYPE.SUBDISCIPLINE) {
$("#science-areas-th").html("Sub-Disciplines");
me.widget.fnSettings()._iDisplayLength = 10;
me.currentSelectedFilter = SCIMAP_TYPE.SUBDISCIPLINE;
$("a#csv").attr("href", entityMapOfScienceSubDisciplineCSVURL);
} else {
$("#science-areas-th").html("Disciplines");
me.currentSelectedFilter = SCIMAP_TYPE.DISCIPLINE;
me.widget.fnSettings()._iDisplayLength = 13;
$("a#csv").attr("href", entityMapOfScienceDisciplineCSVURL);
}
ACTIVE_DISCIPLINE_SUBDISCIPLINE_FILTER = me.currentSelectedFilter;
me.widget.fnDraw();
}
});

View file

@ -48,8 +48,6 @@ function addClickListener(marker, actionFunction) {
return GEVENT.addListener(marker, 'click', actionFunction);
}
function removeListeners(handlers) {
$.each(handlers, function(){
GEVENT.removeListener(this);
});
function removeListener(handler) {
GEVENT.removeListener(handler);
}

View file

@ -1,21 +1,17 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
var map;
var markerManager;
var universityModeMarkerManagers;
var textControl;
var legendControl;
var downloader;
var sliderControl;
var currentVisMode;
var currentController;
var visModeControllers = {};
var dataTableWidgets = {};
var responseContainerID = "map-of-science-response";
var loadingScreenTimeout;
/*
* This method will setup the options for loading screen & then activate the
* loading screen.
* */
*/
function setupLoadingScreen() {
$.blockUI.defaults.overlayCSS = {
@ -44,11 +40,10 @@ function setupLoadingScreen() {
+ '</i> is now being refreshed. The visualization will load as soon as we are done computing, '
+ 'or you can come back in a few minutes.</h3>')
.css({'cursor': 'pointer'});
}, 10 * 1000);
}
function loadMap() {
function initMap() {
var gMap = google.maps;
var centerLatLng = new google.maps.LatLng(50, 0);
@ -66,36 +61,21 @@ function loadMap() {
var mapName = 'Scimap';
createScimapType(map, mapName);
map.setMapTypeId(mapName);
}
function initMapControls() {
//textControl = new TextControl({map: map, divClass: 'time_div'});
//textControl.setText("1991");
sliderControl = new SliderControlPanel({
map:map,
controlPositions: google.maps.ControlPosition.RIGHT_BOTTOM
});
downloader = new DownloadManager();
}
function initVisModeController() {
var controller = new EntityVisModeController(map);
var controller = new EntityVisModeController(map, sliderControl);
visModeControllers[controller.visMode] = controller;
switchVisMode(controller.visMode);
}
function initDataTableWidget() {
var widget = new DataTableWidget();
dataTableWidgets[widget.widgetType] = widget;
}
function initMarkers() {
downloader = new DownloadManager();
loadMarkers(ENTITY_VIS_MODE, scienceMapDataURL, false);
}
function initMap() {
setupLoadingScreen();
loadMap();
initMapControls();
initVisModeController();
initDataTableWidget();
initMarkers();
currentController.loadData(scienceMapDataURL, false);
}
function helper() {
@ -104,5 +84,7 @@ function helper() {
/* Using .load instead of .ready due to issue with IE and Google Maps API */
$(window).load(function() {
setupLoadingScreen();
initMap();
initVisModeController();
});

View file

@ -12,6 +12,13 @@ var MarkerManager = Class.extend({
addMarker: function(key, marker) {
this.keyToMarker[key] = marker;
},
length: function() {
var size = 0;
for (var key in this.keyToMarker) {
if (this.keyToMarker.hasOwnProperty(key)) size++;
}
return size;
},
getMarker: function(key) {
return this.keyToMarker[key];
},
@ -29,6 +36,7 @@ var MarkerManager = Class.extend({
});
},
addMarkersToMap: function() {
// console.log(this.keyToMarker);
$.each(this.keyToMarker, function(i, marker) {
marker.addToMap();
});
@ -79,6 +87,37 @@ ScimapMarkerManager = MarkerManager.extend({
marker.setSize(me.sizeCodingFunc(marker.getValue()));
marker.setColor(me.colorStrategy.getColor(key));
}
},
display: function(numberOfMarkers) {
$.each(this.keyToMarker, function(i, marker) {
if (i <= numberOfMarkers) {
marker.show();
} else {
marker.hide();
}
});
},
mouseIn: function(key) {
var marker = this.getMarker(key);
if (marker) {
marker.focus();
}
},
mouseInAll: function() {
$.each(this.keyToMarker, function(i, marker) {
marker.focus();
});
},
mouseIn: function(key) {
var marker = this.getMarker(key);
if (marker) {
marker.unfocus();
}
},
mouseOutAll: function() {
$.each(this.keyToMarker, function(i, marker) {
marker.unfocus();
});
}
});

View file

@ -1,3 +1,5 @@
var INFO_WINDOW = createInfoWindow("", 300);
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
var Polygon = Class.extend({
init : function(options) {
@ -21,8 +23,8 @@ var Polygon = Class.extend({
this.registerEvents();
},
removeFromMap : function() {
this.polygon.setMap(null);
this.unregisterEvents();
this.polygon.setMap(null);
},
show : function() {
this.polygon.setMap(this.options.map);
@ -38,16 +40,28 @@ var Polygon = Class.extend({
setTitle : function(title) {
this.polygon.title = title;
},
setOptions: function(options) {
this.polygon.setOptions(options);
},
registerEvent : function(handler) {
var me = this;
if (me.handlers == null) {
me.handlers = new Array();
}
me.handlers.push(handler);
},
unregisterEvent : function(handler) {
if (this.handlers[handler]) {
removeListener(handler);
delete(this.handlers[handler]);
}
},
registerEvents : function() {
var handlers = new Array();
var polygon = this.polygon;
handlers.push(addClickListener(polygon, function() {
updateIFrame(this.url);
}));
this.handlers = handlers;
},
unregisterEvents : function() {
removeListeners(this.handlers);
$.each(this.handlers, function(){
removeListener(this);
});
this.handlers = null;
}
});

View file

@ -0,0 +1,139 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
var DEFAULT_SLIDER_VALUE = 20;
var ScimapWidget = Class.extend({
init: function(map, sliderControl) {
this.activeManager = null;
this.isUnloaded = true;
this.map = map;
this.sliderControl = sliderControl;
this.initView();
},
initView: function(){
var me = this;
me.initMarkerManagers();
me.sliderControl.setChangeEventHandler(function(event, ui) {
me.updateDisplayedMarkers(ui.value);
});
me.show(SCIMAP_TYPE.DISCIPLINE);
},
initMarkerManagers: function() {
if (this.keyToMarkerManagers == null) {
var managers = {};
// Create discipline Marker Manager
managers[SCIMAP_TYPE.DISCIPLINE] = new DisciplineMarkerManager(
this.map,
new DisciplineColorStrategy(),
null
);
// Create subdiscipline Marker Manager
managers[SCIMAP_TYPE.SUBDISCIPLINE] = new SubdisciplineMarkerManager(
this.map,
new SubdisciplineColorStrategy(),
null
);
this.keyToMarkerManagers = managers;
}
},
needLoaded: function(){
return this.isUnloaded;
},
loadJsonData: function(data) {
var me = this;
me.uri = data.uri;
me.label = data.label;
me.pubsWithNoJournals = data.pubsWithNoJournals;
me.pubsWithInvalidJournals = data.pubsWithInvalidJournals;
me.pubsMapped = data.pubsMapped;
$.each(this.keyToMarkerManagers, function(key, manager) {
// Need to create the AreaSizeCoding function
manager.setSizeCoder(new CircleSizeCoder({
scaler: new Scaler({ maxValue: me.pubsMapped })
}));
//markerManager.setSiseCodingFunction(new AreaSizeCoding(0, data.pubsMapped));
$.each(data.subdisciplineActivity, function(subdiscipline, density) {
// Create marker and add it to manager
var marker = manager.createMarker(subdiscipline, density);
}); // end each subdisciplineActivity
}); // end each markerManagers
me.updateMap();
this.isUnloaded = false;
},
mouseIn: function(key, childKey) {
var manager = this.getMarkerManager(key);
// Focus if only it is an active manager
if (manager == this.activeManager) {
// Focus all if no childKey is given
if (childKey) {
manager.mouseIn(childKey);
} else {
manager.mouseInAll();
}
}
},
mouseOut: function(key, childKey) {
var manager = this.getMarkerManager(key);
// Focus if only it is an active manager
if (manager == this.activeManager) {
// Unfocus all if no childKey is given
if (childKey) {
manager.mouseOut(childKey);
} else {
manager.mouseOutAll();
}
}
},
getMarkerManager: function(key) {
return this.keyToMarkerManagers[key];
},
hasKey: function(key) {
return (this.keyToMarkerManagers.hasOwnProperty(key));
},
show: function(key) {
var manager = this.getMarkerManager(key);
if (manager) {
this._switchActiveManager(manager);
}
},
hide: function(key) {
var manager = this.getMarkerManager(key);
if (this.activeManager == manager) {
this.cleanup();
}
},
_switchActiveManager: function(manager) {
if (this.activeManager != manager) {
this.cleanUp();
manager.addMarkersToMap();
this.activeManager = manager;
this.updateMap();
}
},
cleanUp: function() {
if (this.activeManager) {
this.activeManager.removeMarkersFromMap();
}
},
updateDisplayedMarkers: function(numberOfMarkers) {
this.activeManager.display(numberOfMarkers);
},
updateMap: function() {
var manager = this.activeManager;
if (manager) {
var length = manager.length();
var slider = this.sliderControl;
slider.setMin(Math.min(1, length));
slider.setMax(length);
slider.setValue(Math.min(DEFAULT_SLIDER_VALUE, length));
}
},
changeFilter: function(filterType) {
this.show(filterType);
}
});

View file

@ -33,39 +33,3 @@ function switchVisMode(visMode) {
}
return
}
function loadMarkers(visMode, url, sync) {
// Download data from server and add to markerManager if not gotten already
var controller = getVisModeController(visMode);
if (controller.needLoaded()) {
if (sync) {
downloader.downloadAndWait(url, function(data) {
loadJSONToMarkerManager(data, visMode);
loadJSONToDataTableWidget(data);
});
} else {
downloader.download(url, function(data) {
loadJSONToMarkerManager(data, visMode);
loadJSONToDataTableWidget(data);
});
}
} // end if
}
function loadJSONToMarkerManager(data, visMode) {
if (data) {
var controller = getVisModeController(visMode);
controller.loadJsonData(data[0]);
}
}
function loadJSONToDataTableWidget(data) {
if (data) {
var widget = dataTableWidgets["MAIN_SCIENCE_AREAS"];
widget.loadJsonData(data[0]);
widget.initView();
$("#" + responseContainerID).unblock();
}
}

View file

@ -2,88 +2,91 @@
var ENTITY_VIS_MODE = "ENTITY";
var EntityVisModeController = Class.extend({
init: function(map) {
this.keyToMarkerManagers = {};
this.activeManager = null;
init: function(map, sliderControl) {
this.visMode = ENTITY_VIS_MODE;
this.isUnloaded = true;
this.map = map;
this.initMarkerManagers(map);
this.initWidgets(map, sliderControl);
},
initMarkerManagers: function(map) {
var managers = this.keyToMarkerManagers;
initFilter: function() {
// Create discipline Marker Manager
managers['discipline'] = new DisciplineMarkerManager(
map,
new DisciplineColorStrategy(),
null
);
var dom = {
disciplineFilterID: "discipline-filter",
subdisciplinesFilterID: "subdisciplines-filter",
filterOptionClass: "filter-option",
activeFilterClass: "active-filter"
},
// Create subdiscipline Marker Manager
managers['subdiscipline'] = new SubdisciplineMarkerManager(
map,
new SubdisciplineColorStrategy(),
null
);
$("." + dom.filterOptionClass).live('click', function() {
if (!$(this).hasClass(dom.activeFilterClass)) {
if ($(this).attr('id') === dom.subdisciplinesFilterID) {
$("#" + dom.disciplineFilterID).removeClass(dom.activeFilterClass);
$.each(this.widgets, function(i, widget) {
widget.changeFilter(SCIMAP_TYPE.SUBDISCIPLINE);
});
} else if ($(this).attr('id') === dom.disciplineFilterID) {
$("#" + dom.subdisciplinesFilterID).removeClass(dom.activeFilterClass);
$.each(this.widgets, function(i, widget) {
widget.changeFilter(SCIMAP_TYPE.DISCIPLINE);
});
}
$(this).addClass('active-filter');
}
});
},
initView: function(){
this.show('subdiscipline');
initWidgets: function(map, sliderControl) {
var widgets = {};
widgets['scimap'] = new ScimapWidget(map, sliderControl);
widgets['sci_area_table'] = new DataTableWidget();
this.widgets = widgets;
},
needLoaded: function(){
needLoaded: function() {
return this.isUnloaded;
},
loadJsonData: function(data) {
initView: function() {
$.each(this.widgets, function(i, widget) {
widget.initView();
});
},
loadData: function(url, sync) {
// Download data from server and add to markerManager if not gotten already
var me = this;
me.uri = data.uri;
me.label = data.label;
me.pubsWithNoJournals = data.pubsWithNoJournals;
me.pubsWithInvalidJournals = data.pubsWithInvalidJournals;
me.pubsMapped = data.pubsMapped;
$.each(this.keyToMarkerManagers, function(key, manager) {
// Need to create the AreaSizeCoding function
manager.setSizeCoder(new CircleSizeCoder({
scaler: new Scaler({ maxValue: me.pubsMapped })
}));
//markerManager.setSiseCodingFunction(new AreaSizeCoding(0, data.pubsMapped));
$.each(data.subdisciplineActivity, function(subdiscipline, density) {
// Create marker and add it to manager
var marker = manager.createMarker(subdiscipline, density);
if (isActiveVisMode(me.visMode) && manager == me.activeManager) {
marker.show();
}
}); // end each subdisciplineActivity
}); // end each markerManagers
this.isUnloaded = false;
if (me.isUnloaded) {
if (sync) {
downloader.downloadAndWait(url, function(data) {
me.loadJsonData(me, data[0]);
});
} else {
downloader.download(url, function(data) {
me.loadJsonData(me, data[0]);
});
}
} // end if
},
getMarkerManager: function(key) {
return this.keyToMarkerManagers[key];
},
hasKey: function(key) {
return (this.keyToMarkerManagers.hasOwnProperty(key));
loadJsonData: function(me, data) {
$.each(me.widgets, function(i, widget) {
widget.loadJsonData(data);
});
me.isUnloaded = false;
$("#" + responseContainerID).unblock();
},
// key can be discippline or subdiscipline
show: function(key) {
var manager = this.getMarkerManager(key);
var activeManager = this.activeManager;
if (activeManager != manager) {
this.cleanUp();
manager.addMarkersToMap();
}
this.activeManager = manager;
$.each(this.widgets, function(i, widget) {
widget.show(key);
});
},
hide: function(key) {
var manager = this.getMarkerManager(key);
if (this.activeManager == manager) {
this.cleanup();
}
$.each(this.widgets, function(i, widget) {
widget.hide(key);
});
},
cleanUp: function() {
if (this.activeManager) {
this.activeManager.removeMarkersFromMap();
}
$.each(this.widgets, function(i, widget) {
widget.cleanUp(key);
});
}
});

View file

@ -59,12 +59,14 @@ ${scripts.add('<script type="text/javascript" src="http://maps.google.com/maps/a
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/ClassExtendUtils.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/DownloadManager.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/GMapAPI.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/ControlPanel.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/ColorStrategy.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/SizeCoding.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/CustomScimaps.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/Polygon.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/CustomMarker.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/MarkerManager.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/ScimapWidget.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/DataTableWidget.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/VisModeControllers.js"></script>',
'<script type="text/javascript" src="${urls.base}/js/visualization/mapofscience/VisCommonControl.js"></script>',