metamaps--metamaps/frontend/src/Metamaps/Filter.js

454 lines
14 KiB
JavaScript
Raw Normal View History

/* global $ */
2016-04-15 00:36:50 +00:00
2016-09-22 15:51:33 +00:00
import _ from 'lodash'
2016-09-22 09:36:47 +00:00
import Active from './Active'
import Control from './Control'
import DataModel from './DataModel'
2016-09-22 10:31:56 +00:00
import GlobalUI from './GlobalUI'
2016-09-22 09:36:47 +00:00
import Settings from './Settings'
import Visualize from './Visualize'
const Filter = {
2016-04-15 00:36:50 +00:00
filters: {
name: '',
metacodes: [],
mappers: [],
synapses: []
},
visible: {
metacodes: [],
mappers: [],
synapses: []
},
isOpen: false,
changing: false,
2016-11-07 20:25:08 +00:00
init: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
$('.sidebarFilterIcon').click(self.toggleBox)
$('.sidebarFilterBox .showAllMetacodes').click(self.filterNoMetacodes)
$('.sidebarFilterBox .showAllSynapses').click(self.filterNoSynapses)
$('.sidebarFilterBox .showAllMappers').click(self.filterNoMappers)
$('.sidebarFilterBox .hideAllMetacodes').click(self.filterAllMetacodes)
$('.sidebarFilterBox .hideAllSynapses').click(self.filterAllSynapses)
$('.sidebarFilterBox .hideAllMappers').click(self.filterAllMappers)
self.bindLiClicks()
self.getFilterData()
},
2016-11-07 20:25:08 +00:00
toggleBox: function(event) {
var self = Filter
2016-04-15 00:36:50 +00:00
if (self.isOpen) self.close()
else self.open()
event.stopPropagation()
},
2016-11-07 20:25:08 +00:00
open: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
2016-09-22 10:31:56 +00:00
GlobalUI.Account.close()
2016-04-15 00:36:50 +00:00
$('.sidebarFilterIcon div').addClass('hide')
if (!self.isOpen && !self.changing) {
self.changing = true
var height = $(document).height() - 108
2016-11-07 20:25:08 +00:00
$('.sidebarFilterBox').css('max-height', height + 'px').fadeIn(200, function() {
2016-04-15 00:36:50 +00:00
self.changing = false
self.isOpen = true
})
}
},
2016-11-07 20:25:08 +00:00
close: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
$('.sidebarFilterIcon div').removeClass('hide')
if (!self.changing) {
self.changing = true
2016-11-07 20:25:08 +00:00
$('.sidebarFilterBox').fadeOut(200, function() {
2016-04-15 00:36:50 +00:00
self.changing = false
self.isOpen = false
})
}
},
2016-11-07 20:25:08 +00:00
reset: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
self.filters.metacodes = []
self.filters.mappers = []
self.filters.synapses = []
self.visible.metacodes = []
self.visible.mappers = []
self.visible.synapses = []
$('#filter_by_metacode ul').empty()
$('#filter_by_mapper ul').empty()
$('#filter_by_synapse ul').empty()
$('.filterBox .showAll').addClass('active')
},
/*
Most of this data essentially depends on the ruby function which are happening for filter inside view filterBox
But what these function do is load this data into three accessible array within java : metacodes, mappers and synapses
*/
2016-11-07 20:25:08 +00:00
getFilterData: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
var metacode, mapper, synapse
2016-11-07 20:25:08 +00:00
$('#filter_by_metacode li').each(function() {
2016-04-15 00:36:50 +00:00
metacode = $(this).attr('data-id')
self.filters.metacodes.push(metacode)
self.visible.metacodes.push(metacode)
})
2016-11-07 20:25:08 +00:00
$('#filter_by_mapper li').each(function() {
2016-04-15 00:36:50 +00:00
mapper = ($(this).attr('data-id'))
self.filters.mappers.push(mapper)
self.visible.mappers.push(mapper)
})
2016-11-07 20:25:08 +00:00
$('#filter_by_synapse li').each(function() {
2016-04-15 00:36:50 +00:00
synapse = ($(this).attr('data-id'))
self.filters.synapses.push(synapse)
self.visible.synapses.push(synapse)
})
},
2016-11-07 20:25:08 +00:00
bindLiClicks: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
$('#filter_by_metacode ul li').unbind().click(self.toggleMetacode)
$('#filter_by_mapper ul li').unbind().click(self.toggleMapper)
$('#filter_by_synapse ul li').unbind().click(self.toggleSynapse)
},
// an abstraction function for checkMetacodes, checkMappers, checkSynapses to reduce
// code redundancy
/*
@param
*/
2016-11-07 20:25:08 +00:00
updateFilters: function(collection, propertyToCheck, correlatedModel, filtersToUse, listToModify) {
var self = Filter
2016-04-15 00:36:50 +00:00
var newList = []
var removed = []
var added = []
// the first option enables us to accept
// ['Topics', 'Synapses'] as 'collection'
if (typeof collection === 'object') {
2016-11-07 20:25:08 +00:00
DataModel[collection[0]].each(function(model) {
2016-04-15 00:36:50 +00:00
var prop = model.get(propertyToCheck)
if (prop !== null) {
prop = prop.toString()
if (newList.indexOf(prop) === -1) {
newList.push(prop)
}
}
})
2016-11-07 20:25:08 +00:00
DataModel[collection[1]].each(function(model) {
2016-04-15 00:36:50 +00:00
var prop = model.get(propertyToCheck)
if (prop !== null) {
prop = prop.toString()
if (newList.indexOf(prop) === -1) {
newList.push(prop)
}
}
})
} else if (typeof collection === 'string') {
2016-11-07 20:25:08 +00:00
DataModel[collection].each(function(model) {
2016-04-15 00:36:50 +00:00
var prop = model.get(propertyToCheck)
if (prop !== null) {
prop = prop.toString()
if (newList.indexOf(prop) === -1) {
newList.push(prop)
}
}
})
}
removed = _.difference(self.filters[filtersToUse], newList)
added = _.difference(newList, self.filters[filtersToUse])
// remove the list items for things no longer present on the map
2016-11-07 20:25:08 +00:00
_.each(removed, function(identifier) {
$('#filter_by_' + listToModify + ' li[data-id="' + identifier + '"]').fadeOut('fast', function() {
2016-04-15 00:36:50 +00:00
$(this).remove()
})
const index = self.visible[filtersToUse].indexOf(identifier)
2016-04-15 00:36:50 +00:00
self.visible[filtersToUse].splice(index, 1)
})
var model, li, jQueryLi
2016-11-07 20:25:08 +00:00
function sortAlpha(a, b) {
2016-04-15 00:36:50 +00:00
return a.childNodes[1].innerHTML.toLowerCase() > b.childNodes[1].innerHTML.toLowerCase() ? 1 : -1
}
// for each new filter to be added, create a list item for it and fade it in
2016-11-07 20:25:08 +00:00
_.each(added, function(identifier) {
model = DataModel[correlatedModel].get(identifier) ||
2016-11-07 20:25:08 +00:00
DataModel[correlatedModel].find(function(model) {
2016-04-15 00:36:50 +00:00
return model.get(propertyToCheck) === identifier
})
li = model.prepareLiForFilter()
jQueryLi = $(li).hide()
$('li', '#filter_by_' + listToModify + ' ul').add(jQueryLi.fadeIn('fast'))
.sort(sortAlpha).appendTo('#filter_by_' + listToModify + ' ul')
self.visible[filtersToUse].push(identifier)
})
// update the list of filters with the new list we just generated
self.filters[filtersToUse] = newList
// make sure clicks on list items still trigger the right events
self.bindLiClicks()
},
2016-11-07 20:25:08 +00:00
checkMetacodes: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
self.updateFilters('Topics', 'metacode_id', 'Metacodes', 'metacodes', 'metacode')
},
2016-11-07 20:25:08 +00:00
checkMappers: function() {
var self = Filter
2016-11-07 20:25:08 +00:00
if (Active.Map) {
2016-04-15 00:36:50 +00:00
self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper')
} else {
// on topic view
self.updateFilters(['Topics', 'Synapses'], 'user_id', 'Creators', 'mappers', 'mapper')
}
},
2016-11-07 20:25:08 +00:00
checkSynapses: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
self.updateFilters('Synapses', 'desc', 'Synapses', 'synapses', 'synapse')
},
2016-11-07 20:25:08 +00:00
filterAllMetacodes: function(e) {
var self = Filter
2016-04-15 00:36:50 +00:00
$('#filter_by_metacode ul li').addClass('toggledOff')
$('.showAllMetacodes').removeClass('active')
$('.hideAllMetacodes').addClass('active')
self.visible.metacodes = []
self.passFilters()
},
2016-11-07 20:25:08 +00:00
filterNoMetacodes: function(e) {
var self = Filter
2016-04-15 00:36:50 +00:00
$('#filter_by_metacode ul li').removeClass('toggledOff')
$('.showAllMetacodes').addClass('active')
$('.hideAllMetacodes').removeClass('active')
self.visible.metacodes = self.filters.metacodes.slice()
self.passFilters()
},
2016-11-07 20:25:08 +00:00
filterAllMappers: function(e) {
var self = Filter
2016-04-15 00:36:50 +00:00
$('#filter_by_mapper ul li').addClass('toggledOff')
$('.showAllMappers').removeClass('active')
$('.hideAllMappers').addClass('active')
self.visible.mappers = []
self.passFilters()
},
2016-11-07 20:25:08 +00:00
filterNoMappers: function(e) {
var self = Filter
2016-04-15 00:36:50 +00:00
$('#filter_by_mapper ul li').removeClass('toggledOff')
$('.showAllMappers').addClass('active')
$('.hideAllMappers').removeClass('active')
self.visible.mappers = self.filters.mappers.slice()
self.passFilters()
},
2016-11-07 20:25:08 +00:00
filterAllSynapses: function(e) {
var self = Filter
2016-04-15 00:36:50 +00:00
$('#filter_by_synapse ul li').addClass('toggledOff')
$('.showAllSynapses').removeClass('active')
$('.hideAllSynapses').addClass('active')
self.visible.synapses = []
self.passFilters()
},
2016-11-07 20:25:08 +00:00
filterNoSynapses: function(e) {
var self = Filter
2016-04-15 00:36:50 +00:00
$('#filter_by_synapse ul li').removeClass('toggledOff')
$('.showAllSynapses').addClass('active')
$('.hideAllSynapses').removeClass('active')
self.visible.synapses = self.filters.synapses.slice()
self.passFilters()
},
// an abstraction function for toggleMetacode, toggleMapper, toggleSynapse
// to reduce code redundancy
// gets called in the context of a list item in a filter box
2016-11-07 20:25:08 +00:00
toggleLi: function(whichToFilter) {
var self = Filter
2016-04-15 00:36:50 +00:00
var id = $(this).attr('data-id')
2016-11-07 20:25:08 +00:00
if (self.visible[whichToFilter].indexOf(id) === -1) {
2016-04-15 00:36:50 +00:00
self.visible[whichToFilter].push(id)
$(this).removeClass('toggledOff')
} else {
2016-11-07 20:25:08 +00:00
const index = self.visible[whichToFilter].indexOf(id)
2016-04-15 00:36:50 +00:00
self.visible[whichToFilter].splice(index, 1)
$(this).addClass('toggledOff')
}
self.passFilters()
},
2016-11-07 20:25:08 +00:00
toggleMetacode: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
self.toggleLi.call(this, 'metacodes')
if (self.visible.metacodes.length === self.filters.metacodes.length) {
$('.showAllMetacodes').addClass('active')
$('.hideAllMetacodes').removeClass('active')
2016-11-07 20:25:08 +00:00
} else if (self.visible.metacodes.length === 0) {
2016-04-15 00:36:50 +00:00
$('.showAllMetacodes').removeClass('active')
$('.hideAllMetacodes').addClass('active')
} else {
$('.showAllMetacodes').removeClass('active')
$('.hideAllMetacodes').removeClass('active')
}
},
2016-11-07 20:25:08 +00:00
toggleMapper: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
self.toggleLi.call(this, 'mappers')
if (self.visible.mappers.length === self.filters.mappers.length) {
$('.showAllMappers').addClass('active')
$('.hideAllMappers').removeClass('active')
2016-11-07 20:25:08 +00:00
} else if (self.visible.mappers.length === 0) {
2016-04-15 00:36:50 +00:00
$('.showAllMappers').removeClass('active')
$('.hideAllMappers').addClass('active')
} else {
$('.showAllMappers').removeClass('active')
$('.hideAllMappers').removeClass('active')
}
},
2016-11-07 20:25:08 +00:00
toggleSynapse: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
self.toggleLi.call(this, 'synapses')
if (self.visible.synapses.length === self.filters.synapses.length) {
$('.showAllSynapses').addClass('active')
$('.hideAllSynapses').removeClass('active')
2016-11-07 20:25:08 +00:00
} else if (self.visible.synapses.length === 0) {
2016-04-15 00:36:50 +00:00
$('.showAllSynapses').removeClass('active')
$('.hideAllSynapses').addClass('active')
} else {
$('.showAllSynapses').removeClass('active')
$('.hideAllSynapses').removeClass('active')
}
},
2016-11-07 20:25:08 +00:00
passFilters: function() {
var self = Filter
2016-04-15 00:36:50 +00:00
var visible = self.visible
var passesMetacode, passesMapper, passesSynapse
2016-11-07 20:25:08 +00:00
var opacityForFilter = Active.Map ? 0 : 0.4
2016-04-15 00:36:50 +00:00
2016-11-07 20:25:08 +00:00
DataModel.Topics.each(function(topic) {
2016-04-15 00:36:50 +00:00
var n = topic.get('node')
2016-11-07 20:25:08 +00:00
var metacodeId = topic.get('metacode_id').toString()
2016-04-15 00:36:50 +00:00
2016-11-07 20:25:08 +00:00
if (visible.metacodes.indexOf(metacodeId) === -1) passesMetacode = false
2016-04-15 00:36:50 +00:00
else passesMetacode = true
2016-11-07 20:25:08 +00:00
if (Active.Map) {
2016-04-15 00:36:50 +00:00
// when on a map,
// we filter by mapper according to the person who added the
// topic or synapse to the map
2016-11-07 20:25:08 +00:00
let userId = topic.getMapping().get('user_id').toString()
if (visible.mappers.indexOf(userId) === -1) passesMapper = false
2016-04-15 00:36:50 +00:00
else passesMapper = true
} else {
// when on a topic view,
// we filter by mapper according to the person who created the
// topic or synapse
2016-11-07 20:25:08 +00:00
let userId = topic.get('user_id').toString()
if (visible.mappers.indexOf(userId) === -1) passesMapper = false
2016-04-15 00:36:50 +00:00
else passesMapper = true
}
if (passesMetacode && passesMapper) {
if (n) {
n.setData('alpha', 1, 'end')
2016-11-07 20:25:08 +00:00
} else {
console.log(topic)
2016-04-15 00:36:50 +00:00
}
} else {
if (n) {
2016-09-22 09:36:47 +00:00
Control.deselectNode(n, true)
2016-04-15 00:36:50 +00:00
n.setData('alpha', opacityForFilter, 'end')
2016-11-07 20:25:08 +00:00
n.eachAdjacency(function(e) {
2016-09-22 09:36:47 +00:00
Control.deselectEdge(e, true)
2016-04-15 00:36:50 +00:00
})
2016-11-07 20:25:08 +00:00
} else {
console.log(topic)
2016-04-15 00:36:50 +00:00
}
}
})
// flag all the edges back to 'untouched'
2016-11-07 20:25:08 +00:00
DataModel.Synapses.each(function(synapse) {
2016-04-15 00:36:50 +00:00
var e = synapse.get('edge')
e.setData('touched', false)
})
2016-11-07 20:25:08 +00:00
DataModel.Synapses.each(function(synapse) {
2016-04-15 00:36:50 +00:00
var e = synapse.get('edge')
var desc
2016-11-07 20:25:08 +00:00
var userId = synapse.get('user_id').toString()
2016-04-15 00:36:50 +00:00
if (e && !e.getData('touched')) {
var synapses = e.getData('synapses')
// if any of the synapses represent by the edge are still unfiltered
// leave the edge visible
passesSynapse = false
2016-11-07 20:25:08 +00:00
for (let i = 0; i < synapses.length; i++) {
2016-04-15 00:36:50 +00:00
desc = synapses[i].get('desc')
if (visible.synapses.indexOf(desc) > -1) passesSynapse = true
}
// if the synapse description being displayed is now being
// filtered, set the displayIndex to the first unfiltered synapse if there is one
var displayIndex = e.getData('displayIndex') ? e.getData('displayIndex') : 0
var displayedSynapse = synapses[displayIndex]
desc = displayedSynapse.get('desc')
2016-11-07 20:25:08 +00:00
if (passesSynapse && visible.synapses.indexOf(desc) === -1) {
2016-04-15 00:36:50 +00:00
// iterate and find an unfiltered one
2016-11-07 20:25:08 +00:00
for (let i = 0; i < synapses.length; i++) {
2016-04-15 00:36:50 +00:00
desc = synapses[i].get('desc')
if (visible.synapses.indexOf(desc) > -1) {
e.setData('displayIndex', i)
break
}
}
}
2016-11-07 20:25:08 +00:00
if (Active.Map) {
2016-04-15 00:36:50 +00:00
// when on a map,
// we filter by mapper according to the person who added the
// topic or synapse to the map
2016-11-07 20:25:08 +00:00
userId = synapse.getMapping().get('user_id').toString()
2016-04-15 00:36:50 +00:00
}
2016-11-07 20:25:08 +00:00
if (visible.mappers.indexOf(userId) === -1) passesMapper = false
2016-04-15 00:36:50 +00:00
else passesMapper = true
2016-09-22 09:36:47 +00:00
var color = Settings.colors.synapses.normal
2016-04-15 00:36:50 +00:00
if (passesSynapse && passesMapper) {
e.setData('alpha', 1, 'end')
e.setData('color', color, 'end')
} else {
2016-09-22 09:36:47 +00:00
Control.deselectEdge(e, true)
2016-04-15 00:36:50 +00:00
e.setData('alpha', opacityForFilter, 'end')
}
e.setData('touched', true)
2016-11-07 20:25:08 +00:00
} else if (!e) {
console.log(synapse)
2016-04-15 00:36:50 +00:00
}
})
// run the animation
2016-09-22 09:36:47 +00:00
Visualize.mGraph.fx.animate({
2016-04-15 00:36:50 +00:00
modes: ['node-property:alpha',
'edge-property:alpha'],
duration: 200
})
}
}
export default Filter