Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Third level control on feature and events tree with new hovering effects #544

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion index.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ function attr($attr, $file) {
<link rel="stylesheet" href="/resources/css/layout.css" />
<link rel="stylesheet" href="/resources/css/accordions.css" />
<link rel="stylesheet" href="/resources/css/dialogs.css" />
<link rel="stylesheet" href="/resources/css/celestial-bodies.css" />
<link rel="stylesheet" href="/resources/css/events.css" />
<link rel="stylesheet" href="/resources/css/event-viewer.css" />
<link rel="stylesheet" href="/resources/css/media-manager.css" />
Expand All @@ -128,7 +129,6 @@ function attr($attr, $file) {
<link rel="stylesheet" href="/resources/css/youtube.css" />
<link rel="stylesheet" href="/resources/css/font-awesome.min.css" />
<link rel="stylesheet" href="/resources/css/helioviewer-views.css" />
<link rel="stylesheet" href="/resources/css/celestial-bodies.css" />
<?php
} else {
?>
Expand Down
5 changes: 4 additions & 1 deletion resources/css/events.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
width: 23px;
transform-origin: bottom;
}

.event-label, .event-label-hover {
color: white;
font-family: Arial, Helvetica, sans-serif;
Expand All @@ -47,10 +48,12 @@
top: 4px;
white-space: nowrap;
}

.event-label-hover {
background-color: rgba(24, 24, 24, 0.95);
z-index: 1000;
font-size: 13px;
}

.event-region {
background-repeat: no-repeat;
position: absolute;
Expand Down
198 changes: 180 additions & 18 deletions resources/js/Events/EventManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var EventManager = Class.extend({
this._uniqueId = treeid

this.updateRequestTime();
setTimeout($.proxy(this._queryEventFRMs, this), 100);
setTimeout($.proxy(this._queryEventFRMs, this), 100);

// Set up javascript event handlers
$(document).bind("fetch-eventFRMs", $.proxy(this._queryEventFRMs, this));
Expand Down Expand Up @@ -84,7 +84,7 @@ var EventManager = Class.extend({
},

_getCheckedEvents: function () {
return Helioviewer.userSettings.get("state.events." + this._uniqueId + ".layers");
return Helioviewer.userSettings.get("state.events_v2." + this._uniqueId + ".layers");
},

/**
Expand Down Expand Up @@ -191,19 +191,33 @@ var EventManager = Class.extend({
});
});
this._events = all_events;

$.each( this._events, function(i, event) {
if ( typeof self._eventTypes[event['pin']] != 'undefined' ) {
self._eventMarkers.push(
new EventMarker(eventGlossary,
self._eventTypes[event['pin']]._eventFRMs[event['name']],
event, i+1)
);

let parentFRM = self._eventTypes[event['pin']]._eventFRMs[event['name']];
let eventMarker = new EventMarker(eventGlossary, parentFRM, event, i+1);

self._eventMarkers.push(eventMarker);
}
});
this._toggleEvents();
},

/**
* @description generate event instance id from event variables from backend
* @param {string} evenType of eventInstance
* @param {string} frmName of eventInstance
* @param {string} eventID of eventInstance, this id is not css or jquery friendly , that is why we need base64 encode it to make it friendly
* @returns {string} generate event instance id
*/
_makeEventInstanceTreeNodeID: function(eventType, frmName, eventID) {

let escapedFrmName = this._escapeInvalidCssChars(frmName);
let encodedEventID = this._escapeInvalidCssChars(btoa(eventID));

return `${eventType}--${escapedFrmName}--${encodedEventID}`;
},

/**
* Generates jsTree structure from HEK search data and then constructs
* a new tree if one does not exist, or reloads the existing one if
Expand All @@ -229,7 +243,10 @@ var EventManager = Class.extend({

obj = Object();
obj['data'] = event_type_arr[0];
obj['attr'] = { 'id' : event_type_arr[1] };
obj['attr'] = {
'id' : event_type_arr[1],
'hvtype': 'event_type',
};
obj['state'] = 'open';
obj['children'] = [];

Expand All @@ -240,18 +257,30 @@ var EventManager = Class.extend({
let group_count = group.data.length;
type_count += group_count;

// Generate event instances nodes for jstree
let group_children = group.data.map(d => {
return {
'data': d.short_label ?? d.label,
'attr': {
'id': self._makeEventInstanceTreeNodeID(event_type_arr[1], group.name, d.id),
'hvtype': 'event_instance',
},
'children':[]
}
});

count_str = '';
if ( group_count > 0 ) {
count_str = " ("+group_count+")";
self._jsTreeData[index].children.push(
{
'data': group.name+count_str,
'attr':
{
'id': event_type_arr[1]
+ '--'
+ self._escapeInvalidCssChars(group.name)
}
'attr': {
'id': event_type_arr[1]+'--'+ self._escapeInvalidCssChars(group.name),
'hvtype': 'frm'
},
'children': group_children,
'state' : 'closed',
}
);
}
Expand All @@ -266,7 +295,6 @@ var EventManager = Class.extend({
index++;
});


// Create a new EventTree object only if one hasn't already been created
if (!self._eventTree) {
self._eventTree = new EventTree(this._uniqueId, this._jsTreeData, this._treeContainer, self);
Expand All @@ -293,6 +321,7 @@ var EventManager = Class.extend({

_escapeInvalidCssChars: function (selector) {
selector = selector.replace(/ /g, "_");
selector = selector.replace(/=/g, "_");
selector = selector.replace(/([\+\.\(\)])/g, '\\$1');

return selector;
Expand Down Expand Up @@ -360,6 +389,10 @@ var EventManager = Class.extend({
_toggleEvents: function () {
var newState, checkedEventTypes = [], checkedFRMs = {}, self = this;

// This a tree structure, where keys are frms not partially selected
// values are the ids of event instances , selected under this frm inside jstree
var notFullySelectedFRMSAndChildrens = {};

newState = this._getCheckedEvents();

// Populate checkedEventTypes and checkedFRMs to make it easier to
Expand All @@ -370,9 +403,30 @@ var EventManager = Class.extend({

checkedFRMs[checkedTypeObj['event_type']] = [];
$.each ( checkedTypeObj['frms'], function(j, frmName) {
var frmNameChanged = frmName.replace(/\\/g,'');
var frmNameChanged = frmName.replace(/\\/g,'');
checkedFRMs[checkedTypeObj['event_type']].push(frmNameChanged);
});

// Iterate on partially selected events under frm
// we are going to build above state object: notFullySelectedFRMSAndChildrens
$.each ( checkedTypeObj['event_instances'], function(j, eventInstance) {
var eventInstanceNewName = eventInstance.replace(/\\/g,'');
let parsedFrm = eventInstanceNewName.split("--")[1];

// Frm for those event_instances, should be included into the visible frm list
if(!checkedFRMs[checkedTypeObj['event_type']].includes(parsedFrm)) {
checkedFRMs[checkedTypeObj['event_type']].push(parsedFrm);
}

// If we haven't already seen frm , in our fake frm and childrens data, define it
// or add it
if(!notFullySelectedFRMSAndChildrens.hasOwnProperty(parsedFrm)) {
notFullySelectedFRMSAndChildrens[parsedFrm] = [eventInstanceNewName];
} else {
notFullySelectedFRMSAndChildrens[parsedFrm].push(eventInstanceNewName);
}

});
});

$.each( this._eventTypes, function(eventTypeName, eventTypeObj) {
Expand All @@ -386,10 +440,42 @@ var EventManager = Class.extend({
else {
// eventTypeName/frmName pair is checked
// so .show() this FRM's event layer
let underScoredFrmName = frmName.replace(/ /g,'_');
if ( checkedFRMs[eventTypeName][0] == 'all' ||
$.inArray(frmName.replace(/ /g,'_'), checkedFRMs[eventTypeName]) != -1 ) {
$.inArray(underScoredFrmName, checkedFRMs[eventTypeName]) != -1 ) {

self._eventTypes[eventTypeName]._eventFRMs[frmName].domNode.show();

// For each event markers of frm , we need to make them visible.
// because we are hiding them occasionaly
self._eventMarkers.filter(em => {
return em.belongsToFrm(frmName) && em.belongsToEventType(eventTypeName)
}).forEach(m => m.setVisibility(true));

// if this frm is not fully selected
// we are going to hide its children which are not in our checked event_instances
// event_instances are the deepest level in the jstree, they are the individual markers
if(notFullySelectedFRMSAndChildrens.hasOwnProperty(underScoredFrmName)) {

let eventsToBeShownForFRM = notFullySelectedFRMSAndChildrens[underScoredFrmName];

let concerningEventMarkers = self._eventMarkers.forEach(em => {

// generate jsTreeCheckBoxID from this marker
// TODO _makeEventInstanceTreeNodeID can be moved to EventMarker
let jsTreeCheckboxID = self._makeEventInstanceTreeNodeID(eventTypeName, underScoredFrmName, em.id);

// if our id for this marker not in selected list
let notClickedChildOfFRM = !eventsToBeShownForFRM.includes(jsTreeCheckboxID);
let childToHide = em.belongsToEventType(eventTypeName) && em.belongsToFrm(frmName) && notClickedChildOfFRM;

// please hide it
if(childToHide) {
em.setVisibility(false);
}

})
}
}
// eventTypeName/frmName pair is NOT checked
// so .hide() this FRM's event layer
Expand All @@ -403,6 +489,82 @@ var EventManager = Class.extend({
this.eventLabels();
},

/**
* @description emphasize markers matching the given jsTreeNodeID, this function parses jsTreeNodeID, decides it is frm or eventtype or eventinstance , then emphasize matching markers.
* @param {string} jsTreeNodeID. nodeIds generated when building the tree
* @returns void
*/
emphasizeMarkers: function (jsTreeNodeID) {
self = this;
return (event) => {
let parts = jsTreeNodeID.split('--');

let markersToEmphasize = [];

// this is an event instance
if(parts.length == 3) {
markersToEmphasize = this._eventMarkers.filter(em => {
return jsTreeNodeID == self._makeEventInstanceTreeNodeID(em.pin, em.name, em.id);
});
}

// this is an frm
if(parts.length == 2) {
markersToEmphasize = this._eventMarkers.filter(em => {
return em.belongsToFrm(parts[1]);
});
}

// this is an event type
if(parts.length == 1) {
markersToEmphasize = this._eventMarkers.filter(em => {
return em.belongsToEventType(parts[0])
});
}

markersToEmphasize.forEach(m => {
m.emphasize();
});
}
},

/**
* @description deEmphasize markers matching the given jsTreeNodeID, this function parses jsTreeNodeID, decides it is frm or eventtype or eventinstance , then deEmphasize matching markers.
* @param {string} jsTreeNodeID. nodeIds generated when building the tree
* @returns void
*/
deEmphasizeMarkers: function (jsTreeNodeID) {
return (event) => {
let parts = jsTreeNodeID.split('--');
let markersToDeEmphasize = [];

// this is an event instance
if(parts.length == 3) {
markersToDeEmphasize = this._eventMarkers.filter(em => {
return jsTreeNodeID == self._makeEventInstanceTreeNodeID(em.pin, em.name, em.id);
});
}

// this is an frm
if(parts.length == 2) {
markersToDeEmphasize = this._eventMarkers.filter(em => {
return em.belongsToFrm(parts[1])
});
}

// this is an event type
if(parts.length == 1) {
markersToDeEmphasize = this._eventMarkers.filter(em => {
return em.belongsToEventType(parts[0])
});
}

markersToDeEmphasize.forEach(m => {
m.deEmphasize();
});
}
},

toggleEventLabels: function (event, labelsBtn) {

if (typeof labelsBtn == 'undefined') {
Expand Down
Loading
Loading