From a4d31241a8cebbbe47579304360b5bf9173ade3a Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 14:25:49 +0800 Subject: [PATCH 01/26] move Metamaps code into webpack --- app/assets/javascripts/application.js | 32 +- .../javascripts/src/Metamaps.Erb.js.erb | 18 + .../javascripts/src/Metamaps.GlobalUI.js | 717 ------------------ .../src/Metamaps}/Metamaps.Account.js | 1 + .../src/Metamaps}/Metamaps.Admin.js | 1 + .../src/Metamaps}/Metamaps.AutoLayout.js | 1 + .../src/Metamaps}/Metamaps.Backbone.js | 1 + .../src/Metamaps}/Metamaps.Control.js | 1 + .../src/Metamaps}/Metamaps.Create.js | 1 + .../src/Metamaps}/Metamaps.Debug.js | 2 + .../src/Metamaps}/Metamaps.Filter.js | 1 + frontend/src/Metamaps/Metamaps.GlobalUI.js | 680 +++++++++++++++++ .../src/Metamaps}/Metamaps.Import.js | 1 + .../src/Metamaps}/Metamaps.JIT.js | 3 +- .../src/Metamaps}/Metamaps.Listeners.js | 1 + .../src/Metamaps}/Metamaps.Map.js | 1 + .../src/Metamaps}/Metamaps.Mapper.js | 1 + .../src/Metamaps}/Metamaps.Mobile.js | 1 + .../src/Metamaps}/Metamaps.Organize.js | 1 + .../src/Metamaps}/Metamaps.PasteInput.js | 1 + .../src/Metamaps/Metamaps.ReactComponents.js | 7 + .../src/Metamaps}/Metamaps.Realtime.js | 2 + .../src/Metamaps}/Metamaps.Router.js | 1 + .../src/Metamaps}/Metamaps.Synapse.js | 1 + .../src/Metamaps}/Metamaps.SynapseCard.js | 1 + .../src/Metamaps}/Metamaps.Topic.js | 1 + .../src/Metamaps}/Metamaps.TopicCard.js | 7 +- .../src/Metamaps}/Metamaps.Util.js | 1 + .../src/Metamaps}/Metamaps.Views.js | 1 + .../src/Metamaps}/Metamaps.Visualize.js | 1 + .../src/Metamaps/index.js | 49 +- frontend/src/index.js | 13 +- 32 files changed, 775 insertions(+), 776 deletions(-) create mode 100644 app/assets/javascripts/src/Metamaps.Erb.js.erb delete mode 100644 app/assets/javascripts/src/Metamaps.GlobalUI.js rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Account.js (98%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Admin.js (97%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.AutoLayout.js (97%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Backbone.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Control.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Create.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Debug.js (73%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Filter.js (99%) create mode 100644 frontend/src/Metamaps/Metamaps.GlobalUI.js rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Import.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.JIT.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Listeners.js (98%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Map.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Mapper.js (91%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Mobile.js (95%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Organize.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.PasteInput.js (98%) create mode 100644 frontend/src/Metamaps/Metamaps.ReactComponents.js rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Realtime.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Router.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Synapse.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.SynapseCard.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Topic.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.TopicCard.js (98%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Util.js (99%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Views.js (98%) rename {app/assets/javascripts/src => frontend/src/Metamaps}/Metamaps.Visualize.js (99%) rename app/assets/javascripts/src/Metamaps.js.erb => frontend/src/Metamaps/index.js (60%) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 14f565fa..03dac4fb 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,37 +13,11 @@ //= require jquery //= require jquery-ui //= require jquery_ujs -//= require ./webpacked/metamaps.bundle //= require_directory ./lib -//= require ./src/Metamaps.GlobalUI -//= require ./src/Metamaps.Router -//= require ./src/Metamaps.Backbone -//= require ./src/Metamaps.Views +//= require ./src/JIT +//= require ./src/Metamaps.Erb +//= require ./webpacked/metamaps.bundle //= require ./src/views/chatView //= require ./src/views/videoView //= require ./src/views/room -//= require ./src/JIT //= require ./src/check-canvas-support -//= require ./src/Metamaps -//= require ./src/Metamaps.Create -//= require ./src/Metamaps.TopicCard -//= require ./src/Metamaps.SynapseCard -//= require ./src/Metamaps.Visualize -//= require ./src/Metamaps.Util -//= require ./src/Metamaps.Realtime -//= require ./src/Metamaps.Control -//= require ./src/Metamaps.Filter -//= require ./src/Metamaps.Listeners -//= require ./src/Metamaps.Organize -//= require ./src/Metamaps.Topic -//= require ./src/Metamaps.Synapse -//= require ./src/Metamaps.Map -//= require ./src/Metamaps.Account -//= require ./src/Metamaps.Mapper -//= require ./src/Metamaps.Mobile -//= require ./src/Metamaps.Admin -//= require ./src/Metamaps.Import -//= require ./src/Metamaps.AutoLayout -//= require ./src/Metamaps.PasteInput -//= require ./src/Metamaps.JIT -//= require ./src/Metamaps.Debug diff --git a/app/assets/javascripts/src/Metamaps.Erb.js.erb b/app/assets/javascripts/src/Metamaps.Erb.js.erb new file mode 100644 index 00000000..90eba5e5 --- /dev/null +++ b/app/assets/javascripts/src/Metamaps.Erb.js.erb @@ -0,0 +1,18 @@ +/* global Metamaps */ + +/* + * Metamaps.Erb.js.erb + */ + +/* erb variables from rails */ +window.Metamaps = window.Metamaps || {} +Metamaps.Erb = {} +Metamaps.Erb['REALTIME_SERVER'] = '<%= ENV['REALTIME_SERVER'] %>' +Metamaps.Erb['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>' +Metamaps.Erb['user.png'] = '<%= asset_path('user.png') %>' +Metamaps.Erb['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>' +Metamaps.Erb['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>' +Metamaps.Erb['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>' +Metamaps.Erb['synapse16.png'] = '<%= asset_path('synapse16.png') %>' +Metamaps.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %> +Metamaps.VERSION = '<%= METAMAPS_VERSION %>' diff --git a/app/assets/javascripts/src/Metamaps.GlobalUI.js b/app/assets/javascripts/src/Metamaps.GlobalUI.js deleted file mode 100644 index a6466fdc..00000000 --- a/app/assets/javascripts/src/Metamaps.GlobalUI.js +++ /dev/null @@ -1,717 +0,0 @@ -var Metamaps = window.Metamaps || {}; // this variable declaration defines a Javascript object that will contain all the variables and functions used by us, broken down into 'sub-modules' that look something like this -/* - -* unless you are on a page with the Javascript InfoVis Toolkit (Topic or Map) the only section in the metamaps -* object will be these -GlobalUI -Active -Maps -Mappers -Backbone - -* all these get added when you are on a page with the Javascript Infovis Toolkit -Settings -Touch -Mouse -Selected -Metacodes -Topics -Synapses -Mappings -Create -TopicCard -SynapseCard -Visualize -Util -Realtime -Control -Filter -Listeners -Organize -Map -Mapper -Topic -Synapse -JIT -*/ - -Metamaps.Active = { - Map: null, - Topic: null, - Mapper: null -}; -Metamaps.Maps = {}; - -$(document).ready(function () { - // initialize all the modules - for (var prop in Metamaps) { - // this runs the init function within each sub-object on the Metamaps one - if (Metamaps.hasOwnProperty(prop) && - Metamaps[prop] != null && - Metamaps[prop].hasOwnProperty('init') && - typeof (Metamaps[prop].init) == 'function' - ) { - Metamaps[prop].init() - } - } - // load whichever page you are on - if (Metamaps.currentSection === "explore") { - var capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1) - - Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ) - if (Metamaps.currentPage === "mapper") { - Metamaps.Views.exploreMaps.fetchUserThenRender() - } - else { - Metamaps.Views.exploreMaps.render() - } - Metamaps.GlobalUI.showDiv('#explore') - } - else if (Metamaps.currentSection === "" && Metamaps.Active.Mapper) { - Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) - Metamaps.Views.exploreMaps.render() - Metamaps.GlobalUI.showDiv('#explore') - } - else if (Metamaps.Active.Map || Metamaps.Active.Topic) { - Metamaps.Loading.show() - Metamaps.JIT.prepareVizData() - Metamaps.GlobalUI.showDiv('#infovis') - } -}); - -Metamaps.GlobalUI = { - notifyTimeout: null, - lightbox: null, - init: function () { - var self = Metamaps.GlobalUI; - - self.Search.init(); - self.CreateMap.init(); - self.Account.init(); - - if ($('#toast').html().trim()) self.notifyUser($('#toast').html()) - - //bind lightbox clicks - $('.openLightbox').click(function (event) { - self.openLightbox($(this).attr('data-open')); - event.preventDefault(); - return false; - }); - - $('#lightbox_screen, #lightbox_close').click(self.closeLightbox); - - // initialize global backbone models and collections - if (Metamaps.Active.Mapper) Metamaps.Active.Mapper = new Metamaps.Backbone.Mapper(Metamaps.Active.Mapper); - - var myCollection = Metamaps.Maps.Mine ? Metamaps.Maps.Mine : []; - var sharedCollection = Metamaps.Maps.Shared ? Metamaps.Maps.Shared : []; - var starredCollection = Metamaps.Maps.Starred ? Metamaps.Maps.Starred : []; - var mapperCollection = []; - var mapperOptionsObj = {id: 'mapper', sortBy: 'updated_at' }; - if (Metamaps.Maps.Mapper) { - mapperCollection = Metamaps.Maps.Mapper.models; - mapperOptionsObj.mapperId = Metamaps.Maps.Mapper.id; - } - var featuredCollection = Metamaps.Maps.Featured ? Metamaps.Maps.Featured : []; - var activeCollection = Metamaps.Maps.Active ? Metamaps.Maps.Active : []; - Metamaps.Maps.Mine = new Metamaps.Backbone.MapsCollection(myCollection, {id: 'mine', sortBy: 'updated_at' }); - Metamaps.Maps.Shared = new Metamaps.Backbone.MapsCollection(sharedCollection, {id: 'shared', sortBy: 'updated_at' }); - Metamaps.Maps.Starred = new Metamaps.Backbone.MapsCollection(starredCollection, {id: 'starred', sortBy: 'updated_at' }); - // 'Mapper' refers to another mapper - Metamaps.Maps.Mapper = new Metamaps.Backbone.MapsCollection(mapperCollection, mapperOptionsObj); - Metamaps.Maps.Featured = new Metamaps.Backbone.MapsCollection(featuredCollection, {id: 'featured', sortBy: 'updated_at' }); - Metamaps.Maps.Active = new Metamaps.Backbone.MapsCollection(activeCollection, {id: 'active', sortBy: 'updated_at' }); - }, - showDiv: function (selector) { - $(selector).show() - $(selector).animate({ - opacity: 1 - }, 200, 'easeOutCubic') - }, - hideDiv: function (selector) { - $(selector).animate({ - opacity: 0 - }, 200, 'easeInCubic', function () { $(this).hide() }) - }, - openLightbox: function (which) { - var self = Metamaps.GlobalUI; - - $('.lightboxContent').hide(); - $('#' + which).show(); - - self.lightbox = which; - - $('#lightbox_overlay').show(); - - var heightOfContent = '-' + ($('#lightbox_main').height() / 2) + 'px'; - // animate the content in from the bottom - $('#lightbox_main').animate({ - 'top': '50%', - 'margin-top': heightOfContent - }, 200, 'easeOutCubic'); - - // fade the black overlay in - $('#lightbox_screen').animate({ - 'opacity': '0.42' - }, 200); - - if (which == "switchMetacodes") { - Metamaps.Create.isSwitchingSet = true; - } - }, - - closeLightbox: function (event) { - var self = Metamaps.GlobalUI; - - if (event) event.preventDefault(); - - // animate the lightbox content offscreen - $('#lightbox_main').animate({ - 'top': '100%', - 'margin-top': '0' - }, 200, 'easeInCubic'); - - // fade the black overlay out - $('#lightbox_screen').animate({ - 'opacity': '0.0' - }, 200, function () { - $('#lightbox_overlay').hide(); - }); - - if (self.lightbox === 'forkmap') Metamaps.GlobalUI.CreateMap.reset('fork_map'); - if (self.lightbox === 'newmap') Metamaps.GlobalUI.CreateMap.reset('new_map'); - if (Metamaps.Create && Metamaps.Create.isSwitchingSet) { - Metamaps.Create.cancelMetacodeSetSwitch(); - } - self.lightbox = null; - }, - notifyUser: function (message, leaveOpen) { - var self = Metamaps.GlobalUI; - - $('#toast').html(message) - self.showDiv('#toast') - clearTimeout(self.notifyTimeOut); - if (!leaveOpen) { - self.notifyTimeOut = setTimeout(function () { - self.hideDiv('#toast') - }, 8000); - } - }, - clearNotify: function() { - var self = Metamaps.GlobalUI; - - clearTimeout(self.notifyTimeOut); - self.hideDiv('#toast') - }, - shareInvite: function(inviteLink) { - window.prompt("To copy the invite link, press: Ctrl+C, Enter", inviteLink); - } -}; - -Metamaps.GlobalUI.CreateMap = { - newMap: null, - emptyMapForm: "", - emptyForkMapForm: "", - topicsToMap: [], - synapsesToMap: [], - init: function () { - var self = Metamaps.GlobalUI.CreateMap; - - self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); - - self.bindFormEvents(); - - self.emptyMapForm = $('#new_map').html(); - - }, - bindFormEvents: function () { - var self = Metamaps.GlobalUI.CreateMap; - - $('.new_map input, .new_map div').unbind('keypress').bind('keypress', function(event) { - if (event.keyCode === 13) self.submit() - }) - - $('.new_map button.cancel').unbind().bind('click', function (event) { - event.preventDefault(); - Metamaps.GlobalUI.closeLightbox(); - }); - $('.new_map button.submitMap').unbind().bind('click', self.submit); - - // bind permission changer events on the createMap form - $('.permIcon').unbind().bind('click', self.switchPermission); - }, - closeSuccess: function () { - $('#mapCreatedSuccess').fadeOut(300, function(){ - $(this).remove(); - }); - }, - generateSuccessMessage: function (id) { - var stringStart = "
SUCCESS!
Your map has been created. Do you want to: Go to your new map"; - stringStart += "ORStay on this "; - var page = Metamaps.Active.Map ? 'map' : 'page'; - var stringEnd = "
"; - return stringStart + page + stringEnd; - }, - switchPermission: function () { - var self = Metamaps.GlobalUI.CreateMap; - - self.newMap.set('permission', $(this).attr('data-permission')); - $(this).siblings('.permIcon').find('.mapPermIcon').removeClass('selected'); - $(this).find('.mapPermIcon').addClass('selected'); - - var permText = $(this).find('.tip').html(); - $(this).parents('.new_map').find('.permText').html(permText); - }, - submit: function (event) { - if (event) event.preventDefault(); - - var self = Metamaps.GlobalUI.CreateMap; - - if (Metamaps.GlobalUI.lightbox === 'forkmap') { - self.newMap.set('topicsToMap', self.topicsToMap); - self.newMap.set('synapsesToMap', self.synapsesToMap); - } - - var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; - var $form = $(formId); - - self.newMap.set('name', $form.find('#map_name').val()); - self.newMap.set('desc', $form.find('#map_desc').val()); - - if (self.newMap.get('name').length===0){ - self.throwMapNameError(); - return; - } - - self.newMap.save(null, { - success: self.success - // TODO add error message - }); - - Metamaps.GlobalUI.closeLightbox(); - Metamaps.GlobalUI.notifyUser('Working...'); - }, - throwMapNameError: function () { - var self = Metamaps.GlobalUI.CreateMap; - - var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; - var $form = $(formId); - - var message = $("
Please enter a map name...
"); - - $form.find('#map_name').after(message); - setTimeout(function(){ - message.fadeOut('fast', function(){ - message.remove(); - }); - }, 5000); - }, - success: function (model) { - var self = Metamaps.GlobalUI.CreateMap; - - //push the new map onto the collection of 'my maps' - Metamaps.Maps.Mine.add(model); - - var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; - var form = $(formId); - - Metamaps.GlobalUI.clearNotify(); - $('#wrapper').append(self.generateSuccessMessage(model.id)); - - }, - reset: function (id) { - var self = Metamaps.GlobalUI.CreateMap; - - var form = $('#' + id); - - if (id === "fork_map") { - self.topicsToMap = []; - self.synapsesToMap = []; - form.html(self.emptyForkMapForm); - } - else { - form.html(self.emptyMapForm); - } - - self.bindFormEvents(); - self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); - - return false; - }, -}; - - -Metamaps.GlobalUI.Account = { - isOpen: false, - changing: false, - init: function () { - var self = Metamaps.GlobalUI.Account; - - $('.sidebarAccountIcon').click(self.toggleBox); - $('.sidebarAccountBox').click(function(event){ - event.stopPropagation(); - }); - $('body').click(self.close); - }, - toggleBox: function (event) { - var self = Metamaps.GlobalUI.Account; - - if (self.isOpen) self.close(); - else self.open(); - - event.stopPropagation(); - }, - open: function () { - var self = Metamaps.GlobalUI.Account; - - Metamaps.Filter.close(); - $('.sidebarAccountIcon .tooltipsUnder').addClass('hide'); - - - if (!self.isOpen && !self.changing) { - self.changing = true; - $('.sidebarAccountBox').fadeIn(200, function () { - self.changing = false; - self.isOpen = true; - $('.sidebarAccountBox #user_email').focus(); - }); - } - }, - close: function () { - var self = Metamaps.GlobalUI.Account; - - $('.sidebarAccountIcon .tooltipsUnder').removeClass('hide'); - if (!self.changing) { - self.changing = true; - $('.sidebarAccountBox #user_email').blur(); - $('.sidebarAccountBox').fadeOut(200, function () { - self.changing = false; - self.isOpen = false; - }); - } - } -}; - - - -Metamaps.GlobalUI.Search = { - locked: false, - isOpen: false, - limitTopicsToMe: false, - limitMapsToMe: false, - timeOut: null, - changing: false, - optionsInitialized: false, - init: function () { - var self = Metamaps.GlobalUI.Search; - - var loader = new CanvasLoader('searchLoading'); - loader.setColor('#4fb5c0'); // default is '#000000' - loader.setDiameter(24); // default is 40 - loader.setDensity(41); // default is 40 - loader.setRange(0.9); // default is 1.3 - loader.show(); // Hidden by default - - // bind the hover events - $(".sidebarSearch").hover(function () { - self.open() - }, function () { - self.close(800, false) - }); - - $('.sidebarSearchIcon').click(function (e) { - $('.sidebarSearchField').focus(); - }); - $('.sidebarSearch').click(function (e) { - e.stopPropagation(); - }); - $('body').click(function (e) { - self.close(0, false); - }); - - // open if the search is closed and user hits ctrl+/ - // close if they hit ESC - $('body').bind('keyup', function (e) { - switch (e.which) { - case 191: - if ((e.ctrlKey && !self.isOpen) || (e.ctrlKey && self.locked)) { - self.open(true); // true for focus - } - break; - case 27: - if (self.isOpen) { - self.close(0, true); - } - break; - - default: - break; //console.log(e.which); - } - }); - - self.startTypeahead(); - }, - lock: function() { - var self = Metamaps.GlobalUI.Search; - self.locked = true; - }, - unlock: function() { - var self = Metamaps.GlobalUI.Search; - self.locked = false; - }, - open: function (focus) { - var self = Metamaps.GlobalUI.Search; - - clearTimeout(self.timeOut); - if (!self.isOpen && !self.changing && !self.locked) { - self.changing = true; - $('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({ - width: '400px' - }, 300, function () { - if (focus) $('.sidebarSearchField').focus(); - $('.sidebarSearchField, .sidebarSearch .tt-hint').css({ - padding: '7px 10px 3px 10px', - width: '380px' - }); - self.changing = false; - self.isOpen = true; - }); - } - }, - close: function (closeAfter, bypass) { - // for now - return - - var self = Metamaps.GlobalUI.Search; - - self.timeOut = setTimeout(function () { - if (!self.locked && !self.changing && self.isOpen && (bypass || $('.sidebarSearchField.tt-input').val() == '')) { - self.changing = true; - $('.sidebarSearchField, .sidebarSearch .tt-hint').css({ - padding: '7px 0 3px 0', - width: '400px' - }); - $('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({ - width: '0' - }, 300, function () { - $('.sidebarSearchField').typeahead('val', ''); - $('.sidebarSearchField').blur(); - self.changing = false; - self.isOpen = false; - }); - } - }, closeAfter); - }, - startTypeahead: function () { - var self = Metamaps.GlobalUI.Search; - - var mapheader = Metamaps.Active.Mapper ? '

Maps

' : '

Maps

'; - var topicheader = Metamaps.Active.Mapper ? '

Topics

' : '

Topics

'; - var mapperheader = '

Mappers

'; - - var topics = { - name: 'topics', - limit: 9999, - - display: function(s) { return s.label; }, - templates: { - notFound: function(s) { - return Hogan.compile(topicheader + $('#topicSearchTemplate').html()).render({ - value: "No results", - label: "No results", - typeImageURL: Metamaps.Erb['icons/wildcard.png'], - rtype: "noresult" - }); - }, - header: topicheader, - suggestion: function(s) { - return Hogan.compile($('#topicSearchTemplate').html()).render(s); - }, - }, - source: new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), - queryTokenizer: Bloodhound.tokenizers.whitespace, - remote: { - url: '/search/topics', - prepare: function(query, settings) { - settings.url += '?term=' + query; - if (Metamaps.Active.Mapper && self.limitTopicsToMe) { - settings.url += "&user=" + Metamaps.Active.Mapper.id.toString(); - } - return settings; - }, - }, - }), - }; - - var maps = { - name: 'maps', - limit: 9999, - display: function(s) { return s.label; }, - templates: { - notFound: function(s) { - return Hogan.compile(mapheader + $('#mapSearchTemplate').html()).render({ - value: "No results", - label: "No results", - rtype: "noresult" - }); - }, - header: mapheader, - suggestion: function(s) { - return Hogan.compile($('#mapSearchTemplate').html()).render(s); - }, - }, - source: new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), - queryTokenizer: Bloodhound.tokenizers.whitespace, - remote: { - url: '/search/maps', - prepare: function(query, settings) { - settings.url += '?term=' + query; - if (Metamaps.Active.Mapper && self.limitMapsToMe) { - settings.url += "&user=" + Metamaps.Active.Mapper.id.toString(); - } - return settings; - }, - }, - }), - }; - - var mappers = { - name: 'mappers', - limit: 9999, - display: function(s) { return s.label; }, - templates: { - notFound: function(s) { - return Hogan.compile(mapperheader + $('#mapperSearchTemplate').html()).render({ - value: "No results", - label: "No results", - rtype: "noresult", - profile: Metamaps.Erb['user.png'] - }); - }, - header: mapperheader, - suggestion: function(s) { - return Hogan.compile($('#mapperSearchTemplate').html()).render(s); - }, - }, - source: new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), - queryTokenizer: Bloodhound.tokenizers.whitespace, - remote: { - url: '/search/mappers?term=%QUERY', - wildcard: '%QUERY', - }, - }), - }; - - // Take all that crazy setup data and put it together into one beautiful typeahead call! - $('.sidebarSearchField').typeahead( - { - highlight: true, - }, - [topics, maps, mappers] - ); - - //Set max height of the search results box to prevent it from covering bottom left footer - $('.sidebarSearchField').bind('typeahead:render', function (event) { - self.initSearchOptions(); - self.hideLoader(); - var h = $(window).height(); - $(".tt-dropdown-menu").css('max-height', h - 100); - if (self.limitTopicsToMe) { - $('#limitTopicsToMe').prop('checked', true); - } - if (self.limitMapsToMe) { - $('#limitMapsToMe').prop('checked', true); - } - }); - $(window).resize(function () { - var h = $(window).height(); - $(".tt-dropdown-menu").css('max-height', h - 100); - }); - - // tell the autocomplete to launch a new tab with the topic, map, or mapper you clicked on - $('.sidebarSearchField').bind('typeahead:select', self.handleResultClick); - - // don't do it, if they clicked on a 'addToMap' button - $('.sidebarSearch button.addToMap').click(function (event) { - event.stopPropagation(); - }); - - // make sure that when you click on 'limit to me' or 'toggle section' it works - $('.sidebarSearchField.tt-input').keyup(function(){ - if ($('.sidebarSearchField.tt-input').val() === '') { - self.hideLoader(); - } else { - self.showLoader(); - } - }); - - }, - handleResultClick: function (event, datum, dataset) { - var self = Metamaps.GlobalUI.Search; - - self.hideLoader(); - - if (["topic", "map", "mapper"].indexOf(datum.rtype) !== -1) { - self.close(0, true); - var win; - if (datum.rtype == "topic") { - Metamaps.Router.topics(datum.id); - } else if (datum.rtype == "map") { - Metamaps.Router.maps(datum.id); - } else if (datum.rtype == "mapper") { - Metamaps.Router.explore("mapper", datum.id); - } - } - }, - initSearchOptions: function () { - var self = Metamaps.GlobalUI.Search; - - function toggleResultSet(set) { - var s = $('.tt-dataset-' + set + ' .tt-suggestion, .tt-dataset-' + set + ' .resultnoresult'); - if (s.is(':visible')) { - s.hide(); - $(this).removeClass('minimizeResults').addClass('maximizeResults'); - } else { - s.show(); - $(this).removeClass('maximizeResults').addClass('minimizeResults'); - } - } - - $('.limitToMe').unbind().bind("change", function (e) { - if ($(this).attr('id') == 'limitTopicsToMe') { - self.limitTopicsToMe = !self.limitTopicsToMe; - } - if ($(this).attr('id') == 'limitMapsToMe') { - self.limitMapsToMe = !self.limitMapsToMe; - } - - // set the value of the search equal to itself to retrigger the - // autocomplete event - var searchQuery = $('.sidebarSearchField.tt-input').val(); - $(".sidebarSearchField").typeahead('val', '') - .typeahead('val', searchQuery); - }); - - // when the user clicks minimize section, hide the results for that section - $('.minimizeMapperResults').unbind().click(function (e) { - toggleResultSet.call(this, 'mappers'); - }); - $('.minimizeTopicResults').unbind().click(function (e) { - toggleResultSet.call(this, 'topics'); - }); - $('.minimizeMapResults').unbind().click(function (e) { - toggleResultSet.call(this, 'maps'); - }); - }, - hideLoader: function () { - $('#searchLoading').hide(); - }, - showLoader: function () { - $('#searchLoading').show(); - } -}; diff --git a/app/assets/javascripts/src/Metamaps.Account.js b/frontend/src/Metamaps/Metamaps.Account.js similarity index 98% rename from app/assets/javascripts/src/Metamaps.Account.js rename to frontend/src/Metamaps/Metamaps.Account.js index a2286ad8..66348481 100644 --- a/app/assets/javascripts/src/Metamaps.Account.js +++ b/frontend/src/Metamaps/Metamaps.Account.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Admin.js b/frontend/src/Metamaps/Metamaps.Admin.js similarity index 97% rename from app/assets/javascripts/src/Metamaps.Admin.js rename to frontend/src/Metamaps/Metamaps.Admin.js index a0192012..8dcaed5b 100644 --- a/app/assets/javascripts/src/Metamaps.Admin.js +++ b/frontend/src/Metamaps/Metamaps.Admin.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.AutoLayout.js b/frontend/src/Metamaps/Metamaps.AutoLayout.js similarity index 97% rename from app/assets/javascripts/src/Metamaps.AutoLayout.js rename to frontend/src/Metamaps/Metamaps.AutoLayout.js index 51e105c2..2360204b 100644 --- a/app/assets/javascripts/src/Metamaps.AutoLayout.js +++ b/frontend/src/Metamaps/Metamaps.AutoLayout.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps */ /* diff --git a/app/assets/javascripts/src/Metamaps.Backbone.js b/frontend/src/Metamaps/Metamaps.Backbone.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Backbone.js rename to frontend/src/Metamaps/Metamaps.Backbone.js index 2c1f58af..3c991e0b 100644 --- a/app/assets/javascripts/src/Metamaps.Backbone.js +++ b/frontend/src/Metamaps/Metamaps.Backbone.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, Backbone, _, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Control.js b/frontend/src/Metamaps/Metamaps.Control.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Control.js rename to frontend/src/Metamaps/Metamaps.Control.js index da6854c2..33623927 100644 --- a/app/assets/javascripts/src/Metamaps.Control.js +++ b/frontend/src/Metamaps/Metamaps.Control.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Create.js b/frontend/src/Metamaps/Metamaps.Create.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Create.js rename to frontend/src/Metamaps/Metamaps.Create.js index 6f3bbb62..1bd4216f 100644 --- a/app/assets/javascripts/src/Metamaps.Create.js +++ b/frontend/src/Metamaps/Metamaps.Create.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Debug.js b/frontend/src/Metamaps/Metamaps.Debug.js similarity index 73% rename from app/assets/javascripts/src/Metamaps.Debug.js rename to frontend/src/Metamaps/Metamaps.Debug.js index accd93a9..7bc71979 100644 --- a/app/assets/javascripts/src/Metamaps.Debug.js +++ b/frontend/src/Metamaps/Metamaps.Debug.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* * Metamaps.Debug.js.erb * @@ -10,4 +11,5 @@ Metamaps.Debug = function () { } Metamaps.debug = function () { Metamaps.Debug() +window.Metamaps = window.Metamaps || {} } diff --git a/app/assets/javascripts/src/Metamaps.Filter.js b/frontend/src/Metamaps/Metamaps.Filter.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Filter.js rename to frontend/src/Metamaps/Metamaps.Filter.js index 1dba099c..367918e6 100644 --- a/app/assets/javascripts/src/Metamaps.Filter.js +++ b/frontend/src/Metamaps/Metamaps.Filter.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/frontend/src/Metamaps/Metamaps.GlobalUI.js b/frontend/src/Metamaps/Metamaps.GlobalUI.js new file mode 100644 index 00000000..d5fe6caa --- /dev/null +++ b/frontend/src/Metamaps/Metamaps.GlobalUI.js @@ -0,0 +1,680 @@ +window.Metamaps = window.Metamaps || {}; + +Metamaps.Active = Metamaps.Active || { + Map: null, + Topic: null, + Mapper: null +}; +Metamaps.Maps = Metamaps.Maps || {} + +$(document).ready(function () { + // initialize all the modules + for (var prop in Metamaps) { + // this runs the init function within each sub-object on the Metamaps one + if (Metamaps.hasOwnProperty(prop) && + Metamaps[prop] != null && + Metamaps[prop].hasOwnProperty('init') && + typeof (Metamaps[prop].init) == 'function' + ) { + Metamaps[prop].init() + } + } + // load whichever page you are on + if (Metamaps.currentSection === "explore") { + var capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1) + + Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ) + if (Metamaps.currentPage === "mapper") { + Metamaps.Views.exploreMaps.fetchUserThenRender() + } + else { + Metamaps.Views.exploreMaps.render() + } + Metamaps.GlobalUI.showDiv('#explore') + } + else if (Metamaps.currentSection === "" && Metamaps.Active.Mapper) { + Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) + Metamaps.Views.exploreMaps.render() + Metamaps.GlobalUI.showDiv('#explore') + } + else if (Metamaps.Active.Map || Metamaps.Active.Topic) { + Metamaps.Loading.show() + Metamaps.JIT.prepareVizData() + Metamaps.GlobalUI.showDiv('#infovis') + } +}); + +Metamaps.GlobalUI = { + notifyTimeout: null, + lightbox: null, + init: function () { + var self = Metamaps.GlobalUI; + + self.Search.init(); + self.CreateMap.init(); + self.Account.init(); + + if ($('#toast').html().trim()) self.notifyUser($('#toast').html()) + + //bind lightbox clicks + $('.openLightbox').click(function (event) { + self.openLightbox($(this).attr('data-open')); + event.preventDefault(); + return false; + }); + + $('#lightbox_screen, #lightbox_close').click(self.closeLightbox); + + // initialize global backbone models and collections + if (Metamaps.Active.Mapper) Metamaps.Active.Mapper = new Metamaps.Backbone.Mapper(Metamaps.Active.Mapper); + + var myCollection = Metamaps.Maps.Mine ? Metamaps.Maps.Mine : []; + var sharedCollection = Metamaps.Maps.Shared ? Metamaps.Maps.Shared : []; + var starredCollection = Metamaps.Maps.Starred ? Metamaps.Maps.Starred : []; + var mapperCollection = []; + var mapperOptionsObj = {id: 'mapper', sortBy: 'updated_at' }; + if (Metamaps.Maps.Mapper) { + mapperCollection = Metamaps.Maps.Mapper.models; + mapperOptionsObj.mapperId = Metamaps.Maps.Mapper.id; + } + var featuredCollection = Metamaps.Maps.Featured ? Metamaps.Maps.Featured : []; + var activeCollection = Metamaps.Maps.Active ? Metamaps.Maps.Active : []; + Metamaps.Maps.Mine = new Metamaps.Backbone.MapsCollection(myCollection, {id: 'mine', sortBy: 'updated_at' }); + Metamaps.Maps.Shared = new Metamaps.Backbone.MapsCollection(sharedCollection, {id: 'shared', sortBy: 'updated_at' }); + Metamaps.Maps.Starred = new Metamaps.Backbone.MapsCollection(starredCollection, {id: 'starred', sortBy: 'updated_at' }); + // 'Mapper' refers to another mapper + Metamaps.Maps.Mapper = new Metamaps.Backbone.MapsCollection(mapperCollection, mapperOptionsObj); + Metamaps.Maps.Featured = new Metamaps.Backbone.MapsCollection(featuredCollection, {id: 'featured', sortBy: 'updated_at' }); + Metamaps.Maps.Active = new Metamaps.Backbone.MapsCollection(activeCollection, {id: 'active', sortBy: 'updated_at' }); + }, + showDiv: function (selector) { + $(selector).show() + $(selector).animate({ + opacity: 1 + }, 200, 'easeOutCubic') + }, + hideDiv: function (selector) { + $(selector).animate({ + opacity: 0 + }, 200, 'easeInCubic', function () { $(this).hide() }) + }, + openLightbox: function (which) { + var self = Metamaps.GlobalUI; + + $('.lightboxContent').hide(); + $('#' + which).show(); + + self.lightbox = which; + + $('#lightbox_overlay').show(); + + var heightOfContent = '-' + ($('#lightbox_main').height() / 2) + 'px'; + // animate the content in from the bottom + $('#lightbox_main').animate({ + 'top': '50%', + 'margin-top': heightOfContent + }, 200, 'easeOutCubic'); + + // fade the black overlay in + $('#lightbox_screen').animate({ + 'opacity': '0.42' + }, 200); + + if (which == "switchMetacodes") { + Metamaps.Create.isSwitchingSet = true; + } + }, + + closeLightbox: function (event) { + var self = Metamaps.GlobalUI; + + if (event) event.preventDefault(); + + // animate the lightbox content offscreen + $('#lightbox_main').animate({ + 'top': '100%', + 'margin-top': '0' + }, 200, 'easeInCubic'); + + // fade the black overlay out + $('#lightbox_screen').animate({ + 'opacity': '0.0' + }, 200, function () { + $('#lightbox_overlay').hide(); + }); + + if (self.lightbox === 'forkmap') Metamaps.GlobalUI.CreateMap.reset('fork_map'); + if (self.lightbox === 'newmap') Metamaps.GlobalUI.CreateMap.reset('new_map'); + if (Metamaps.Create && Metamaps.Create.isSwitchingSet) { + Metamaps.Create.cancelMetacodeSetSwitch(); + } + self.lightbox = null; + }, + notifyUser: function (message, leaveOpen) { + var self = Metamaps.GlobalUI; + + $('#toast').html(message) + self.showDiv('#toast') + clearTimeout(self.notifyTimeOut); + if (!leaveOpen) { + self.notifyTimeOut = setTimeout(function () { + self.hideDiv('#toast') + }, 8000); + } + }, + clearNotify: function() { + var self = Metamaps.GlobalUI; + + clearTimeout(self.notifyTimeOut); + self.hideDiv('#toast') + }, + shareInvite: function(inviteLink) { + window.prompt("To copy the invite link, press: Ctrl+C, Enter", inviteLink); + } +}; + +Metamaps.GlobalUI.CreateMap = { + newMap: null, + emptyMapForm: "", + emptyForkMapForm: "", + topicsToMap: [], + synapsesToMap: [], + init: function () { + var self = Metamaps.GlobalUI.CreateMap; + + self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); + + self.bindFormEvents(); + + self.emptyMapForm = $('#new_map').html(); + + }, + bindFormEvents: function () { + var self = Metamaps.GlobalUI.CreateMap; + + $('.new_map input, .new_map div').unbind('keypress').bind('keypress', function(event) { + if (event.keyCode === 13) self.submit() + }) + + $('.new_map button.cancel').unbind().bind('click', function (event) { + event.preventDefault(); + Metamaps.GlobalUI.closeLightbox(); + }); + $('.new_map button.submitMap').unbind().bind('click', self.submit); + + // bind permission changer events on the createMap form + $('.permIcon').unbind().bind('click', self.switchPermission); + }, + closeSuccess: function () { + $('#mapCreatedSuccess').fadeOut(300, function(){ + $(this).remove(); + }); + }, + generateSuccessMessage: function (id) { + var stringStart = "
SUCCESS!
Your map has been created. Do you want to: Go to your new map"; + stringStart += "ORStay on this "; + var page = Metamaps.Active.Map ? 'map' : 'page'; + var stringEnd = "
"; + return stringStart + page + stringEnd; + }, + switchPermission: function () { + var self = Metamaps.GlobalUI.CreateMap; + + self.newMap.set('permission', $(this).attr('data-permission')); + $(this).siblings('.permIcon').find('.mapPermIcon').removeClass('selected'); + $(this).find('.mapPermIcon').addClass('selected'); + + var permText = $(this).find('.tip').html(); + $(this).parents('.new_map').find('.permText').html(permText); + }, + submit: function (event) { + if (event) event.preventDefault(); + + var self = Metamaps.GlobalUI.CreateMap; + + if (Metamaps.GlobalUI.lightbox === 'forkmap') { + self.newMap.set('topicsToMap', self.topicsToMap); + self.newMap.set('synapsesToMap', self.synapsesToMap); + } + + var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var $form = $(formId); + + self.newMap.set('name', $form.find('#map_name').val()); + self.newMap.set('desc', $form.find('#map_desc').val()); + + if (self.newMap.get('name').length===0){ + self.throwMapNameError(); + return; + } + + self.newMap.save(null, { + success: self.success + // TODO add error message + }); + + Metamaps.GlobalUI.closeLightbox(); + Metamaps.GlobalUI.notifyUser('Working...'); + }, + throwMapNameError: function () { + var self = Metamaps.GlobalUI.CreateMap; + + var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var $form = $(formId); + + var message = $("
Please enter a map name...
"); + + $form.find('#map_name').after(message); + setTimeout(function(){ + message.fadeOut('fast', function(){ + message.remove(); + }); + }, 5000); + }, + success: function (model) { + var self = Metamaps.GlobalUI.CreateMap; + + //push the new map onto the collection of 'my maps' + Metamaps.Maps.Mine.add(model); + + var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var form = $(formId); + + Metamaps.GlobalUI.clearNotify(); + $('#wrapper').append(self.generateSuccessMessage(model.id)); + + }, + reset: function (id) { + var self = Metamaps.GlobalUI.CreateMap; + + var form = $('#' + id); + + if (id === "fork_map") { + self.topicsToMap = []; + self.synapsesToMap = []; + form.html(self.emptyForkMapForm); + } + else { + form.html(self.emptyMapForm); + } + + self.bindFormEvents(); + self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); + + return false; + }, +}; + + +Metamaps.GlobalUI.Account = { + isOpen: false, + changing: false, + init: function () { + var self = Metamaps.GlobalUI.Account; + + $('.sidebarAccountIcon').click(self.toggleBox); + $('.sidebarAccountBox').click(function(event){ + event.stopPropagation(); + }); + $('body').click(self.close); + }, + toggleBox: function (event) { + var self = Metamaps.GlobalUI.Account; + + if (self.isOpen) self.close(); + else self.open(); + + event.stopPropagation(); + }, + open: function () { + var self = Metamaps.GlobalUI.Account; + + Metamaps.Filter.close(); + $('.sidebarAccountIcon .tooltipsUnder').addClass('hide'); + + + if (!self.isOpen && !self.changing) { + self.changing = true; + $('.sidebarAccountBox').fadeIn(200, function () { + self.changing = false; + self.isOpen = true; + $('.sidebarAccountBox #user_email').focus(); + }); + } + }, + close: function () { + var self = Metamaps.GlobalUI.Account; + + $('.sidebarAccountIcon .tooltipsUnder').removeClass('hide'); + if (!self.changing) { + self.changing = true; + $('.sidebarAccountBox #user_email').blur(); + $('.sidebarAccountBox').fadeOut(200, function () { + self.changing = false; + self.isOpen = false; + }); + } + } +}; + +Metamaps.GlobalUI.Search = { + locked: false, + isOpen: false, + limitTopicsToMe: false, + limitMapsToMe: false, + timeOut: null, + changing: false, + optionsInitialized: false, + init: function () { + var self = Metamaps.GlobalUI.Search; + + var loader = new CanvasLoader('searchLoading'); + loader.setColor('#4fb5c0'); // default is '#000000' + loader.setDiameter(24); // default is 40 + loader.setDensity(41); // default is 40 + loader.setRange(0.9); // default is 1.3 + loader.show(); // Hidden by default + + // bind the hover events + $(".sidebarSearch").hover(function () { + self.open() + }, function () { + self.close(800, false) + }); + + $('.sidebarSearchIcon').click(function (e) { + $('.sidebarSearchField').focus(); + }); + $('.sidebarSearch').click(function (e) { + e.stopPropagation(); + }); + $('body').click(function (e) { + self.close(0, false); + }); + + // open if the search is closed and user hits ctrl+/ + // close if they hit ESC + $('body').bind('keyup', function (e) { + switch (e.which) { + case 191: + if ((e.ctrlKey && !self.isOpen) || (e.ctrlKey && self.locked)) { + self.open(true); // true for focus + } + break; + case 27: + if (self.isOpen) { + self.close(0, true); + } + break; + + default: + break; //console.log(e.which); + } + }); + + self.startTypeahead(); + }, + lock: function() { + var self = Metamaps.GlobalUI.Search; + self.locked = true; + }, + unlock: function() { + var self = Metamaps.GlobalUI.Search; + self.locked = false; + }, + open: function (focus) { + var self = Metamaps.GlobalUI.Search; + + clearTimeout(self.timeOut); + if (!self.isOpen && !self.changing && !self.locked) { + self.changing = true; + $('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({ + width: '400px' + }, 300, function () { + if (focus) $('.sidebarSearchField').focus(); + $('.sidebarSearchField, .sidebarSearch .tt-hint').css({ + padding: '7px 10px 3px 10px', + width: '380px' + }); + self.changing = false; + self.isOpen = true; + }); + } + }, + close: function (closeAfter, bypass) { + // for now + return + + var self = Metamaps.GlobalUI.Search; + + self.timeOut = setTimeout(function () { + if (!self.locked && !self.changing && self.isOpen && (bypass || $('.sidebarSearchField.tt-input').val() == '')) { + self.changing = true; + $('.sidebarSearchField, .sidebarSearch .tt-hint').css({ + padding: '7px 0 3px 0', + width: '400px' + }); + $('.sidebarSearch .twitter-typeahead, .sidebarSearch .tt-hint, .sidebarSearchField').animate({ + width: '0' + }, 300, function () { + $('.sidebarSearchField').typeahead('val', ''); + $('.sidebarSearchField').blur(); + self.changing = false; + self.isOpen = false; + }); + } + }, closeAfter); + }, + startTypeahead: function () { + var self = Metamaps.GlobalUI.Search; + + var mapheader = Metamaps.Active.Mapper ? '

Maps

' : '

Maps

'; + var topicheader = Metamaps.Active.Mapper ? '

Topics

' : '

Topics

'; + var mapperheader = '

Mappers

'; + + var topics = { + name: 'topics', + limit: 9999, + + display: function(s) { return s.label; }, + templates: { + notFound: function(s) { + return Hogan.compile(topicheader + $('#topicSearchTemplate').html()).render({ + value: "No results", + label: "No results", + typeImageURL: Metamaps.Erb['icons/wildcard.png'], + rtype: "noresult" + }); + }, + header: topicheader, + suggestion: function(s) { + return Hogan.compile($('#topicSearchTemplate').html()).render(s); + }, + }, + source: new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + remote: { + url: '/search/topics', + prepare: function(query, settings) { + settings.url += '?term=' + query; + if (Metamaps.Active.Mapper && self.limitTopicsToMe) { + settings.url += "&user=" + Metamaps.Active.Mapper.id.toString(); + } + return settings; + }, + }, + }), + }; + + var maps = { + name: 'maps', + limit: 9999, + display: function(s) { return s.label; }, + templates: { + notFound: function(s) { + return Hogan.compile(mapheader + $('#mapSearchTemplate').html()).render({ + value: "No results", + label: "No results", + rtype: "noresult" + }); + }, + header: mapheader, + suggestion: function(s) { + return Hogan.compile($('#mapSearchTemplate').html()).render(s); + }, + }, + source: new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + remote: { + url: '/search/maps', + prepare: function(query, settings) { + settings.url += '?term=' + query; + if (Metamaps.Active.Mapper && self.limitMapsToMe) { + settings.url += "&user=" + Metamaps.Active.Mapper.id.toString(); + } + return settings; + }, + }, + }), + }; + + var mappers = { + name: 'mappers', + limit: 9999, + display: function(s) { return s.label; }, + templates: { + notFound: function(s) { + return Hogan.compile(mapperheader + $('#mapperSearchTemplate').html()).render({ + value: "No results", + label: "No results", + rtype: "noresult", + profile: Metamaps.Erb['user.png'] + }); + }, + header: mapperheader, + suggestion: function(s) { + return Hogan.compile($('#mapperSearchTemplate').html()).render(s); + }, + }, + source: new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + remote: { + url: '/search/mappers?term=%QUERY', + wildcard: '%QUERY', + }, + }), + }; + + // Take all that crazy setup data and put it together into one beautiful typeahead call! + $('.sidebarSearchField').typeahead( + { + highlight: true, + }, + [topics, maps, mappers] + ); + + //Set max height of the search results box to prevent it from covering bottom left footer + $('.sidebarSearchField').bind('typeahead:render', function (event) { + self.initSearchOptions(); + self.hideLoader(); + var h = $(window).height(); + $(".tt-dropdown-menu").css('max-height', h - 100); + if (self.limitTopicsToMe) { + $('#limitTopicsToMe').prop('checked', true); + } + if (self.limitMapsToMe) { + $('#limitMapsToMe').prop('checked', true); + } + }); + $(window).resize(function () { + var h = $(window).height(); + $(".tt-dropdown-menu").css('max-height', h - 100); + }); + + // tell the autocomplete to launch a new tab with the topic, map, or mapper you clicked on + $('.sidebarSearchField').bind('typeahead:select', self.handleResultClick); + + // don't do it, if they clicked on a 'addToMap' button + $('.sidebarSearch button.addToMap').click(function (event) { + event.stopPropagation(); + }); + + // make sure that when you click on 'limit to me' or 'toggle section' it works + $('.sidebarSearchField.tt-input').keyup(function(){ + if ($('.sidebarSearchField.tt-input').val() === '') { + self.hideLoader(); + } else { + self.showLoader(); + } + }); + + }, + handleResultClick: function (event, datum, dataset) { + var self = Metamaps.GlobalUI.Search; + + self.hideLoader(); + + if (["topic", "map", "mapper"].indexOf(datum.rtype) !== -1) { + self.close(0, true); + var win; + if (datum.rtype == "topic") { + Metamaps.Router.topics(datum.id); + } else if (datum.rtype == "map") { + Metamaps.Router.maps(datum.id); + } else if (datum.rtype == "mapper") { + Metamaps.Router.explore("mapper", datum.id); + } + } + }, + initSearchOptions: function () { + var self = Metamaps.GlobalUI.Search; + + function toggleResultSet(set) { + var s = $('.tt-dataset-' + set + ' .tt-suggestion, .tt-dataset-' + set + ' .resultnoresult'); + if (s.is(':visible')) { + s.hide(); + $(this).removeClass('minimizeResults').addClass('maximizeResults'); + } else { + s.show(); + $(this).removeClass('maximizeResults').addClass('minimizeResults'); + } + } + + $('.limitToMe').unbind().bind("change", function (e) { + if ($(this).attr('id') == 'limitTopicsToMe') { + self.limitTopicsToMe = !self.limitTopicsToMe; + } + if ($(this).attr('id') == 'limitMapsToMe') { + self.limitMapsToMe = !self.limitMapsToMe; + } + + // set the value of the search equal to itself to retrigger the + // autocomplete event + var searchQuery = $('.sidebarSearchField.tt-input').val(); + $(".sidebarSearchField").typeahead('val', '') + .typeahead('val', searchQuery); + }); + + // when the user clicks minimize section, hide the results for that section + $('.minimizeMapperResults').unbind().click(function (e) { + toggleResultSet.call(this, 'mappers'); + }); + $('.minimizeTopicResults').unbind().click(function (e) { + toggleResultSet.call(this, 'topics'); + }); + $('.minimizeMapResults').unbind().click(function (e) { + toggleResultSet.call(this, 'maps'); + }); + }, + hideLoader: function () { + $('#searchLoading').hide(); + }, + showLoader: function () { + $('#searchLoading').show(); + } +} diff --git a/app/assets/javascripts/src/Metamaps.Import.js b/frontend/src/Metamaps/Metamaps.Import.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Import.js rename to frontend/src/Metamaps/Metamaps.Import.js index 2dee51d0..426071f0 100644 --- a/app/assets/javascripts/src/Metamaps.Import.js +++ b/frontend/src/Metamaps/Metamaps.Import.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.JIT.js b/frontend/src/Metamaps/Metamaps.JIT.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.JIT.js rename to frontend/src/Metamaps/Metamaps.JIT.js index d5e82081..cfdd921d 100644 --- a/app/assets/javascripts/src/Metamaps.JIT.js +++ b/frontend/src/Metamaps/Metamaps.JIT.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} Metamaps.JIT = { events: { topicDrag: 'Metamaps:JIT:events:topicDrag', @@ -819,7 +820,7 @@ Metamaps.JIT = { } } // - temp = eventInfo.getNode() + let temp = eventInfo.getNode() if (temp != false && temp.id != node.id && Metamaps.Selected.Nodes.indexOf(temp) == -1) { // this means a Node has been returned Metamaps.tempNode2 = temp diff --git a/app/assets/javascripts/src/Metamaps.Listeners.js b/frontend/src/Metamaps/Metamaps.Listeners.js similarity index 98% rename from app/assets/javascripts/src/Metamaps.Listeners.js rename to frontend/src/Metamaps/Metamaps.Listeners.js index 948893cb..e6c4e1b9 100644 --- a/app/assets/javascripts/src/Metamaps.Listeners.js +++ b/frontend/src/Metamaps/Metamaps.Listeners.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Map.js b/frontend/src/Metamaps/Metamaps.Map.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Map.js rename to frontend/src/Metamaps/Metamaps.Map.js index 264e3c48..e925a92c 100644 --- a/app/assets/javascripts/src/Metamaps.Map.js +++ b/frontend/src/Metamaps/Metamaps.Map.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Mapper.js b/frontend/src/Metamaps/Metamaps.Mapper.js similarity index 91% rename from app/assets/javascripts/src/Metamaps.Mapper.js rename to frontend/src/Metamaps/Metamaps.Mapper.js index 7d565479..f8a530b8 100644 --- a/app/assets/javascripts/src/Metamaps.Mapper.js +++ b/frontend/src/Metamaps/Metamaps.Mapper.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Mobile.js b/frontend/src/Metamaps/Metamaps.Mobile.js similarity index 95% rename from app/assets/javascripts/src/Metamaps.Mobile.js rename to frontend/src/Metamaps/Metamaps.Mobile.js index 1a55f081..fcd76b2f 100644 --- a/app/assets/javascripts/src/Metamaps.Mobile.js +++ b/frontend/src/Metamaps/Metamaps.Mobile.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Organize.js b/frontend/src/Metamaps/Metamaps.Organize.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Organize.js rename to frontend/src/Metamaps/Metamaps.Organize.js index b2463280..220cb83a 100644 --- a/app/assets/javascripts/src/Metamaps.Organize.js +++ b/frontend/src/Metamaps/Metamaps.Organize.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.PasteInput.js b/frontend/src/Metamaps/Metamaps.PasteInput.js similarity index 98% rename from app/assets/javascripts/src/Metamaps.PasteInput.js rename to frontend/src/Metamaps/Metamaps.PasteInput.js index aaf848d0..3e933e41 100644 --- a/app/assets/javascripts/src/Metamaps.PasteInput.js +++ b/frontend/src/Metamaps/Metamaps.PasteInput.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/frontend/src/Metamaps/Metamaps.ReactComponents.js b/frontend/src/Metamaps/Metamaps.ReactComponents.js new file mode 100644 index 00000000..a1de0f40 --- /dev/null +++ b/frontend/src/Metamaps/Metamaps.ReactComponents.js @@ -0,0 +1,7 @@ +window.Metamaps = window.Metamaps || {} + +import Maps from '../components/Maps' + +Metamaps.ReactComponents = { + Maps +} diff --git a/app/assets/javascripts/src/Metamaps.Realtime.js b/frontend/src/Metamaps/Metamaps.Realtime.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Realtime.js rename to frontend/src/Metamaps/Metamaps.Realtime.js index 620a561a..0b62648f 100644 --- a/app/assets/javascripts/src/Metamaps.Realtime.js +++ b/frontend/src/Metamaps/Metamaps.Realtime.js @@ -1,3 +1,5 @@ +window.Metamaps = window.Metamaps || {} + /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Router.js b/frontend/src/Metamaps/Metamaps.Router.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Router.js rename to frontend/src/Metamaps/Metamaps.Router.js index 3ef30986..417c9b9e 100644 --- a/app/assets/javascripts/src/Metamaps.Router.js +++ b/frontend/src/Metamaps/Metamaps.Router.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, Backbone, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Synapse.js b/frontend/src/Metamaps/Metamaps.Synapse.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Synapse.js rename to frontend/src/Metamaps/Metamaps.Synapse.js index ceed219d..20cf0f9c 100644 --- a/app/assets/javascripts/src/Metamaps.Synapse.js +++ b/frontend/src/Metamaps/Metamaps.Synapse.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.SynapseCard.js b/frontend/src/Metamaps/Metamaps.SynapseCard.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.SynapseCard.js rename to frontend/src/Metamaps/Metamaps.SynapseCard.js index f71601e5..aff207a9 100644 --- a/app/assets/javascripts/src/Metamaps.SynapseCard.js +++ b/frontend/src/Metamaps/Metamaps.SynapseCard.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Topic.js b/frontend/src/Metamaps/Metamaps.Topic.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Topic.js rename to frontend/src/Metamaps/Metamaps.Topic.js index a0ebfa82..faa8b336 100644 --- a/app/assets/javascripts/src/Metamaps.Topic.js +++ b/frontend/src/Metamaps/Metamaps.Topic.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.TopicCard.js b/frontend/src/Metamaps/Metamaps.TopicCard.js similarity index 98% rename from app/assets/javascripts/src/Metamaps.TopicCard.js rename to frontend/src/Metamaps/Metamaps.TopicCard.js index 1453104d..fc007f3b 100644 --- a/app/assets/javascripts/src/Metamaps.TopicCard.js +++ b/frontend/src/Metamaps/Metamaps.TopicCard.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -421,18 +422,18 @@ Metamaps.TopicCard = { var inmapsLinks = topic.get('inmapsLinks') || [] nodeValues.inmaps = '' if (inmapsAr.length < 6) { - for (i = 0; i < inmapsAr.length; i++) { + for (let i = 0; i < inmapsAr.length; i++) { var url = '/maps/' + inmapsLinks[i] nodeValues.inmaps += '
  • ' + inmapsAr[i] + '
  • ' } } else { - for (i = 0; i < 5; i++) { + for (let i = 0; i < 5; i++) { var url = '/maps/' + inmapsLinks[i] nodeValues.inmaps += '
  • ' + inmapsAr[i] + '
  • ' } extra = inmapsAr.length - 5 nodeValues.inmaps += '
  • See ' + extra + ' more...
  • ' - for (i = 5; i < inmapsAr.length; i++) { + for (let i = 5; i < inmapsAr.length; i++) { var url = '/maps/' + inmapsLinks[i] nodeValues.inmaps += '
  • ' + inmapsAr[i] + '
  • ' } diff --git a/app/assets/javascripts/src/Metamaps.Util.js b/frontend/src/Metamaps/Metamaps.Util.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Util.js rename to frontend/src/Metamaps/Metamaps.Util.js index e150d3bb..9ff9c470 100644 --- a/app/assets/javascripts/src/Metamaps.Util.js +++ b/frontend/src/Metamaps/Metamaps.Util.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps */ /* diff --git a/app/assets/javascripts/src/Metamaps.Views.js b/frontend/src/Metamaps/Metamaps.Views.js similarity index 98% rename from app/assets/javascripts/src/Metamaps.Views.js rename to frontend/src/Metamaps/Metamaps.Views.js index d027d22c..eb5fdb7c 100644 --- a/app/assets/javascripts/src/Metamaps.Views.js +++ b/frontend/src/Metamaps/Metamaps.Views.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* diff --git a/app/assets/javascripts/src/Metamaps.Visualize.js b/frontend/src/Metamaps/Metamaps.Visualize.js similarity index 99% rename from app/assets/javascripts/src/Metamaps.Visualize.js rename to frontend/src/Metamaps/Metamaps.Visualize.js index 7168c03a..f5ce8c79 100644 --- a/app/assets/javascripts/src/Metamaps.Visualize.js +++ b/frontend/src/Metamaps/Metamaps.Visualize.js @@ -1,3 +1,4 @@ +window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* * Metamaps.Visualize diff --git a/app/assets/javascripts/src/Metamaps.js.erb b/frontend/src/Metamaps/index.js similarity index 60% rename from app/assets/javascripts/src/Metamaps.js.erb rename to frontend/src/Metamaps/index.js index 839d701e..bf54483d 100644 --- a/app/assets/javascripts/src/Metamaps.js.erb +++ b/frontend/src/Metamaps/index.js @@ -1,26 +1,10 @@ -/* global Metamaps */ - -/* - * Metamaps.js.erb - */ +window.Metamaps = window.Metamaps || {} // TODO eliminate these 5 top-level variables Metamaps.panningInt = null Metamaps.tempNode = null Metamaps.tempInit = false Metamaps.tempNode2 = null -Metamaps.VERSION = '<%= METAMAPS_VERSION %>' - -/* erb variables from rails */ -Metamaps.Erb = {} -Metamaps.Erb['REALTIME_SERVER'] = '<%= ENV['REALTIME_SERVER'] %>' -Metamaps.Erb['junto_spinner_darkgrey.gif'] = '<%= asset_path('junto_spinner_darkgrey.gif') %>' -Metamaps.Erb['user.png'] = '<%= asset_path('user.png') %>' -Metamaps.Erb['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>' -Metamaps.Erb['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>' -Metamaps.Erb['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>' -Metamaps.Erb['synapse16.png'] = '<%= asset_path('synapse16.png') %>' -Metamaps.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %> Metamaps.Settings = { embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages @@ -65,10 +49,39 @@ Metamaps.Mouse = { Metamaps.Selected = { reset: function () { var self = Metamaps.Selected - self.Nodes = [] self.Edges = [] }, Nodes: [], Edges: [] } + +require('./Metamaps.Account') +require('./Metamaps.Admin') +require('./Metamaps.AutoLayout') +require('./Metamaps.Backbone') +require('./Metamaps.Control') +require('./Metamaps.Create') +require('./Metamaps.Debug') +require('./Metamaps.Filter') +require('./Metamaps.GlobalUI') +require('./Metamaps.Import') +require('./Metamaps.JIT') +require('./Metamaps.Listeners') +require('./Metamaps.Map') +require('./Metamaps.Mapper') +require('./Metamaps.Mobile') +require('./Metamaps.Organize') +require('./Metamaps.PasteInput') +require('./Metamaps.Realtime') +require('./Metamaps.Router') +require('./Metamaps.Synapse') +require('./Metamaps.SynapseCard') +require('./Metamaps.Topic') +require('./Metamaps.TopicCard') +require('./Metamaps.Util') +require('./Metamaps.Views') +require('./Metamaps.Visualize') +require('./Metamaps.ReactComponents') + +export default window.Metamaps diff --git a/frontend/src/index.js b/frontend/src/index.js index 0556f4c1..e5705512 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -2,17 +2,14 @@ import React from 'react' import ReactDOM from 'react-dom' import Backbone from 'backbone' import _ from 'underscore' -import Maps from './components/Maps.js' -// this is optional really, if we import components directly React will be -// in the bundle, so we won't need a global reference +import Metamaps from './Metamaps' + +// create global references to some libraries window.React = React window.ReactDOM = ReactDOM -Backbone.$ = window.$ +Backbone.$ = window.$ // jquery from rails window.Backbone = Backbone window._ = _ -window.Metamaps = window.Metamaps || {} -window.Metamaps.ReactComponents = { - Maps -} +window.Metamaps = Metamaps From d02c836805e36b0611872a04f481a759e902b58a Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 14:35:14 +0800 Subject: [PATCH 02/26] remove Metamaps from filenames --- .../{Metamaps.Account.js => Account.js} | 0 .../Metamaps/{Metamaps.Admin.js => Admin.js} | 0 .../{Metamaps.AutoLayout.js => AutoLayout.js} | 0 .../{Metamaps.Backbone.js => Backbone.js} | 0 frontend/src/Metamaps/Constants.js | 57 +++++++++ .../{Metamaps.Control.js => Control.js} | 0 .../{Metamaps.Create.js => Create.js} | 0 .../Metamaps/{Metamaps.Debug.js => Debug.js} | 0 .../{Metamaps.Filter.js => Filter.js} | 0 .../{Metamaps.GlobalUI.js => GlobalUI.js} | 0 .../{Metamaps.Import.js => Import.js} | 0 .../src/Metamaps/{Metamaps.JIT.js => JIT.js} | 1 + .../{Metamaps.Listeners.js => Listeners.js} | 0 .../src/Metamaps/{Metamaps.Map.js => Map.js} | 0 .../{Metamaps.Mapper.js => Mapper.js} | 0 .../{Metamaps.Mobile.js => Mobile.js} | 0 .../{Metamaps.Organize.js => Organize.js} | 0 .../{Metamaps.PasteInput.js => PasteInput.js} | 0 ....ReactComponents.js => ReactComponents.js} | 0 .../{Metamaps.Realtime.js => Realtime.js} | 0 .../{Metamaps.Router.js => Router.js} | 0 .../{Metamaps.Synapse.js => Synapse.js} | 0 ...Metamaps.SynapseCard.js => SynapseCard.js} | 0 .../Metamaps/{Metamaps.Topic.js => Topic.js} | 0 .../{Metamaps.TopicCard.js => TopicCard.js} | 0 .../Metamaps/{Metamaps.Util.js => Util.js} | 0 .../Metamaps/{Metamaps.Views.js => Views.js} | 0 .../{Metamaps.Visualize.js => Visualize.js} | 0 frontend/src/Metamaps/index.js | 110 +++++------------- 29 files changed, 86 insertions(+), 82 deletions(-) rename frontend/src/Metamaps/{Metamaps.Account.js => Account.js} (100%) rename frontend/src/Metamaps/{Metamaps.Admin.js => Admin.js} (100%) rename frontend/src/Metamaps/{Metamaps.AutoLayout.js => AutoLayout.js} (100%) rename frontend/src/Metamaps/{Metamaps.Backbone.js => Backbone.js} (100%) create mode 100644 frontend/src/Metamaps/Constants.js rename frontend/src/Metamaps/{Metamaps.Control.js => Control.js} (100%) rename frontend/src/Metamaps/{Metamaps.Create.js => Create.js} (100%) rename frontend/src/Metamaps/{Metamaps.Debug.js => Debug.js} (100%) rename frontend/src/Metamaps/{Metamaps.Filter.js => Filter.js} (100%) rename frontend/src/Metamaps/{Metamaps.GlobalUI.js => GlobalUI.js} (100%) rename frontend/src/Metamaps/{Metamaps.Import.js => Import.js} (100%) rename frontend/src/Metamaps/{Metamaps.JIT.js => JIT.js} (99%) rename frontend/src/Metamaps/{Metamaps.Listeners.js => Listeners.js} (100%) rename frontend/src/Metamaps/{Metamaps.Map.js => Map.js} (100%) rename frontend/src/Metamaps/{Metamaps.Mapper.js => Mapper.js} (100%) rename frontend/src/Metamaps/{Metamaps.Mobile.js => Mobile.js} (100%) rename frontend/src/Metamaps/{Metamaps.Organize.js => Organize.js} (100%) rename frontend/src/Metamaps/{Metamaps.PasteInput.js => PasteInput.js} (100%) rename frontend/src/Metamaps/{Metamaps.ReactComponents.js => ReactComponents.js} (100%) rename frontend/src/Metamaps/{Metamaps.Realtime.js => Realtime.js} (100%) rename frontend/src/Metamaps/{Metamaps.Router.js => Router.js} (100%) rename frontend/src/Metamaps/{Metamaps.Synapse.js => Synapse.js} (100%) rename frontend/src/Metamaps/{Metamaps.SynapseCard.js => SynapseCard.js} (100%) rename frontend/src/Metamaps/{Metamaps.Topic.js => Topic.js} (100%) rename frontend/src/Metamaps/{Metamaps.TopicCard.js => TopicCard.js} (100%) rename frontend/src/Metamaps/{Metamaps.Util.js => Util.js} (100%) rename frontend/src/Metamaps/{Metamaps.Views.js => Views.js} (100%) rename frontend/src/Metamaps/{Metamaps.Visualize.js => Visualize.js} (100%) diff --git a/frontend/src/Metamaps/Metamaps.Account.js b/frontend/src/Metamaps/Account.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Account.js rename to frontend/src/Metamaps/Account.js diff --git a/frontend/src/Metamaps/Metamaps.Admin.js b/frontend/src/Metamaps/Admin.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Admin.js rename to frontend/src/Metamaps/Admin.js diff --git a/frontend/src/Metamaps/Metamaps.AutoLayout.js b/frontend/src/Metamaps/AutoLayout.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.AutoLayout.js rename to frontend/src/Metamaps/AutoLayout.js diff --git a/frontend/src/Metamaps/Metamaps.Backbone.js b/frontend/src/Metamaps/Backbone.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Backbone.js rename to frontend/src/Metamaps/Backbone.js diff --git a/frontend/src/Metamaps/Constants.js b/frontend/src/Metamaps/Constants.js new file mode 100644 index 00000000..f56c463a --- /dev/null +++ b/frontend/src/Metamaps/Constants.js @@ -0,0 +1,57 @@ +window.Metamaps = window.Metamaps || {} + +// TODO eliminate these 5 top-level variables +Metamaps.panningInt = null +Metamaps.tempNode = null +Metamaps.tempInit = false +Metamaps.tempNode2 = null + +Metamaps.Settings = { + embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages + sandbox: false, // puts the app into a mode (when true) where it only creates data locally, and isn't writing it to the database + colors: { + background: '#344A58', + synapses: { + normal: '#888888', + hover: '#888888', + selected: '#FFFFFF' + }, + topics: { + selected: '#FFFFFF' + }, + labels: { + background: '#18202E', + text: '#DDD' + } + }, +} + +Metamaps.Touch = { + touchPos: null, // this stores the x and y values of a current touch event + touchDragNode: null // this stores a reference to a JIT node that is being dragged +} + +Metamaps.Mouse = { + didPan: false, + didBoxZoom: false, + changeInX: 0, + changeInY: 0, + edgeHoveringOver: false, + boxStartCoordinates: false, + boxEndCoordinates: false, + synapseStartCoordinates: [], + synapseEndCoordinates: null, + lastNodeClick: 0, + lastCanvasClick: 0, + DOUBLE_CLICK_TOLERANCE: 300 +} + +Metamaps.Selected = { + reset: function () { + var self = Metamaps.Selected + self.Nodes = [] + self.Edges = [] + }, + Nodes: [], + Edges: [] +} diff --git a/frontend/src/Metamaps/Metamaps.Control.js b/frontend/src/Metamaps/Control.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Control.js rename to frontend/src/Metamaps/Control.js diff --git a/frontend/src/Metamaps/Metamaps.Create.js b/frontend/src/Metamaps/Create.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Create.js rename to frontend/src/Metamaps/Create.js diff --git a/frontend/src/Metamaps/Metamaps.Debug.js b/frontend/src/Metamaps/Debug.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Debug.js rename to frontend/src/Metamaps/Debug.js diff --git a/frontend/src/Metamaps/Metamaps.Filter.js b/frontend/src/Metamaps/Filter.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Filter.js rename to frontend/src/Metamaps/Filter.js diff --git a/frontend/src/Metamaps/Metamaps.GlobalUI.js b/frontend/src/Metamaps/GlobalUI.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.GlobalUI.js rename to frontend/src/Metamaps/GlobalUI.js diff --git a/frontend/src/Metamaps/Metamaps.Import.js b/frontend/src/Metamaps/Import.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Import.js rename to frontend/src/Metamaps/Import.js diff --git a/frontend/src/Metamaps/Metamaps.JIT.js b/frontend/src/Metamaps/JIT.js similarity index 99% rename from frontend/src/Metamaps/Metamaps.JIT.js rename to frontend/src/Metamaps/JIT.js index cfdd921d..57ab60bf 100644 --- a/frontend/src/Metamaps/Metamaps.JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -1,4 +1,5 @@ window.Metamaps = window.Metamaps || {} + Metamaps.JIT = { events: { topicDrag: 'Metamaps:JIT:events:topicDrag', diff --git a/frontend/src/Metamaps/Metamaps.Listeners.js b/frontend/src/Metamaps/Listeners.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Listeners.js rename to frontend/src/Metamaps/Listeners.js diff --git a/frontend/src/Metamaps/Metamaps.Map.js b/frontend/src/Metamaps/Map.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Map.js rename to frontend/src/Metamaps/Map.js diff --git a/frontend/src/Metamaps/Metamaps.Mapper.js b/frontend/src/Metamaps/Mapper.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Mapper.js rename to frontend/src/Metamaps/Mapper.js diff --git a/frontend/src/Metamaps/Metamaps.Mobile.js b/frontend/src/Metamaps/Mobile.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Mobile.js rename to frontend/src/Metamaps/Mobile.js diff --git a/frontend/src/Metamaps/Metamaps.Organize.js b/frontend/src/Metamaps/Organize.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Organize.js rename to frontend/src/Metamaps/Organize.js diff --git a/frontend/src/Metamaps/Metamaps.PasteInput.js b/frontend/src/Metamaps/PasteInput.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.PasteInput.js rename to frontend/src/Metamaps/PasteInput.js diff --git a/frontend/src/Metamaps/Metamaps.ReactComponents.js b/frontend/src/Metamaps/ReactComponents.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.ReactComponents.js rename to frontend/src/Metamaps/ReactComponents.js diff --git a/frontend/src/Metamaps/Metamaps.Realtime.js b/frontend/src/Metamaps/Realtime.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Realtime.js rename to frontend/src/Metamaps/Realtime.js diff --git a/frontend/src/Metamaps/Metamaps.Router.js b/frontend/src/Metamaps/Router.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Router.js rename to frontend/src/Metamaps/Router.js diff --git a/frontend/src/Metamaps/Metamaps.Synapse.js b/frontend/src/Metamaps/Synapse.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Synapse.js rename to frontend/src/Metamaps/Synapse.js diff --git a/frontend/src/Metamaps/Metamaps.SynapseCard.js b/frontend/src/Metamaps/SynapseCard.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.SynapseCard.js rename to frontend/src/Metamaps/SynapseCard.js diff --git a/frontend/src/Metamaps/Metamaps.Topic.js b/frontend/src/Metamaps/Topic.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Topic.js rename to frontend/src/Metamaps/Topic.js diff --git a/frontend/src/Metamaps/Metamaps.TopicCard.js b/frontend/src/Metamaps/TopicCard.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.TopicCard.js rename to frontend/src/Metamaps/TopicCard.js diff --git a/frontend/src/Metamaps/Metamaps.Util.js b/frontend/src/Metamaps/Util.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Util.js rename to frontend/src/Metamaps/Util.js diff --git a/frontend/src/Metamaps/Metamaps.Views.js b/frontend/src/Metamaps/Views.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Views.js rename to frontend/src/Metamaps/Views.js diff --git a/frontend/src/Metamaps/Metamaps.Visualize.js b/frontend/src/Metamaps/Visualize.js similarity index 100% rename from frontend/src/Metamaps/Metamaps.Visualize.js rename to frontend/src/Metamaps/Visualize.js diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index bf54483d..ef50b564 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -1,87 +1,33 @@ window.Metamaps = window.Metamaps || {} -// TODO eliminate these 5 top-level variables -Metamaps.panningInt = null -Metamaps.tempNode = null -Metamaps.tempInit = false -Metamaps.tempNode2 = null +import './Constants' -Metamaps.Settings = { - embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages - sandbox: false, // puts the app into a mode (when true) where it only creates data locally, and isn't writing it to the database - colors: { - background: '#344A58', - synapses: { - normal: '#888888', - hover: '#888888', - selected: '#FFFFFF' - }, - topics: { - selected: '#FFFFFF' - }, - labels: { - background: '#18202E', - text: '#DDD' - } - }, -} - -Metamaps.Touch = { - touchPos: null, // this stores the x and y values of a current touch event - touchDragNode: null // this stores a reference to a JIT node that is being dragged -} - -Metamaps.Mouse = { - didPan: false, - didBoxZoom: false, - changeInX: 0, - changeInY: 0, - edgeHoveringOver: false, - boxStartCoordinates: false, - boxEndCoordinates: false, - synapseStartCoordinates: [], - synapseEndCoordinates: null, - lastNodeClick: 0, - lastCanvasClick: 0, - DOUBLE_CLICK_TOLERANCE: 300 -} - -Metamaps.Selected = { - reset: function () { - var self = Metamaps.Selected - self.Nodes = [] - self.Edges = [] - }, - Nodes: [], - Edges: [] -} - -require('./Metamaps.Account') -require('./Metamaps.Admin') -require('./Metamaps.AutoLayout') -require('./Metamaps.Backbone') -require('./Metamaps.Control') -require('./Metamaps.Create') -require('./Metamaps.Debug') -require('./Metamaps.Filter') -require('./Metamaps.GlobalUI') -require('./Metamaps.Import') -require('./Metamaps.JIT') -require('./Metamaps.Listeners') -require('./Metamaps.Map') -require('./Metamaps.Mapper') -require('./Metamaps.Mobile') -require('./Metamaps.Organize') -require('./Metamaps.PasteInput') -require('./Metamaps.Realtime') -require('./Metamaps.Router') -require('./Metamaps.Synapse') -require('./Metamaps.SynapseCard') -require('./Metamaps.Topic') -require('./Metamaps.TopicCard') -require('./Metamaps.Util') -require('./Metamaps.Views') -require('./Metamaps.Visualize') -require('./Metamaps.ReactComponents') +import './Account' +import './Admin' +import './AutoLayout' +import './Backbone' +import './Control' +import './Create' +import './Debug' +import './Filter' +import './GlobalUI' +import './Import' +import './JIT' +import './Listeners' +import './Map' +import './Mapper' +import './Mobile' +import './Organize' +import './PasteInput' +import './Realtime' +import './Router' +import './Synapse' +import './SynapseCard' +import './Topic' +import './TopicCard' +import './Util' +import './Views' +import './Visualize' +import './ReactComponents' export default window.Metamaps From 03446f548aad8f6956d4339f35a12dec2b88007f Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 15:21:59 +0800 Subject: [PATCH 03/26] start making the code modular. many files still need global scape --- frontend/src/Metamaps/Account.js | 2 + frontend/src/Metamaps/Admin.js | 13 +- frontend/src/Metamaps/AutoLayout.js | 13 +- frontend/src/Metamaps/Backbone.js | 2 + frontend/src/Metamaps/Constants.js | 1 - frontend/src/Metamaps/Control.js | 44 +-- frontend/src/Metamaps/Create.js | 74 ++-- frontend/src/Metamaps/Debug.js | 19 +- frontend/src/Metamaps/Filter.js | 51 +-- frontend/src/Metamaps/GlobalUI.js | 2 + frontend/src/Metamaps/Import.js | 19 +- frontend/src/Metamaps/JIT.js | 92 ++--- frontend/src/Metamaps/Listeners.js | 7 +- frontend/src/Metamaps/Map.js | 3 + frontend/src/Metamaps/Mapper.js | 26 +- frontend/src/Metamaps/Mobile.js | 7 +- frontend/src/Metamaps/Organize.js | 8 +- frontend/src/Metamaps/PasteInput.js | 9 +- frontend/src/Metamaps/ReactComponents.js | 6 +- frontend/src/Metamaps/Realtime.js | 154 ++++---- frontend/src/Metamaps/Router.js | 430 +++++++++++------------ frontend/src/Metamaps/Synapse.js | 11 +- frontend/src/Metamaps/SynapseCard.js | 15 +- frontend/src/Metamaps/Topic.js | 7 +- frontend/src/Metamaps/TopicCard.js | 29 +- frontend/src/Metamaps/Util.js | 9 +- frontend/src/Metamaps/Views.js | 15 +- frontend/src/Metamaps/Visualize.js | 14 +- frontend/src/Metamaps/index.js | 82 +++-- 29 files changed, 598 insertions(+), 566 deletions(-) diff --git a/frontend/src/Metamaps/Account.js b/frontend/src/Metamaps/Account.js index 66348481..95a1a69f 100644 --- a/frontend/src/Metamaps/Account.js +++ b/frontend/src/Metamaps/Account.js @@ -121,3 +121,5 @@ Metamaps.Account = { $('#user_password_confirmation').val('') } } + +export default Metamaps.Account diff --git a/frontend/src/Metamaps/Admin.js b/frontend/src/Metamaps/Admin.js index 8dcaed5b..10cbc6d8 100644 --- a/frontend/src/Metamaps/Admin.js +++ b/frontend/src/Metamaps/Admin.js @@ -1,13 +1,6 @@ -window.Metamaps = window.Metamaps || {} -/* global Metamaps, $ */ +/* global $ */ -/* - * Metamaps.Admin.js.erb - * - * Dependencies: none! - */ - -Metamaps.Admin = { +const Admin = { selectMetacodes: [], allMetacodes: [], init: function () { @@ -53,3 +46,5 @@ Metamaps.Admin = { } } } + +export default Admin diff --git a/frontend/src/Metamaps/AutoLayout.js b/frontend/src/Metamaps/AutoLayout.js index 2360204b..386b61ef 100644 --- a/frontend/src/Metamaps/AutoLayout.js +++ b/frontend/src/Metamaps/AutoLayout.js @@ -1,13 +1,4 @@ -window.Metamaps = window.Metamaps || {} -/* global Metamaps */ - -/* - * Metmaaps.AutoLayout.js - * - * Dependencies: none! - */ - -Metamaps.AutoLayout = { +const AutoLayout = { nextX: 0, nextY: 0, sideLength: 1, @@ -74,3 +65,5 @@ Metamaps.AutoLayout = { self.turnCount = 0 } } + +export default AutoLayout diff --git a/frontend/src/Metamaps/Backbone.js b/frontend/src/Metamaps/Backbone.js index 3c991e0b..ce62c6be 100644 --- a/frontend/src/Metamaps/Backbone.js +++ b/frontend/src/Metamaps/Backbone.js @@ -695,3 +695,5 @@ Metamaps.Backbone.init = function () { } self.attachCollectionEvents() }; // end Metamaps.Backbone.init + +export default Metamaps.Backbone diff --git a/frontend/src/Metamaps/Constants.js b/frontend/src/Metamaps/Constants.js index f56c463a..a79054e6 100644 --- a/frontend/src/Metamaps/Constants.js +++ b/frontend/src/Metamaps/Constants.js @@ -1,7 +1,6 @@ window.Metamaps = window.Metamaps || {} // TODO eliminate these 5 top-level variables -Metamaps.panningInt = null Metamaps.tempNode = null Metamaps.tempInit = false Metamaps.tempNode2 = null diff --git a/frontend/src/Metamaps/Control.js b/frontend/src/Metamaps/Control.js index 33623927..b9df0d2c 100644 --- a/frontend/src/Metamaps/Control.js +++ b/frontend/src/Metamaps/Control.js @@ -1,12 +1,10 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* - * Metamaps.Control.js.erb + * Metamaps.Control.js * * Dependencies: * - Metamaps.Active - * - Metamaps.Control * - Metamaps.Filter * - Metamaps.GlobalUI * - Metamaps.JIT @@ -20,7 +18,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Visualize */ -Metamaps.Control = { +const Control = { init: function () {}, selectNode: function (node, e) { var filtered = node.getData('alpha') === 0 @@ -34,7 +32,7 @@ Metamaps.Control = { var l = Metamaps.Selected.Nodes.length for (var i = l - 1; i >= 0; i -= 1) { var node = Metamaps.Selected.Nodes[i] - Metamaps.Control.deselectNode(node) + Control.deselectNode(node) } Metamaps.Visualize.mGraph.plot() }, @@ -64,8 +62,8 @@ Metamaps.Control = { var r = confirm(text + 'Are you sure you want to permanently delete them all? This will remove them from all maps they appear on.') if (r == true) { - Metamaps.Control.deleteSelectedEdges() - Metamaps.Control.deleteSelectedNodes() + Control.deleteSelectedEdges() + Control.deleteSelectedNodes() } }, deleteSelectedNodes: function () { // refers to deleting topics permanently @@ -81,7 +79,7 @@ Metamaps.Control = { var l = Metamaps.Selected.Nodes.length for (var i = l - 1; i >= 0; i -= 1) { var node = Metamaps.Selected.Nodes[i] - Metamaps.Control.deleteNode(node.id) + Control.deleteNode(node.id) } }, deleteNode: function (nodeid) { // refers to deleting topics permanently @@ -106,7 +104,7 @@ Metamaps.Control = { $(document).trigger(Metamaps.JIT.events.deleteTopic, [{ mappableid: mappableid }]) - Metamaps.Control.hideNode(nodeid) + Control.hideNode(nodeid) } else { Metamaps.GlobalUI.notifyUser('Only topics you created can be deleted') } @@ -120,7 +118,7 @@ Metamaps.Control = { _.each(nodeids, function(nodeid) { if (Metamaps.Active.Topic.id !== nodeid) { Metamaps.Topics.remove(nodeid) - Metamaps.Control.hideNode(nodeid) + Control.hideNode(nodeid) } }) return @@ -139,7 +137,7 @@ Metamaps.Control = { for (i = l - 1; i >= 0; i -= 1) { node = Metamaps.Selected.Nodes[i] - Metamaps.Control.removeNode(node.id) + Control.removeNode(node.id) } }, removeNode: function (nodeid) { // refers to removing topics permanently from a map @@ -161,7 +159,7 @@ Metamaps.Control = { $(document).trigger(Metamaps.JIT.events.removeTopic, [{ mappableid: mappableid }]) - Metamaps.Control.hideNode(nodeid) + Control.hideNode(nodeid) }, hideSelectedNodes: function () { var l = Metamaps.Selected.Nodes.length, @@ -170,14 +168,14 @@ Metamaps.Control = { for (i = l - 1; i >= 0; i -= 1) { node = Metamaps.Selected.Nodes[i] - Metamaps.Control.hideNode(node.id) + Control.hideNode(node.id) } }, hideNode: function (nodeid) { var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid) var graph = Metamaps.Visualize.mGraph - Metamaps.Control.deselectNode(node) + Control.deselectNode(node) node.setData('alpha', 0, 'end') node.eachAdjacency(function (adj) { @@ -218,7 +216,7 @@ Metamaps.Control = { var l = Metamaps.Selected.Edges.length for (var i = l - 1; i >= 0; i -= 1) { var edge = Metamaps.Selected.Edges[i] - Metamaps.Control.deselectEdge(edge) + Control.deselectEdge(edge) } Metamaps.Visualize.mGraph.plot() }, @@ -258,7 +256,7 @@ Metamaps.Control = { for (var i = l - 1; i >= 0; i -= 1) { edge = Metamaps.Selected.Edges[i] - Metamaps.Control.deleteEdge(edge) + Control.deleteEdge(edge) } }, deleteEdge: function (edge) { @@ -279,7 +277,7 @@ Metamaps.Control = { var permToDelete = Metamaps.Active.Mapper.id === synapse.get('user_id') || Metamaps.Active.Mapper.get('admin') if (permToDelete) { if (edge.getData('synapses').length - 1 === 0) { - Metamaps.Control.hideEdge(edge) + Control.hideEdge(edge) } var mappableid = synapse.id synapse.destroy() @@ -315,7 +313,7 @@ Metamaps.Control = { for (i = l - 1; i >= 0; i -= 1) { edge = Metamaps.Selected.Edges[i] - Metamaps.Control.removeEdge(edge) + Control.removeEdge(edge) } Metamaps.Selected.Edges = [ ] }, @@ -330,7 +328,7 @@ Metamaps.Control = { } if (edge.getData('mappings').length - 1 === 0) { - Metamaps.Control.hideEdge(edge) + Control.hideEdge(edge) } var index = edge.getData('displayIndex') ? edge.getData('displayIndex') : 0 @@ -357,7 +355,7 @@ Metamaps.Control = { i for (i = l - 1; i >= 0; i -= 1) { edge = Metamaps.Selected.Edges[i] - Metamaps.Control.hideEdge(edge) + Control.hideEdge(edge) } Metamaps.Selected.Edges = [ ] }, @@ -365,7 +363,7 @@ Metamaps.Control = { var from = edge.nodeFrom.id var to = edge.nodeTo.id edge.setData('alpha', 0, 'end') - Metamaps.Control.deselectEdge(edge) + Control.deselectEdge(edge) Metamaps.Visualize.mGraph.fx.animate({ modes: ['edge-property:alpha'], duration: 500 @@ -449,4 +447,6 @@ Metamaps.Control = { Metamaps.GlobalUI.notifyUser(message) Metamaps.Visualize.mGraph.plot() }, -}; // end Metamaps.Control +} + +export default Control diff --git a/frontend/src/Metamaps/Create.js b/frontend/src/Metamaps/Create.js index 1bd4216f..1348e9d2 100644 --- a/frontend/src/Metamaps/Create.js +++ b/frontend/src/Metamaps/Create.js @@ -15,7 +15,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Visualize */ -Metamaps.Create = { +const Create = { isSwitchingSet: false, // indicates whether the metacode set switch lightbox is open selectedMetacodeSet: null, selectedMetacodeSetIndex: null, @@ -24,7 +24,7 @@ Metamaps.Create = { selectedMetacodes: [], newSelectedMetacodes: [], init: function () { - var self = Metamaps.Create + var self = Create self.newTopic.init() self.newSynapse.init() @@ -37,7 +37,7 @@ Metamaps.Create = { $('.customMetacodeList li').click(self.toggleMetacodeSelected) // within the custom metacode set tab }, toggleMetacodeSelected: function () { - var self = Metamaps.Create + var self = Create if ($(this).attr('class') != 'toggledOff') { $(this).addClass('toggledOff') @@ -52,29 +52,29 @@ Metamaps.Create = { } }, updateMetacodeSet: function (set, index, custom) { - if (custom && Metamaps.Create.newSelectedMetacodes.length == 0) { + if (custom && Create.newSelectedMetacodes.length == 0) { alert('Please select at least one metacode to use!') return false } var codesToSwitchToIds var metacodeModels = new Metamaps.Backbone.MetacodeCollection() - Metamaps.Create.selectedMetacodeSetIndex = index - Metamaps.Create.selectedMetacodeSet = 'metacodeset-' + set + Create.selectedMetacodeSetIndex = index + Create.selectedMetacodeSet = 'metacodeset-' + set if (!custom) { codesToSwitchToIds = $('#metacodeSwitchTabs' + set).attr('data-metacodes').split(',') $('.customMetacodeList li').addClass('toggledOff') - Metamaps.Create.selectedMetacodes = [] - Metamaps.Create.selectedMetacodeNames = [] - Metamaps.Create.newSelectedMetacodes = [] - Metamaps.Create.newSelectedMetacodeNames = [] + Create.selectedMetacodes = [] + Create.selectedMetacodeNames = [] + Create.newSelectedMetacodes = [] + Create.newSelectedMetacodeNames = [] } else if (custom) { // uses .slice to avoid setting the two arrays to the same actual array - Metamaps.Create.selectedMetacodes = Metamaps.Create.newSelectedMetacodes.slice(0) - Metamaps.Create.selectedMetacodeNames = Metamaps.Create.newSelectedMetacodeNames.slice(0) - codesToSwitchToIds = Metamaps.Create.selectedMetacodes.slice(0) + Create.selectedMetacodes = Create.newSelectedMetacodes.slice(0) + Create.selectedMetacodeNames = Create.newSelectedMetacodeNames.slice(0) + codesToSwitchToIds = Create.selectedMetacodes.slice(0) } // sort by name @@ -106,7 +106,7 @@ Metamaps.Create = { var mdata = { 'metacodes': { - 'value': custom ? Metamaps.Create.selectedMetacodes.toString() : Metamaps.Create.selectedMetacodeSet + 'value': custom ? Create.selectedMetacodes.toString() : Create.selectedMetacodeSet } } $.ajax({ @@ -124,7 +124,7 @@ Metamaps.Create = { }, cancelMetacodeSetSwitch: function () { - var self = Metamaps.Create + var self = Create self.isSwitchingSet = false if (self.selectedMetacodeSet != 'metacodeset-custom') { @@ -149,17 +149,17 @@ Metamaps.Create = { newTopic: { init: function () { $('#topic_name').keyup(function () { - Metamaps.Create.newTopic.name = $(this).val() + Create.newTopic.name = $(this).val() }) $('.pinCarousel').click(function() { - if (Metamaps.Create.newTopic.pinned) { + if (Create.newTopic.pinned) { $('.pinCarousel').removeClass('isPinned') - Metamaps.Create.newTopic.pinned = false + Create.newTopic.pinned = false } else { $('.pinCarousel').addClass('isPinned') - Metamaps.Create.newTopic.pinned = true + Create.newTopic.pinned = true } }) @@ -221,24 +221,24 @@ Metamaps.Create = { $('#new_topic').fadeIn('fast', function () { $('#topic_name').focus() }) - Metamaps.Create.newTopic.beingCreated = true - Metamaps.Create.newTopic.name = '' + Create.newTopic.beingCreated = true + Create.newTopic.name = '' }, hide: function (force) { - if (force || !Metamaps.Create.newTopic.pinned) { + if (force || !Create.newTopic.pinned) { $('#new_topic').fadeOut('fast') - Metamaps.Create.newTopic.beingCreated = false + Create.newTopic.beingCreated = false } if (force) { $('.pinCarousel').removeClass('isPinned') - Metamaps.Create.newTopic.pinned = false + Create.newTopic.pinned = false } $('#topic_name').typeahead('val', '') } }, newSynapse: { init: function () { - var self = Metamaps.Create.newSynapse + var self = Create.newSynapse var synapseBloodhound = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'), @@ -254,7 +254,7 @@ Metamaps.Create = { remote: { url: '/search/synapses?topic1id=%TOPIC1&topic2id=%TOPIC2', prepare: function (query, settings) { - var self = Metamaps.Create.newSynapse + var self = Create.newSynapse if (Metamaps.Selected.Nodes.length < 2) { settings.url = settings.url.replace('%TOPIC1', self.topic1id).replace('%TOPIC2', self.topic2id) return settings @@ -300,13 +300,13 @@ Metamaps.Create = { if (e.keyCode === BACKSPACE && $(this).val() === '' || e.keyCode === DELETE && $(this).val() === '' || e.keyCode === ESC) { - Metamaps.Create.newSynapse.hide() + Create.newSynapse.hide() } // if - Metamaps.Create.newSynapse.description = $(this).val() + Create.newSynapse.description = $(this).val() }) $('#synapse_desc').focusout(function () { - if (Metamaps.Create.newSynapse.beingCreated) { + if (Create.newSynapse.beingCreated) { Metamaps.Synapse.createSynapseLocally() } }) @@ -315,7 +315,7 @@ Metamaps.Create = { if (datum.id) { // if they clicked on an existing synapse get it Metamaps.Synapse.getSynapseFromAutocomplete(datum.id) } else { - Metamaps.Create.newSynapse.description = datum.value + Create.newSynapse.description = datum.value Metamaps.Synapse.createSynapseLocally() } }) @@ -329,17 +329,19 @@ Metamaps.Create = { $('#new_synapse').fadeIn(100, function () { $('#synapse_desc').focus() }) - Metamaps.Create.newSynapse.beingCreated = true + Create.newSynapse.beingCreated = true }, hide: function () { $('#new_synapse').fadeOut('fast') $('#synapse_desc').typeahead('val', '') - Metamaps.Create.newSynapse.beingCreated = false - Metamaps.Create.newTopic.addSynapse = false - Metamaps.Create.newSynapse.topic1id = 0 - Metamaps.Create.newSynapse.topic2id = 0 + Create.newSynapse.beingCreated = false + Create.newTopic.addSynapse = false + Create.newSynapse.topic1id = 0 + Create.newSynapse.topic2id = 0 Metamaps.Mouse.synapseStartCoordinates = [] Metamaps.Visualize.mGraph.plot() }, } -}; // end Metamaps.Create +} + +export default Create diff --git a/frontend/src/Metamaps/Debug.js b/frontend/src/Metamaps/Debug.js index 7bc71979..e8e40e69 100644 --- a/frontend/src/Metamaps/Debug.js +++ b/frontend/src/Metamaps/Debug.js @@ -1,15 +1,6 @@ -window.Metamaps = window.Metamaps || {} -/* - * Metamaps.Debug.js.erb - * - * Dependencies: none! - */ +const Debug = () => { + console.debug(window.Metamaps) + console.debug(`Metamaps Version: ${window.Metamaps.VERSION}`) +} -Metamaps.Debug = function () { - console.debug(Metamaps) - console.debug('Metamaps Version: ' + Metamaps.VERSION) -} -Metamaps.debug = function () { - Metamaps.Debug() -window.Metamaps = window.Metamaps || {} -} +export default Debug diff --git a/frontend/src/Metamaps/Filter.js b/frontend/src/Metamaps/Filter.js index 367918e6..cc21f7e2 100644 --- a/frontend/src/Metamaps/Filter.js +++ b/frontend/src/Metamaps/Filter.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -16,7 +15,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Topics * - Metamaps.Visualize */ -Metamaps.Filter = { +const Filter = { filters: { name: '', metacodes: [], @@ -31,7 +30,7 @@ Metamaps.Filter = { isOpen: false, changing: false, init: function () { - var self = Metamaps.Filter + var self = Filter $('.sidebarFilterIcon').click(self.toggleBox) @@ -46,7 +45,7 @@ Metamaps.Filter = { self.getFilterData() }, toggleBox: function (event) { - var self = Metamaps.Filter + var self = Filter if (self.isOpen) self.close() else self.open() @@ -54,7 +53,7 @@ Metamaps.Filter = { event.stopPropagation() }, open: function () { - var self = Metamaps.Filter + var self = Filter Metamaps.GlobalUI.Account.close() $('.sidebarFilterIcon div').addClass('hide') @@ -70,7 +69,7 @@ Metamaps.Filter = { } }, close: function () { - var self = Metamaps.Filter + var self = Filter $('.sidebarFilterIcon div').removeClass('hide') if (!self.changing) { @@ -83,7 +82,7 @@ Metamaps.Filter = { } }, reset: function () { - var self = Metamaps.Filter + var self = Filter self.filters.metacodes = [] self.filters.mappers = [] @@ -103,7 +102,7 @@ Metamaps.Filter = { But what these function do is load this data into three accessible array within java : metacodes, mappers and synapses */ getFilterData: function () { - var self = Metamaps.Filter + var self = Filter var metacode, mapper, synapse @@ -126,7 +125,7 @@ Metamaps.Filter = { }) }, bindLiClicks: function () { - var self = Metamaps.Filter + var self = Filter $('#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) @@ -137,7 +136,7 @@ Metamaps.Filter = { @param */ updateFilters: function (collection, propertyToCheck, correlatedModel, filtersToUse, listToModify) { - var self = Metamaps.Filter + var self = Filter var newList = [] var removed = [] @@ -212,11 +211,11 @@ Metamaps.Filter = { self.bindLiClicks() }, checkMetacodes: function () { - var self = Metamaps.Filter + var self = Filter self.updateFilters('Topics', 'metacode_id', 'Metacodes', 'metacodes', 'metacode') }, checkMappers: function () { - var self = Metamaps.Filter + var self = Filter var onMap = Metamaps.Active.Map ? true : false if (onMap) { self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper') @@ -226,11 +225,11 @@ Metamaps.Filter = { } }, checkSynapses: function () { - var self = Metamaps.Filter + var self = Filter self.updateFilters('Synapses', 'desc', 'Synapses', 'synapses', 'synapse') }, filterAllMetacodes: function (e) { - var self = Metamaps.Filter + var self = Filter $('#filter_by_metacode ul li').addClass('toggledOff') $('.showAllMetacodes').removeClass('active') $('.hideAllMetacodes').addClass('active') @@ -238,7 +237,7 @@ Metamaps.Filter = { self.passFilters() }, filterNoMetacodes: function (e) { - var self = Metamaps.Filter + var self = Filter $('#filter_by_metacode ul li').removeClass('toggledOff') $('.showAllMetacodes').addClass('active') $('.hideAllMetacodes').removeClass('active') @@ -246,7 +245,7 @@ Metamaps.Filter = { self.passFilters() }, filterAllMappers: function (e) { - var self = Metamaps.Filter + var self = Filter $('#filter_by_mapper ul li').addClass('toggledOff') $('.showAllMappers').removeClass('active') $('.hideAllMappers').addClass('active') @@ -254,7 +253,7 @@ Metamaps.Filter = { self.passFilters() }, filterNoMappers: function (e) { - var self = Metamaps.Filter + var self = Filter $('#filter_by_mapper ul li').removeClass('toggledOff') $('.showAllMappers').addClass('active') $('.hideAllMappers').removeClass('active') @@ -262,7 +261,7 @@ Metamaps.Filter = { self.passFilters() }, filterAllSynapses: function (e) { - var self = Metamaps.Filter + var self = Filter $('#filter_by_synapse ul li').addClass('toggledOff') $('.showAllSynapses').removeClass('active') $('.hideAllSynapses').addClass('active') @@ -270,7 +269,7 @@ Metamaps.Filter = { self.passFilters() }, filterNoSynapses: function (e) { - var self = Metamaps.Filter + var self = Filter $('#filter_by_synapse ul li').removeClass('toggledOff') $('.showAllSynapses').addClass('active') $('.hideAllSynapses').removeClass('active') @@ -281,7 +280,7 @@ Metamaps.Filter = { // to reduce code redundancy // gets called in the context of a list item in a filter box toggleLi: function (whichToFilter) { - var self = Metamaps.Filter, index + var self = Filter, index var id = $(this).attr('data-id') if (self.visible[whichToFilter].indexOf(id) == -1) { self.visible[whichToFilter].push(id) @@ -294,7 +293,7 @@ Metamaps.Filter = { self.passFilters() }, toggleMetacode: function () { - var self = Metamaps.Filter + var self = Filter self.toggleLi.call(this, 'metacodes') if (self.visible.metacodes.length === self.filters.metacodes.length) { @@ -310,7 +309,7 @@ Metamaps.Filter = { } }, toggleMapper: function () { - var self = Metamaps.Filter + var self = Filter self.toggleLi.call(this, 'mappers') if (self.visible.mappers.length === self.filters.mappers.length) { @@ -326,7 +325,7 @@ Metamaps.Filter = { } }, toggleSynapse: function () { - var self = Metamaps.Filter + var self = Filter self.toggleLi.call(this, 'synapses') if (self.visible.synapses.length === self.filters.synapses.length) { @@ -342,7 +341,7 @@ Metamaps.Filter = { } }, passFilters: function () { - var self = Metamaps.Filter + var self = Filter var visible = self.visible var passesMetacode, passesMapper, passesSynapse @@ -464,4 +463,6 @@ Metamaps.Filter = { duration: 200 }) } -}; // end Metamaps.Filter +} + +export default Filter diff --git a/frontend/src/Metamaps/GlobalUI.js b/frontend/src/Metamaps/GlobalUI.js index d5fe6caa..e4522c2f 100644 --- a/frontend/src/Metamaps/GlobalUI.js +++ b/frontend/src/Metamaps/GlobalUI.js @@ -678,3 +678,5 @@ Metamaps.GlobalUI.Search = { $('#searchLoading').show(); } } + +export default Metamaps.GlobalUI diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index 426071f0..e963ca32 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -14,7 +13,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Topics */ -Metamaps.Import = { +const Import = { // note that user is not imported topicWhitelist: [ 'id', 'name', 'metacode', 'x', 'y', 'description', 'link', 'permission' @@ -25,19 +24,19 @@ Metamaps.Import = { cidMappings: {}, // to be filled by import_id => cid mappings handleTSV: function (text) { - var self = Metamaps.Import + var self = Import results = self.parseTabbedString(text) self.handle(results) }, handleJSON: function (text) { - var self = Metamaps.Import + var self = Import results = JSON.parse(text) self.handle(results) }, handle: function(results) { - var self = Metamaps.Import + var self = Import var topics = results.topics var synapses = results.synapses @@ -61,7 +60,7 @@ Metamaps.Import = { }, parseTabbedString: function (text) { - var self = Metamaps.Import + var self = Import // determine line ending and split lines var delim = '\n' @@ -187,7 +186,7 @@ Metamaps.Import = { }, importTopics: function (parsedTopics) { - var self = Metamaps.Import + var self = Import // up to 25 topics: scale 100 // up to 81 topics: scale 200 @@ -220,7 +219,7 @@ Metamaps.Import = { }, importSynapses: function (parsedSynapses) { - var self = Metamaps.Import + var self = Import parsedSynapses.forEach(function (synapse) { // only createSynapseWithParameters once both topics are persisted @@ -256,7 +255,7 @@ Metamaps.Import = { createTopicWithParameters: function (name, metacode_name, permission, desc, link, xloc, yloc, import_id, opts) { - var self = Metamaps.Import + var self = Import $(document).trigger(Metamaps.Map.events.editedByActiveMapper) var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null if (metacode === null) { @@ -325,3 +324,5 @@ Metamaps.Import = { Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, true) } } + +export default Import diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index 57ab60bf..a93e3341 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -1,6 +1,8 @@ -window.Metamaps = window.Metamaps || {} +/* global Metamaps */ -Metamaps.JIT = { +let panningInt + +const JIT = { events: { topicDrag: 'Metamaps:JIT:events:topicDrag', newTopic: 'Metamaps:JIT:events:newTopic', @@ -18,7 +20,7 @@ Metamaps.JIT = { * This method will bind the event handlers it is interested and initialize the class. */ init: function () { - var self = Metamaps.JIT + var self = JIT $('.zoomIn').click(self.zoomIn) $('.zoomOut').click(self.zoomOut) @@ -94,7 +96,7 @@ Metamaps.JIT = { return [jitReady, synapsesToRemove] }, prepareVizData: function () { - var self = Metamaps.JIT + var self = JIT var mapping // reset/empty vizData @@ -148,7 +150,7 @@ Metamaps.JIT = { var color = Metamaps.Settings.colors.synapses.normal canvas.getCtx().fillStyle = canvas.getCtx().strokeStyle = color } - Metamaps.JIT.renderEdgeArrows($jit.Graph.Plot.edgeHelper, adj, synapse, canvas) + JIT.renderEdgeArrows($jit.Graph.Plot.edgeHelper, adj, synapse, canvas) // check for edge label in data var desc = synapse.get('desc') @@ -253,7 +255,7 @@ Metamaps.JIT = { duration: 800, onComplete: function () { Metamaps.Visualize.mGraph.busy = false - $(document).trigger(Metamaps.JIT.events.animationDone) + $(document).trigger(JIT.events.animationDone) } }, animateFDLayout: { @@ -323,26 +325,26 @@ Metamaps.JIT = { enable: true, enableForEdges: true, onMouseMove: function (node, eventInfo, e) { - Metamaps.JIT.onMouseMoveHandler(node, eventInfo, e) + JIT.onMouseMoveHandler(node, eventInfo, e) // console.log('called mouse move handler') }, // Update node positions when dragged onDragMove: function (node, eventInfo, e) { - Metamaps.JIT.onDragMoveTopicHandler(node, eventInfo, e) + JIT.onDragMoveTopicHandler(node, eventInfo, e) // console.log('called drag move handler') }, onDragEnd: function (node, eventInfo, e) { - Metamaps.JIT.onDragEndTopicHandler(node, eventInfo, e, false) + JIT.onDragEndTopicHandler(node, eventInfo, e, false) // console.log('called drag end handler') }, onDragCancel: function (node, eventInfo, e) { - Metamaps.JIT.onDragCancelHandler(node, eventInfo, e, false) + JIT.onDragCancelHandler(node, eventInfo, e, false) }, // Implement the same handler for touchscreens onTouchStart: function (node, eventInfo, e) {}, // Implement the same handler for touchscreens onTouchMove: function (node, eventInfo, e) { - Metamaps.JIT.onDragMoveTopicHandler(node, eventInfo, e) + JIT.onDragMoveTopicHandler(node, eventInfo, e) }, // Implement the same handler for touchscreens onTouchEnd: function (node, eventInfo, e) {}, @@ -361,7 +363,7 @@ Metamaps.JIT = { var bS = Metamaps.Mouse.boxStartCoordinates var bE = Metamaps.Mouse.boxEndCoordinates if (Math.abs(bS.x - bE.x) > 20 && Math.abs(bS.y - bE.y) > 20) { - Metamaps.JIT.zoomToBox(e) + JIT.zoomToBox(e) return } else { Metamaps.Mouse.boxStartCoordinates = null @@ -373,7 +375,7 @@ Metamaps.JIT = { if (e.shiftKey) { Metamaps.Visualize.mGraph.busy = false Metamaps.Mouse.boxEndCoordinates = eventInfo.getPos() - Metamaps.JIT.selectWithBox(e) + JIT.selectWithBox(e) // console.log('called select with box') return } @@ -383,13 +385,13 @@ Metamaps.JIT = { // clicking on a edge, node, or clicking on blank part of canvas? if (node.nodeFrom) { - Metamaps.JIT.selectEdgeOnClickHandler(node, e) + JIT.selectEdgeOnClickHandler(node, e) // console.log('called selectEdgeOnClickHandler') } else if (node && !node.nodeFrom) { - Metamaps.JIT.selectNodeOnClickHandler(node, e) + JIT.selectNodeOnClickHandler(node, e) // console.log('called selectNodeOnClickHandler') } else { - Metamaps.JIT.canvasClickHandler(eventInfo.getPos(), e) + JIT.canvasClickHandler(eventInfo.getPos(), e) // console.log('called canvasClickHandler') } // if }, @@ -401,7 +403,7 @@ Metamaps.JIT = { if (Metamaps.Mouse.boxStartCoordinates) { Metamaps.Visualize.mGraph.busy = false Metamaps.Mouse.boxEndCoordinates = eventInfo.getPos() - Metamaps.JIT.selectWithBox(e) + JIT.selectWithBox(e) return } @@ -409,9 +411,9 @@ Metamaps.JIT = { // clicking on a edge, node, or clicking on blank part of canvas? if (node.nodeFrom) { - Metamaps.JIT.selectEdgeOnRightClickHandler(node, e) + JIT.selectEdgeOnRightClickHandler(node, e) } else if (node && !node.nodeFrom) { - Metamaps.JIT.selectNodeOnRightClickHandler(node, e) + JIT.selectNodeOnRightClickHandler(node, e) } else { // console.log('right clicked on open space') } @@ -455,7 +457,7 @@ Metamaps.JIT = { // if the topic has a link, draw a small image to indicate that var hasLink = topic && topic.get('link') !== '' && topic.get('link') !== null - var linkImage = Metamaps.JIT.topicLinkImage + var linkImage = JIT.topicLinkImage var linkImageLoaded = linkImage.complete || (typeof linkImage.naturalWidth !== 'undefined' && linkImage.naturalWidth !== 0) @@ -465,7 +467,7 @@ Metamaps.JIT = { // if the topic has a desc, draw a small image to indicate that var hasDesc = topic && topic.get('desc') !== '' && topic.get('desc') !== null - var descImage = Metamaps.JIT.topicDescImage + var descImage = JIT.topicDescImage var descImageLoaded = descImage.complete || (typeof descImage.naturalWidth !== 'undefined' && descImage.naturalWidth !== 0) @@ -500,7 +502,7 @@ Metamaps.JIT = { edgeSettings: { 'customEdge': { 'render': function (adj, canvas) { - Metamaps.JIT.edgeRender(adj, canvas) + JIT.edgeRender(adj, canvas) }, 'contains': function (adj, pos) { var from = adj.nodeFrom.pos.getc(), @@ -667,7 +669,7 @@ Metamaps.JIT = { Metamaps.Visualize.mGraph.plot() }, // onMouseLeave onMouseMoveHandler: function (node, eventInfo, e) { - var self = Metamaps.JIT + var self = JIT if (Metamaps.Visualize.mGraph.busy) return @@ -721,7 +723,7 @@ Metamaps.JIT = { Metamaps.Control.deselectAllNodes() }, // escKeyHandler onDragMoveTopicHandler: function (node, eventInfo, e) { - var self = Metamaps.JIT + var self = JIT // this is used to send nodes that are moving to // other realtime collaborators on the same map @@ -751,7 +753,7 @@ Metamaps.JIT = { // to be the same as on other collaborators // maps positionsToSend[topic.id] = pos - $(document).trigger(Metamaps.JIT.events.topicDrag, [positionsToSend]) + $(document).trigger(JIT.events.topicDrag, [positionsToSend]) } } else { var len = Metamaps.Selected.Nodes.length @@ -782,7 +784,7 @@ Metamaps.JIT = { } // for if (Metamaps.Active.Map) { - $(document).trigger(Metamaps.JIT.events.topicDrag, [positionsToSend]) + $(document).trigger(JIT.events.topicDrag, [positionsToSend]) } } // if @@ -1201,7 +1203,7 @@ Metamaps.JIT = { selectNodeOnClickHandler: function (node, e) { if (Metamaps.Visualize.mGraph.busy) return - var self = Metamaps.JIT + var self = JIT // catch right click on mac, which is often like ctrl+click if (navigator.platform.indexOf('Mac') != -1 && e.ctrlKey) { @@ -1222,7 +1224,7 @@ Metamaps.JIT = { } else { // wait a certain length of time, then check again, then run this code setTimeout(function () { - if (!Metamaps.JIT.nodeWasDoubleClicked()) { + if (!JIT.nodeWasDoubleClicked()) { var nodeAlreadySelected = node.selected if (!e.shiftKey) { @@ -1403,7 +1405,7 @@ Metamaps.JIT = { var fetch_sent = false $('.rc-siblings').hover(function () { if (!fetch_sent) { - Metamaps.JIT.populateRightClickSiblings(node) + JIT.populateRightClickSiblings(node) fetch_sent = true } }) @@ -1414,7 +1416,7 @@ Metamaps.JIT = { }) }, // selectNodeOnRightClickHandler, populateRightClickSiblings: function (node) { - var self = Metamaps.JIT + var self = JIT // depending on how many topics are selected, do different things @@ -1456,7 +1458,7 @@ Metamaps.JIT = { selectEdgeOnClickHandler: function (adj, e) { if (Metamaps.Visualize.mGraph.busy) return - var self = Metamaps.JIT + var self = JIT // catch right click on mac, which is often like ctrl+click if (navigator.platform.indexOf('Mac') != -1 && e.ctrlKey) { @@ -1471,7 +1473,7 @@ Metamaps.JIT = { } else { // wait a certain length of time, then check again, then run this code setTimeout(function () { - if (!Metamaps.JIT.nodeWasDoubleClicked()) { + if (!JIT.nodeWasDoubleClicked()) { var edgeAlreadySelected = Metamaps.Selected.Edges.indexOf(adj) !== -1 if (!e.shiftKey) { @@ -1611,17 +1613,17 @@ Metamaps.JIT = { easing = 1 // frictional value easing = 1 - window.clearInterval(Metamaps.panningInt) - Metamaps.panningInt = setInterval(function () { + window.clearInterval(panningInt) + panningInt = setInterval(function () { myTimer() }, 1) function myTimer () { Metamaps.Visualize.mGraph.canvas.translate(x_velocity * easing * 1 / sx, y_velocity * easing * 1 / sy) - $(document).trigger(Metamaps.JIT.events.pan) + $(document).trigger(JIT.events.pan) easing = easing * 0.75 - if (easing < 0.1) window.clearInterval(Metamaps.panningInt) + if (easing < 0.1) window.clearInterval(panningInt) } }, // SmoothPanning renderMidArrow: function (from, to, dim, swap, canvas, placement, newSynapse) { @@ -1666,7 +1668,7 @@ Metamaps.JIT = { ctx.stroke() }, // renderMidArrow renderEdgeArrows: function (edgeHelper, adj, synapse, canvas) { - var self = Metamaps.JIT + var self = JIT var directionCat = synapse.get('category') var direction = synapse.getDirection() @@ -1720,11 +1722,11 @@ Metamaps.JIT = { }, // renderEdgeArrows zoomIn: function (event) { Metamaps.Visualize.mGraph.canvas.scale(1.25, 1.25) - $(document).trigger(Metamaps.JIT.events.zoom, [event]) + $(document).trigger(JIT.events.zoom, [event]) }, zoomOut: function (event) { Metamaps.Visualize.mGraph.canvas.scale(0.8, 0.8) - $(document).trigger(Metamaps.JIT.events.zoom, [event]) + $(document).trigger(JIT.events.zoom, [event]) }, centerMap: function (canvas) { var offsetScale = canvas.scaleOffsetX @@ -1743,7 +1745,7 @@ Metamaps.JIT = { eY = Metamaps.Mouse.boxEndCoordinates.y var canvas = Metamaps.Visualize.mGraph.canvas - Metamaps.JIT.centerMap(canvas) + JIT.centerMap(canvas) var height = $(document).height(), width = $(document).width() @@ -1770,14 +1772,14 @@ Metamaps.JIT = { var cogY = (sY + eY) / 2 canvas.translate(-1 * cogX, -1 * cogY) - $(document).trigger(Metamaps.JIT.events.zoom, [event]) + $(document).trigger(JIT.events.zoom, [event]) Metamaps.Mouse.boxStartCoordinates = false Metamaps.Mouse.boxEndCoordinates = false Metamaps.Visualize.mGraph.plot() }, zoomExtents: function (event, canvas, denySelected) { - Metamaps.JIT.centerMap(canvas) + JIT.centerMap(canvas) var height = canvas.getSize().height, width = canvas.getSize().width, maxX, minX, maxY, minY, counter = 0 @@ -1847,7 +1849,7 @@ Metamaps.JIT = { canvas.scale(scaleMultiplier, scaleMultiplier) } - $(document).trigger(Metamaps.JIT.events.zoom, [event]) + $(document).trigger(JIT.events.zoom, [event]) } else if (nodes.length == 1) { nodes.forEach(function (n) { @@ -1855,8 +1857,10 @@ Metamaps.JIT = { y = n.pos.y canvas.translate(-1 * x, -1 * y) - $(document).trigger(Metamaps.JIT.events.zoom, [event]) + $(document).trigger(JIT.events.zoom, [event]) }) } } } + +export default JIT diff --git a/frontend/src/Metamaps/Listeners.js b/frontend/src/Metamaps/Listeners.js index e6c4e1b9..af244961 100644 --- a/frontend/src/Metamaps/Listeners.js +++ b/frontend/src/Metamaps/Listeners.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -10,7 +9,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.JIT * - Metamaps.Visualize */ -Metamaps.Listeners = { +const Listeners = { init: function () { var self = this $(document).on('keydown', function (e) { @@ -120,4 +119,6 @@ Metamaps.Listeners = { Metamaps.Topic.fetchRelatives(nodes) } } -}; // end Metamaps.Listeners +} + +export default Listeners diff --git a/frontend/src/Metamaps/Map.js b/frontend/src/Metamaps/Map.js index e925a92c..690c2a6d 100644 --- a/frontend/src/Metamaps/Map.js +++ b/frontend/src/Metamaps/Map.js @@ -1,4 +1,5 @@ window.Metamaps = window.Metamaps || {} + /* global Metamaps, $ */ /* @@ -753,3 +754,5 @@ Metamaps.Map.InfoBox = { } } }; // end Metamaps.Map.InfoBox + +export default Metamaps.Map diff --git a/frontend/src/Metamaps/Mapper.js b/frontend/src/Metamaps/Mapper.js index f8a530b8..114d4f8c 100644 --- a/frontend/src/Metamaps/Mapper.js +++ b/frontend/src/Metamaps/Mapper.js @@ -1,21 +1,21 @@ -window.Metamaps = window.Metamaps || {} -/* global Metamaps, $ */ +/* global Metamaps */ /* - * Metamaps.Mapper.js.erb - * - * Dependencies: none! + * Dependencies: + * - Metamaps.Backbone */ - -Metamaps.Mapper = { +const Mapper = { // this function is to retrieve a mapper JSON object from the database // @param id = the id of the mapper to retrieve get: function (id, callback) { - return $.ajax({ - url: '/users/' + id + '.json', - success: function (data) { - callback(new Metamaps.Backbone.Mapper(data)) - } + return fetch(`/users/${id}.json`, { + }).then(response => { + if (!response.ok) throw response + return response.json() + }).then(payload => { + callback(new Metamaps.Backbone.Mapper(payload)) }) } -}; // end Metamaps.Mapper +} + +export default Mapper diff --git a/frontend/src/Metamaps/Mobile.js b/frontend/src/Metamaps/Mobile.js index fcd76b2f..e062ca45 100644 --- a/frontend/src/Metamaps/Mobile.js +++ b/frontend/src/Metamaps/Mobile.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -9,7 +8,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Map */ -Metamaps.Mobile = { +const Mobile = { init: function () { var self = Metamaps.Mobile @@ -23,7 +22,7 @@ Metamaps.Mobile = { $('#header_content').width($(document).width() - 70) }, liClick: function () { - var self = Metamaps.Mobile + var self = Mobile $('#header_content').html($(this).text()) self.toggleMenu() }, @@ -36,3 +35,5 @@ Metamaps.Mobile = { } } } + +export default Mobile diff --git a/frontend/src/Metamaps/Organize.js b/frontend/src/Metamaps/Organize.js index 220cb83a..71905568 100644 --- a/frontend/src/Metamaps/Organize.js +++ b/frontend/src/Metamaps/Organize.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -7,8 +6,7 @@ window.Metamaps = window.Metamaps || {} * Dependencies: * - Metamaps.Visualize */ -Metamaps.Organize = { - init: function () {}, +const Organize = { arrange: function (layout, centerNode) { // first option for layout to implement is 'grid', will do an evenly spaced grid with its center at the 0,0 origin if (layout == 'grid') { @@ -115,4 +113,6 @@ Metamaps.Organize = { var newOriginY = (lowY + highY) / 2 } else alert('please call function with a valid layout dammit!') } -}; // end Metamaps.Organize +} + +export default Organize diff --git a/frontend/src/Metamaps/PasteInput.js b/frontend/src/Metamaps/PasteInput.js index 3e933e41..9676e783 100644 --- a/frontend/src/Metamaps/PasteInput.js +++ b/frontend/src/Metamaps/PasteInput.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -9,12 +8,12 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.AutoLayout */ -Metamaps.PasteInput = { +const PasteInput = { // thanks to https://github.com/kevva/url-regex URL_REGEX: new RegExp('^(?:(?:(?:[a-z]+:)?//)|www\.)(?:\S+(?::\S*)?@)?(?:localhost|(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){3}|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#][^\s"]*)?$'), init: function () { - var self = Metamaps.PasteInput + var self = PasteInput // intercept dragged files // see http://stackoverflow.com/questions/6756583 @@ -59,7 +58,7 @@ Metamaps.PasteInput = { }, handle: function(text, coords) { - var self = Metamaps.PasteInput + var self = PasteInput if (text.match(self.URL_REGEX)) { self.handleURL(text, coords) @@ -109,3 +108,5 @@ Metamaps.PasteInput = { Metamaps.Import.handleTSV(text) } } + +export default PasteInput diff --git a/frontend/src/Metamaps/ReactComponents.js b/frontend/src/Metamaps/ReactComponents.js index a1de0f40..a2495245 100644 --- a/frontend/src/Metamaps/ReactComponents.js +++ b/frontend/src/Metamaps/ReactComponents.js @@ -1,7 +1,7 @@ -window.Metamaps = window.Metamaps || {} - import Maps from '../components/Maps' -Metamaps.ReactComponents = { +const ReactComponents = { Maps } + +export default ReactComponents diff --git a/frontend/src/Metamaps/Realtime.js b/frontend/src/Metamaps/Realtime.js index 0b62648f..35d00f06 100644 --- a/frontend/src/Metamaps/Realtime.js +++ b/frontend/src/Metamaps/Realtime.js @@ -1,5 +1,3 @@ -window.Metamaps = window.Metamaps || {} - /* global Metamaps, $ */ /* @@ -26,7 +24,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Visualize */ -Metamaps.Realtime = { +const Realtime = { videoId: 'video-wrapper', socket: null, webrtc: null, @@ -39,7 +37,7 @@ Metamaps.Realtime = { inConversation: false, localVideo: null, init: function () { - var self = Metamaps.Realtime + var self = Realtime self.addJuntoListeners() @@ -102,7 +100,7 @@ Metamaps.Realtime = { } // if Metamaps.Active.Mapper }, addJuntoListeners: function () { - var self = Metamaps.Realtime + var self = Realtime $(document).on(Metamaps.Views.chatView.events.openTray, function () { $('.main').addClass('compressed') @@ -128,7 +126,7 @@ Metamaps.Realtime = { }) }, handleVideoAdded: function (v, id) { - var self = Metamaps.Realtime + var self = Realtime self.positionVideos() v.setParent($('#wrapper')) v.$container.find('.video-cutoff').css({ @@ -137,7 +135,7 @@ Metamaps.Realtime = { $('#wrapper').append(v.$container) }, positionVideos: function () { - var self = Metamaps.Realtime + var self = Realtime var videoIds = Object.keys(self.room.videos) var numOfVideos = videoIds.length var numOfVideosToPosition = _.filter(videoIds, function (id) { @@ -169,7 +167,7 @@ Metamaps.Realtime = { } // do self first - var myVideo = Metamaps.Realtime.localVideo.view + var myVideo = Realtime.localVideo.view if (!myVideo.manuallyPositioned) { myVideo.$container.css({ top: yFormula() + 'px', @@ -187,7 +185,7 @@ Metamaps.Realtime = { }) }, startActiveMap: function () { - var self = Metamaps.Realtime + var self = Realtime if (Metamaps.Active.Map && Metamaps.Active.Mapper) { if (Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper)) { @@ -200,7 +198,7 @@ Metamaps.Realtime = { } }, endActiveMap: function () { - var self = Metamaps.Realtime + var self = Realtime $(document).off('.map') self.socket.removeAllListeners() @@ -215,7 +213,7 @@ Metamaps.Realtime = { } }, turnOn: function (notify) { - var self = Metamaps.Realtime + var self = Realtime if (notify) self.sendRealtimeOn() self.status = true @@ -238,11 +236,11 @@ Metamaps.Realtime = { self.room.chat.addParticipant(self.activeMapper) }, checkForACallToJoin: function () { - var self = Metamaps.Realtime + var self = Realtime self.socket.emit('checkForCall', { room: self.room.room, mapid: Metamaps.Active.Map.id }) }, promptToJoin: function () { - var self = Metamaps.Realtime + var self = Realtime var notifyText = "There's a conversation happening, want to join?" notifyText += ' ' @@ -251,7 +249,7 @@ Metamaps.Realtime = { self.room.conversationInProgress() }, conversationHasBegun: function () { - var self = Metamaps.Realtime + var self = Realtime if (self.inConversation) return var notifyText = "There's a conversation starting, want to join?" @@ -261,7 +259,7 @@ Metamaps.Realtime = { self.room.conversationInProgress() }, countOthersInConversation: function () { - var self = Metamaps.Realtime + var self = Realtime var count = 0 for (var key in self.mappersOnMap) { @@ -270,7 +268,7 @@ Metamaps.Realtime = { return count }, mapperJoinedCall: function (id) { - var self = Metamaps.Realtime + var self = Realtime var mapper = self.mappersOnMap[id] if (mapper) { @@ -285,7 +283,7 @@ Metamaps.Realtime = { } }, mapperLeftCall: function (id) { - var self = Metamaps.Realtime + var self = Realtime var mapper = self.mappersOnMap[id] if (mapper) { @@ -305,7 +303,7 @@ Metamaps.Realtime = { } }, callEnded: function () { - var self = Metamaps.Realtime + var self = Realtime self.room.conversationEnding() self.room.leaveVideoOnly() @@ -324,7 +322,7 @@ Metamaps.Realtime = { self.webrtc.webrtc.localStreams = [] }, invitedToCall: function (inviter) { - var self = Metamaps.Realtime + var self = Realtime self.room.chat.sound.stop('sessioninvite') self.room.chat.sound.play('sessioninvite') @@ -337,7 +335,7 @@ Metamaps.Realtime = { Metamaps.GlobalUI.notifyUser(notifyText, true) }, invitedToJoin: function (inviter) { - var self = Metamaps.Realtime + var self = Realtime self.room.chat.sound.stop('sessioninvite') self.room.chat.sound.play('sessioninvite') @@ -349,7 +347,7 @@ Metamaps.Realtime = { Metamaps.GlobalUI.notifyUser(notifyText, true) }, acceptCall: function (userid) { - var self = Metamaps.Realtime + var self = Realtime self.room.chat.sound.stop('sessioninvite') self.socket.emit('callAccepted', { mapid: Metamaps.Active.Map.id, @@ -361,7 +359,7 @@ Metamaps.Realtime = { Metamaps.GlobalUI.clearNotify() }, denyCall: function (userid) { - var self = Metamaps.Realtime + var self = Realtime self.room.chat.sound.stop('sessioninvite') self.socket.emit('callDenied', { mapid: Metamaps.Active.Map.id, @@ -371,7 +369,7 @@ Metamaps.Realtime = { Metamaps.GlobalUI.clearNotify() }, denyInvite: function (userid) { - var self = Metamaps.Realtime + var self = Realtime self.room.chat.sound.stop('sessioninvite') self.socket.emit('inviteDenied', { mapid: Metamaps.Active.Map.id, @@ -381,7 +379,7 @@ Metamaps.Realtime = { Metamaps.GlobalUI.clearNotify() }, inviteACall: function (userid) { - var self = Metamaps.Realtime + var self = Realtime self.socket.emit('inviteACall', { mapid: Metamaps.Active.Map.id, inviter: Metamaps.Active.Mapper.id, @@ -391,7 +389,7 @@ Metamaps.Realtime = { Metamaps.GlobalUI.clearNotify() }, inviteToJoin: function (userid) { - var self = Metamaps.Realtime + var self = Realtime self.socket.emit('inviteToJoin', { mapid: Metamaps.Active.Map.id, inviter: Metamaps.Active.Mapper.id, @@ -400,7 +398,7 @@ Metamaps.Realtime = { self.room.chat.invitationPending(userid) }, callAccepted: function (userid) { - var self = Metamaps.Realtime + var self = Realtime var username = self.mappersOnMap[userid].name Metamaps.GlobalUI.notifyUser('Conversation starting...') @@ -408,21 +406,21 @@ Metamaps.Realtime = { self.room.chat.invitationAnswered(userid) }, callDenied: function (userid) { - var self = Metamaps.Realtime + var self = Realtime var username = self.mappersOnMap[userid].name Metamaps.GlobalUI.notifyUser(username + " didn't accept your invitation") self.room.chat.invitationAnswered(userid) }, inviteDenied: function (userid) { - var self = Metamaps.Realtime + var self = Realtime var username = self.mappersOnMap[userid].name Metamaps.GlobalUI.notifyUser(username + " didn't accept your invitation") self.room.chat.invitationAnswered(userid) }, joinCall: function () { - var self = Metamaps.Realtime + var self = Realtime self.webrtc.off('readyToCall') self.webrtc.once('readyToCall', function () { @@ -446,7 +444,7 @@ Metamaps.Realtime = { self.room.chat.mapperJoinedCall(Metamaps.Active.Mapper.id) }, leaveCall: function () { - var self = Metamaps.Realtime + var self = Realtime self.socket.emit('mapperLeftCall', { mapid: Metamaps.Active.Map.id, @@ -465,7 +463,7 @@ Metamaps.Realtime = { } }, turnOff: function (silent) { - var self = Metamaps.Realtime + var self = Realtime if (self.status) { if (!silent) self.sendRealtimeOff() @@ -479,8 +477,8 @@ Metamaps.Realtime = { } }, setupSocket: function () { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket var myId = Metamaps.Active.Mapper.id socket.emit('newMapperNotify', { @@ -614,14 +612,14 @@ Metamaps.Realtime = { $(document).on(Metamaps.Views.room.events.newMessage + '.map', sendNewMessage) }, attachMapListener: function () { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket socket.on('mapChangeFromServer', self.mapChange) }, sendRealtimeOn: function () { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket // send this new mapper back your details, and the awareness that you're online var update = { @@ -632,8 +630,8 @@ Metamaps.Realtime = { socket.emit('notifyStartRealtime', update) }, sendRealtimeOff: function () { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket // send this new mapper back your details, and the awareness that you're online var update = { @@ -644,8 +642,8 @@ Metamaps.Realtime = { socket.emit('notifyStopRealtime', update) }, updateMapperList: function (data) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket // data.userid // data.username @@ -675,8 +673,8 @@ Metamaps.Realtime = { } }, newPeerOnMap: function (data) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket // data.userid // data.username @@ -743,8 +741,8 @@ Metamaps.Realtime = { }) }, lostPeerOnMap: function (data) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket // data.userid // data.username @@ -763,8 +761,8 @@ Metamaps.Realtime = { } }, newCollaborator: function (data) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket // data.userid // data.username @@ -777,8 +775,8 @@ Metamaps.Realtime = { Metamaps.GlobalUI.notifyUser(data.username + ' just turned on realtime') }, lostCollaborator: function (data) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket // data.userid // data.username @@ -791,15 +789,15 @@ Metamaps.Realtime = { Metamaps.GlobalUI.notifyUser(data.username + ' just turned off realtime') }, updatePeerCoords: function (data) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket self.mappersOnMap[data.userid].coords = {x: data.usercoords.x,y: data.usercoords.y} self.positionPeerIcon(data.userid) }, positionPeerIcons: function () { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket if (self.status) { // if i have realtime turned on for (var key in self.mappersOnMap) { @@ -811,8 +809,8 @@ Metamaps.Realtime = { } }, positionPeerIcon: function (id) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket var boundary = self.chatOpen ? '#wrapper' : document var mapper = self.mappersOnMap[id] @@ -848,8 +846,8 @@ Metamaps.Realtime = { } }, limitPixelsToScreen: function (pixels) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket var boundary = self.chatOpen ? '#wrapper' : document var xLimit, yLimit @@ -866,8 +864,8 @@ Metamaps.Realtime = { return {x: xLimit,y: yLimit} }, sendCoords: function (coords) { - var self = Metamaps.Realtime - var socket = Metamaps.Realtime.socket + var self = Realtime + var socket = Realtime.socket var map = Metamaps.Active.Map var mapper = Metamaps.Active.Mapper @@ -882,7 +880,7 @@ Metamaps.Realtime = { } }, sendTopicDrag: function (positions) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (Metamaps.Active.Map && self.status) { @@ -891,7 +889,7 @@ Metamaps.Realtime = { } }, topicDrag: function (positions) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket var topic @@ -907,7 +905,7 @@ Metamaps.Realtime = { } }, sendTopicChange: function (topic) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket var data = { @@ -929,7 +927,7 @@ Metamaps.Realtime = { } }, sendSynapseChange: function (synapse) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket var data = { @@ -952,7 +950,7 @@ Metamaps.Realtime = { } }, sendMapChange: function (map) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket var data = { @@ -989,7 +987,7 @@ Metamaps.Realtime = { }, // newMessage sendNewMessage: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket var message = data.attributes @@ -997,14 +995,14 @@ Metamaps.Realtime = { socket.emit('newMessage', message) }, newMessage: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket self.room.addMessages(new Metamaps.Backbone.MessageCollection(data)) }, // newTopic sendNewTopic: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (Metamaps.Active.Map && self.status) { @@ -1016,7 +1014,7 @@ Metamaps.Realtime = { newTopic: function (data) { var topic, mapping, mapper, mapperCallback, cancel - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (!self.status) return @@ -1063,7 +1061,7 @@ Metamaps.Realtime = { }, // removeTopic sendDeleteTopic: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (Metamaps.Active.Map) { @@ -1072,7 +1070,7 @@ Metamaps.Realtime = { }, // removeTopic sendRemoveTopic: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (Metamaps.Active.Map) { @@ -1081,7 +1079,7 @@ Metamaps.Realtime = { } }, removeTopic: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (!self.status) return @@ -1097,7 +1095,7 @@ Metamaps.Realtime = { }, // newSynapse sendNewSynapse: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (Metamaps.Active.Map) { @@ -1109,7 +1107,7 @@ Metamaps.Realtime = { newSynapse: function (data) { var topic1, topic2, node1, node2, synapse, mapping, cancel - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (!self.status) return @@ -1160,7 +1158,7 @@ Metamaps.Realtime = { }, // deleteSynapse sendDeleteSynapse: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (Metamaps.Active.Map) { @@ -1170,7 +1168,7 @@ Metamaps.Realtime = { }, // removeSynapse sendRemoveSynapse: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (Metamaps.Active.Map) { @@ -1179,7 +1177,7 @@ Metamaps.Realtime = { } }, removeSynapse: function (data) { - var self = Metamaps.Realtime + var self = Realtime var socket = self.socket if (!self.status) return @@ -1202,4 +1200,6 @@ Metamaps.Realtime = { Metamaps.Mappings.remove(mapping) } }, -}; // end Metamaps.Realtime +} + +export default Realtime diff --git a/frontend/src/Metamaps/Router.js b/frontend/src/Metamaps/Router.js index 417c9b9e..8aacadd1 100644 --- a/frontend/src/Metamaps/Router.js +++ b/frontend/src/Metamaps/Router.js @@ -16,231 +16,231 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Visualize */ -;(function () { - var Router = Backbone.Router.extend({ - routes: { - '': 'home', // #home - 'explore/:section': 'explore', // #explore/active - 'explore/:section/:id': 'explore', // #explore/mapper/1234 - 'maps/:id': 'maps' // #maps/7 - }, - home: function () { - clearTimeout(Metamaps.Router.timeoutId) +const _Router = Backbone.Router.extend({ + routes: { + '': 'home', // #home + 'explore/:section': 'explore', // #explore/active + 'explore/:section/:id': 'explore', // #explore/mapper/1234 + 'maps/:id': 'maps' // #maps/7 + }, + home: function () { + clearTimeout(Metamaps.Router.timeoutId) - if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps' - else document.title = 'Home | Metamaps' + if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps' + else document.title = 'Home | Metamaps' - Metamaps.Router.currentSection = '' - Metamaps.Router.currentPage = '' - $('.wrapper').removeClass('mapPage topicPage') + Metamaps.Router.currentSection = '' + Metamaps.Router.currentPage = '' + $('.wrapper').removeClass('mapPage topicPage') - var classes = Metamaps.Active.Mapper ? 'homePage explorePage' : 'homePage' - $('.wrapper').addClass(classes) + var classes = Metamaps.Active.Mapper ? 'homePage explorePage' : 'homePage' + $('.wrapper').addClass(classes) - var navigate = function () { - Metamaps.Router.timeoutId = setTimeout(function () { - Metamaps.Router.navigate('') - }, 300) - } + var navigate = function () { + Metamaps.Router.timeoutId = setTimeout(function () { + Metamaps.Router.navigate('') + }, 300) + } - // all this only for the logged in home page - if (Metamaps.Active.Mapper) { - $('.homeButton a').attr('href', '/') - Metamaps.GlobalUI.hideDiv('#yield') - - Metamaps.GlobalUI.showDiv('#explore') - - Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) - if (Metamaps.Maps.Active.length === 0) { - Metamaps.Maps.Active.getMaps(navigate) // this will trigger an explore maps render - } else { - Metamaps.Views.exploreMaps.render(navigate) - } - } else { - // logged out home page - Metamaps.GlobalUI.hideDiv('#explore') - Metamaps.GlobalUI.showDiv('#yield') - Metamaps.Router.timeoutId = setTimeout(navigate, 500) - } - - Metamaps.GlobalUI.hideDiv('#infovis') - Metamaps.GlobalUI.hideDiv('#instructions') - Metamaps.Map.end() - Metamaps.Topic.end() - Metamaps.Active.Map = null - Metamaps.Active.Topic = null - }, - explore: function (section, id) { - clearTimeout(Metamaps.Router.timeoutId) - - // just capitalize the variable section - // either 'featured', 'mapper', or 'active' - var capitalize = section.charAt(0).toUpperCase() + section.slice(1) - - if (section === 'shared' || section === 'featured' || section === 'active' || section === 'starred') { - document.title = 'Explore ' + capitalize + ' Maps | Metamaps' - } else if (section === 'mapper') { - $.ajax({ - url: '/users/' + id + '.json', - success: function (response) { - document.title = response.name + ' | Metamaps' - }, - error: function () {} - }) - } else if (section === 'mine') { - document.title = 'Explore My Maps | Metamaps' - } - - if (Metamaps.Active.Mapper && section != 'mapper') $('.homeButton a').attr('href', '/explore/' + section) - $('.wrapper').removeClass('homePage mapPage topicPage') - $('.wrapper').addClass('explorePage') - - Metamaps.Router.currentSection = 'explore' - Metamaps.Router.currentPage = section - - // this will mean it's a mapper page being loaded - if (id) { - if (Metamaps.Maps.Mapper.mapperId !== id) { - // empty the collection if we are trying to load the maps - // collection of a different mapper than we had previously - Metamaps.Maps.Mapper.reset() - Metamaps.Maps.Mapper.page = 1 - } - Metamaps.Maps.Mapper.mapperId = id - } - - Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps[capitalize]) - - var navigate = function () { - var path = '/explore/' + Metamaps.Router.currentPage - - // alter url if for mapper profile page - if (Metamaps.Router.currentPage === 'mapper') { - path += '/' + Metamaps.Maps.Mapper.mapperId - } - - Metamaps.Router.navigate(path) - } - var navigateTimeout = function () { - Metamaps.Router.timeoutId = setTimeout(navigate, 300) - } - if (Metamaps.Maps[capitalize].length === 0) { - Metamaps.Loading.show() - setTimeout(function () { - Metamaps.Maps[capitalize].getMaps(navigate) // this will trigger an explore maps render - }, 300) // wait 300 milliseconds till the other animations are done to do the fetch - } else { - if (id) { - Metamaps.Views.exploreMaps.fetchUserThenRender(navigateTimeout) - } else { - Metamaps.Views.exploreMaps.render(navigateTimeout) - } - } + // all this only for the logged in home page + if (Metamaps.Active.Mapper) { + $('.homeButton a').attr('href', '/') + Metamaps.GlobalUI.hideDiv('#yield') Metamaps.GlobalUI.showDiv('#explore') - Metamaps.GlobalUI.hideDiv('#yield') - Metamaps.GlobalUI.hideDiv('#infovis') - Metamaps.GlobalUI.hideDiv('#instructions') - Metamaps.Map.end() - Metamaps.Topic.end() - Metamaps.Active.Map = null - Metamaps.Active.Topic = null - }, - maps: function (id) { - clearTimeout(Metamaps.Router.timeoutId) - document.title = 'Map ' + id + ' | Metamaps' - - Metamaps.Router.currentSection = 'map' - Metamaps.Router.currentPage = id - - $('.wrapper').removeClass('homePage explorePage topicPage') - $('.wrapper').addClass('mapPage') - // another class will be added to wrapper if you - // can edit this map '.canEditMap' - - Metamaps.GlobalUI.hideDiv('#yield') - Metamaps.GlobalUI.hideDiv('#explore') - - // clear the visualization, if there was one, before showing its div again - if (Metamaps.Visualize.mGraph) { - Metamaps.Visualize.mGraph.graph.empty() - Metamaps.Visualize.mGraph.plot() - Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas) - } - Metamaps.GlobalUI.showDiv('#infovis') - Metamaps.Topic.end() - Metamaps.Active.Topic = null - - Metamaps.Loading.show() - Metamaps.Map.end() - Metamaps.Map.launch(id) - }, - topics: function (id) { - clearTimeout(Metamaps.Router.timeoutId) - - document.title = 'Topic ' + id + ' | Metamaps' - - Metamaps.Router.currentSection = 'topic' - Metamaps.Router.currentPage = id - - $('.wrapper').removeClass('homePage explorePage mapPage') - $('.wrapper').addClass('topicPage') - - Metamaps.GlobalUI.hideDiv('#yield') - Metamaps.GlobalUI.hideDiv('#explore') - - // clear the visualization, if there was one, before showing its div again - if (Metamaps.Visualize.mGraph) { - Metamaps.Visualize.mGraph.graph.empty() - Metamaps.Visualize.mGraph.plot() - Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas) - } - Metamaps.GlobalUI.showDiv('#infovis') - Metamaps.Map.end() - Metamaps.Active.Map = null - - Metamaps.Topic.end() - Metamaps.Topic.launch(id) - } - }) - - Metamaps.Router = new Router() - Metamaps.Router.currentPage = '' - Metamaps.Router.currentSection = undefined - Metamaps.Router.timeoutId = undefined - - Metamaps.Router.intercept = function (evt) { - var segments - - var href = { - prop: $(this).prop('href'), - attr: $(this).attr('href') - } - var root = window.location.protocol + '//' + window.location.host + Backbone.history.options.root - - if (href.prop && href.prop === root) href.attr = '' - - if (href.prop && href.prop.slice(0, root.length) === root) { - evt.preventDefault() - - segments = href.attr.split('/') - segments.splice(0, 1) // pop off the element created by the first / - - if (href.attr === '') { - Metamaps.Router.home() + Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) + if (Metamaps.Maps.Active.length === 0) { + Metamaps.Maps.Active.getMaps(navigate) // this will trigger an explore maps render } else { - Metamaps.Router[segments[0]](segments[1], segments[2]) + Metamaps.Views.exploreMaps.render(navigate) + } + } else { + // logged out home page + Metamaps.GlobalUI.hideDiv('#explore') + Metamaps.GlobalUI.showDiv('#yield') + Metamaps.Router.timeoutId = setTimeout(navigate, 500) + } + + Metamaps.GlobalUI.hideDiv('#infovis') + Metamaps.GlobalUI.hideDiv('#instructions') + Metamaps.Map.end() + Metamaps.Topic.end() + Metamaps.Active.Map = null + Metamaps.Active.Topic = null + }, + explore: function (section, id) { + clearTimeout(Metamaps.Router.timeoutId) + + // just capitalize the variable section + // either 'featured', 'mapper', or 'active' + var capitalize = section.charAt(0).toUpperCase() + section.slice(1) + + if (section === 'shared' || section === 'featured' || section === 'active' || section === 'starred') { + document.title = 'Explore ' + capitalize + ' Maps | Metamaps' + } else if (section === 'mapper') { + $.ajax({ + url: '/users/' + id + '.json', + success: function (response) { + document.title = response.name + ' | Metamaps' + }, + error: function () {} + }) + } else if (section === 'mine') { + document.title = 'Explore My Maps | Metamaps' + } + + if (Metamaps.Active.Mapper && section != 'mapper') $('.homeButton a').attr('href', '/explore/' + section) + $('.wrapper').removeClass('homePage mapPage topicPage') + $('.wrapper').addClass('explorePage') + + Metamaps.Router.currentSection = 'explore' + Metamaps.Router.currentPage = section + + // this will mean it's a mapper page being loaded + if (id) { + if (Metamaps.Maps.Mapper.mapperId !== id) { + // empty the collection if we are trying to load the maps + // collection of a different mapper than we had previously + Metamaps.Maps.Mapper.reset() + Metamaps.Maps.Mapper.page = 1 + } + Metamaps.Maps.Mapper.mapperId = id + } + + Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps[capitalize]) + + var navigate = function () { + var path = '/explore/' + Metamaps.Router.currentPage + + // alter url if for mapper profile page + if (Metamaps.Router.currentPage === 'mapper') { + path += '/' + Metamaps.Maps.Mapper.mapperId + } + + Metamaps.Router.navigate(path) + } + var navigateTimeout = function () { + Metamaps.Router.timeoutId = setTimeout(navigate, 300) + } + if (Metamaps.Maps[capitalize].length === 0) { + Metamaps.Loading.show() + setTimeout(function () { + Metamaps.Maps[capitalize].getMaps(navigate) // this will trigger an explore maps render + }, 300) // wait 300 milliseconds till the other animations are done to do the fetch + } else { + if (id) { + Metamaps.Views.exploreMaps.fetchUserThenRender(navigateTimeout) + } else { + Metamaps.Views.exploreMaps.render(navigateTimeout) } } - } - Metamaps.Router.init = function () { - Backbone.history.start({ - silent: true, - pushState: true, - root: '/' - }) - $(document).on('click', 'a[data-router="true"]', Metamaps.Router.intercept) + Metamaps.GlobalUI.showDiv('#explore') + Metamaps.GlobalUI.hideDiv('#yield') + Metamaps.GlobalUI.hideDiv('#infovis') + Metamaps.GlobalUI.hideDiv('#instructions') + Metamaps.Map.end() + Metamaps.Topic.end() + Metamaps.Active.Map = null + Metamaps.Active.Topic = null + }, + maps: function (id) { + clearTimeout(Metamaps.Router.timeoutId) + + document.title = 'Map ' + id + ' | Metamaps' + + Metamaps.Router.currentSection = 'map' + Metamaps.Router.currentPage = id + + $('.wrapper').removeClass('homePage explorePage topicPage') + $('.wrapper').addClass('mapPage') + // another class will be added to wrapper if you + // can edit this map '.canEditMap' + + Metamaps.GlobalUI.hideDiv('#yield') + Metamaps.GlobalUI.hideDiv('#explore') + + // clear the visualization, if there was one, before showing its div again + if (Metamaps.Visualize.mGraph) { + Metamaps.Visualize.mGraph.graph.empty() + Metamaps.Visualize.mGraph.plot() + Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas) + } + Metamaps.GlobalUI.showDiv('#infovis') + Metamaps.Topic.end() + Metamaps.Active.Topic = null + + Metamaps.Loading.show() + Metamaps.Map.end() + Metamaps.Map.launch(id) + }, + topics: function (id) { + clearTimeout(Metamaps.Router.timeoutId) + + document.title = 'Topic ' + id + ' | Metamaps' + + Metamaps.Router.currentSection = 'topic' + Metamaps.Router.currentPage = id + + $('.wrapper').removeClass('homePage explorePage mapPage') + $('.wrapper').addClass('topicPage') + + Metamaps.GlobalUI.hideDiv('#yield') + Metamaps.GlobalUI.hideDiv('#explore') + + // clear the visualization, if there was one, before showing its div again + if (Metamaps.Visualize.mGraph) { + Metamaps.Visualize.mGraph.graph.empty() + Metamaps.Visualize.mGraph.plot() + Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas) + } + Metamaps.GlobalUI.showDiv('#infovis') + Metamaps.Map.end() + Metamaps.Active.Map = null + + Metamaps.Topic.end() + Metamaps.Topic.launch(id) } -})() +}) + +const Router = new _Router() +Router.currentPage = '' +Router.currentSection = undefined +Router.timeoutId = undefined + +Router.intercept = function (evt) { + var segments + + var href = { + prop: $(this).prop('href'), + attr: $(this).attr('href') + } + var root = window.location.protocol + '//' + window.location.host + Backbone.history.options.root + + if (href.prop && href.prop === root) href.attr = '' + + if (href.prop && href.prop.slice(0, root.length) === root) { + evt.preventDefault() + + segments = href.attr.split('/') + segments.splice(0, 1) // pop off the element created by the first / + + if (href.attr === '') { + Metamaps.Router.home() + } else { + Metamaps.Router[segments[0]](segments[1], segments[2]) + } + } +} + +Router.init = function () { + Backbone.history.start({ + silent: true, + pushState: true, + root: '/' + }) + $(document).on('click', 'a[data-router="true"]', Metamaps.Router.intercept) +} + +export default Router diff --git a/frontend/src/Metamaps/Synapse.js b/frontend/src/Metamaps/Synapse.js index 20cf0f9c..5258de3b 100644 --- a/frontend/src/Metamaps/Synapse.js +++ b/frontend/src/Metamaps/Synapse.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -18,7 +17,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Visualize */ -Metamaps.Synapse = { +const Synapse = { // this function is to retrieve a synapse JSON object from the database // @param id = the id of the synapse to retrieve get: function (id, callback) { @@ -98,7 +97,7 @@ Metamaps.Synapse = { } }, createSynapseLocally: function () { - var self = Metamaps.Synapse, + var self = Synapse, topic1, topic2, node1, @@ -145,7 +144,7 @@ Metamaps.Synapse = { Metamaps.Create.newSynapse.hide() }, getSynapseFromAutocomplete: function (id) { - var self = Metamaps.Synapse, + var self = Synapse, topic1, topic2, node1, @@ -167,4 +166,6 @@ Metamaps.Synapse = { self.renderSynapse(mapping, synapse, node1, node2, true) } -}; // end Metamaps.Synapse +} + +export default Synapse diff --git a/frontend/src/Metamaps/SynapseCard.js b/frontend/src/Metamaps/SynapseCard.js index aff207a9..93ebb646 100644 --- a/frontend/src/Metamaps/SynapseCard.js +++ b/frontend/src/Metamaps/SynapseCard.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -10,10 +9,10 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Mapper * - Metamaps.Visualize */ -Metamaps.SynapseCard = { +const SynapseCard = { openSynapseCard: null, showCard: function (edge, e) { - var self = Metamaps.SynapseCard + var self = SynapseCard // reset so we don't interfere with other edges, but first, save its x and y var myX = $('#edit_synapse').css('left') @@ -59,11 +58,11 @@ Metamaps.SynapseCard = { hideCard: function () { $('#edit_synapse').remove() - Metamaps.SynapseCard.openSynapseCard = null + SynapseCard.openSynapseCard = null }, populateShowCard: function (edge, synapse) { - var self = Metamaps.SynapseCard + var self = SynapseCard self.add_synapse_count(edge) self.add_desc_form(synapse) @@ -154,7 +153,7 @@ Metamaps.SynapseCard = { var index = parseInt($(this).attr('data-synapse-index')) edge.setData('displayIndex', index) Metamaps.Visualize.mGraph.plot() - Metamaps.SynapseCard.showCard(edge, false) + SynapseCard.showCard(edge, false) }) } }, @@ -286,4 +285,6 @@ Metamaps.SynapseCard = { }) } // if } // add_direction_form -}; // end Metamaps.SynapseCard +} + +export default SynapseCard diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index faa8b336..8de14c34 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -28,7 +27,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.tempNode2 */ -Metamaps.Topic = { +const Topic = { // this function is to retrieve a topic JSON object from the database // @param id = the id of the topic to retrieve get: function (id, callback) { @@ -393,4 +392,6 @@ Metamaps.Topic = { event.preventDefault() return false } -}; // end Metamaps.Topic +} + +export default Topic diff --git a/frontend/src/Metamaps/TopicCard.js b/frontend/src/Metamaps/TopicCard.js index fc007f3b..5a7f1920 100644 --- a/frontend/src/Metamaps/TopicCard.js +++ b/frontend/src/Metamaps/TopicCard.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -13,16 +12,16 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Util * - Metamaps.Visualize */ -Metamaps.TopicCard = { +const TopicCard = { openTopicCard: null, // stores the topic that's currently open authorizedToEdit: false, // stores boolean for edit permission for open topic card init: function () { - var self = Metamaps.TopicCard + var self = TopicCard // initialize best_in_place editing $('.authenticated div.permission.canEdit .best_in_place').best_in_place() - Metamaps.TopicCard.generateShowcardHTML = Hogan.compile($('#topicCardTemplate').html()) + TopicCard.generateShowcardHTML = Hogan.compile($('#topicCardTemplate').html()) // initialize topic card draggability and resizability $('.showcard').draggable({ @@ -39,7 +38,7 @@ Metamaps.TopicCard = { * @param {$jit.Graph.Node} node */ showCard: function (node, opts) { - var self = Metamaps.TopicCard + var self = TopicCard var topic = node.getData('topic') @@ -54,14 +53,14 @@ Metamaps.TopicCard = { }) }, hideCard: function () { - var self = Metamaps.TopicCard + var self = TopicCard $('.showcard').fadeOut('fast') self.openTopicCard = null self.authorizedToEdit = false }, embedlyCardRendered: function (iframe) { - var self = Metamaps.TopicCard + var self = TopicCard $('#embedlyLinkLoader').hide() @@ -78,7 +77,7 @@ Metamaps.TopicCard = { } }, removeLink: function () { - var self = Metamaps.TopicCard + var self = TopicCard self.openTopicCard.save({ link: null }) @@ -88,7 +87,7 @@ Metamaps.TopicCard = { $('.CardOnGraph').removeClass('hasAttachment') }, bindShowCardListeners: function (topic) { - var self = Metamaps.TopicCard + var self = TopicCard var showCard = document.getElementById('showcard') var authorized = self.authorizedToEdit @@ -350,13 +349,13 @@ Metamaps.TopicCard = { }) }, handleInvalidLink: function () { - var self = Metamaps.TopicCard + var self = TopicCard self.removeLink() Metamaps.GlobalUI.notifyUser('Invalid link') }, populateShowCard: function (topic) { - var self = Metamaps.TopicCard + var self = TopicCard var showCard = document.getElementById('showcard') @@ -380,12 +379,12 @@ Metamaps.TopicCard = { showCard.appendChild(perm) } - Metamaps.TopicCard.bindShowCardListeners(topic) + TopicCard.bindShowCardListeners(topic) }, generateShowcardHTML: null, // will be initialized into a Hogan template within init function // generateShowcardHTML buildObject: function (topic) { - var self = Metamaps.TopicCard + var self = TopicCard var nodeValues = {} @@ -456,4 +455,6 @@ Metamaps.TopicCard = { nodeValues.desc = (topic.get('desc') == '' && authorized) ? desc_nil : topic.get('desc') return nodeValues } -}; // end Metamaps.TopicCard +} + +export default TopicCard diff --git a/frontend/src/Metamaps/Util.js b/frontend/src/Metamaps/Util.js index 9ff9c470..e835a15b 100644 --- a/frontend/src/Metamaps/Util.js +++ b/frontend/src/Metamaps/Util.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps */ /* @@ -8,7 +7,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Visualize */ -Metamaps.Util = { +const Util = { // helper function to determine how many lines are needed // Line Splitter Function // copyright Stephen Chapman, 19th April 2006 @@ -92,7 +91,7 @@ Metamaps.Util = { var r = (Math.round(Math.random() * 127) + 127).toString(16) var g = (Math.round(Math.random() * 127) + 127).toString(16) var b = (Math.round(Math.random() * 127) + 127).toString(16) - return Metamaps.Util.colorLuminance('#' + r + g + b, -0.4) + return Util.colorLuminance('#' + r + g + b, -0.4) }, // darkens a hex value by 'lum' percentage colorLuminance: function (hex, lum) { @@ -128,4 +127,6 @@ Metamaps.Util = { checkURLisYoutubeVideo: function (url) { return (url.match(/^https?:\/\/(?:www\.)?youtube.com\/watch\?(?=[^?]*v=\w+)(?:[^\s?]+)?$/) != null) } -}; // end Metamaps.Util +} + +export default Util diff --git a/frontend/src/Metamaps/Views.js b/frontend/src/Metamaps/Views.js index eb5fdb7c..90cd466d 100644 --- a/frontend/src/Metamaps/Views.js +++ b/frontend/src/Metamaps/Views.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* @@ -10,10 +9,10 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.ReactComponents */ -Metamaps.Views = { +const Views = { exploreMaps: { setCollection: function (collection) { - var self = Metamaps.Views.exploreMaps + var self = Views.exploreMaps if (self.collection) { self.collection.off('add', self.render) @@ -26,7 +25,7 @@ Metamaps.Views = { self.collection.on('errorOnFetch', self.handleError) }, render: function (mapperObj, cb) { - var self = Metamaps.Views.exploreMaps + var self = Views.exploreMaps if (typeof mapperObj === 'function') { cb = mapperObj @@ -51,7 +50,7 @@ Metamaps.Views = { Metamaps.Loading.hide() }, loadMore: function () { - var self = Metamaps.Views.exploreMaps + var self = Views.exploreMaps if (self.collection.page != "loadedAll") { self.collection.getMaps() @@ -59,7 +58,7 @@ Metamaps.Views = { else self.render() }, handleSuccess: function (cb) { - var self = Metamaps.Views.exploreMaps + var self = Views.exploreMaps if (self.collection && self.collection.id === 'mapper') { self.fetchUserThenRender(cb) @@ -71,7 +70,7 @@ Metamaps.Views = { console.log('error loading maps!') // TODO }, fetchUserThenRender: function (cb) { - var self = Metamaps.Views.exploreMaps + var self = Views.exploreMaps // first load the mapper object and then call the render function $.ajax({ @@ -86,3 +85,5 @@ Metamaps.Views = { } } } + +export default Views diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index f5ce8c79..5e99519f 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -1,4 +1,3 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ /* * Metamaps.Visualize @@ -13,16 +12,15 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.TopicCard * - Metamaps.Topics * - Metamaps.Touch - * - Metamaps.Visualize */ -Metamaps.Visualize = { +const Visualize = { mGraph: null, // a reference to the graph object. cameraPosition: null, // stores the camera position when using a 3D visualization type: 'ForceDirected', // the type of graph we're building, could be "RGraph", "ForceDirected", or "ForceDirected3D" loadLater: false, // indicates whether there is JSON that should be loaded right in the offset, or whether to wait till the first topic is created init: function () { - var self = Metamaps.Visualize + var self = Visualize // disable awkward dragging of the canvas element that would sometimes happen $('#infovis-canvas').on('dragstart', function (event) { event.preventDefault() @@ -48,7 +46,7 @@ Metamaps.Visualize = { }) }, computePositions: function () { - var self = Metamaps.Visualize, + var self = Visualize, mapping if (self.type == 'RGraph') { @@ -112,7 +110,7 @@ Metamaps.Visualize = { * */ render: function () { - var self = Metamaps.Visualize, RGraphSettings, FDSettings + var self = Visualize, RGraphSettings, FDSettings if (self.type == 'RGraph' && (!self.mGraph || self.mGraph instanceof $jit.ForceDirected)) { // clear the previous canvas from #infovis @@ -217,4 +215,6 @@ Metamaps.Visualize = { } }, 800) } -}; // end Metamaps.Visualize +} + +export default Visualize diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index ef50b564..926529ca 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -2,32 +2,60 @@ window.Metamaps = window.Metamaps || {} import './Constants' -import './Account' -import './Admin' -import './AutoLayout' -import './Backbone' -import './Control' -import './Create' -import './Debug' -import './Filter' -import './GlobalUI' -import './Import' -import './JIT' -import './Listeners' -import './Map' -import './Mapper' -import './Mobile' -import './Organize' -import './PasteInput' -import './Realtime' -import './Router' -import './Synapse' -import './SynapseCard' -import './Topic' -import './TopicCard' -import './Util' -import './Views' -import './Visualize' -import './ReactComponents' +import Account from './Account' +import Admin from './Admin' +import AutoLayout from './AutoLayout' +import Backbone from './Backbone' +import Control from './Control' +import Create from './Create' +import Debug from './Debug' +import Filter from './Filter' +import GlobalUI from './GlobalUI' +import Import from './Import' +import JIT from './JIT' +import Listeners from './Listeners' +import Map from './Map' +import Mapper from './Mapper' +import Mobile from './Mobile' +import Organize from './Organize' +import PasteInput from './PasteInput' +import Realtime from './Realtime' +import Router from './Router' +import Synapse from './Synapse' +import SynapseCard from './SynapseCard' +import Topic from './Topic' +import TopicCard from './TopicCard' +import Util from './Util' +import Views from './Views' +import Visualize from './Visualize' +import ReactComponents from './ReactComponents' + +Metamaps.Account = Account +Metamaps.Admin = Admin +Metamaps.AutoLayout = AutoLayout +Metamaps.Backbone = Backbone +Metamaps.Control = Control +Metamaps.Create = Create +Metamaps.Debug = Debug +Metamaps.Filter = Filter +Metamaps.GlobalUI = GlobalUI +Metamaps.Import = Import +Metamaps.JIT = JIT +Metamaps.Listeners = Listeners +Metamaps.Map = Map +Metamaps.Mapper = Mapper +Metamaps.Mobile = Mobile +Metamaps.Organize = Organize +Metamaps.PasteInput = PasteInput +Metamaps.Realtime = Realtime +Metamaps.ReactComponents = ReactComponents +Metamaps.Router = Router +Metamaps.Synapse = Synapse +Metamaps.SynapseCard = SynapseCard +Metamaps.Topic = Topic +Metamaps.TopicCard = TopicCard +Metamaps.Util = Util +Metamaps.Views = Views +Metamaps.Visualize = Visualize export default window.Metamaps From 7f83f86460d9c9b3eb5e1dc201d0689ea04b8084 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 15:29:55 +0800 Subject: [PATCH 04/26] refactor a bit, make a comment about the Constants file --- frontend/src/Metamaps/Constants.js | 12 ++- frontend/src/Metamaps/GlobalUI.js | 133 ++++++++++------------------- frontend/src/Metamaps/index.js | 38 +++++++++ 3 files changed, 93 insertions(+), 90 deletions(-) diff --git a/frontend/src/Metamaps/Constants.js b/frontend/src/Metamaps/Constants.js index a79054e6..ab62ba14 100644 --- a/frontend/src/Metamaps/Constants.js +++ b/frontend/src/Metamaps/Constants.js @@ -1,10 +1,20 @@ window.Metamaps = window.Metamaps || {} -// TODO eliminate these 5 top-level variables +// TODO everything in this file should be moved into one of the other modules +// Either as a local constant, or as a local constant with a globally available getter/setter + Metamaps.tempNode = null Metamaps.tempInit = false Metamaps.tempNode2 = null +Metamaps.Active = Metamaps.Active || { + Map: null, + Topic: null, + Mapper: null +}; + +Metamaps.Maps = Metamaps.Maps || {} + Metamaps.Settings = { embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages sandbox: false, // puts the app into a mode (when true) where it only creates data locally, and isn't writing it to the database diff --git a/frontend/src/Metamaps/GlobalUI.js b/frontend/src/Metamaps/GlobalUI.js index e4522c2f..5abf25ee 100644 --- a/frontend/src/Metamaps/GlobalUI.js +++ b/frontend/src/Metamaps/GlobalUI.js @@ -1,54 +1,10 @@ window.Metamaps = window.Metamaps || {}; -Metamaps.Active = Metamaps.Active || { - Map: null, - Topic: null, - Mapper: null -}; -Metamaps.Maps = Metamaps.Maps || {} - -$(document).ready(function () { - // initialize all the modules - for (var prop in Metamaps) { - // this runs the init function within each sub-object on the Metamaps one - if (Metamaps.hasOwnProperty(prop) && - Metamaps[prop] != null && - Metamaps[prop].hasOwnProperty('init') && - typeof (Metamaps[prop].init) == 'function' - ) { - Metamaps[prop].init() - } - } - // load whichever page you are on - if (Metamaps.currentSection === "explore") { - var capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1) - - Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ) - if (Metamaps.currentPage === "mapper") { - Metamaps.Views.exploreMaps.fetchUserThenRender() - } - else { - Metamaps.Views.exploreMaps.render() - } - Metamaps.GlobalUI.showDiv('#explore') - } - else if (Metamaps.currentSection === "" && Metamaps.Active.Mapper) { - Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) - Metamaps.Views.exploreMaps.render() - Metamaps.GlobalUI.showDiv('#explore') - } - else if (Metamaps.Active.Map || Metamaps.Active.Topic) { - Metamaps.Loading.show() - Metamaps.JIT.prepareVizData() - Metamaps.GlobalUI.showDiv('#infovis') - } -}); - -Metamaps.GlobalUI = { +const GlobalUI = { notifyTimeout: null, lightbox: null, init: function () { - var self = Metamaps.GlobalUI; + var self = GlobalUI; self.Search.init(); self.CreateMap.init(); @@ -99,7 +55,7 @@ Metamaps.GlobalUI = { }, 200, 'easeInCubic', function () { $(this).hide() }) }, openLightbox: function (which) { - var self = Metamaps.GlobalUI; + var self = GlobalUI; $('.lightboxContent').hide(); $('#' + which).show(); @@ -126,7 +82,7 @@ Metamaps.GlobalUI = { }, closeLightbox: function (event) { - var self = Metamaps.GlobalUI; + var self = GlobalUI; if (event) event.preventDefault(); @@ -143,15 +99,15 @@ Metamaps.GlobalUI = { $('#lightbox_overlay').hide(); }); - if (self.lightbox === 'forkmap') Metamaps.GlobalUI.CreateMap.reset('fork_map'); - if (self.lightbox === 'newmap') Metamaps.GlobalUI.CreateMap.reset('new_map'); + if (self.lightbox === 'forkmap') GlobalUI.CreateMap.reset('fork_map'); + if (self.lightbox === 'newmap') GlobalUI.CreateMap.reset('new_map'); if (Metamaps.Create && Metamaps.Create.isSwitchingSet) { Metamaps.Create.cancelMetacodeSetSwitch(); } self.lightbox = null; }, notifyUser: function (message, leaveOpen) { - var self = Metamaps.GlobalUI; + var self = GlobalUI; $('#toast').html(message) self.showDiv('#toast') @@ -163,7 +119,7 @@ Metamaps.GlobalUI = { } }, clearNotify: function() { - var self = Metamaps.GlobalUI; + var self = GlobalUI; clearTimeout(self.notifyTimeOut); self.hideDiv('#toast') @@ -171,16 +127,16 @@ Metamaps.GlobalUI = { shareInvite: function(inviteLink) { window.prompt("To copy the invite link, press: Ctrl+C, Enter", inviteLink); } -}; +} -Metamaps.GlobalUI.CreateMap = { +GlobalUI.CreateMap = { newMap: null, emptyMapForm: "", emptyForkMapForm: "", topicsToMap: [], synapsesToMap: [], init: function () { - var self = Metamaps.GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); @@ -190,7 +146,7 @@ Metamaps.GlobalUI.CreateMap = { }, bindFormEvents: function () { - var self = Metamaps.GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; $('.new_map input, .new_map div').unbind('keypress').bind('keypress', function(event) { if (event.keyCode === 13) self.submit() @@ -198,7 +154,7 @@ Metamaps.GlobalUI.CreateMap = { $('.new_map button.cancel').unbind().bind('click', function (event) { event.preventDefault(); - Metamaps.GlobalUI.closeLightbox(); + GlobalUI.closeLightbox(); }); $('.new_map button.submitMap').unbind().bind('click', self.submit); @@ -213,14 +169,14 @@ Metamaps.GlobalUI.CreateMap = { generateSuccessMessage: function (id) { var stringStart = ""; return stringStart + page + stringEnd; }, switchPermission: function () { - var self = Metamaps.GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; self.newMap.set('permission', $(this).attr('data-permission')); $(this).siblings('.permIcon').find('.mapPermIcon').removeClass('selected'); @@ -232,14 +188,14 @@ Metamaps.GlobalUI.CreateMap = { submit: function (event) { if (event) event.preventDefault(); - var self = Metamaps.GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; - if (Metamaps.GlobalUI.lightbox === 'forkmap') { + if (GlobalUI.lightbox === 'forkmap') { self.newMap.set('topicsToMap', self.topicsToMap); self.newMap.set('synapsesToMap', self.synapsesToMap); } - var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; var $form = $(formId); self.newMap.set('name', $form.find('#map_name').val()); @@ -255,13 +211,13 @@ Metamaps.GlobalUI.CreateMap = { // TODO add error message }); - Metamaps.GlobalUI.closeLightbox(); - Metamaps.GlobalUI.notifyUser('Working...'); + GlobalUI.closeLightbox(); + GlobalUI.notifyUser('Working...'); }, throwMapNameError: function () { - var self = Metamaps.GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; - var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; var $form = $(formId); var message = $(""); @@ -274,20 +230,20 @@ Metamaps.GlobalUI.CreateMap = { }, 5000); }, success: function (model) { - var self = Metamaps.GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; //push the new map onto the collection of 'my maps' Metamaps.Maps.Mine.add(model); - var formId = Metamaps.GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; var form = $(formId); - Metamaps.GlobalUI.clearNotify(); + GlobalUI.clearNotify(); $('#wrapper').append(self.generateSuccessMessage(model.id)); }, reset: function (id) { - var self = Metamaps.GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; var form = $('#' + id); @@ -305,14 +261,13 @@ Metamaps.GlobalUI.CreateMap = { return false; }, -}; +} - -Metamaps.GlobalUI.Account = { +GlobalUI.Account = { isOpen: false, changing: false, init: function () { - var self = Metamaps.GlobalUI.Account; + var self = GlobalUI.Account; $('.sidebarAccountIcon').click(self.toggleBox); $('.sidebarAccountBox').click(function(event){ @@ -321,7 +276,7 @@ Metamaps.GlobalUI.Account = { $('body').click(self.close); }, toggleBox: function (event) { - var self = Metamaps.GlobalUI.Account; + var self = GlobalUI.Account; if (self.isOpen) self.close(); else self.open(); @@ -329,7 +284,7 @@ Metamaps.GlobalUI.Account = { event.stopPropagation(); }, open: function () { - var self = Metamaps.GlobalUI.Account; + var self = GlobalUI.Account; Metamaps.Filter.close(); $('.sidebarAccountIcon .tooltipsUnder').addClass('hide'); @@ -345,7 +300,7 @@ Metamaps.GlobalUI.Account = { } }, close: function () { - var self = Metamaps.GlobalUI.Account; + var self = GlobalUI.Account; $('.sidebarAccountIcon .tooltipsUnder').removeClass('hide'); if (!self.changing) { @@ -357,9 +312,9 @@ Metamaps.GlobalUI.Account = { }); } } -}; +} -Metamaps.GlobalUI.Search = { +GlobalUI.Search = { locked: false, isOpen: false, limitTopicsToMe: false, @@ -368,7 +323,7 @@ Metamaps.GlobalUI.Search = { changing: false, optionsInitialized: false, init: function () { - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; var loader = new CanvasLoader('searchLoading'); loader.setColor('#4fb5c0'); // default is '#000000' @@ -417,15 +372,15 @@ Metamaps.GlobalUI.Search = { self.startTypeahead(); }, lock: function() { - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; self.locked = true; }, unlock: function() { - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; self.locked = false; }, open: function (focus) { - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; clearTimeout(self.timeOut); if (!self.isOpen && !self.changing && !self.locked) { @@ -447,7 +402,7 @@ Metamaps.GlobalUI.Search = { // for now return - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; self.timeOut = setTimeout(function () { if (!self.locked && !self.changing && self.isOpen && (bypass || $('.sidebarSearchField.tt-input').val() == '')) { @@ -468,7 +423,7 @@ Metamaps.GlobalUI.Search = { }, closeAfter); }, startTypeahead: function () { - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; var mapheader = Metamaps.Active.Mapper ? '

    Maps

    ' : '

    Maps

    '; var topicheader = Metamaps.Active.Mapper ? '

    Topics

    ' : '

    Topics

    '; @@ -615,7 +570,7 @@ Metamaps.GlobalUI.Search = { }, handleResultClick: function (event, datum, dataset) { - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; self.hideLoader(); @@ -632,7 +587,7 @@ Metamaps.GlobalUI.Search = { } }, initSearchOptions: function () { - var self = Metamaps.GlobalUI.Search; + var self = GlobalUI.Search; function toggleResultSet(set) { var s = $('.tt-dataset-' + set + ' .tt-suggestion, .tt-dataset-' + set + ' .resultnoresult'); @@ -679,4 +634,4 @@ Metamaps.GlobalUI.Search = { } } -export default Metamaps.GlobalUI +export default GlobalUI diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 926529ca..21d2af3a 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -1,3 +1,4 @@ +/* global $ */ window.Metamaps = window.Metamaps || {} import './Constants' @@ -58,4 +59,41 @@ Metamaps.Util = Util Metamaps.Views = Views Metamaps.Visualize = Visualize +$(document).ready(function () { + // initialize all the modules + for (var prop in Metamaps) { + // this runs the init function within each sub-object on the Metamaps one + if (Metamaps.hasOwnProperty(prop) && + Metamaps[prop] != null && + Metamaps[prop].hasOwnProperty('init') && + typeof (Metamaps[prop].init) == 'function' + ) { + Metamaps[prop].init() + } + } + // load whichever page you are on + if (Metamaps.currentSection === "explore") { + var capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1) + + Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ) + if (Metamaps.currentPage === "mapper") { + Metamaps.Views.exploreMaps.fetchUserThenRender() + } + else { + Metamaps.Views.exploreMaps.render() + } + Metamaps.GlobalUI.showDiv('#explore') + } + else if (Metamaps.currentSection === "" && Metamaps.Active.Mapper) { + Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) + Metamaps.Views.exploreMaps.render() + Metamaps.GlobalUI.showDiv('#explore') + } + else if (Metamaps.Active.Map || Metamaps.Active.Topic) { + Metamaps.Loading.show() + Metamaps.JIT.prepareVizData() + Metamaps.GlobalUI.showDiv('#infovis') + } +}); + export default window.Metamaps From d97b5c297729bb9420fac3ce61dd3659d78bd5a8 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 15:32:08 +0800 Subject: [PATCH 05/26] make Util modular --- frontend/src/Metamaps/Util.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/frontend/src/Metamaps/Util.js b/frontend/src/Metamaps/Util.js index e835a15b..9eb715de 100644 --- a/frontend/src/Metamaps/Util.js +++ b/frontend/src/Metamaps/Util.js @@ -1,11 +1,4 @@ -/* global Metamaps */ - -/* - * Metamaps.Util.js - * - * Dependencies: - * - Metamaps.Visualize - */ +import Visualize from './Visualize' const Util = { // helper function to determine how many lines are needed @@ -45,8 +38,8 @@ const Util = { return Math.sqrt(Math.pow((p2.x - p1.x), 2) + Math.pow((p2.y - p1.y), 2)) }, coordsToPixels: function (coords) { - if (Metamaps.Visualize.mGraph) { - var canvas = Metamaps.Visualize.mGraph.canvas, + if (Visualize.mGraph) { + var canvas = Visualize.mGraph.canvas, s = canvas.getSize(), p = canvas.getPos(), ox = canvas.translateOffsetX, @@ -67,8 +60,8 @@ const Util = { }, pixelsToCoords: function (pixels) { var coords - if (Metamaps.Visualize.mGraph) { - var canvas = Metamaps.Visualize.mGraph.canvas, + if (Visualize.mGraph) { + var canvas = Visualize.mGraph.canvas, s = canvas.getSize(), p = canvas.getPos(), ox = canvas.translateOffsetX, From c0f63abc59eaf2cd4d105e6bb766c4105beafc04 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 16:30:20 +0800 Subject: [PATCH 06/26] upgrade testing to es6 --- frontend/test/Metamaps.Import.spec.js | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/test/Metamaps.Import.spec.js b/frontend/test/Metamaps.Import.spec.js index 8dcf8e97..68946bea 100644 --- a/frontend/test/Metamaps.Import.spec.js +++ b/frontend/test/Metamaps.Import.spec.js @@ -1,13 +1,13 @@ /* global describe, it */ -const chai = require('chai') -const expect = chai.expect -Metamaps = {} -require('../../app/assets/javascripts/src/Metamaps.Import') +import chai from 'chai' +import Import from '../src/Metamaps/Import' + +const { expect } = chai describe('Metamaps.Import.js', function () { it('has a topic whitelist', function () { - expect(Metamaps.Import.topicWhitelist).to.deep.equal( + expect(Import.topicWhitelist).to.deep.equal( ['id', 'name', 'metacode', 'x', 'y', 'description', 'link', 'permission'] ) }) diff --git a/package.json b/package.json index a2227300..495b4f4b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "build": "webpack", "build:watch": "webpack --watch", - "test": "mocha frontend/test || (echo 'Run `npm install` to setup testing' && false)" + "test": "mocha --compilers js:babel-core/register frontend/test || (echo 'Run `npm install` to setup testing' && false)" }, "repository": { "type": "git", From 0a109895f77ca0bae9c6f5065e464aa5c06adead Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 16:32:10 +0800 Subject: [PATCH 07/26] merge realtime/package.json into top level package.json --- doc/production/first-deploy.md | 2 -- doc/production/pull-changes.md | 4 +--- package.json | 2 ++ realtime/package.json | 10 ---------- 4 files changed, 3 insertions(+), 15 deletions(-) delete mode 100644 realtime/package.json diff --git a/doc/production/first-deploy.md b/doc/production/first-deploy.md index cf98eda4..cc3a1f4a 100644 --- a/doc/production/first-deploy.md +++ b/doc/production/first-deploy.md @@ -87,8 +87,6 @@ server to see what problems show up: sudo npm install -g forever (crontab -u metamaps -l 2>/dev/null; echo "@reboot $(which forever) --append -l /home/metamaps/logs/forever.realtime.log start /home/metamaps/metamaps/realtime/realtime-server.js") | crontab -u metamaps - - cd /home/metamaps/metamaps/realtime - npm install mkdir -p /home/metamaps/logs forever --append -l /home/metamaps/logs/forever.realtime.log \ start /home/metamaps/metamaps/realtime/realtime-server.js diff --git a/doc/production/pull-changes.md b/doc/production/pull-changes.md index 0fb5d568..30f41cf5 100644 --- a/doc/production/pull-changes.md +++ b/doc/production/pull-changes.md @@ -29,9 +29,7 @@ Now that you have the code, run these commands: rake perms:fix passenger-config restart-app . - cd realtime - npm install - forever list #find the uid, e.g. xQKv + forever list #find the uid of the realtime server, e.g. xQKv forever restart xQKv sudo service metamaps_delayed_job restart diff --git a/package.json b/package.json index 495b4f4b..925323ac 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,11 @@ "chai": "^3.5.0", "jquery": "1.12.1", "mocha": "^3.0.2", + "node-uuid": "1.2.0", "react": "^15.3.0", "react-dom": "^15.3.0", "requirejs": "^2.1.1", + "socket.io": "0.9.12", "underscore": "^1.4.4", "webpack": "^1.13.1" } diff --git a/realtime/package.json b/realtime/package.json deleted file mode 100644 index 5b5b08f4..00000000 --- a/realtime/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "RoR-real-time", - "description": "providing real-time sychronization for ruby on rails", - "version": "0.0.1", - "private": true, - "dependencies": { - "socket.io": "0.9.12", - "node-uuid": "1.2.0" - } -} From 056213415772c38b738e64223502bc5cb6b493c0 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 17:00:12 +0800 Subject: [PATCH 08/26] low hanging fruit Here is my TODO list: already done ==> Account.js <== ==> Admin.js <== ==> AutoLayout.js <== ==> Listeners.js <== ==> Mapper.js <== ==> Organize.js <== ==> PasteInput.js <== ==> ReactComponents.js <== ==> Util.js <== TODO (I think) simple to make modular ==> Backbone.js <== ==> Control.js <== ==> Create.js <== ==> Filter.js <== ==> Import.js <== ==> Mobile.js <== ==> Synapse.js <== ==> SynapseCard.js <== ==> Topic.js <== ==> TopicCard.js <== ==> Views.js <== ==> Visualize.js <== TODO hard to make modular ==> Constants.js <== ==> Debug.js <== ==> GlobalUI.js <== ==> JIT.js <== ==> Map.js <== ==> Realtime.js <== ==> Router.js <== --- frontend/src/Metamaps/Account.js | 28 +++++++++-------------- frontend/src/Metamaps/Admin.js | 10 ++++----- frontend/src/Metamaps/Listeners.js | 2 -- frontend/src/Metamaps/Mapper.js | 8 ++----- frontend/src/Metamaps/Mobile.js | 2 +- frontend/src/Metamaps/Organize.js | 35 +++++++++++++---------------- frontend/src/Metamaps/PasteInput.js | 19 ++++++---------- 7 files changed, 41 insertions(+), 63 deletions(-) diff --git a/frontend/src/Metamaps/Account.js b/frontend/src/Metamaps/Account.js index 95a1a69f..f424019f 100644 --- a/frontend/src/Metamaps/Account.js +++ b/frontend/src/Metamaps/Account.js @@ -1,14 +1,6 @@ -window.Metamaps = window.Metamaps || {} -/* global Metamaps, $ */ +/* uses window.Metamaps.Erb */ -/* - * Metamaps.Account.js.erb - * - * Dependencies: - * - Metamaps.Erb - */ - -Metamaps.Account = { +const Account = { listenersInitialized: false, init: function () { var self = Metamaps.Account @@ -20,24 +12,24 @@ Metamaps.Account = { self.listenersInitialized = true }, toggleChangePicture: function () { - var self = Metamaps.Account + var self = Account $('.userImageMenu').toggle() if (!self.listenersInitialized) self.initListeners() }, openChangePicture: function () { - var self = Metamaps.Account + var self = Account $('.userImageMenu').show() if (!self.listenersInitialized) self.initListeners() }, closeChangePicture: function () { - var self = Metamaps.Account + var self = Account $('.userImageMenu').hide() }, showLoading: function () { - var self = Metamaps.Account + var self = Account var loader = new CanvasLoader('accountPageLoading') loader.setColor('#4FC059'); // default is '#000000' @@ -48,7 +40,7 @@ Metamaps.Account = { $('#accountPageLoading').show() }, showImagePreview: function () { - var self = Metamaps.Account + var self = Account var file = $('#user_image')[0].files[0] @@ -94,10 +86,10 @@ Metamaps.Account = { } }, removePicture: function () { - var self = Metamaps.Account + var self = Account $('.userImageDiv canvas').remove() - $('.userImageDiv img').attr('src', Metamaps.Erb['user.png']).show() + $('.userImageDiv img').attr('src', window.Metamaps.Erb['user.png']).show() $('.userImageMenu').hide() var input = $('#user_image') @@ -122,4 +114,4 @@ Metamaps.Account = { } } -export default Metamaps.Account +export default Account diff --git a/frontend/src/Metamaps/Admin.js b/frontend/src/Metamaps/Admin.js index 10cbc6d8..5d080c2e 100644 --- a/frontend/src/Metamaps/Admin.js +++ b/frontend/src/Metamaps/Admin.js @@ -4,26 +4,26 @@ const Admin = { selectMetacodes: [], allMetacodes: [], init: function () { - var self = Metamaps.Admin + var self = Admin $('#metacodes_value').val(self.selectMetacodes.toString()) }, selectAll: function () { - var self = Metamaps.Admin + var self = Admin $('.editMetacodes li').removeClass('toggledOff') self.selectMetacodes = self.allMetacodes.slice(0) $('#metacodes_value').val(self.selectMetacodes.toString()) }, deselectAll: function () { - var self = Metamaps.Admin + var self = Admin $('.editMetacodes li').addClass('toggledOff') self.selectMetacodes = [] $('#metacodes_value').val(0) }, liClickHandler: function () { - var self = Metamaps.Admin + var self = Admin if ($(this).attr('class') != 'toggledOff') { $(this).addClass('toggledOff') @@ -38,7 +38,7 @@ const Admin = { } }, validate: function () { - var self = Metamaps.Admin + var self = Admin if (self.selectMetacodes.length == 0) { alert('Would you pretty please select at least one metacode for the set?') diff --git a/frontend/src/Metamaps/Listeners.js b/frontend/src/Metamaps/Listeners.js index af244961..1c56b679 100644 --- a/frontend/src/Metamaps/Listeners.js +++ b/frontend/src/Metamaps/Listeners.js @@ -1,8 +1,6 @@ /* global Metamaps, $ */ /* - * Metamaps.Listeners.js.erb - * * Dependencies: * - Metamaps.Active * - Metamaps.Control diff --git a/frontend/src/Metamaps/Mapper.js b/frontend/src/Metamaps/Mapper.js index 114d4f8c..ac93c34d 100644 --- a/frontend/src/Metamaps/Mapper.js +++ b/frontend/src/Metamaps/Mapper.js @@ -1,9 +1,5 @@ -/* global Metamaps */ +import Backbone from './Backbone' -/* - * Dependencies: - * - Metamaps.Backbone - */ const Mapper = { // this function is to retrieve a mapper JSON object from the database // @param id = the id of the mapper to retrieve @@ -13,7 +9,7 @@ const Mapper = { if (!response.ok) throw response return response.json() }).then(payload => { - callback(new Metamaps.Backbone.Mapper(payload)) + callback(new Backbone.Mapper(payload)) }) } } diff --git a/frontend/src/Metamaps/Mobile.js b/frontend/src/Metamaps/Mobile.js index e062ca45..9074f521 100644 --- a/frontend/src/Metamaps/Mobile.js +++ b/frontend/src/Metamaps/Mobile.js @@ -10,7 +10,7 @@ const Mobile = { init: function () { - var self = Metamaps.Mobile + var self = Mobile $('#menu_icon').click(self.toggleMenu) $('#mobile_menu li a').click(self.liClick) diff --git a/frontend/src/Metamaps/Organize.js b/frontend/src/Metamaps/Organize.js index 71905568..ee29c2b8 100644 --- a/frontend/src/Metamaps/Organize.js +++ b/frontend/src/Metamaps/Organize.js @@ -1,21 +1,18 @@ -/* global Metamaps, $ */ +/* global $ */ + +import Visualize from './Visualize' +import JIT from './JIT' -/* - * Metamaps.Organize.js.erb - * - * Dependencies: - * - Metamaps.Visualize - */ const Organize = { arrange: function (layout, centerNode) { // first option for layout to implement is 'grid', will do an evenly spaced grid with its center at the 0,0 origin if (layout == 'grid') { - var numNodes = _.size(Metamaps.Visualize.mGraph.graph.nodes); // this will always be an integer, the # of nodes on your graph visualization + var numNodes = _.size(Visualize.mGraph.graph.nodes); // this will always be an integer, the # of nodes on your graph visualization var numColumns = Math.floor(Math.sqrt(numNodes)) // the number of columns to make an even grid var GRIDSPACE = 400 var row = 0 var column = 0 - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + Visualize.mGraph.graph.eachNode(function (n) { if (column == numColumns) { column = 0 row += 1 @@ -26,14 +23,14 @@ const Organize = { n.setPos(newPos, 'end') column += 1 }) - Metamaps.Visualize.mGraph.animate(Metamaps.JIT.ForceDirected.animateSavedLayout) + Visualize.mGraph.animate(JIT.ForceDirected.animateSavedLayout) } else if (layout == 'grid_full') { // this will always be an integer, the # of nodes on your graph visualization - var numNodes = _.size(Metamaps.Visualize.mGraph.graph.nodes) + var numNodes = _.size(Visualize.mGraph.graph.nodes) // var numColumns = Math.floor(Math.sqrt(numNodes)) // the number of columns to make an even grid // var GRIDSPACE = 400 - var height = Metamaps.Visualize.mGraph.canvas.getSize(0).height - var width = Metamaps.Visualize.mGraph.canvas.getSize(0).width + var height = Visualize.mGraph.canvas.getSize(0).height + var width = Visualize.mGraph.canvas.getSize(0).width var totalArea = height * width var cellArea = totalArea / numNodes var ratio = height / width @@ -44,7 +41,7 @@ const Organize = { var totalCells = row * column if (totalCells) - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + Visualize.mGraph.graph.eachNode(function (n) { if (column == numColumns) { column = 0 row += 1 @@ -55,7 +52,7 @@ const Organize = { n.setPos(newPos, 'end') column += 1 }) - Metamaps.Visualize.mGraph.animate(Metamaps.JIT.ForceDirected.animateSavedLayout) + Visualize.mGraph.animate(JIT.ForceDirected.animateSavedLayout) } else if (layout == 'radial') { var centerX = centerNode.getPos().x var centerY = centerNode.getPos().y @@ -87,16 +84,16 @@ const Organize = { }) } radial(centerNode, 1, 0) - Metamaps.Visualize.mGraph.animate(Metamaps.JIT.ForceDirected.animateSavedLayout) + Visualize.mGraph.animate(JIT.ForceDirected.animateSavedLayout) } else if (layout == 'center_viewport') { var lowX = 0, lowY = 0, highX = 0, highY = 0 - var oldOriginX = Metamaps.Visualize.mGraph.canvas.translateOffsetX - var oldOriginY = Metamaps.Visualize.mGraph.canvas.translateOffsetY + var oldOriginX = Visualize.mGraph.canvas.translateOffsetX + var oldOriginY = Visualize.mGraph.canvas.translateOffsetY - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + Visualize.mGraph.graph.eachNode(function (n) { if (n.id === 1) { lowX = n.getPos().x lowY = n.getPos().y diff --git a/frontend/src/Metamaps/PasteInput.js b/frontend/src/Metamaps/PasteInput.js index 9676e783..ebe1d944 100644 --- a/frontend/src/Metamaps/PasteInput.js +++ b/frontend/src/Metamaps/PasteInput.js @@ -1,12 +1,7 @@ -/* global Metamaps, $ */ +/* global $ */ -/* - * Metamaps.PasteInput.js.erb - * - * Dependencies: - * - Metamaps.Import - * - Metamaps.AutoLayout - */ +import AutoLayout from './AutoLayout' +import Import from './Import' const PasteInput = { // thanks to https://github.com/kevva/url-regex @@ -74,13 +69,13 @@ const PasteInput = { handleURL: function (text, coords) { var title = 'Link' if (!coords || !coords.x || !coords.y) { - coords = Metamaps.AutoLayout.getNextCoord() + coords = AutoLayout.getNextCoord() } var import_id = null // don't store a cidMapping var permission = null // use default - Metamaps.Import.createTopicWithParameters( + Import.createTopicWithParameters( title, 'Reference', // metacode - todo fix permission, @@ -101,11 +96,11 @@ const PasteInput = { }, handleJSON: function (text) { - Metamaps.Import.handleJSON(text) + Import.handleJSON(text) }, handleTSV: function (text) { - Metamaps.Import.handleTSV(text) + Import.handleTSV(text) } } From 8f100d99cb82bb3204f264fd6212619d7dbf9603 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 17:05:28 +0800 Subject: [PATCH 09/26] start to do stuff that may/may not work --- frontend/src/Metamaps/Active.js | 7 +++++++ frontend/src/Metamaps/Constants.js | 5 ----- frontend/src/Metamaps/index.js | 11 ++++++----- 3 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 frontend/src/Metamaps/Active.js diff --git a/frontend/src/Metamaps/Active.js b/frontend/src/Metamaps/Active.js new file mode 100644 index 00000000..c61a8bb9 --- /dev/null +++ b/frontend/src/Metamaps/Active.js @@ -0,0 +1,7 @@ +const Active = { + Map: null, + Topic: null, + Mapper: null +}; + +export default Active diff --git a/frontend/src/Metamaps/Constants.js b/frontend/src/Metamaps/Constants.js index ab62ba14..e887f24c 100644 --- a/frontend/src/Metamaps/Constants.js +++ b/frontend/src/Metamaps/Constants.js @@ -7,11 +7,6 @@ Metamaps.tempNode = null Metamaps.tempInit = false Metamaps.tempNode2 = null -Metamaps.Active = Metamaps.Active || { - Map: null, - Topic: null, - Mapper: null -}; Metamaps.Maps = Metamaps.Maps || {} diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 21d2af3a..598533c0 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -1,9 +1,9 @@ /* global $ */ -window.Metamaps = window.Metamaps || {} import './Constants' import Account from './Account' +import Active from './Active' import Admin from './Admin' import AutoLayout from './AutoLayout' import Backbone from './Backbone' @@ -32,6 +32,7 @@ import Visualize from './Visualize' import ReactComponents from './ReactComponents' Metamaps.Account = Account +Metamaps.Active = Active Metamaps.Admin = Admin Metamaps.AutoLayout = AutoLayout Metamaps.Backbone = Backbone @@ -59,9 +60,9 @@ Metamaps.Util = Util Metamaps.Views = Views Metamaps.Visualize = Visualize -$(document).ready(function () { +document.addEventListener("DOMContentLoaded", function() { // initialize all the modules - for (var prop in Metamaps) { + for (const prop in Metamaps) { // this runs the init function within each sub-object on the Metamaps one if (Metamaps.hasOwnProperty(prop) && Metamaps[prop] != null && @@ -73,7 +74,7 @@ $(document).ready(function () { } // load whichever page you are on if (Metamaps.currentSection === "explore") { - var capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1) + const capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1) Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ) if (Metamaps.currentPage === "mapper") { @@ -96,4 +97,4 @@ $(document).ready(function () { } }); -export default window.Metamaps +export default Metamaps From 9c1543de6467fb5eab9d059e111d4e533b6436c0 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 17:08:53 +0800 Subject: [PATCH 10/26] move some variables into JIT --- frontend/src/Metamaps/Constants.js | 5 --- frontend/src/Metamaps/JIT.js | 58 ++++++++++++++++-------------- frontend/src/Metamaps/Topic.js | 15 ++++---- 3 files changed, 37 insertions(+), 41 deletions(-) diff --git a/frontend/src/Metamaps/Constants.js b/frontend/src/Metamaps/Constants.js index e887f24c..9d0818ab 100644 --- a/frontend/src/Metamaps/Constants.js +++ b/frontend/src/Metamaps/Constants.js @@ -3,11 +3,6 @@ window.Metamaps = window.Metamaps || {} // TODO everything in this file should be moved into one of the other modules // Either as a local constant, or as a local constant with a globally available getter/setter -Metamaps.tempNode = null -Metamaps.tempInit = false -Metamaps.tempNode2 = null - - Metamaps.Maps = Metamaps.Maps || {} Metamaps.Settings = { diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index a93e3341..ec8195de 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -3,6 +3,10 @@ let panningInt const JIT = { + tempInit: false, + tempNode: null, + tempNode2: null, + events: { topicDrag: 'Metamaps:JIT:events:topicDrag', newTopic: 'Metamaps:JIT:events:newTopic', @@ -795,9 +799,9 @@ const JIT = { } // if it's a right click or holding down alt, start synapse creation ->third option is for firefox else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && authorized) { - if (Metamaps.tempInit == false) { - Metamaps.tempNode = node - Metamaps.tempInit = true + if (JIT.tempInit == false) { + JIT.tempNode = node + JIT.tempInit = true Metamaps.Create.newTopic.hide() Metamaps.Create.newSynapse.hide() @@ -813,8 +817,8 @@ const JIT = { } } else { Metamaps.Mouse.synapseStartCoordinates = [{ - x: Metamaps.tempNode.pos.getc().x, - y: Metamaps.tempNode.pos.getc().y + x: JIT.tempNode.pos.getc().x, + y: JIT.tempNode.pos.getc().y }] } Metamaps.Mouse.synapseEndCoordinates = { @@ -825,11 +829,11 @@ const JIT = { // let temp = eventInfo.getNode() if (temp != false && temp.id != node.id && Metamaps.Selected.Nodes.indexOf(temp) == -1) { // this means a Node has been returned - Metamaps.tempNode2 = temp + JIT.tempNode2 = temp Metamaps.Mouse.synapseEndCoordinates = { - x: Metamaps.tempNode2.pos.getc().x, - y: Metamaps.tempNode2.pos.getc().y + x: JIT.tempNode2.pos.getc().x, + y: JIT.tempNode2.pos.getc().y } // before making the highlighted one bigger, make sure all the others are regular size @@ -839,7 +843,7 @@ const JIT = { temp.setData('dim', 35, 'current') Metamaps.Visualize.mGraph.plot() } else if (!temp) { - Metamaps.tempNode2 = null + JIT.tempNode2 = null Metamaps.Visualize.mGraph.graph.eachNode(function (n) { n.setData('dim', 25, 'current') }) @@ -867,10 +871,10 @@ const JIT = { } }, // onDragMoveTopicHandler onDragCancelHandler: function (node, eventInfo, e) { - Metamaps.tempNode = null - if (Metamaps.tempNode2) Metamaps.tempNode2.setData('dim', 25, 'current') - Metamaps.tempNode2 = null - Metamaps.tempInit = false + JIT.tempNode = null + if (JIT.tempNode2) JIT.tempNode2.setData('dim', 25, 'current') + JIT.tempNode2 = null + JIT.tempInit = false // reset the draw synapse positions to false Metamaps.Mouse.synapseStartCoordinates = [] Metamaps.Mouse.synapseEndCoordinates = null @@ -879,27 +883,27 @@ const JIT = { onDragEndTopicHandler: function (node, eventInfo, e) { var midpoint = {}, pixelPos, mapping - if (Metamaps.tempInit && Metamaps.tempNode2 == null) { + if (JIT.tempInit && JIT.tempNode2 == null) { // this means you want to add a new topic, and then a synapse Metamaps.Create.newTopic.addSynapse = true Metamaps.Create.newTopic.open() - } else if (Metamaps.tempInit && Metamaps.tempNode2 != null) { + } else if (JIT.tempInit && JIT.tempNode2 != null) { // this means you want to create a synapse between two existing topics Metamaps.Create.newTopic.addSynapse = false - Metamaps.Create.newSynapse.topic1id = Metamaps.tempNode.getData('topic').id - Metamaps.Create.newSynapse.topic2id = Metamaps.tempNode2.getData('topic').id - Metamaps.tempNode2.setData('dim', 25, 'current') + Metamaps.Create.newSynapse.topic1id = JIT.tempNode.getData('topic').id + Metamaps.Create.newSynapse.topic2id = JIT.tempNode2.getData('topic').id + JIT.tempNode2.setData('dim', 25, 'current') Metamaps.Visualize.mGraph.plot() - midpoint.x = Metamaps.tempNode.pos.getc().x + (Metamaps.tempNode2.pos.getc().x - Metamaps.tempNode.pos.getc().x) / 2 - midpoint.y = Metamaps.tempNode.pos.getc().y + (Metamaps.tempNode2.pos.getc().y - Metamaps.tempNode.pos.getc().y) / 2 + midpoint.x = JIT.tempNode.pos.getc().x + (JIT.tempNode2.pos.getc().x - JIT.tempNode.pos.getc().x) / 2 + midpoint.y = JIT.tempNode.pos.getc().y + (JIT.tempNode2.pos.getc().y - JIT.tempNode.pos.getc().y) / 2 pixelPos = Metamaps.Util.coordsToPixels(midpoint) $('#new_synapse').css('left', pixelPos.x + 'px') $('#new_synapse').css('top', pixelPos.y + 'px') Metamaps.Create.newSynapse.open() - Metamaps.tempNode = null - Metamaps.tempNode2 = null - Metamaps.tempInit = false - } else if (!Metamaps.tempInit && node && !node.nodeFrom) { + JIT.tempNode = null + JIT.tempNode2 = null + JIT.tempInit = false + } else if (!JIT.tempInit && node && !node.nodeFrom) { // this means you dragged an existing node, autosave that to the database // check whether to save mappings @@ -977,9 +981,9 @@ const JIT = { // reset the draw synapse positions to false Metamaps.Mouse.synapseStartCoordinates = [] Metamaps.Mouse.synapseEndCoordinates = null - Metamaps.tempInit = false - Metamaps.tempNode = null - Metamaps.tempNode2 = null + JIT.tempInit = false + JIT.tempNode = null + JIT.tempNode2 = null if (!e.ctrlKey && !e.shiftKey) { Metamaps.Control.deselectAllEdges() Metamaps.Control.deselectAllNodes() diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index 8de14c34..0ebcc118 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -22,9 +22,6 @@ * - Metamaps.Topics * - Metamaps.Util * - Metamaps.Visualize - * - Metamaps.tempInit - * - Metamaps.tempNode - * - Metamaps.tempNode2 */ const Topic = { @@ -218,11 +215,11 @@ const Topic = { nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'end') } if (Metamaps.Create.newTopic.addSynapse && permitCreateSynapseAfter) { - Metamaps.Create.newSynapse.topic1id = Metamaps.tempNode.getData('topic').id + Metamaps.Create.newSynapse.topic1id = JIT.tempNode.getData('topic').id // position the form - midpoint.x = Metamaps.tempNode.pos.getc().x + (nodeOnViz.pos.getc().x - Metamaps.tempNode.pos.getc().x) / 2 - midpoint.y = Metamaps.tempNode.pos.getc().y + (nodeOnViz.pos.getc().y - Metamaps.tempNode.pos.getc().y) / 2 + midpoint.x = JIT.tempNode.pos.getc().x + (nodeOnViz.pos.getc().x - JIT.tempNode.pos.getc().x) / 2 + midpoint.y = JIT.tempNode.pos.getc().y + (nodeOnViz.pos.getc().y - JIT.tempNode.pos.getc().y) / 2 pixelPos = Metamaps.Util.coordsToPixels(midpoint) $('#new_synapse').css('left', pixelPos.x + 'px') $('#new_synapse').css('top', pixelPos.y + 'px') @@ -232,9 +229,9 @@ const Topic = { modes: ['node-property:dim'], duration: 500, onComplete: function () { - Metamaps.tempNode = null - Metamaps.tempNode2 = null - Metamaps.tempInit = false + JIT.tempNode = null + JIT.tempNode2 = null + JIT.tempInit = false } }) } else { From 8ed2b3ffc17d7206672853d0dedac7b8dacb64b2 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 17:14:34 +0800 Subject: [PATCH 11/26] remove Constants.js --- frontend/src/Metamaps/Constants.js | 56 ------------------------------ frontend/src/Metamaps/Mouse.js | 16 +++++++++ frontend/src/Metamaps/Selected.js | 11 ++++++ frontend/src/Metamaps/Settings.js | 21 +++++++++++ frontend/src/Metamaps/Visualize.js | 6 ++-- frontend/src/Metamaps/index.js | 9 +++-- 6 files changed, 58 insertions(+), 61 deletions(-) delete mode 100644 frontend/src/Metamaps/Constants.js create mode 100644 frontend/src/Metamaps/Mouse.js create mode 100644 frontend/src/Metamaps/Selected.js create mode 100644 frontend/src/Metamaps/Settings.js diff --git a/frontend/src/Metamaps/Constants.js b/frontend/src/Metamaps/Constants.js deleted file mode 100644 index 9d0818ab..00000000 --- a/frontend/src/Metamaps/Constants.js +++ /dev/null @@ -1,56 +0,0 @@ -window.Metamaps = window.Metamaps || {} - -// TODO everything in this file should be moved into one of the other modules -// Either as a local constant, or as a local constant with a globally available getter/setter - -Metamaps.Maps = Metamaps.Maps || {} - -Metamaps.Settings = { - embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages - sandbox: false, // puts the app into a mode (when true) where it only creates data locally, and isn't writing it to the database - colors: { - background: '#344A58', - synapses: { - normal: '#888888', - hover: '#888888', - selected: '#FFFFFF' - }, - topics: { - selected: '#FFFFFF' - }, - labels: { - background: '#18202E', - text: '#DDD' - } - }, -} - -Metamaps.Touch = { - touchPos: null, // this stores the x and y values of a current touch event - touchDragNode: null // this stores a reference to a JIT node that is being dragged -} - -Metamaps.Mouse = { - didPan: false, - didBoxZoom: false, - changeInX: 0, - changeInY: 0, - edgeHoveringOver: false, - boxStartCoordinates: false, - boxEndCoordinates: false, - synapseStartCoordinates: [], - synapseEndCoordinates: null, - lastNodeClick: 0, - lastCanvasClick: 0, - DOUBLE_CLICK_TOLERANCE: 300 -} - -Metamaps.Selected = { - reset: function () { - var self = Metamaps.Selected - self.Nodes = [] - self.Edges = [] - }, - Nodes: [], - Edges: [] -} diff --git a/frontend/src/Metamaps/Mouse.js b/frontend/src/Metamaps/Mouse.js new file mode 100644 index 00000000..9989bc20 --- /dev/null +++ b/frontend/src/Metamaps/Mouse.js @@ -0,0 +1,16 @@ +const Mouse = { + didPan: false, + didBoxZoom: false, + changeInX: 0, + changeInY: 0, + edgeHoveringOver: false, + boxStartCoordinates: false, + boxEndCoordinates: false, + synapseStartCoordinates: [], + synapseEndCoordinates: null, + lastNodeClick: 0, + lastCanvasClick: 0, + DOUBLE_CLICK_TOLERANCE: 300 +} + +export default Mouse diff --git a/frontend/src/Metamaps/Selected.js b/frontend/src/Metamaps/Selected.js new file mode 100644 index 00000000..396270ab --- /dev/null +++ b/frontend/src/Metamaps/Selected.js @@ -0,0 +1,11 @@ +const Selected = { + reset: function () { + var self = Metamaps.Selected + self.Nodes = [] + self.Edges = [] + }, + Nodes: [], + Edges: [] +} + +export default Selected diff --git a/frontend/src/Metamaps/Settings.js b/frontend/src/Metamaps/Settings.js new file mode 100644 index 00000000..687a6629 --- /dev/null +++ b/frontend/src/Metamaps/Settings.js @@ -0,0 +1,21 @@ +const Settings = { + embed: false, // indicates that the app is on a page that is optimized for embedding in iFrames on other web pages + sandbox: false, // puts the app into a mode (when true) where it only creates data locally, and isn't writing it to the database + colors: { + background: '#344A58', + synapses: { + normal: '#888888', + hover: '#888888', + selected: '#FFFFFF' + }, + topics: { + selected: '#FFFFFF' + }, + labels: { + background: '#18202E', + text: '#DDD' + } + }, +} + +export default Settings diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index 5e99519f..4aa65772 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -11,7 +11,6 @@ * - Metamaps.Synapses * - Metamaps.TopicCard * - Metamaps.Topics - * - Metamaps.Touch */ const Visualize = { @@ -19,6 +18,7 @@ const Visualize = { cameraPosition: null, // stores the camera position when using a 3D visualization type: 'ForceDirected', // the type of graph we're building, could be "RGraph", "ForceDirected", or "ForceDirected3D" loadLater: false, // indicates whether there is JSON that should be loaded right in the offset, or whether to wait till the first topic is created + touchDragNode: null, init: function () { var self = Visualize // disable awkward dragging of the canvas element that would sometimes happen @@ -40,9 +40,9 @@ const Visualize = { // prevent touch events on the canvas from default behaviour $('#infovis-canvas').bind('touchend touchcancel', function (event) { lastDist = 0 - if (!self.mGraph.events.touchMoved && !Metamaps.Touch.touchDragNode) Metamaps.TopicCard.hideCurrentCard() + if (!self.mGraph.events.touchMoved && !Visualize.touchDragNode) Metamaps.TopicCard.hideCurrentCard() self.mGraph.events.touched = self.mGraph.events.touchMoved = false - Metamaps.Touch.touchDragNode = false + Visualize.touchDragNode = false }) }, computePositions: function () { diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 598533c0..37e93492 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -1,7 +1,5 @@ /* global $ */ -import './Constants' - import Account from './Account' import Active from './Active' import Admin from './Admin' @@ -18,10 +16,13 @@ import Listeners from './Listeners' import Map from './Map' import Mapper from './Mapper' import Mobile from './Mobile' +import Mouse from './Mouse' import Organize from './Organize' import PasteInput from './PasteInput' import Realtime from './Realtime' import Router from './Router' +import Selected from './Selected' +import Settings from './Settings' import Synapse from './Synapse' import SynapseCard from './SynapseCard' import Topic from './Topic' @@ -45,13 +46,17 @@ Metamaps.Import = Import Metamaps.JIT = JIT Metamaps.Listeners = Listeners Metamaps.Map = Map +Metamaps.Maps = {} Metamaps.Mapper = Mapper Metamaps.Mobile = Mobile +Metamaps.Mouse = Mouse Metamaps.Organize = Organize Metamaps.PasteInput = PasteInput Metamaps.Realtime = Realtime Metamaps.ReactComponents = ReactComponents Metamaps.Router = Router +Metamaps.Selected = Selected +Metamaps.Settings = Settings Metamaps.Synapse = Synapse Metamaps.SynapseCard = SynapseCard Metamaps.Topic = Topic From 0065b201c7b12c7eb7d76db7a33ee225e6e87094 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 17:36:47 +0800 Subject: [PATCH 12/26] make more code modular --- frontend/src/Metamaps/Control.js | 187 ++++++++++++++------------- frontend/src/Metamaps/Create.js | 26 ++-- frontend/src/Metamaps/Filter.js | 25 ++-- frontend/src/Metamaps/Import.js | 13 +- frontend/src/Metamaps/Mobile.js | 15 +-- frontend/src/Metamaps/SynapseCard.js | 35 +++-- frontend/src/Metamaps/Topic.js | 37 +++--- frontend/src/Metamaps/TopicCard.js | 25 ++-- frontend/src/Metamaps/Views.js | 10 +- frontend/src/Metamaps/Visualize.js | 48 +++---- 10 files changed, 209 insertions(+), 212 deletions(-) diff --git a/frontend/src/Metamaps/Control.js b/frontend/src/Metamaps/Control.js index b9df0d2c..3eecb126 100644 --- a/frontend/src/Metamaps/Control.js +++ b/frontend/src/Metamaps/Control.js @@ -1,21 +1,22 @@ /* global Metamaps, $ */ +import Active from './Active' +import Filter from './Filter' +import JIT from './JIT' +import Mouse from './Mouse' +import Selected from './Selected' +import Settings from './Settings' +import Visualize from './Visualize' + /* * Metamaps.Control.js * * Dependencies: - * - Metamaps.Active - * - Metamaps.Filter * - Metamaps.GlobalUI - * - Metamaps.JIT * - Metamaps.Mappings * - Metamaps.Metacodes - * - Metamaps.Mouse - * - Metamaps.Selected - * - Metamaps.Settings * - Metamaps.Synapses * - Metamaps.Topics - * - Metamaps.Visualize */ const Control = { @@ -23,37 +24,37 @@ const Control = { selectNode: function (node, e) { var filtered = node.getData('alpha') === 0 - if (filtered || Metamaps.Selected.Nodes.indexOf(node) != -1) return + if (filtered || Selected.Nodes.indexOf(node) != -1) return node.selected = true node.setData('dim', 30, 'current') - Metamaps.Selected.Nodes.push(node) + Selected.Nodes.push(node) }, deselectAllNodes: function () { - var l = Metamaps.Selected.Nodes.length + var l = Selected.Nodes.length for (var i = l - 1; i >= 0; i -= 1) { - var node = Metamaps.Selected.Nodes[i] + var node = Selected.Nodes[i] Control.deselectNode(node) } - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() }, deselectNode: function (node) { delete node.selected node.setData('dim', 25, 'current') // remove the node - Metamaps.Selected.Nodes.splice( - Metamaps.Selected.Nodes.indexOf(node), 1) + Selected.Nodes.splice( + Selected.Nodes.indexOf(node), 1) }, deleteSelected: function () { - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var n = Metamaps.Selected.Nodes.length - var e = Metamaps.Selected.Edges.length + var n = Selected.Nodes.length + var e = Selected.Edges.length var ntext = n == 1 ? '1 topic' : n + ' topics' var etext = e == 1 ? '1 synapse' : e + ' synapses' var text = 'You have ' + ntext + ' and ' + etext + ' selected. ' - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') @@ -67,41 +68,41 @@ const Control = { } }, deleteSelectedNodes: function () { // refers to deleting topics permanently - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') return } - var l = Metamaps.Selected.Nodes.length + var l = Selected.Nodes.length for (var i = l - 1; i >= 0; i -= 1) { - var node = Metamaps.Selected.Nodes[i] + var node = Selected.Nodes[i] Control.deleteNode(node.id) } }, deleteNode: function (nodeid) { // refers to deleting topics permanently - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') return } - var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid) + var node = Visualize.mGraph.graph.getNode(nodeid) var topic = node.getData('topic') - var permToDelete = Metamaps.Active.Mapper.id === topic.get('user_id') || Metamaps.Active.Mapper.get('admin') + var permToDelete = Active.Mapper.id === topic.get('user_id') || Active.Mapper.get('admin') if (permToDelete) { var mappableid = topic.id var mapping = node.getData('mapping') topic.destroy() Metamaps.Mappings.remove(mapping) - $(document).trigger(Metamaps.JIT.events.deleteTopic, [{ + $(document).trigger(JIT.events.deleteTopic, [{ mappableid: mappableid }]) Control.hideNode(nodeid) @@ -110,25 +111,25 @@ const Control = { } }, removeSelectedNodes: function () { // refers to removing topics permanently from a map - if (Metamaps.Active.Topic) { + if (Active.Topic) { // hideNode will handle synapses as well - var nodeids = _.map(Metamaps.Selected.Nodes, function(node) { + var nodeids = _.map(Selected.Nodes, function(node) { return node.id }) _.each(nodeids, function(nodeid) { - if (Metamaps.Active.Topic.id !== nodeid) { + if (Active.Topic.id !== nodeid) { Metamaps.Topics.remove(nodeid) Control.hideNode(nodeid) } }) return } - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var l = Metamaps.Selected.Nodes.length, + var l = Selected.Nodes.length, i, node, - authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') @@ -136,15 +137,15 @@ const Control = { } for (i = l - 1; i >= 0; i -= 1) { - node = Metamaps.Selected.Nodes[i] + node = Selected.Nodes[i] Control.removeNode(node.id) } }, removeNode: function (nodeid) { // refers to removing topics permanently from a map - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) - var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) + var node = Visualize.mGraph.graph.getNode(nodeid) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') @@ -156,24 +157,24 @@ const Control = { var mapping = node.getData('mapping') mapping.destroy() Metamaps.Topics.remove(topic) - $(document).trigger(Metamaps.JIT.events.removeTopic, [{ + $(document).trigger(JIT.events.removeTopic, [{ mappableid: mappableid }]) Control.hideNode(nodeid) }, hideSelectedNodes: function () { - var l = Metamaps.Selected.Nodes.length, + var l = Selected.Nodes.length, i, node for (i = l - 1; i >= 0; i -= 1) { - node = Metamaps.Selected.Nodes[i] + node = Selected.Nodes[i] Control.hideNode(node.id) } }, hideNode: function (nodeid) { - var node = Metamaps.Visualize.mGraph.graph.getNode(nodeid) - var graph = Metamaps.Visualize.mGraph + var node = Visualize.mGraph.graph.getNode(nodeid) + var graph = Visualize.mGraph Control.deselectNode(node) @@ -181,73 +182,73 @@ const Control = { node.eachAdjacency(function (adj) { adj.setData('alpha', 0, 'end') }) - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.animate({ modes: ['node-property:alpha', 'edge-property:alpha' ], duration: 500 }) setTimeout(function () { - if (nodeid == Metamaps.Visualize.mGraph.root) { // && Metamaps.Visualize.type === "RGraph" + if (nodeid == Visualize.mGraph.root) { // && Visualize.type === "RGraph" var newroot = _.find(graph.graph.nodes, function (n) { return n.id !== nodeid; }) graph.root = newroot ? newroot.id : null } - Metamaps.Visualize.mGraph.graph.removeNode(nodeid) + Visualize.mGraph.graph.removeNode(nodeid) }, 500) - Metamaps.Filter.checkMetacodes() - Metamaps.Filter.checkMappers() + Filter.checkMetacodes() + Filter.checkMappers() }, selectEdge: function (edge) { var filtered = edge.getData('alpha') === 0; // don't select if the edge is filtered - if (filtered || Metamaps.Selected.Edges.indexOf(edge) != -1) return + if (filtered || Selected.Edges.indexOf(edge) != -1) return - var width = Metamaps.Mouse.edgeHoveringOver === edge ? 4 : 2 + var width = Mouse.edgeHoveringOver === edge ? 4 : 2 edge.setDataset('current', { showDesc: true, lineWidth: width, - color: Metamaps.Settings.colors.synapses.selected + color: Settings.colors.synapses.selected }) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() - Metamaps.Selected.Edges.push(edge) + Selected.Edges.push(edge) }, deselectAllEdges: function () { - var l = Metamaps.Selected.Edges.length + var l = Selected.Edges.length for (var i = l - 1; i >= 0; i -= 1) { - var edge = Metamaps.Selected.Edges[i] + var edge = Selected.Edges[i] Control.deselectEdge(edge) } - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() }, deselectEdge: function (edge) { edge.setData('showDesc', false, 'current') edge.setDataset('current', { lineWidth: 2, - color: Metamaps.Settings.colors.synapses.normal + color: Settings.colors.synapses.normal }) - if (Metamaps.Mouse.edgeHoveringOver == edge) { + if (Mouse.edgeHoveringOver == edge) { edge.setDataset('current', { showDesc: true, lineWidth: 4 }) } - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() // remove the edge - Metamaps.Selected.Edges.splice( - Metamaps.Selected.Edges.indexOf(edge), 1) + Selected.Edges.splice( + Selected.Edges.indexOf(edge), 1) }, deleteSelectedEdges: function () { // refers to deleting topics permanently var edge, - l = Metamaps.Selected.Edges.length + l = Selected.Edges.length - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') @@ -255,14 +256,14 @@ const Control = { } for (var i = l - 1; i >= 0; i -= 1) { - edge = Metamaps.Selected.Edges[i] + edge = Selected.Edges[i] Control.deleteEdge(edge) } }, deleteEdge: function (edge) { - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') @@ -274,7 +275,7 @@ const Control = { var synapse = edge.getData('synapses')[index] var mapping = edge.getData('mappings')[index] - var permToDelete = Metamaps.Active.Mapper.id === synapse.get('user_id') || Metamaps.Active.Mapper.get('admin') + var permToDelete = Active.Mapper.id === synapse.get('user_id') || Active.Mapper.get('admin') if (permToDelete) { if (edge.getData('synapses').length - 1 === 0) { Control.hideEdge(edge) @@ -289,7 +290,7 @@ const Control = { if (edge.getData('displayIndex')) { delete edge.data.$displayIndex } - $(document).trigger(Metamaps.JIT.events.deleteSynapse, [{ + $(document).trigger(JIT.events.deleteSynapse, [{ mappableid: mappableid }]) } else { @@ -298,13 +299,13 @@ const Control = { }, removeSelectedEdges: function () { // Topic view is handled by removeSelectedNodes - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var l = Metamaps.Selected.Edges.length, + var l = Selected.Edges.length, i, edge - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') @@ -312,15 +313,15 @@ const Control = { } for (i = l - 1; i >= 0; i -= 1) { - edge = Metamaps.Selected.Edges[i] + edge = Selected.Edges[i] Control.removeEdge(edge) } - Metamaps.Selected.Edges = [ ] + Selected.Edges = [ ] }, removeEdge: function (edge) { - if (!Metamaps.Active.Map) return + if (!Active.Map) return - var authorized = Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') @@ -345,34 +346,34 @@ const Control = { if (edge.getData('displayIndex')) { delete edge.data.$displayIndex } - $(document).trigger(Metamaps.JIT.events.removeSynapse, [{ + $(document).trigger(JIT.events.removeSynapse, [{ mappableid: mappableid }]) }, hideSelectedEdges: function () { var edge, - l = Metamaps.Selected.Edges.length, + l = Selected.Edges.length, i for (i = l - 1; i >= 0; i -= 1) { - edge = Metamaps.Selected.Edges[i] + edge = Selected.Edges[i] Control.hideEdge(edge) } - Metamaps.Selected.Edges = [ ] + Selected.Edges = [ ] }, hideEdge: function (edge) { var from = edge.nodeFrom.id var to = edge.nodeTo.id edge.setData('alpha', 0, 'end') Control.deselectEdge(edge) - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.animate({ modes: ['edge-property:alpha'], duration: 500 }) setTimeout(function () { - Metamaps.Visualize.mGraph.graph.removeAdjacence(from, to) + Visualize.mGraph.graph.removeAdjacence(from, to) }, 500) - Metamaps.Filter.checkSynapses() - Metamaps.Filter.checkMappers() + Filter.checkSynapses() + Filter.checkMappers() }, updateSelectedPermissions: function (permission) { var edge, synapse, node, topic @@ -384,12 +385,12 @@ const Control = { sCount = 0 // change the permission of the selected synapses, if logged in user is the original creator - var l = Metamaps.Selected.Edges.length + var l = Selected.Edges.length for (var i = l - 1; i >= 0; i -= 1) { - edge = Metamaps.Selected.Edges[i] + edge = Selected.Edges[i] synapse = edge.getData('synapses')[0] - if (synapse.authorizePermissionChange(Metamaps.Active.Mapper)) { + if (synapse.authorizePermissionChange(Active.Mapper)) { synapse.save({ permission: permission }) @@ -398,12 +399,12 @@ const Control = { } // change the permission of the selected topics, if logged in user is the original creator - var l = Metamaps.Selected.Nodes.length + var l = Selected.Nodes.length for (var i = l - 1; i >= 0; i -= 1) { - node = Metamaps.Selected.Nodes[i] + node = Selected.Nodes[i] topic = node.getData('topic') - if (topic.authorizePermissionChange(Metamaps.Active.Mapper)) { + if (topic.authorizePermissionChange(Active.Mapper)) { topic.save({ permission: permission }) @@ -428,12 +429,12 @@ const Control = { var nCount = 0 // change the permission of the selected topics, if logged in user is the original creator - var l = Metamaps.Selected.Nodes.length + var l = Selected.Nodes.length for (var i = l - 1; i >= 0; i -= 1) { - node = Metamaps.Selected.Nodes[i] + node = Selected.Nodes[i] topic = node.getData('topic') - if (topic.authorizeToEdit(Metamaps.Active.Mapper)) { + if (topic.authorizeToEdit(Active.Mapper)) { topic.save({ 'metacode_id': metacode_id }) @@ -445,7 +446,7 @@ const Control = { var message = nString + ' you can edit updated to ' + metacode.get('name') Metamaps.GlobalUI.notifyUser(message) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() }, } diff --git a/frontend/src/Metamaps/Create.js b/frontend/src/Metamaps/Create.js index 1348e9d2..49267d6d 100644 --- a/frontend/src/Metamaps/Create.js +++ b/frontend/src/Metamaps/Create.js @@ -1,6 +1,11 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, $ */ +import Mouse from './Mouse' +import Selected from './Selected' +import Synapse from './Synapse' +import Topic from './Topic' +import Visualize from './Visualize' + /* * Metamaps.Create.js * @@ -8,11 +13,6 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Backbone * - Metamaps.GlobalUI * - Metamaps.Metacodes - * - Metamaps.Mouse - * - Metamaps.Selected - * - Metamaps.Synapse - * - Metamaps.Topic - * - Metamaps.Visualize */ const Create = { @@ -193,7 +193,7 @@ const Create = { // tell the autocomplete to submit the form with the topic you clicked on if you pick from the autocomplete $('#topic_name').bind('typeahead:select', function (event, datum, dataset) { - Metamaps.Topic.getTopicFromAutocomplete(datum.id) + Topic.getTopicFromAutocomplete(datum.id) }) // initialize metacode spinner and then hide it @@ -255,7 +255,7 @@ const Create = { url: '/search/synapses?topic1id=%TOPIC1&topic2id=%TOPIC2', prepare: function (query, settings) { var self = Create.newSynapse - if (Metamaps.Selected.Nodes.length < 2) { + if (Selected.Nodes.length < 2) { settings.url = settings.url.replace('%TOPIC1', self.topic1id).replace('%TOPIC2', self.topic2id) return settings } else { @@ -307,16 +307,16 @@ const Create = { $('#synapse_desc').focusout(function () { if (Create.newSynapse.beingCreated) { - Metamaps.Synapse.createSynapseLocally() + Synapse.createSynapseLocally() } }) $('#synapse_desc').bind('typeahead:select', function (event, datum, dataset) { if (datum.id) { // if they clicked on an existing synapse get it - Metamaps.Synapse.getSynapseFromAutocomplete(datum.id) + Synapse.getSynapseFromAutocomplete(datum.id) } else { Create.newSynapse.description = datum.value - Metamaps.Synapse.createSynapseLocally() + Synapse.createSynapseLocally() } }) }, @@ -338,8 +338,8 @@ const Create = { Create.newTopic.addSynapse = false Create.newSynapse.topic1id = 0 Create.newSynapse.topic2id = 0 - Metamaps.Mouse.synapseStartCoordinates = [] - Metamaps.Visualize.mGraph.plot() + Mouse.synapseStartCoordinates = [] + Visualize.mGraph.plot() }, } } diff --git a/frontend/src/Metamaps/Filter.js b/frontend/src/Metamaps/Filter.js index cc21f7e2..aed9964d 100644 --- a/frontend/src/Metamaps/Filter.js +++ b/frontend/src/Metamaps/Filter.js @@ -1,19 +1,20 @@ /* global Metamaps, $ */ +import Active from './Active' +import Control from './Control' +import Settings from './Settings' +import Visualize from './Visualize' + /* * Metamaps.Filter.js.erb * * Dependencies: - * - Metamaps.Active - * - Metamaps.Control * - Metamaps.Creators * - Metamaps.GlobalUI * - Metamaps.Mappers * - Metamaps.Metacodes - * - Metamaps.Settings * - Metamaps.Synapses * - Metamaps.Topics - * - Metamaps.Visualize */ const Filter = { filters: { @@ -216,7 +217,7 @@ const Filter = { }, checkMappers: function () { var self = Filter - var onMap = Metamaps.Active.Map ? true : false + var onMap = Active.Map ? true : false if (onMap) { self.updateFilters('Mappings', 'user_id', 'Mappers', 'mappers', 'mapper') } else { @@ -347,10 +348,10 @@ const Filter = { var passesMetacode, passesMapper, passesSynapse var onMap - if (Metamaps.Active.Map) { + if (Active.Map) { onMap = true } - else if (Metamaps.Active.Topic) { + else if (Active.Topic) { onMap = false } @@ -386,10 +387,10 @@ const Filter = { else console.log(topic) } else { if (n) { - Metamaps.Control.deselectNode(n, true) + Control.deselectNode(n, true) n.setData('alpha', opacityForFilter, 'end') n.eachAdjacency(function (e) { - Metamaps.Control.deselectEdge(e, true) + Control.deselectEdge(e, true) }) } else console.log(topic) @@ -442,12 +443,12 @@ const Filter = { if (visible.mappers.indexOf(user_id) == -1) passesMapper = false else passesMapper = true - var color = Metamaps.Settings.colors.synapses.normal + var color = Settings.colors.synapses.normal if (passesSynapse && passesMapper) { e.setData('alpha', 1, 'end') e.setData('color', color, 'end') } else { - Metamaps.Control.deselectEdge(e, true) + Control.deselectEdge(e, true) e.setData('alpha', opacityForFilter, 'end') } @@ -457,7 +458,7 @@ const Filter = { }) // run the animation - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.animate({ modes: ['node-property:alpha', 'edge-property:alpha'], duration: 200 diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index e963ca32..bc0bab30 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -1,12 +1,13 @@ /* global Metamaps, $ */ +import Active from './Active' +import Map from './Map' + /* * Metamaps.Import.js.erb * * Dependencies: - * - Metamaps.Active * - Metamaps.Backbone - * - Metamaps.Map * - Metamaps.Mappings * - Metamaps.Metacodes * - Metamaps.Synapses @@ -256,15 +257,15 @@ const Import = { createTopicWithParameters: function (name, metacode_name, permission, desc, link, xloc, yloc, import_id, opts) { var self = Import - $(document).trigger(Metamaps.Map.events.editedByActiveMapper) + $(document).trigger(Map.events.editedByActiveMapper) var metacode = Metamaps.Metacodes.where({name: metacode_name})[0] || null if (metacode === null) { metacode = Metamaps.Metacodes.where({ name: 'Wildcard' })[0] console.warn("Couldn't find metacode " + metacode_name + ' so used Wildcard instead.') } - var topic_permission = permission || Metamaps.Active.Map.get('permission') - var defer_to_map_id = permission === topic_permission ? Metamaps.Active.Map.get('id') : null + var topic_permission = permission || Active.Map.get('permission') + var defer_to_map_id = permission === topic_permission ? Active.Map.get('id') : null var topic = new Metamaps.Backbone.Topic({ name: name, metacode_id: metacode.id, @@ -272,7 +273,7 @@ const Import = { defer_to_map_id: defer_to_map_id, desc: desc || "", link: link || "", - calculated_permission: Metamaps.Active.Map.get('permission') + calculated_permission: Active.Map.get('permission') }) Metamaps.Topics.add(topic) diff --git a/frontend/src/Metamaps/Mobile.js b/frontend/src/Metamaps/Mobile.js index 9074f521..fddd90a4 100644 --- a/frontend/src/Metamaps/Mobile.js +++ b/frontend/src/Metamaps/Mobile.js @@ -1,12 +1,7 @@ -/* global Metamaps, $ */ +/* global $ */ -/* - * Metamaps.Mobile.js - * - * Dependencies: - * - Metamaps.Active - * - Metamaps.Map - */ +import Active from './Active' +import Map from './Map' const Mobile = { init: function () { @@ -30,8 +25,8 @@ const Mobile = { $('#mobile_menu').toggle() }, titleClick: function () { - if (Metamaps.Active.Map) { - Metamaps.Map.InfoBox.open() + if (Active.Map) { + Map.InfoBox.open() } } } diff --git a/frontend/src/Metamaps/SynapseCard.js b/frontend/src/Metamaps/SynapseCard.js index 93ebb646..e0315486 100644 --- a/frontend/src/Metamaps/SynapseCard.js +++ b/frontend/src/Metamaps/SynapseCard.js @@ -1,14 +1,9 @@ /* global Metamaps, $ */ +import Active from './Active' +import Control from './Control' +import Mapper from './Mapper' +import Visualize from './Visualize' -/* - * Metamaps.SynapseCard.js - * - * Dependencies: - * - Metamaps.Active - * - Metamaps.Control - * - Metamaps.Mapper - * - Metamaps.Visualize - */ const SynapseCard = { openSynapseCard: null, showCard: function (edge, e) { @@ -20,7 +15,7 @@ const SynapseCard = { $('#edit_synapse').remove() // so label is missing while editing - Metamaps.Control.deselectEdge(edge) + Control.deselectEdge(edge) var index = edge.getData('displayIndex') ? edge.getData('displayIndex') : 0 var synapse = edge.getData('synapses')[index]; // for now, just get the first synapse @@ -30,9 +25,9 @@ const SynapseCard = { var edit_div = document.createElement('div') edit_div.innerHTML = '
    ' edit_div.setAttribute('id', 'edit_synapse') - if (synapse.authorizeToEdit(Metamaps.Active.Mapper)) { + if (synapse.authorizeToEdit(Active.Mapper)) { edit_div.className = 'permission canEdit' - edit_div.className += synapse.authorizePermissionChange(Metamaps.Active.Mapper) ? ' yourEdge' : '' + edit_div.className += synapse.authorizePermissionChange(Active.Mapper) ? ' yourEdge' : '' } else { edit_div.className = 'permission cannotEdit' } @@ -94,7 +89,7 @@ const SynapseCard = { // if edge data is blank or just whitespace, populate it with data_nil if ($('#edit_synapse_desc').html().trim() == '') { - if (synapse.authorizeToEdit(Metamaps.Active.Mapper)) { + if (synapse.authorizeToEdit(Active.Mapper)) { $('#edit_synapse_desc').html(data_nil) } else { $('#edit_synapse_desc').html('(no description)') @@ -109,8 +104,8 @@ const SynapseCard = { synapse.set('desc', desc) } synapse.trigger('saved') - Metamaps.Control.selectEdge(synapse.get('edge')) - Metamaps.Visualize.mGraph.plot() + Control.selectEdge(synapse.get('edge')) + Visualize.mGraph.plot() }) }, add_drop_down: function (edge, synapse) { @@ -152,7 +147,7 @@ const SynapseCard = { e.stopPropagation() var index = parseInt($(this).attr('data-synapse-index')) edge.setData('displayIndex', index) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() SynapseCard.showCard(edge, false) }) } @@ -167,7 +162,7 @@ const SynapseCard = { var setMapperImage = function (mapper) { $('#edgeUser img').attr('src', mapper.get('image')) } - Metamaps.Mapper.get(synapse.get('user_id'), setMapperImage) + Mapper.get(synapse.get('user_id'), setMapperImage) }, add_perms_form: function (synapse) { @@ -210,7 +205,7 @@ const SynapseCard = { $('#edit_synapse .permissionSelect').remove() } - if (synapse.authorizePermissionChange(Metamaps.Active.Mapper)) { + if (synapse.authorizePermissionChange(Active.Mapper)) { $('#edit_synapse.yourEdge .mapPerm').click(openPermissionSelect) $('#edit_synapse').click(hidePermissionSelect) } @@ -257,7 +252,7 @@ const SynapseCard = { $('#edit_synapse_right').addClass('checked') } - if (synapse.authorizeToEdit(Metamaps.Active.Mapper)) { + if (synapse.authorizeToEdit(Active.Mapper)) { $('#edit_synapse_left, #edit_synapse_right').click(function () { $(this).toggleClass('checked') @@ -281,7 +276,7 @@ const SynapseCard = { node1_id: dir[0], node2_id: dir[1] }) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() }) } // if } // add_direction_form diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index 0ebcc118..ab93e419 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -1,26 +1,25 @@ /* global Metamaps, $ */ +import Active from './Active' +import JIT from './JIT' +import Selected from './Selected' +import Settings from './Settings' +import Util from './Util' + /* * Metamaps.Topic.js.erb * * Dependencies: - * - Metamaps.Active - * - Metamaps.Backbone * - Metamaps.Backbone * - Metamaps.Create * - Metamaps.Creators - * - Metamaps.Famous * - Metamaps.Filter * - Metamaps.GlobalUI - * - Metamaps.JIT * - Metamaps.Mappings - * - Metamaps.Selected - * - Metamaps.Settings * - Metamaps.SynapseCard * - Metamaps.Synapses * - Metamaps.TopicCard * - Metamaps.Topics - * - Metamaps.Util * - Metamaps.Visualize */ @@ -58,7 +57,7 @@ const Topic = { launch: function (id) { var bb = Metamaps.Backbone var start = function (data) { - Metamaps.Active.Topic = new bb.Topic(data.topic) + Active.Topic = new bb.Topic(data.topic) Metamaps.Creators = new bb.MapperCollection(data.creators) Metamaps.Topics = new bb.TopicCollection([data.topic].concat(data.relatives)) Metamaps.Synapses = new bb.SynapseCollection(data.synapses) @@ -69,13 +68,13 @@ const Topic = { // build and render the visualization Metamaps.Visualize.type = 'RGraph' - Metamaps.JIT.prepareVizData() + JIT.prepareVizData() // update filters Metamaps.Filter.reset() // reset selected arrays - Metamaps.Selected.reset() + Selected.reset() // these three update the actual filter box with the right list items Metamaps.Filter.checkMetacodes() @@ -83,7 +82,7 @@ const Topic = { Metamaps.Filter.checkMappers() // for mobile - $('#header_content').html(Metamaps.Active.Topic.get('name')) + $('#header_content').html(Active.Topic.get('name')) } $.ajax({ @@ -92,7 +91,7 @@ const Topic = { }) }, end: function () { - if (Metamaps.Active.Topic) { + if (Active.Topic) { $('.rightclickmenu').remove() Metamaps.TopicCard.hideCard() Metamaps.SynapseCard.hideCard() @@ -110,7 +109,7 @@ const Topic = { } }) Metamaps.Router.navigate('/topics/' + nodeid) - Metamaps.Active.Topic = Metamaps.Topics.get(nodeid) + Active.Topic = Metamaps.Topics.get(nodeid) } }, fetchRelatives: function (nodes, metacode_id) { @@ -141,7 +140,7 @@ const Topic = { topicColl.add(topic) var synapseColl = new Metamaps.Backbone.SynapseCollection(data.synapses) - var graph = Metamaps.JIT.convertModelsToJIT(topicColl, synapseColl)[0] + var graph = JIT.convertModelsToJIT(topicColl, synapseColl)[0] Metamaps.Visualize.mGraph.op.sum(graph, { type: 'fade', duration: 500, @@ -267,14 +266,14 @@ const Topic = { mappableid: mappingModel.get('mappable_id') } - $(document).trigger(Metamaps.JIT.events.newTopic, [newTopicData]) + $(document).trigger(JIT.events.newTopic, [newTopicData]) // call a success callback if provided if (opts.success) { opts.success(topicModel) } } var topicSuccessCallback = function (topicModel, response) { - if (Metamaps.Active.Map) { + if (Active.Map) { mapping.save({ mappable_id: topicModel.id }, { success: function (model, response) { mappingSuccessCallback(model, response, topicModel) @@ -290,7 +289,7 @@ const Topic = { } } - if (!Metamaps.Settings.sandbox && createNewInDB) { + if (!Settings.sandbox && createNewInDB) { if (topic.isNew()) { topic.save(null, { success: topicSuccessCallback, @@ -298,7 +297,7 @@ const Topic = { console.log('error saving topic to database') } }) - } else if (!topic.isNew() && Metamaps.Active.Map) { + } else if (!topic.isNew() && Active.Map) { mapping.save(null, { success: mappingSuccessCallback }) @@ -323,7 +322,7 @@ const Topic = { var topic = new Metamaps.Backbone.Topic({ name: Metamaps.Create.newTopic.name, metacode_id: metacode.id, - defer_to_map_id: Metamaps.Active.Map.id + defer_to_map_id: Active.Map.id }) Metamaps.Topics.add(topic) diff --git a/frontend/src/Metamaps/TopicCard.js b/frontend/src/Metamaps/TopicCard.js index 5a7f1920..ebc79575 100644 --- a/frontend/src/Metamaps/TopicCard.js +++ b/frontend/src/Metamaps/TopicCard.js @@ -1,16 +1,17 @@ /* global Metamaps, $ */ +import Active from './Active' +import Mapper from './Mapper' +import Util from './Util' +import Visualize from './Visualize' + /* * Metamaps.TopicCard.js * * Dependencies: - * - Metamaps.Active * - Metamaps.GlobalUI - * - Metamaps.Mapper * - Metamaps.Metacodes * - Metamaps.Router - * - Metamaps.Util - * - Metamaps.Visualize */ const TopicCard = { openTopicCard: null, // stores the topic that's currently open @@ -43,7 +44,7 @@ const TopicCard = { var topic = node.getData('topic') self.openTopicCard = topic - self.authorizedToEdit = topic.authorizeToEdit(Metamaps.Active.Mapper) + self.authorizedToEdit = topic.authorizeToEdit(Active.Mapper) // populate the card that's about to show with the right topics data self.populateShowCard(topic) return $('.showcard').fadeIn('fast', function() { @@ -96,7 +97,7 @@ const TopicCard = { var setMapperImage = function (mapper) { $('.contributorIcon').attr('src', mapper.get('image')) } - Metamaps.Mapper.get(topic.get('user_id'), setMapperImage) + Mapper.get(topic.get('user_id'), setMapperImage) // starting embed.ly var resetFunc = function () { @@ -179,7 +180,7 @@ const TopicCard = { topic.save({ metacode_id: metacode.id }) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() $('.metacodeSelect').hide().removeClass('onRightEdge onBottomEdge') $('.metacodeTitle').hide() $('.showcard .icon').css('z-index', '1') @@ -265,7 +266,7 @@ const TopicCard = { // bind best_in_place ajax callbacks bipName.bind('ajax:success', function () { - var name = Metamaps.Util.decodeEntities($(this).html()) + var name = Util.decodeEntities($(this).html()) topic.set('name', name) topic.trigger('saved') }) @@ -313,7 +314,7 @@ const TopicCard = { } // ability to change permission var selectingPermission = false - if (topic.authorizePermissionChange(Metamaps.Active.Mapper)) { + if (topic.authorizePermissionChange(Active.Mapper)) { $('.showcard .yourTopic .mapPerm').click(openPermissionSelect) $('.showcard').click(hidePermissionSelect) } @@ -364,11 +365,11 @@ const TopicCard = { var topicForTemplate = self.buildObject(topic) var html = self.generateShowcardHTML.render(topicForTemplate) - if (topic.authorizeToEdit(Metamaps.Active.Mapper)) { + if (topic.authorizeToEdit(Active.Mapper)) { var perm = document.createElement('div') var string = 'permission canEdit' - if (topic.authorizePermissionChange(Metamaps.Active.Mapper)) string += ' yourTopic' + if (topic.authorizePermissionChange(Active.Mapper)) string += ' yourTopic' perm.className = string perm.innerHTML = html showCard.appendChild(perm) @@ -388,7 +389,7 @@ const TopicCard = { var nodeValues = {} - var authorized = topic.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = topic.authorizeToEdit(Active.Mapper) if (!authorized) { } else { diff --git a/frontend/src/Metamaps/Views.js b/frontend/src/Metamaps/Views.js index 90cd466d..aee0fdf0 100644 --- a/frontend/src/Metamaps/Views.js +++ b/frontend/src/Metamaps/Views.js @@ -1,12 +1,14 @@ /* global Metamaps, $ */ +import Active from './Active' +import ReactComponents from './ReactComponents' +import ReactDOM from 'react-dom' // TODO ensure this isn't a double import + /* * Metamaps.Views.js.erb * * Dependencies: * - Metamaps.Loading - * - Metamaps.Active - * - Metamaps.ReactComponents */ const Views = { @@ -33,7 +35,7 @@ const Views = { } var exploreObj = { - currentUser: Metamaps.Active.Mapper, + currentUser: Active.Mapper, section: self.collection.id, displayStyle: 'grid', maps: self.collection, @@ -42,7 +44,7 @@ const Views = { loadMore: self.loadMore } ReactDOM.render( - React.createElement(Metamaps.ReactComponents.Maps, exploreObj), + React.createElement(ReactComponents.Maps, exploreObj), document.getElementById('explore') ) diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index 4aa65772..9e44e8e8 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -1,10 +1,12 @@ /* global Metamaps, $ */ + +import Active from './Active' +import JIT from './JIT' + /* * Metamaps.Visualize * * Dependencies: - * - Metamaps.Active - * - Metamaps.JIT * - Metamaps.Loading * - Metamaps.Metacodes * - Metamaps.Router @@ -34,7 +36,7 @@ const Visualize = { // prevent touch events on the canvas from default behaviour $('#infovis-canvas').bind('touchmove', function (event) { - // Metamaps.JIT.touchPanZoomHandler(event) + // JIT.touchPanZoomHandler(event) }) // prevent touch events on the canvas from default behaviour @@ -116,25 +118,25 @@ const Visualize = { // clear the previous canvas from #infovis $('#infovis').empty() - RGraphSettings = $.extend(true, {}, Metamaps.JIT.ForceDirected.graphSettings) + RGraphSettings = $.extend(true, {}, JIT.ForceDirected.graphSettings) - $jit.RGraph.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings) - $jit.RGraph.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings) + $jit.RGraph.Plot.NodeTypes.implement(JIT.ForceDirected.nodeSettings) + $jit.RGraph.Plot.EdgeTypes.implement(JIT.ForceDirected.edgeSettings) RGraphSettings.width = $(document).width() RGraphSettings.height = $(document).height() - RGraphSettings.background = Metamaps.JIT.RGraph.background - RGraphSettings.levelDistance = Metamaps.JIT.RGraph.levelDistance + RGraphSettings.background = JIT.RGraph.background + RGraphSettings.levelDistance = JIT.RGraph.levelDistance self.mGraph = new $jit.RGraph(RGraphSettings) } else if (self.type == 'ForceDirected' && (!self.mGraph || self.mGraph instanceof $jit.RGraph)) { // clear the previous canvas from #infovis $('#infovis').empty() - FDSettings = $.extend(true, {}, Metamaps.JIT.ForceDirected.graphSettings) + FDSettings = $.extend(true, {}, JIT.ForceDirected.graphSettings) - $jit.ForceDirected.Plot.NodeTypes.implement(Metamaps.JIT.ForceDirected.nodeSettings) - $jit.ForceDirected.Plot.EdgeTypes.implement(Metamaps.JIT.ForceDirected.edgeSettings) + $jit.ForceDirected.Plot.NodeTypes.implement(JIT.ForceDirected.nodeSettings) + $jit.ForceDirected.Plot.EdgeTypes.implement(JIT.ForceDirected.edgeSettings) FDSettings.width = $('body').width() FDSettings.height = $('body').height() @@ -145,14 +147,14 @@ const Visualize = { $('#infovis').empty() // init ForceDirected3D - self.mGraph = new $jit.ForceDirected3D(Metamaps.JIT.ForceDirected3D.graphSettings) + self.mGraph = new $jit.ForceDirected3D(JIT.ForceDirected3D.graphSettings) self.cameraPosition = self.mGraph.canvas.canvases[0].camera.position } else { self.mGraph.graph.empty() } - if (self.type == 'ForceDirected' && Metamaps.Active.Mapper) $.post('/maps/' + Metamaps.Active.Map.id + '/events/user_presence') + if (self.type == 'ForceDirected' && Active.Mapper) $.post('/maps/' + Active.Map.id + '/events/user_presence') function runAnimation () { Metamaps.Loading.hide() @@ -160,22 +162,22 @@ const Visualize = { if (!self.loadLater) { // load JSON data. var rootIndex = 0 - if (Metamaps.Active.Topic) { - var node = _.find(Metamaps.JIT.vizData, function (node) { - return node.id === Metamaps.Active.Topic.id + if (Active.Topic) { + var node = _.find(JIT.vizData, function (node) { + return node.id === Active.Topic.id }) - rootIndex = _.indexOf(Metamaps.JIT.vizData, node) + rootIndex = _.indexOf(JIT.vizData, node) } - self.mGraph.loadJSON(Metamaps.JIT.vizData, rootIndex) + self.mGraph.loadJSON(JIT.vizData, rootIndex) // compute positions and plot. self.computePositions() self.mGraph.busy = true if (self.type == 'RGraph') { - self.mGraph.fx.animate(Metamaps.JIT.RGraph.animate) + self.mGraph.fx.animate(JIT.RGraph.animate) } else if (self.type == 'ForceDirected') { - self.mGraph.animate(Metamaps.JIT.ForceDirected.animateSavedLayout) + self.mGraph.animate(JIT.ForceDirected.animateSavedLayout) } else if (self.type == 'ForceDirected3D') { - self.mGraph.animate(Metamaps.JIT.ForceDirected.animateFDLayout) + self.mGraph.animate(JIT.ForceDirected.animateFDLayout) } } } @@ -204,8 +206,8 @@ const Visualize = { // update the url now that the map is ready clearTimeout(Metamaps.Router.timeoutId) Metamaps.Router.timeoutId = setTimeout(function () { - var m = Metamaps.Active.Map - var t = Metamaps.Active.Topic + var m = Active.Map + var t = Active.Topic if (m && window.location.pathname !== '/maps/' + m.id) { Metamaps.Router.navigate('/maps/' + m.id) From 120c2c0b673d21b32e372820fce78b16b3d68c4b Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 18:31:56 +0800 Subject: [PATCH 13/26] finish most except Backbone --- frontend/src/Metamaps/Account.js | 9 +- frontend/src/Metamaps/AutoLayout.js | 4 +- frontend/src/Metamaps/Backbone.js | 30 +- frontend/src/Metamaps/Control.js | 32 +- frontend/src/Metamaps/Create.js | 4 +- frontend/src/Metamaps/Debug.js | 6 +- frontend/src/Metamaps/Filter.js | 4 +- frontend/src/Metamaps/GlobalUI.js | 557 ++++++++++++++------------- frontend/src/Metamaps/Import.js | 9 +- frontend/src/Metamaps/JIT.js | 485 ++++++++++++----------- frontend/src/Metamaps/Listeners.js | 77 ++-- frontend/src/Metamaps/Map.js | 180 ++++----- frontend/src/Metamaps/Mapper.js | 6 +- frontend/src/Metamaps/PasteInput.js | 6 +- frontend/src/Metamaps/Realtime.js | 320 ++++++++------- frontend/src/Metamaps/Router.js | 158 ++++---- frontend/src/Metamaps/Synapse.js | 52 +-- frontend/src/Metamaps/SynapseCard.js | 2 +- frontend/src/Metamaps/Topic.js | 127 +++--- frontend/src/Metamaps/TopicCard.js | 8 +- frontend/src/Metamaps/Visualize.js | 14 +- frontend/src/Metamaps/index.js | 20 +- 22 files changed, 1077 insertions(+), 1033 deletions(-) diff --git a/frontend/src/Metamaps/Account.js b/frontend/src/Metamaps/Account.js index f424019f..10311cbd 100644 --- a/frontend/src/Metamaps/Account.js +++ b/frontend/src/Metamaps/Account.js @@ -1,12 +1,11 @@ -/* uses window.Metamaps.Erb */ +/* + * Metamaps.Erb + */ const Account = { listenersInitialized: false, - init: function () { - var self = Metamaps.Account - }, initListeners: function () { - var self = Metamaps.Account + var self = Account $('#user_image').change(self.showImagePreview) self.listenersInitialized = true diff --git a/frontend/src/Metamaps/AutoLayout.js b/frontend/src/Metamaps/AutoLayout.js index 386b61ef..ee9dc33c 100644 --- a/frontend/src/Metamaps/AutoLayout.js +++ b/frontend/src/Metamaps/AutoLayout.js @@ -8,7 +8,7 @@ const AutoLayout = { timeToTurn: 0, getNextCoord: function () { - var self = Metamaps.AutoLayout + var self = AutoLayout var nextX = self.nextX var nextY = self.nextY @@ -55,7 +55,7 @@ const AutoLayout = { } }, resetSpiral: function () { - var self = Metamaps.AutoLayout + var self = AutoLayout self.nextX = 0 self.nextY = 0 self.nextXshift = 1 diff --git a/frontend/src/Metamaps/Backbone.js b/frontend/src/Metamaps/Backbone.js index ce62c6be..9f18ef32 100644 --- a/frontend/src/Metamaps/Backbone.js +++ b/frontend/src/Metamaps/Backbone.js @@ -26,9 +26,9 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Visualize */ -Metamaps.Backbone = {} +const _Backbone = {} -Metamaps.Backbone.Map = Backbone.Model.extend({ +_Backbone.Map = Backbone.Model.extend({ urlRoot: '/maps', blacklist: ['created_at', 'updated_at', 'created_at_clean', 'updated_at_clean', 'user_name', 'contributor_count', 'topic_count', 'synapse_count', 'topics', 'synapses', 'mappings', 'mappers'], toJSON: function (options) { @@ -82,7 +82,7 @@ Metamaps.Backbone.Map = Backbone.Model.extend({ return Metamaps.Mapper.get(this.get('user_id')) }, fetchContained: function () { - var bb = Metamaps.Backbone + var bb = _Backbone var that = this var start = function (data) { that.set('mappers', new bb.MapperCollection(data.mappers)) @@ -143,8 +143,8 @@ Metamaps.Backbone.Map = Backbone.Model.extend({ } } }) -Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({ - model: Metamaps.Backbone.Map, +_Backbone.MapsCollection = Backbone.Collection.extend({ + model: _Backbone.Map, initialize: function (models, options) { this.id = options.id this.sortBy = options.sortBy @@ -211,7 +211,7 @@ Metamaps.Backbone.MapsCollection = Backbone.Collection.extend({ } }) -Metamaps.Backbone.Message = Backbone.Model.extend({ +_Backbone.Message = Backbone.Model.extend({ urlRoot: '/messages', blacklist: ['created_at', 'updated_at'], toJSON: function (options) { @@ -227,12 +227,12 @@ Metamaps.Backbone.Message = Backbone.Model.extend({ */ } }) -Metamaps.Backbone.MessageCollection = Backbone.Collection.extend({ - model: Metamaps.Backbone.Message, +_Backbone.MessageCollection = Backbone.Collection.extend({ + model: _Backbone.Message, url: '/messages' }) -Metamaps.Backbone.Mapper = Backbone.Model.extend({ +_Backbone.Mapper = Backbone.Model.extend({ urlRoot: '/users', blacklist: ['created_at', 'updated_at'], toJSON: function (options) { @@ -248,13 +248,13 @@ Metamaps.Backbone.Mapper = Backbone.Model.extend({ } }) -Metamaps.Backbone.MapperCollection = Backbone.Collection.extend({ - model: Metamaps.Backbone.Mapper, +_Backbone.MapperCollection = Backbone.Collection.extend({ + model: _Backbone.Mapper, url: '/users' }) -Metamaps.Backbone.init = function () { - var self = Metamaps.Backbone +_Backbone.init = function () { + var self = _Backbone self.Metacode = Backbone.Model.extend({ initialize: function () { @@ -694,6 +694,6 @@ Metamaps.Backbone.init = function () { } } self.attachCollectionEvents() -}; // end Metamaps.Backbone.init +}; // end _Backbone.init -export default Metamaps.Backbone +export default _Backbone diff --git a/frontend/src/Metamaps/Control.js b/frontend/src/Metamaps/Control.js index 3eecb126..9e13e40c 100644 --- a/frontend/src/Metamaps/Control.js +++ b/frontend/src/Metamaps/Control.js @@ -2,6 +2,7 @@ import Active from './Active' import Filter from './Filter' +import GlobalUI from './GlobalUI' import JIT from './JIT' import Mouse from './Mouse' import Selected from './Selected' @@ -12,7 +13,6 @@ import Visualize from './Visualize' * Metamaps.Control.js * * Dependencies: - * - Metamaps.GlobalUI * - Metamaps.Mappings * - Metamaps.Metacodes * - Metamaps.Synapses @@ -57,7 +57,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -73,7 +73,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -89,7 +89,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -107,7 +107,7 @@ const Control = { }]) Control.hideNode(nodeid) } else { - Metamaps.GlobalUI.notifyUser('Only topics you created can be deleted') + GlobalUI.notifyUser('Only topics you created can be deleted') } }, removeSelectedNodes: function () { // refers to removing topics permanently from a map @@ -132,7 +132,7 @@ const Control = { authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -148,7 +148,7 @@ const Control = { var node = Visualize.mGraph.graph.getNode(nodeid) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -251,7 +251,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -266,7 +266,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -294,7 +294,7 @@ const Control = { mappableid: mappableid }]) } else { - Metamaps.GlobalUI.notifyUser('Only synapses you created can be deleted') + GlobalUI.notifyUser('Only synapses you created can be deleted') } }, removeSelectedEdges: function () { @@ -308,7 +308,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -324,7 +324,7 @@ const Control = { var authorized = Active.Map.authorizeToEdit(Active.Mapper) if (!authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') return } @@ -378,7 +378,7 @@ const Control = { updateSelectedPermissions: function (permission) { var edge, synapse, node, topic - Metamaps.GlobalUI.notifyUser('Working...') + GlobalUI.notifyUser('Working...') // variables to keep track of how many nodes and synapses you had the ability to change the permission of var nCount = 0, @@ -416,12 +416,12 @@ const Control = { var sString = sCount == 1 ? (sCount.toString() + ' synapse') : (sCount.toString() + ' synapses') var message = nString + sString + ' you created updated to ' + permission - Metamaps.GlobalUI.notifyUser(message) + GlobalUI.notifyUser(message) }, updateSelectedMetacodes: function (metacode_id) { var node, topic - Metamaps.GlobalUI.notifyUser('Working...') + GlobalUI.notifyUser('Working...') var metacode = Metamaps.Metacodes.get(metacode_id) @@ -445,7 +445,7 @@ const Control = { var nString = nCount == 1 ? (nCount.toString() + ' topic') : (nCount.toString() + ' topics') var message = nString + ' you can edit updated to ' + metacode.get('name') - Metamaps.GlobalUI.notifyUser(message) + GlobalUI.notifyUser(message) Visualize.mGraph.plot() }, } diff --git a/frontend/src/Metamaps/Create.js b/frontend/src/Metamaps/Create.js index 49267d6d..c9252aba 100644 --- a/frontend/src/Metamaps/Create.js +++ b/frontend/src/Metamaps/Create.js @@ -5,13 +5,13 @@ import Selected from './Selected' import Synapse from './Synapse' import Topic from './Topic' import Visualize from './Visualize' +import GlobalUI from './GlobalUI' /* * Metamaps.Create.js * * Dependencies: * - Metamaps.Backbone - * - Metamaps.GlobalUI * - Metamaps.Metacodes */ @@ -101,7 +101,7 @@ const Create = { bringToFront: true }) - Metamaps.GlobalUI.closeLightbox() + GlobalUI.closeLightbox() $('#topic_name').focus() var mdata = { diff --git a/frontend/src/Metamaps/Debug.js b/frontend/src/Metamaps/Debug.js index e8e40e69..0fe5f769 100644 --- a/frontend/src/Metamaps/Debug.js +++ b/frontend/src/Metamaps/Debug.js @@ -1,6 +1,6 @@ -const Debug = () => { - console.debug(window.Metamaps) - console.debug(`Metamaps Version: ${window.Metamaps.VERSION}`) +const Debug = (arg = window.Metamaps) => { + console.debug(arg) + console.debug(`Metamaps Version: ${arg.VERSION}`) } export default Debug diff --git a/frontend/src/Metamaps/Filter.js b/frontend/src/Metamaps/Filter.js index aed9964d..38c4f369 100644 --- a/frontend/src/Metamaps/Filter.js +++ b/frontend/src/Metamaps/Filter.js @@ -2,6 +2,7 @@ import Active from './Active' import Control from './Control' +import GlobalUI from './GlobalUI' import Settings from './Settings' import Visualize from './Visualize' @@ -10,7 +11,6 @@ import Visualize from './Visualize' * * Dependencies: * - Metamaps.Creators - * - Metamaps.GlobalUI * - Metamaps.Mappers * - Metamaps.Metacodes * - Metamaps.Synapses @@ -56,7 +56,7 @@ const Filter = { open: function () { var self = Filter - Metamaps.GlobalUI.Account.close() + GlobalUI.Account.close() $('.sidebarFilterIcon div').addClass('hide') if (!self.isOpen && !self.changing) { diff --git a/frontend/src/Metamaps/GlobalUI.js b/frontend/src/Metamaps/GlobalUI.js index 5abf25ee..b24b31c7 100644 --- a/frontend/src/Metamaps/GlobalUI.js +++ b/frontend/src/Metamaps/GlobalUI.js @@ -1,317 +1,326 @@ -window.Metamaps = window.Metamaps || {}; +import Active from './Active' +import Create from './Create' +import Filter from './Filter' +import Router from './Router' + +/* + * Metamaps.Backbone + * Metamaps.Erb + * Metamaps.Maps + */ const GlobalUI = { - notifyTimeout: null, - lightbox: null, - init: function () { - var self = GlobalUI; + notifyTimeout: null, + lightbox: null, + init: function () { + var self = GlobalUI; - self.Search.init(); - self.CreateMap.init(); - self.Account.init(); - - if ($('#toast').html().trim()) self.notifyUser($('#toast').html()) + self.Search.init(); + self.CreateMap.init(); + self.Account.init(); - //bind lightbox clicks - $('.openLightbox').click(function (event) { - self.openLightbox($(this).attr('data-open')); - event.preventDefault(); - return false; - }); + if ($('#toast').html().trim()) self.notifyUser($('#toast').html()) - $('#lightbox_screen, #lightbox_close').click(self.closeLightbox); + //bind lightbox clicks + $('.openLightbox').click(function (event) { + self.openLightbox($(this).attr('data-open')); + event.preventDefault(); + return false; + }); - // initialize global backbone models and collections - if (Metamaps.Active.Mapper) Metamaps.Active.Mapper = new Metamaps.Backbone.Mapper(Metamaps.Active.Mapper); + $('#lightbox_screen, #lightbox_close').click(self.closeLightbox); - var myCollection = Metamaps.Maps.Mine ? Metamaps.Maps.Mine : []; - var sharedCollection = Metamaps.Maps.Shared ? Metamaps.Maps.Shared : []; - var starredCollection = Metamaps.Maps.Starred ? Metamaps.Maps.Starred : []; - var mapperCollection = []; - var mapperOptionsObj = {id: 'mapper', sortBy: 'updated_at' }; - if (Metamaps.Maps.Mapper) { - mapperCollection = Metamaps.Maps.Mapper.models; - mapperOptionsObj.mapperId = Metamaps.Maps.Mapper.id; - } - var featuredCollection = Metamaps.Maps.Featured ? Metamaps.Maps.Featured : []; - var activeCollection = Metamaps.Maps.Active ? Metamaps.Maps.Active : []; - Metamaps.Maps.Mine = new Metamaps.Backbone.MapsCollection(myCollection, {id: 'mine', sortBy: 'updated_at' }); - Metamaps.Maps.Shared = new Metamaps.Backbone.MapsCollection(sharedCollection, {id: 'shared', sortBy: 'updated_at' }); - Metamaps.Maps.Starred = new Metamaps.Backbone.MapsCollection(starredCollection, {id: 'starred', sortBy: 'updated_at' }); - // 'Mapper' refers to another mapper - Metamaps.Maps.Mapper = new Metamaps.Backbone.MapsCollection(mapperCollection, mapperOptionsObj); - Metamaps.Maps.Featured = new Metamaps.Backbone.MapsCollection(featuredCollection, {id: 'featured', sortBy: 'updated_at' }); - Metamaps.Maps.Active = new Metamaps.Backbone.MapsCollection(activeCollection, {id: 'active', sortBy: 'updated_at' }); - }, - showDiv: function (selector) { - $(selector).show() - $(selector).animate({ - opacity: 1 - }, 200, 'easeOutCubic') - }, - hideDiv: function (selector) { - $(selector).animate({ - opacity: 0 - }, 200, 'easeInCubic', function () { $(this).hide() }) - }, - openLightbox: function (which) { - var self = GlobalUI; + // initialize global backbone models and collections + if (Active.Mapper) Active.Mapper = new Metamaps.Backbone.Mapper(Active.Mapper); - $('.lightboxContent').hide(); - $('#' + which).show(); - - self.lightbox = which; - - $('#lightbox_overlay').show(); - - var heightOfContent = '-' + ($('#lightbox_main').height() / 2) + 'px'; - // animate the content in from the bottom - $('#lightbox_main').animate({ - 'top': '50%', - 'margin-top': heightOfContent - }, 200, 'easeOutCubic'); - - // fade the black overlay in - $('#lightbox_screen').animate({ - 'opacity': '0.42' - }, 200); - - if (which == "switchMetacodes") { - Metamaps.Create.isSwitchingSet = true; - } - }, - - closeLightbox: function (event) { - var self = GlobalUI; - - if (event) event.preventDefault(); - - // animate the lightbox content offscreen - $('#lightbox_main').animate({ - 'top': '100%', - 'margin-top': '0' - }, 200, 'easeInCubic'); - - // fade the black overlay out - $('#lightbox_screen').animate({ - 'opacity': '0.0' - }, 200, function () { - $('#lightbox_overlay').hide(); - }); - - if (self.lightbox === 'forkmap') GlobalUI.CreateMap.reset('fork_map'); - if (self.lightbox === 'newmap') GlobalUI.CreateMap.reset('new_map'); - if (Metamaps.Create && Metamaps.Create.isSwitchingSet) { - Metamaps.Create.cancelMetacodeSetSwitch(); - } - self.lightbox = null; - }, - notifyUser: function (message, leaveOpen) { - var self = GlobalUI; - - $('#toast').html(message) - self.showDiv('#toast') - clearTimeout(self.notifyTimeOut); - if (!leaveOpen) { - self.notifyTimeOut = setTimeout(function () { - self.hideDiv('#toast') - }, 8000); - } - }, - clearNotify: function() { - var self = GlobalUI; - - clearTimeout(self.notifyTimeOut); - self.hideDiv('#toast') - }, - shareInvite: function(inviteLink) { - window.prompt("To copy the invite link, press: Ctrl+C, Enter", inviteLink); + var myCollection = Metamaps.Maps.Mine ? Metamaps.Maps.Mine : []; + var sharedCollection = Metamaps.Maps.Shared ? Metamaps.Maps.Shared : []; + var starredCollection = Metamaps.Maps.Starred ? Metamaps.Maps.Starred : []; + var mapperCollection = []; + var mapperOptionsObj = {id: 'mapper', sortBy: 'updated_at' }; + if (Metamaps.Maps.Mapper) { + mapperCollection = Metamaps.Maps.Mapper.models; + mapperOptionsObj.mapperId = Metamaps.Maps.Mapper.id; } + var featuredCollection = Metamaps.Maps.Featured ? Metamaps.Maps.Featured : []; + var activeCollection = Metamaps.Maps.Active ? Metamaps.Maps.Active : []; + Metamaps.Maps.Mine = new Metamaps.Backbone.MapsCollection(myCollection, {id: 'mine', sortBy: 'updated_at' }); + Metamaps.Maps.Shared = new Metamaps.Backbone.MapsCollection(sharedCollection, {id: 'shared', sortBy: 'updated_at' }); + Metamaps.Maps.Starred = new Metamaps.Backbone.MapsCollection(starredCollection, {id: 'starred', sortBy: 'updated_at' }); + // 'Mapper' refers to another mapper + Metamaps.Maps.Mapper = new Metamaps.Backbone.MapsCollection(mapperCollection, mapperOptionsObj); + Metamaps.Maps.Featured = new Metamaps.Backbone.MapsCollection(featuredCollection, {id: 'featured', sortBy: 'updated_at' }); + Metamaps.Maps.Active = new Metamaps.Backbone.MapsCollection(activeCollection, {id: 'active', sortBy: 'updated_at' }); + }, + showDiv: function (selector) { + $(selector).show() + $(selector).animate({ + opacity: 1 + }, 200, 'easeOutCubic') + }, + hideDiv: function (selector) { + $(selector).animate({ + opacity: 0 + }, 200, 'easeInCubic', function () { $(this).hide() }) + }, + openLightbox: function (which) { + var self = GlobalUI; + + $('.lightboxContent').hide(); + $('#' + which).show(); + + self.lightbox = which; + + $('#lightbox_overlay').show(); + + var heightOfContent = '-' + ($('#lightbox_main').height() / 2) + 'px'; + // animate the content in from the bottom + $('#lightbox_main').animate({ + 'top': '50%', + 'margin-top': heightOfContent + }, 200, 'easeOutCubic'); + + // fade the black overlay in + $('#lightbox_screen').animate({ + 'opacity': '0.42' + }, 200); + + if (which == "switchMetacodes") { + Create.isSwitchingSet = true; + } + }, + + closeLightbox: function (event) { + var self = GlobalUI; + + if (event) event.preventDefault(); + + // animate the lightbox content offscreen + $('#lightbox_main').animate({ + 'top': '100%', + 'margin-top': '0' + }, 200, 'easeInCubic'); + + // fade the black overlay out + $('#lightbox_screen').animate({ + 'opacity': '0.0' + }, 200, function () { + $('#lightbox_overlay').hide(); + }); + + if (self.lightbox === 'forkmap') GlobalUI.CreateMap.reset('fork_map'); + if (self.lightbox === 'newmap') GlobalUI.CreateMap.reset('new_map'); + if (Create && Create.isSwitchingSet) { + Create.cancelMetacodeSetSwitch(); + } + self.lightbox = null; + }, + notifyUser: function (message, leaveOpen) { + var self = GlobalUI; + + $('#toast').html(message) + self.showDiv('#toast') + clearTimeout(self.notifyTimeOut); + if (!leaveOpen) { + self.notifyTimeOut = setTimeout(function () { + self.hideDiv('#toast') + }, 8000); + } + }, + clearNotify: function() { + var self = GlobalUI; + + clearTimeout(self.notifyTimeOut); + self.hideDiv('#toast') + }, + shareInvite: function(inviteLink) { + window.prompt("To copy the invite link, press: Ctrl+C, Enter", inviteLink); + } } GlobalUI.CreateMap = { - newMap: null, - emptyMapForm: "", - emptyForkMapForm: "", - topicsToMap: [], - synapsesToMap: [], - init: function () { - var self = GlobalUI.CreateMap; + newMap: null, + emptyMapForm: "", + emptyForkMapForm: "", + topicsToMap: [], + synapsesToMap: [], + init: function () { + var self = GlobalUI.CreateMap; - self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); + self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); - self.bindFormEvents(); + self.bindFormEvents(); - self.emptyMapForm = $('#new_map').html(); + self.emptyMapForm = $('#new_map').html(); - }, - bindFormEvents: function () { - var self = GlobalUI.CreateMap; + }, + bindFormEvents: function () { + var self = GlobalUI.CreateMap; - $('.new_map input, .new_map div').unbind('keypress').bind('keypress', function(event) { - if (event.keyCode === 13) self.submit() - }) + $('.new_map input, .new_map div').unbind('keypress').bind('keypress', function(event) { + if (event.keyCode === 13) self.submit() + }) - $('.new_map button.cancel').unbind().bind('click', function (event) { - event.preventDefault(); - GlobalUI.closeLightbox(); - }); - $('.new_map button.submitMap').unbind().bind('click', self.submit); + $('.new_map button.cancel').unbind().bind('click', function (event) { + event.preventDefault(); + GlobalUI.closeLightbox(); + }); + $('.new_map button.submitMap').unbind().bind('click', self.submit); - // bind permission changer events on the createMap form - $('.permIcon').unbind().bind('click', self.switchPermission); - }, - closeSuccess: function () { - $('#mapCreatedSuccess').fadeOut(300, function(){ - $(this).remove(); - }); - }, - generateSuccessMessage: function (id) { - var stringStart = "
    SUCCESS!
    Your map has been created. Do you want to: Go to your new map"; - stringStart += "ORStay on this "; - var page = Metamaps.Active.Map ? 'map' : 'page'; - var stringEnd = "
    "; - return stringStart + page + stringEnd; - }, - switchPermission: function () { - var self = GlobalUI.CreateMap; + // bind permission changer events on the createMap form + $('.permIcon').unbind().bind('click', self.switchPermission); + }, + closeSuccess: function () { + $('#mapCreatedSuccess').fadeOut(300, function(){ + $(this).remove(); + }); + }, + generateSuccessMessage: function (id) { + var stringStart = "
    SUCCESS!
    Your map has been created. Do you want to: Go to your new map"; + stringStart += "ORStay on this "; + var page = Active.Map ? 'map' : 'page'; + var stringEnd = "
    "; + return stringStart + page + stringEnd; + }, + switchPermission: function () { + var self = GlobalUI.CreateMap; - self.newMap.set('permission', $(this).attr('data-permission')); - $(this).siblings('.permIcon').find('.mapPermIcon').removeClass('selected'); - $(this).find('.mapPermIcon').addClass('selected'); + self.newMap.set('permission', $(this).attr('data-permission')); + $(this).siblings('.permIcon').find('.mapPermIcon').removeClass('selected'); + $(this).find('.mapPermIcon').addClass('selected'); - var permText = $(this).find('.tip').html(); - $(this).parents('.new_map').find('.permText').html(permText); - }, - submit: function (event) { - if (event) event.preventDefault(); + var permText = $(this).find('.tip').html(); + $(this).parents('.new_map').find('.permText').html(permText); + }, + submit: function (event) { + if (event) event.preventDefault(); - var self = GlobalUI.CreateMap; + var self = GlobalUI.CreateMap; - if (GlobalUI.lightbox === 'forkmap') { - self.newMap.set('topicsToMap', self.topicsToMap); - self.newMap.set('synapsesToMap', self.synapsesToMap); - } + if (GlobalUI.lightbox === 'forkmap') { + self.newMap.set('topicsToMap', self.topicsToMap); + self.newMap.set('synapsesToMap', self.synapsesToMap); + } - var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; - var $form = $(formId); + var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var $form = $(formId); - self.newMap.set('name', $form.find('#map_name').val()); - self.newMap.set('desc', $form.find('#map_desc').val()); + self.newMap.set('name', $form.find('#map_name').val()); + self.newMap.set('desc', $form.find('#map_desc').val()); - if (self.newMap.get('name').length===0){ - self.throwMapNameError(); - return; - } + if (self.newMap.get('name').length===0){ + self.throwMapNameError(); + return; + } - self.newMap.save(null, { - success: self.success - // TODO add error message - }); + self.newMap.save(null, { + success: self.success + // TODO add error message + }); - GlobalUI.closeLightbox(); - GlobalUI.notifyUser('Working...'); - }, - throwMapNameError: function () { - var self = GlobalUI.CreateMap; + GlobalUI.closeLightbox(); + GlobalUI.notifyUser('Working...'); + }, + throwMapNameError: function () { + var self = GlobalUI.CreateMap; - var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; - var $form = $(formId); + var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var $form = $(formId); - var message = $(""); + var message = $(""); - $form.find('#map_name').after(message); - setTimeout(function(){ - message.fadeOut('fast', function(){ - message.remove(); - }); - }, 5000); - }, - success: function (model) { - var self = GlobalUI.CreateMap; + $form.find('#map_name').after(message); + setTimeout(function(){ + message.fadeOut('fast', function(){ + message.remove(); + }); + }, 5000); + }, + success: function (model) { + var self = GlobalUI.CreateMap; - //push the new map onto the collection of 'my maps' - Metamaps.Maps.Mine.add(model); + //push the new map onto the collection of 'my maps' + Metamaps.Maps.Mine.add(model); - var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; - var form = $(formId); + var formId = GlobalUI.lightbox === 'forkmap' ? '#fork_map' : '#new_map'; + var form = $(formId); - GlobalUI.clearNotify(); - $('#wrapper').append(self.generateSuccessMessage(model.id)); + GlobalUI.clearNotify(); + $('#wrapper').append(self.generateSuccessMessage(model.id)); - }, - reset: function (id) { - var self = GlobalUI.CreateMap; + }, + reset: function (id) { + var self = GlobalUI.CreateMap; - var form = $('#' + id); + var form = $('#' + id); - if (id === "fork_map") { - self.topicsToMap = []; - self.synapsesToMap = []; - form.html(self.emptyForkMapForm); - } - else { - form.html(self.emptyMapForm); - } + if (id === "fork_map") { + self.topicsToMap = []; + self.synapsesToMap = []; + form.html(self.emptyForkMapForm); + } + else { + form.html(self.emptyMapForm); + } - self.bindFormEvents(); - self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); + self.bindFormEvents(); + self.newMap = new Metamaps.Backbone.Map({ permission: 'commons' }); - return false; - }, + return false; + }, } GlobalUI.Account = { - isOpen: false, - changing: false, - init: function () { - var self = GlobalUI.Account; + isOpen: false, + changing: false, + init: function () { + var self = GlobalUI.Account; - $('.sidebarAccountIcon').click(self.toggleBox); - $('.sidebarAccountBox').click(function(event){ - event.stopPropagation(); - }); - $('body').click(self.close); - }, - toggleBox: function (event) { - var self = GlobalUI.Account; + $('.sidebarAccountIcon').click(self.toggleBox); + $('.sidebarAccountBox').click(function(event){ + event.stopPropagation(); + }); + $('body').click(self.close); + }, + toggleBox: function (event) { + var self = GlobalUI.Account; - if (self.isOpen) self.close(); - else self.open(); + if (self.isOpen) self.close(); + else self.open(); - event.stopPropagation(); - }, - open: function () { - var self = GlobalUI.Account; + event.stopPropagation(); + }, + open: function () { + var self = GlobalUI.Account; - Metamaps.Filter.close(); - $('.sidebarAccountIcon .tooltipsUnder').addClass('hide'); + Filter.close(); + $('.sidebarAccountIcon .tooltipsUnder').addClass('hide'); - if (!self.isOpen && !self.changing) { - self.changing = true; - $('.sidebarAccountBox').fadeIn(200, function () { - self.changing = false; - self.isOpen = true; - $('.sidebarAccountBox #user_email').focus(); - }); - } - }, - close: function () { - var self = GlobalUI.Account; - - $('.sidebarAccountIcon .tooltipsUnder').removeClass('hide'); - if (!self.changing) { - self.changing = true; - $('.sidebarAccountBox #user_email').blur(); - $('.sidebarAccountBox').fadeOut(200, function () { - self.changing = false; - self.isOpen = false; - }); - } + if (!self.isOpen && !self.changing) { + self.changing = true; + $('.sidebarAccountBox').fadeIn(200, function () { + self.changing = false; + self.isOpen = true; + $('.sidebarAccountBox #user_email').focus(); + }); } + }, + close: function () { + var self = GlobalUI.Account; + + $('.sidebarAccountIcon .tooltipsUnder').removeClass('hide'); + if (!self.changing) { + self.changing = true; + $('.sidebarAccountBox #user_email').blur(); + $('.sidebarAccountBox').fadeOut(200, function () { + self.changing = false; + self.isOpen = false; + }); + } + } } GlobalUI.Search = { @@ -425,8 +434,8 @@ GlobalUI.Search = { startTypeahead: function () { var self = GlobalUI.Search; - var mapheader = Metamaps.Active.Mapper ? '

    Maps

    ' : '

    Maps

    '; - var topicheader = Metamaps.Active.Mapper ? '

    Topics

    ' : '

    Topics

    '; + var mapheader = Active.Mapper ? '

    Maps

    ' : '

    Maps

    '; + var topicheader = Active.Mapper ? '

    Topics

    ' : '

    Topics

    '; var mapperheader = '

    Mappers

    '; var topics = { @@ -455,8 +464,8 @@ GlobalUI.Search = { url: '/search/topics', prepare: function(query, settings) { settings.url += '?term=' + query; - if (Metamaps.Active.Mapper && self.limitTopicsToMe) { - settings.url += "&user=" + Metamaps.Active.Mapper.id.toString(); + if (Active.Mapper && self.limitTopicsToMe) { + settings.url += "&user=" + Active.Mapper.id.toString(); } return settings; }, @@ -488,8 +497,8 @@ GlobalUI.Search = { url: '/search/maps', prepare: function(query, settings) { settings.url += '?term=' + query; - if (Metamaps.Active.Mapper && self.limitMapsToMe) { - settings.url += "&user=" + Metamaps.Active.Mapper.id.toString(); + if (Active.Mapper && self.limitMapsToMe) { + settings.url += "&user=" + Active.Mapper.id.toString(); } return settings; }, @@ -578,11 +587,11 @@ GlobalUI.Search = { self.close(0, true); var win; if (datum.rtype == "topic") { - Metamaps.Router.topics(datum.id); + Router.topics(datum.id); } else if (datum.rtype == "map") { - Metamaps.Router.maps(datum.id); + Router.maps(datum.id); } else if (datum.rtype == "mapper") { - Metamaps.Router.explore("mapper", datum.id); + Router.explore("mapper", datum.id); } } }, diff --git a/frontend/src/Metamaps/Import.js b/frontend/src/Metamaps/Import.js index bc0bab30..d5a4b4e1 100644 --- a/frontend/src/Metamaps/Import.js +++ b/frontend/src/Metamaps/Import.js @@ -1,7 +1,10 @@ /* global Metamaps, $ */ import Active from './Active' +import GlobalUI from './GlobalUI' import Map from './Map' +import Synapse from './Synapse' +import Topic from './Topic' /* * Metamaps.Import.js.erb @@ -290,11 +293,11 @@ const Import = { Metamaps.Mappings.add(mapping) // this function also includes the creation of the topic in the database - Metamaps.Topic.renderTopic(mapping, topic, true, true, { + Topic.renderTopic(mapping, topic, true, true, { success: opts.success }) - Metamaps.GlobalUI.hideDiv('#instructions') + GlobalUI.hideDiv('#instructions') }, createSynapseWithParameters: function (desc, category, permission, @@ -322,7 +325,7 @@ const Import = { }) Metamaps.Mappings.add(mapping) - Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, true) + Synapse.renderSynapse(mapping, synapse, node1, node2, true) } } diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index ec8195de..50c48985 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -1,5 +1,30 @@ /* global Metamaps */ +import Active from './Active' +import Control from './Control' +import Create from './Create' +import Filter from './Filter' +import GlobalUI from './GlobalUI' +import Map from './Map' +import Mouse from './Mouse' +import Realtime from './Realtime' +import Selected from './Selected' +import Settings from './Settings' +import Synapse from './Synapse' +import SynapseCard from './SynapseCard' +import Topic from './Topic' +import TopicCard from './TopicCard' +import Util from './Util' +import Visualize from './Visualize' + +/* + * Metamaps.Erb + * Metamaps.Mappings + * Metamaps.Metacodes + * Metamaps.Synapses + * Metamaps.Topics + */ + let panningInt const JIT = { @@ -30,11 +55,11 @@ const JIT = { $('.zoomOut').click(self.zoomOut) var zoomExtents = function (event) { - self.zoomExtents(event, Metamaps.Visualize.mGraph.canvas) + self.zoomExtents(event, Visualize.mGraph.canvas) } $('.zoomExtents').click(zoomExtents) - $('.takeScreenshot').click(Metamaps.Map.exportImage) + $('.takeScreenshot').click(Map.exportImage) self.topicDescImage = new Image() self.topicDescImage.src = Metamaps.Erb['topic_description_signifier.png'] @@ -80,7 +105,7 @@ const JIT = { if (existingEdge) { // for when you're dealing with multiple relationships between the same two topics - if (Metamaps.Active.Map) { + if (Active.Map) { mapping = s.getMapping() existingEdge.data['$mappingIDs'].push(mapping.id) } @@ -105,7 +130,7 @@ const JIT = { // reset/empty vizData self.vizData = [] - Metamaps.Visualize.loadLater = false + Visualize.loadLater = false var results = self.convertModelsToJIT(Metamaps.Topics, Metamaps.Synapses) @@ -121,12 +146,12 @@ const JIT = { if (self.vizData.length == 0) { $('#instructions div').hide() $('#instructions div.addTopic').show() - Metamaps.GlobalUI.showDiv('#instructions') - Metamaps.Visualize.loadLater = true + GlobalUI.showDiv('#instructions') + Visualize.loadLater = true } - else Metamaps.GlobalUI.hideDiv('#instructions') + else GlobalUI.hideDiv('#instructions') - Metamaps.Visualize.render() + Visualize.render() }, // prepareVizData edgeRender: function (adj, canvas) { // get nodes cartesian coordinates @@ -151,7 +176,7 @@ const JIT = { // label placement on edges if (canvas.denySelected) { - var color = Metamaps.Settings.colors.synapses.normal + var color = Settings.colors.synapses.normal canvas.getCtx().fillStyle = canvas.getCtx().strokeStyle = color } JIT.renderEdgeArrows($jit.Graph.Plot.edgeHelper, adj, synapse, canvas) @@ -191,7 +216,7 @@ const JIT = { if (!canvas.denySelected && desc != '' && showDesc) { // '&' to '&' - desc = Metamaps.Util.decodeEntities(desc) + desc = Util.decodeEntities(desc) // now adjust the label placement var ctx = canvas.getCtx() @@ -199,7 +224,7 @@ const JIT = { ctx.fillStyle = '#FFF' ctx.textBaseline = 'alphabetic' - var arrayOfLabelLines = Metamaps.Util.splitLine(desc, 30).split('\n') + var arrayOfLabelLines = Util.splitLine(desc, 30).split('\n') var index, lineWidths = [] for (index = 0; index < arrayOfLabelLines.length; ++index) { lineWidths.push(ctx.measureText(arrayOfLabelLines[index]).width) @@ -258,7 +283,7 @@ const JIT = { transition: $jit.Trans.Quad.easeInOut, duration: 800, onComplete: function () { - Metamaps.Visualize.mGraph.busy = false + Visualize.mGraph.busy = false $(document).trigger(JIT.events.animationDone) } }, @@ -267,7 +292,7 @@ const JIT = { transition: $jit.Trans.Elastic.easeOut, duration: 800, onComplete: function () { - Metamaps.Visualize.mGraph.busy = false + Visualize.mGraph.busy = false } }, graphSettings: { @@ -306,7 +331,7 @@ const JIT = { }, Edge: { overridable: true, - color: Metamaps.Settings.colors.synapses.normal, + color: Settings.colors.synapses.normal, type: 'customEdge', lineWidth: 2, alpha: 1 @@ -317,7 +342,7 @@ const JIT = { size: 20, family: 'arial', textBaseline: 'alphabetic', - color: Metamaps.Settings.colors.labels.text + color: Settings.colors.labels.text }, // Add Tips Tips: { @@ -359,26 +384,26 @@ const JIT = { // remove the rightclickmenu $('.rightclickmenu').remove() - if (Metamaps.Mouse.boxStartCoordinates) { + if (Mouse.boxStartCoordinates) { if (e.ctrlKey) { - Metamaps.Visualize.mGraph.busy = false - Metamaps.Mouse.boxEndCoordinates = eventInfo.getPos() + Visualize.mGraph.busy = false + Mouse.boxEndCoordinates = eventInfo.getPos() - var bS = Metamaps.Mouse.boxStartCoordinates - var bE = Metamaps.Mouse.boxEndCoordinates + var bS = Mouse.boxStartCoordinates + var bE = Mouse.boxEndCoordinates if (Math.abs(bS.x - bE.x) > 20 && Math.abs(bS.y - bE.y) > 20) { JIT.zoomToBox(e) return } else { - Metamaps.Mouse.boxStartCoordinates = null - Metamaps.Mouse.boxEndCoordinates = null + Mouse.boxStartCoordinates = null + Mouse.boxEndCoordinates = null } // console.log('called zoom to box') } if (e.shiftKey) { - Metamaps.Visualize.mGraph.busy = false - Metamaps.Mouse.boxEndCoordinates = eventInfo.getPos() + Visualize.mGraph.busy = false + Mouse.boxEndCoordinates = eventInfo.getPos() JIT.selectWithBox(e) // console.log('called select with box') return @@ -404,9 +429,9 @@ const JIT = { // remove the rightclickmenu $('.rightclickmenu').remove() - if (Metamaps.Mouse.boxStartCoordinates) { - Metamaps.Visualize.mGraph.busy = false - Metamaps.Mouse.boxEndCoordinates = eventInfo.getPos() + if (Mouse.boxStartCoordinates) { + Visualize.mGraph.busy = false + Mouse.boxEndCoordinates = eventInfo.getPos() JIT.selectWithBox(e) return } @@ -441,7 +466,7 @@ const JIT = { if (!canvas.denySelected && node.selected) { ctx.beginPath() ctx.arc(pos.x, pos.y, dim + 3, 0, 2 * Math.PI, false) - ctx.strokeStyle = Metamaps.Settings.colors.topics.selected + ctx.strokeStyle = Settings.colors.topics.selected ctx.lineWidth = 2 ctx.stroke() } @@ -482,8 +507,8 @@ const JIT = { 'contains': function (node, pos) { var npos = node.pos.getc(true), dim = node.getData('dim'), - arrayOfLabelLines = Metamaps.Util.splitLine(node.name, 30).split('\n'), - ctx = Metamaps.Visualize.mGraph.canvas.getCtx() + arrayOfLabelLines = Util.splitLine(node.name, 30).split('\n'), + ctx = Visualize.mGraph.canvas.getCtx() var height = 25 * arrayOfLabelLines.length @@ -528,7 +553,7 @@ const JIT = { transition: $jit.Trans.Elastic.easeOut, duration: 2500, onComplete: function () { - Metamaps.Visualize.mGraph.busy = false + Visualize.mGraph.busy = false } }, graphSettings: { @@ -589,13 +614,13 @@ const JIT = { onMouseMove: function (node, eventInfo, e) { // if(this.i++ % 3) return var pos = eventInfo.getPos() - Metamaps.Visualize.cameraPosition.x += (pos.x - Metamaps.Visualize.cameraPosition.x) * 0.5 - Metamaps.Visualize.cameraPosition.y += (-pos.y - Metamaps.Visualize.cameraPosition.y) * 0.5 - Metamaps.Visualize.mGraph.plot() + Visualize.cameraPosition.x += (pos.x - Visualize.cameraPosition.x) * 0.5 + Visualize.cameraPosition.y += (-pos.y - Visualize.cameraPosition.y) * 0.5 + Visualize.mGraph.plot() }, onMouseWheel: function (delta) { - Metamaps.Visualize.cameraPosition.z += -delta * 20 - Metamaps.Visualize.mGraph.plot() + Visualize.cameraPosition.z += -delta * 20 + Visualize.mGraph.plot() }, onClick: function () {} }, @@ -616,7 +641,7 @@ const JIT = { modes: ['polar'], duration: 800, onComplete: function () { - Metamaps.Visualize.mGraph.busy = false + Visualize.mGraph.busy = false } }, // this will just be used to patch the ForceDirected graphsettings with the few things which actually differ @@ -636,10 +661,10 @@ const JIT = { // don't do anything if the edge is filtered // or if the canvas is animating - if (filtered || Metamaps.Visualize.mGraph.busy) return + if (filtered || Visualize.mGraph.busy) return $('canvas').css('cursor', 'pointer') - var edgeIsSelected = Metamaps.Selected.Edges.indexOf(edge) + var edgeIsSelected = Selected.Edges.indexOf(edge) // following if statement only executes if the edge being hovered over is not selected if (edgeIsSelected == -1) { edge.setData('showDesc', true, 'current') @@ -648,16 +673,16 @@ const JIT = { edge.setDataset('end', { lineWidth: 4 }) - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.animate({ modes: ['edge-property:lineWidth'], duration: 100 }) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() }, // onMouseEnter onMouseLeave: function (edge) { if (edge.getData('alpha') === 0) return; // don't do anything if the edge is filtered $('canvas').css('cursor', 'default') - var edgeIsSelected = Metamaps.Selected.Edges.indexOf(edge) + var edgeIsSelected = Selected.Edges.indexOf(edge) // following if statement only executes if the edge being hovered over is not selected if (edgeIsSelected == -1) { edge.setData('showDesc', false, 'current') @@ -666,65 +691,65 @@ const JIT = { edge.setDataset('end', { lineWidth: 2 }) - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.animate({ modes: ['edge-property:lineWidth'], duration: 100 }) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() }, // onMouseLeave onMouseMoveHandler: function (node, eventInfo, e) { var self = JIT - if (Metamaps.Visualize.mGraph.busy) return + if (Visualize.mGraph.busy) return var node = eventInfo.getNode() var edge = eventInfo.getEdge() // if we're on top of a node object, act like there aren't edges under it if (node != false) { - if (Metamaps.Mouse.edgeHoveringOver) { - self.onMouseLeave(Metamaps.Mouse.edgeHoveringOver) + if (Mouse.edgeHoveringOver) { + self.onMouseLeave(Mouse.edgeHoveringOver) } $('canvas').css('cursor', 'pointer') return } - if (edge == false && Metamaps.Mouse.edgeHoveringOver != false) { + if (edge == false && Mouse.edgeHoveringOver != false) { // mouse not on an edge, but we were on an edge previously - self.onMouseLeave(Metamaps.Mouse.edgeHoveringOver) - } else if (edge != false && Metamaps.Mouse.edgeHoveringOver == false) { + self.onMouseLeave(Mouse.edgeHoveringOver) + } else if (edge != false && Mouse.edgeHoveringOver == false) { // mouse is on an edge, but there isn't a stored edge self.onMouseEnter(edge) - } else if (edge != false && Metamaps.Mouse.edgeHoveringOver != edge) { + } else if (edge != false && Mouse.edgeHoveringOver != edge) { // mouse is on an edge, but a different edge is stored - self.onMouseLeave(Metamaps.Mouse.edgeHoveringOver) + self.onMouseLeave(Mouse.edgeHoveringOver) self.onMouseEnter(edge) } // could be false - Metamaps.Mouse.edgeHoveringOver = edge + Mouse.edgeHoveringOver = edge if (!node && !edge) { $('canvas').css('cursor', 'default') } }, // onMouseMoveHandler enterKeyHandler: function () { - var creatingMap = Metamaps.GlobalUI.lightbox + var creatingMap = GlobalUI.lightbox if (creatingMap === 'newmap' || creatingMap === 'forkmap') { - Metamaps.GlobalUI.CreateMap.submit() + GlobalUI.CreateMap.submit() } // this is to submit new topic creation - else if (Metamaps.Create.newTopic.beingCreated) { - Metamaps.Topic.createTopicLocally() + else if (Create.newTopic.beingCreated) { + Topic.createTopicLocally() } // to submit new synapse creation - else if (Metamaps.Create.newSynapse.beingCreated) { - Metamaps.Synapse.createSynapseLocally() + else if (Create.newSynapse.beingCreated) { + Synapse.createSynapseLocally() } }, // enterKeyHandler escKeyHandler: function () { - Metamaps.Control.deselectAllEdges() - Metamaps.Control.deselectAllNodes() + Control.deselectAllEdges() + Control.deselectAllNodes() }, // escKeyHandler onDragMoveTopicHandler: function (node, eventInfo, e) { var self = JIT @@ -734,7 +759,7 @@ const JIT = { var positionsToSend = {} var topic - var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map && Active.Map.authorizeToEdit(Active.Mapper) if (node && !node.nodeFrom) { var pos = eventInfo.getPos() @@ -750,7 +775,7 @@ const JIT = { } else if (whatToDo == 'only-drag-this-one') { node.pos.setc(pos.x, pos.y) - if (Metamaps.Active.Map) { + if (Active.Map) { topic = node.getData('topic') // we use the topic ID not the node id // because we can't depend on the node id @@ -760,24 +785,24 @@ const JIT = { $(document).trigger(JIT.events.topicDrag, [positionsToSend]) } } else { - var len = Metamaps.Selected.Nodes.length + var len = Selected.Nodes.length // first define offset for each node var xOffset = [] var yOffset = [] for (var i = 0; i < len; i += 1) { - var n = Metamaps.Selected.Nodes[i] + var n = Selected.Nodes[i] xOffset[i] = n.pos.x - node.pos.x yOffset[i] = n.pos.y - node.pos.y } // for for (var i = 0; i < len; i += 1) { - var n = Metamaps.Selected.Nodes[i] + var n = Selected.Nodes[i] var x = pos.x + xOffset[i] var y = pos.y + yOffset[i] n.pos.setc(x, y) - if (Metamaps.Active.Map) { + if (Active.Map) { topic = n.getData('topic') // we use the topic ID not the node id // because we can't depend on the node id @@ -787,15 +812,15 @@ const JIT = { } } // for - if (Metamaps.Active.Map) { + if (Active.Map) { $(document).trigger(JIT.events.topicDrag, [positionsToSend]) } } // if if (whatToDo == 'deselect') { - Metamaps.Control.deselectNode(node) + Control.deselectNode(node) } - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } // if it's a right click or holding down alt, start synapse creation ->third option is for firefox else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && authorized) { @@ -803,48 +828,48 @@ const JIT = { JIT.tempNode = node JIT.tempInit = true - Metamaps.Create.newTopic.hide() - Metamaps.Create.newSynapse.hide() + Create.newTopic.hide() + Create.newSynapse.hide() // set the draw synapse start positions - var l = Metamaps.Selected.Nodes.length + var l = Selected.Nodes.length if (l > 0) { for (var i = l - 1; i >= 0; i -= 1) { - var n = Metamaps.Selected.Nodes[i] - Metamaps.Mouse.synapseStartCoordinates.push({ + var n = Selected.Nodes[i] + Mouse.synapseStartCoordinates.push({ x: n.pos.getc().x, y: n.pos.getc().y }) } } else { - Metamaps.Mouse.synapseStartCoordinates = [{ + Mouse.synapseStartCoordinates = [{ x: JIT.tempNode.pos.getc().x, y: JIT.tempNode.pos.getc().y }] } - Metamaps.Mouse.synapseEndCoordinates = { + Mouse.synapseEndCoordinates = { x: pos.x, y: pos.y } } // let temp = eventInfo.getNode() - if (temp != false && temp.id != node.id && Metamaps.Selected.Nodes.indexOf(temp) == -1) { // this means a Node has been returned + if (temp != false && temp.id != node.id && Selected.Nodes.indexOf(temp) == -1) { // this means a Node has been returned JIT.tempNode2 = temp - Metamaps.Mouse.synapseEndCoordinates = { + Mouse.synapseEndCoordinates = { x: JIT.tempNode2.pos.getc().x, y: JIT.tempNode2.pos.getc().y } // before making the highlighted one bigger, make sure all the others are regular size - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + Visualize.mGraph.graph.eachNode(function (n) { n.setData('dim', 25, 'current') }) temp.setData('dim', 35, 'current') - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } else if (!temp) { JIT.tempNode2 = null - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + Visualize.mGraph.graph.eachNode(function (n) { n.setData('dim', 25, 'current') }) // pop up node creation :) @@ -852,21 +877,21 @@ const JIT = { var myY = e.clientY - 30 $('#new_topic').css('left', myX + 'px') $('#new_topic').css('top', myY + 'px') - Metamaps.Create.newTopic.x = eventInfo.getPos().x - Metamaps.Create.newTopic.y = eventInfo.getPos().y - Metamaps.Visualize.mGraph.plot() + Create.newTopic.x = eventInfo.getPos().x + Create.newTopic.y = eventInfo.getPos().y + Visualize.mGraph.plot() - Metamaps.Mouse.synapseEndCoordinates = { + Mouse.synapseEndCoordinates = { x: pos.x, y: pos.y } } } - else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && Metamaps.Active.Topic) { - Metamaps.GlobalUI.notifyUser('Cannot create in Topic view.') + else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && Active.Topic) { + GlobalUI.notifyUser('Cannot create in Topic view.') } else if ((e.button == 2 || (e.button == 0 && e.altKey) || e.buttons == 2) && !authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + GlobalUI.notifyUser('Cannot edit Public map.') } } }, // onDragMoveTopicHandler @@ -876,30 +901,30 @@ const JIT = { JIT.tempNode2 = null JIT.tempInit = false // reset the draw synapse positions to false - Metamaps.Mouse.synapseStartCoordinates = [] - Metamaps.Mouse.synapseEndCoordinates = null - Metamaps.Visualize.mGraph.plot() + Mouse.synapseStartCoordinates = [] + Mouse.synapseEndCoordinates = null + Visualize.mGraph.plot() }, // onDragCancelHandler onDragEndTopicHandler: function (node, eventInfo, e) { var midpoint = {}, pixelPos, mapping if (JIT.tempInit && JIT.tempNode2 == null) { // this means you want to add a new topic, and then a synapse - Metamaps.Create.newTopic.addSynapse = true - Metamaps.Create.newTopic.open() + Create.newTopic.addSynapse = true + Create.newTopic.open() } else if (JIT.tempInit && JIT.tempNode2 != null) { // this means you want to create a synapse between two existing topics - Metamaps.Create.newTopic.addSynapse = false - Metamaps.Create.newSynapse.topic1id = JIT.tempNode.getData('topic').id - Metamaps.Create.newSynapse.topic2id = JIT.tempNode2.getData('topic').id + Create.newTopic.addSynapse = false + Create.newSynapse.topic1id = JIT.tempNode.getData('topic').id + Create.newSynapse.topic2id = JIT.tempNode2.getData('topic').id JIT.tempNode2.setData('dim', 25, 'current') - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() midpoint.x = JIT.tempNode.pos.getc().x + (JIT.tempNode2.pos.getc().x - JIT.tempNode.pos.getc().x) / 2 midpoint.y = JIT.tempNode.pos.getc().y + (JIT.tempNode2.pos.getc().y - JIT.tempNode.pos.getc().y) / 2 - pixelPos = Metamaps.Util.coordsToPixels(midpoint) + pixelPos = Util.coordsToPixels(midpoint) $('#new_synapse').css('left', pixelPos.x + 'px') $('#new_synapse').css('top', pixelPos.y + 'px') - Metamaps.Create.newSynapse.open() + Create.newSynapse.open() JIT.tempNode = null JIT.tempNode2 = null JIT.tempInit = false @@ -908,17 +933,17 @@ const JIT = { // check whether to save mappings var checkWhetherToSave = function () { - var map = Metamaps.Active.Map + var map = Active.Map if (!map) return false - var mapper = Metamaps.Active.Mapper + var mapper = Active.Mapper // this case // covers when it is a public map owned by you // and also when it's a private map var activeMappersMap = map.authorizePermissionChange(mapper) var commonsMap = map.get('permission') === 'commons' - var realtimeOn = Metamaps.Realtime.status + var realtimeOn = Realtime.status // don't save if commons map, and you have realtime off, // even if you're map creator @@ -932,9 +957,9 @@ const JIT = { yloc: node.getPos().y }) // also save any other selected nodes that also got dragged along - var l = Metamaps.Selected.Nodes.length + var l = Selected.Nodes.length for (var i = l - 1; i >= 0; i -= 1) { - var n = Metamaps.Selected.Nodes[i] + var n = Selected.Nodes[i] if (n !== node) { mapping = n.getData('mapping') mapping.save({ @@ -948,61 +973,61 @@ const JIT = { }, // onDragEndTopicHandler canvasClickHandler: function (canvasLoc, e) { // grab the location and timestamp of the click - var storedTime = Metamaps.Mouse.lastCanvasClick + var storedTime = Mouse.lastCanvasClick var now = Date.now() // not compatible with IE8 FYI - Metamaps.Mouse.lastCanvasClick = now + Mouse.lastCanvasClick = now - var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map && Active.Map.authorizeToEdit(Active.Mapper) - if (now - storedTime < Metamaps.Mouse.DOUBLE_CLICK_TOLERANCE && !Metamaps.Mouse.didPan) { - if (Metamaps.Active.Map && !authorized) { - Metamaps.GlobalUI.notifyUser('Cannot edit Public map.') + if (now - storedTime < Mouse.DOUBLE_CLICK_TOLERANCE && !Mouse.didPan) { + if (Active.Map && !authorized) { + GlobalUI.notifyUser('Cannot edit Public map.') return } - else if (Metamaps.Active.Topic) { - Metamaps.GlobalUI.notifyUser('Cannot create in Topic view.') + else if (Active.Topic) { + GlobalUI.notifyUser('Cannot create in Topic view.') return } // DOUBLE CLICK // pop up node creation :) - Metamaps.Create.newTopic.addSynapse = false - Metamaps.Create.newTopic.x = canvasLoc.x - Metamaps.Create.newTopic.y = canvasLoc.y + Create.newTopic.addSynapse = false + Create.newTopic.x = canvasLoc.x + Create.newTopic.y = canvasLoc.y $('#new_topic').css('left', e.clientX + 'px') $('#new_topic').css('top', e.clientY + 'px') - Metamaps.Create.newTopic.open() - } else if (!Metamaps.Mouse.didPan) { + Create.newTopic.open() + } else if (!Mouse.didPan) { // SINGLE CLICK, no pan - Metamaps.Filter.close() - Metamaps.TopicCard.hideCard() - Metamaps.SynapseCard.hideCard() - Metamaps.Create.newTopic.hide() + Filter.close() + TopicCard.hideCard() + SynapseCard.hideCard() + Create.newTopic.hide() $('.rightclickmenu').remove() // reset the draw synapse positions to false - Metamaps.Mouse.synapseStartCoordinates = [] - Metamaps.Mouse.synapseEndCoordinates = null + Mouse.synapseStartCoordinates = [] + Mouse.synapseEndCoordinates = null JIT.tempInit = false JIT.tempNode = null JIT.tempNode2 = null if (!e.ctrlKey && !e.shiftKey) { - Metamaps.Control.deselectAllEdges() - Metamaps.Control.deselectAllNodes() + Control.deselectAllEdges() + Control.deselectAllNodes() } } }, // canvasClickHandler nodeDoubleClickHandler: function (node, e) { - Metamaps.TopicCard.showCard(node) + TopicCard.showCard(node) }, // nodeDoubleClickHandler edgeDoubleClickHandler: function (adj, e) { - Metamaps.SynapseCard.showCard(adj, e) + SynapseCard.showCard(adj, e) }, // nodeDoubleClickHandler nodeWasDoubleClicked: function () { // grab the timestamp of the click - var storedTime = Metamaps.Mouse.lastNodeClick + var storedTime = Mouse.lastNodeClick var now = Date.now() // not compatible with IE8 FYI - Metamaps.Mouse.lastNodeClick = now + Mouse.lastNodeClick = now - if (now - storedTime < Metamaps.Mouse.DOUBLE_CLICK_TOLERANCE) { + if (now - storedTime < Mouse.DOUBLE_CLICK_TOLERANCE) { return true } else { return false @@ -1015,12 +1040,12 @@ const JIT = { // 3 others are selected only, no shift: drag only this one // 4 this node and others were selected, so drag them (just return false) // return value: deselect node again after? - if (Metamaps.Selected.Nodes.length == 0) { + if (Selected.Nodes.length == 0) { return 'only-drag-this-one' } - if (Metamaps.Selected.Nodes.indexOf(node) == -1) { + if (Selected.Nodes.indexOf(node) == -1) { if (e.shiftKey) { - Metamaps.Control.selectNode(node, e) + Control.selectNode(node, e) return 'nothing' } else { return 'only-drag-this-one' @@ -1040,18 +1065,18 @@ const JIT = { }, selectWithBox: function (e) { var self = this - var sX = Metamaps.Mouse.boxStartCoordinates.x, - sY = Metamaps.Mouse.boxStartCoordinates.y, - eX = Metamaps.Mouse.boxEndCoordinates.x, - eY = Metamaps.Mouse.boxEndCoordinates.y + var sX = Mouse.boxStartCoordinates.x, + sY = Mouse.boxStartCoordinates.y, + eX = Mouse.boxEndCoordinates.x, + eY = Mouse.boxEndCoordinates.y if (!e.shiftKey) { - Metamaps.Control.deselectAllNodes() - Metamaps.Control.deselectAllEdges() + Control.deselectAllNodes() + Control.deselectAllEdges() } // select all nodes that are within the box - Metamaps.Visualize.mGraph.graph.eachNode(function(n) { + Visualize.mGraph.graph.eachNode(function(n) { var pos = self.getNodeXY(n) var x = pos.x, y = pos.y @@ -1064,12 +1089,12 @@ const JIT = { (sX < x && x < eX && sY > y && y > eY)) { if (e.shiftKey) { if (n.selected) { - Metamaps.Control.deselectNode(n) + Control.deselectNode(n) } else { - Metamaps.Control.selectNode(n, e) + Control.selectNode(n, e) } } else { - Metamaps.Control.selectNode(n, e) + Control.selectNode(n, e) } } }) @@ -1170,30 +1195,30 @@ const JIT = { if (selectTest) { // shiftKey = toggleSelect, otherwise if (e.shiftKey) { - if (Metamaps.Selected.Edges.indexOf(edge) != -1) { - Metamaps.Control.deselectEdge(edge) + if (Selected.Edges.indexOf(edge) != -1) { + Control.deselectEdge(edge) } else { - Metamaps.Control.selectEdge(edge) + Control.selectEdge(edge) } } else { - Metamaps.Control.selectEdge(edge) + Control.selectEdge(edge) } } }) - Metamaps.Mouse.boxStartCoordinates = false - Metamaps.Mouse.boxEndCoordinates = false - Metamaps.Visualize.mGraph.plot() + Mouse.boxStartCoordinates = false + Mouse.boxEndCoordinates = false + Visualize.mGraph.plot() }, // selectWithBox drawSelectBox: function (eventInfo, e) { - var ctx = Metamaps.Visualize.mGraph.canvas.getCtx() + var ctx = Visualize.mGraph.canvas.getCtx() - var startX = Metamaps.Mouse.boxStartCoordinates.x, - startY = Metamaps.Mouse.boxStartCoordinates.y, + var startX = Mouse.boxStartCoordinates.x, + startY = Mouse.boxStartCoordinates.y, currX = eventInfo.getPos().x, currY = eventInfo.getPos().y - Metamaps.Visualize.mGraph.canvas.clear() - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.canvas.clear() + Visualize.mGraph.plot() ctx.beginPath() ctx.moveTo(startX, startY) @@ -1205,7 +1230,7 @@ const JIT = { ctx.stroke() }, // drawSelectBox selectNodeOnClickHandler: function (node, e) { - if (Metamaps.Visualize.mGraph.busy) return + if (Visualize.mGraph.busy) return var self = JIT @@ -1216,8 +1241,8 @@ const JIT = { } // if on a topic page, let alt+click center you on a new topic - if (Metamaps.Active.Topic && e.altKey) { - Metamaps.RGraph.centerOn(node.id) + if (Active.Topic && e.altKey) { + JIT.RGraph.centerOn(node.id) return } @@ -1232,24 +1257,24 @@ const JIT = { var nodeAlreadySelected = node.selected if (!e.shiftKey) { - Metamaps.Control.deselectAllNodes() - Metamaps.Control.deselectAllEdges() + Control.deselectAllNodes() + Control.deselectAllEdges() } if (nodeAlreadySelected) { - Metamaps.Control.deselectNode(node) + Control.deselectNode(node) } else { - Metamaps.Control.selectNode(node, e) + Control.selectNode(node, e) } // trigger animation to final styles - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.animate({ modes: ['edge-property:lineWidth:color:alpha'], duration: 500 }) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } - }, Metamaps.Mouse.DOUBLE_CLICK_TOLERANCE) + }, Mouse.DOUBLE_CLICK_TOLERANCE) } }, // selectNodeOnClickHandler selectNodeOnRightClickHandler: function (node, e) { @@ -1259,10 +1284,10 @@ const JIT = { e.preventDefault() e.stopPropagation() - if (Metamaps.Visualize.mGraph.busy) return + if (Visualize.mGraph.busy) return // select the node - Metamaps.Control.selectNode(node, e) + Control.selectNode(node, e) // delete old right click menu $('.rightclickmenu').remove() @@ -1272,20 +1297,20 @@ const JIT = { // add the proper options to the menu var menustring = '
      ' - var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map && Active.Map.authorizeToEdit(Active.Mapper) var disabled = authorized ? '' : 'disabled' - if (Metamaps.Active.Map) menustring += '
    • Hide until refresh
      Ctrl+H
    • ' - if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '
    • Remove from map
      Ctrl+M
    • ' - if (Metamaps.Active.Topic) menustring += '
    • Remove from view
      Ctrl+M
    • ' - if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '
    • Delete
      Ctrl+D
    • ' + if (Active.Map) menustring += '
    • Hide until refresh
      Ctrl+H
    • ' + if (Active.Map && Active.Mapper) menustring += '
    • Remove from map
      Ctrl+M
    • ' + if (Active.Topic) menustring += '
    • Remove from view
      Ctrl+M
    • ' + if (Active.Map && Active.Mapper) menustring += '
    • Delete
      Ctrl+D
    • ' - if (Metamaps.Active.Topic) { + if (Active.Topic) { menustring += '
    • Center this topic
      Alt+E
    • ' } menustring += '
    • Open in new tab
    • ' - if (Metamaps.Active.Mapper) { + if (Active.Mapper) { var options = '
      • commons
      • \
      • public
      • \
      • private
      • \ @@ -1299,8 +1324,8 @@ const JIT = { menustring += '
      • Change metacode' + metacodeOptions + '
      • ' } - if (Metamaps.Active.Topic) { - if (!Metamaps.Active.Mapper) { + if (Active.Topic) { + if (!Active.Mapper) { menustring += '
      • ' } @@ -1358,30 +1383,30 @@ const JIT = { if (authorized) { $('.rc-delete').click(function () { $('.rightclickmenu').remove() - Metamaps.Control.deleteSelected() + Control.deleteSelected() }) } // remove the selected things from the map - if (Metamaps.Active.Topic || authorized) { + if (Active.Topic || authorized) { $('.rc-remove').click(function () { $('.rightclickmenu').remove() - Metamaps.Control.removeSelectedEdges() - Metamaps.Control.removeSelectedNodes() + Control.removeSelectedEdges() + Control.removeSelectedNodes() }) } // hide selected nodes and synapses until refresh $('.rc-hide').click(function () { $('.rightclickmenu').remove() - Metamaps.Control.hideSelectedEdges() - Metamaps.Control.hideSelectedNodes() + Control.hideSelectedEdges() + Control.hideSelectedNodes() }) // when in radial, center on the topic you picked $('.rc-center').click(function () { $('.rightclickmenu').remove() - Metamaps.Topic.centerOn(node.id) + Topic.centerOn(node.id) }) // open the entity in a new tab @@ -1395,14 +1420,14 @@ const JIT = { $('.rc-permission li').click(function () { $('.rightclickmenu').remove() // $(this).text() will be 'commons' 'public' or 'private' - Metamaps.Control.updateSelectedPermissions($(this).text()) + Control.updateSelectedPermissions($(this).text()) }) // change the metacode of all the selected nodes that you have edit permission for $('.rc-metacode li li').click(function () { $('.rightclickmenu').remove() // - Metamaps.Control.updateSelectedMetacodes($(this).attr('data-id')) + Control.updateSelectedMetacodes($(this).attr('data-id')) }) // fetch relatives @@ -1416,7 +1441,7 @@ const JIT = { $('.rc-siblings .fetchAll').click(function () { $('.rightclickmenu').remove() // data-id is a metacode id - Metamaps.Topic.fetchRelatives(node) + Topic.fetchRelatives(node) }) }, // selectNodeOnRightClickHandler, populateRightClickSiblings: function (node) { @@ -1448,7 +1473,7 @@ const JIT = { $('.rc-siblings .getSiblings').click(function () { $('.rightclickmenu').remove() // data-id is a metacode id - Metamaps.Topic.fetchRelatives(node, $(this).attr('data-id')) + Topic.fetchRelatives(node, $(this).attr('data-id')) }) } @@ -1460,7 +1485,7 @@ const JIT = { }) }, selectEdgeOnClickHandler: function (adj, e) { - if (Metamaps.Visualize.mGraph.busy) return + if (Visualize.mGraph.busy) return var self = JIT @@ -1478,22 +1503,22 @@ const JIT = { // wait a certain length of time, then check again, then run this code setTimeout(function () { if (!JIT.nodeWasDoubleClicked()) { - var edgeAlreadySelected = Metamaps.Selected.Edges.indexOf(adj) !== -1 + var edgeAlreadySelected = Selected.Edges.indexOf(adj) !== -1 if (!e.shiftKey) { - Metamaps.Control.deselectAllNodes() - Metamaps.Control.deselectAllEdges() + Control.deselectAllNodes() + Control.deselectAllEdges() } if (edgeAlreadySelected) { - Metamaps.Control.deselectEdge(adj) + Control.deselectEdge(adj) } else { - Metamaps.Control.selectEdge(adj) + Control.selectEdge(adj) } - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } - }, Metamaps.Mouse.DOUBLE_CLICK_TOLERANCE) + }, Mouse.DOUBLE_CLICK_TOLERANCE) } }, // selectEdgeOnClickHandler selectEdgeOnRightClickHandler: function (adj, e) { @@ -1507,9 +1532,9 @@ const JIT = { e.preventDefault() e.stopPropagation() - if (Metamaps.Visualize.mGraph.busy) return + if (Visualize.mGraph.busy) return - Metamaps.Control.selectEdge(adj) + Control.selectEdge(adj) // delete old right click menu $('.rightclickmenu').remove() @@ -1520,18 +1545,18 @@ const JIT = { // add the proper options to the menu var menustring = '
          ' - var authorized = Metamaps.Active.Map && Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper) + var authorized = Active.Map && Active.Map.authorizeToEdit(Active.Mapper) var disabled = authorized ? '' : 'disabled' - if (Metamaps.Active.Map) menustring += '
        • Hide until refresh
          Ctrl+H
        • ' - if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '
        • Remove from map
          Ctrl+M
        • ' - if (Metamaps.Active.Topic) menustring += '
        • Remove from view
          Ctrl+M
        • ' - if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '
        • Delete
          Ctrl+D
        • ' + if (Active.Map) menustring += '
        • Hide until refresh
          Ctrl+H
        • ' + if (Active.Map && Active.Mapper) menustring += '
        • Remove from map
          Ctrl+M
        • ' + if (Active.Topic) menustring += '
        • Remove from view
          Ctrl+M
        • ' + if (Active.Map && Active.Mapper) menustring += '
        • Delete
          Ctrl+D
        • ' - if (Metamaps.Active.Map && Metamaps.Active.Mapper) menustring += '
        • ' + if (Active.Map && Active.Mapper) menustring += '
        • ' - if (Metamaps.Active.Mapper) { + if (Active.Mapper) { var permOptions = '
          • commons
          • \
          • public
          • \
          • private
          • \ @@ -1582,7 +1607,7 @@ const JIT = { if (authorized) { $('.rc-delete').click(function () { $('.rightclickmenu').remove() - Metamaps.Control.deleteSelected() + Control.deleteSelected() }) } @@ -1590,30 +1615,30 @@ const JIT = { if (authorized) { $('.rc-remove').click(function () { $('.rightclickmenu').remove() - Metamaps.Control.removeSelectedEdges() - Metamaps.Control.removeSelectedNodes() + Control.removeSelectedEdges() + Control.removeSelectedNodes() }) } // hide selected nodes and synapses until refresh $('.rc-hide').click(function () { $('.rightclickmenu').remove() - Metamaps.Control.hideSelectedEdges() - Metamaps.Control.hideSelectedNodes() + Control.hideSelectedEdges() + Control.hideSelectedNodes() }) // change the permission of all the selected nodes and synapses that you were the originator of $('.rc-permission li').click(function () { $('.rightclickmenu').remove() // $(this).text() will be 'commons' 'public' or 'private' - Metamaps.Control.updateSelectedPermissions($(this).text()) + Control.updateSelectedPermissions($(this).text()) }) }, // selectEdgeOnRightClickHandler SmoothPanning: function () { - var sx = Metamaps.Visualize.mGraph.canvas.scaleOffsetX, - sy = Metamaps.Visualize.mGraph.canvas.scaleOffsetY, - y_velocity = Metamaps.Mouse.changeInY, // initial y velocity - x_velocity = Metamaps.Mouse.changeInX, // initial x velocity + var sx = Visualize.mGraph.canvas.scaleOffsetX, + sy = Visualize.mGraph.canvas.scaleOffsetY, + y_velocity = Mouse.changeInY, // initial y velocity + x_velocity = Mouse.changeInX, // initial x velocity easing = 1 // frictional value easing = 1 @@ -1623,7 +1648,7 @@ const JIT = { }, 1) function myTimer () { - Metamaps.Visualize.mGraph.canvas.translate(x_velocity * easing * 1 / sx, y_velocity * easing * 1 / sy) + Visualize.mGraph.canvas.translate(x_velocity * easing * 1 / sx, y_velocity * easing * 1 / sy) $(document).trigger(JIT.events.pan) easing = easing * 0.75 @@ -1725,11 +1750,11 @@ const JIT = { } }, // renderEdgeArrows zoomIn: function (event) { - Metamaps.Visualize.mGraph.canvas.scale(1.25, 1.25) + Visualize.mGraph.canvas.scale(1.25, 1.25) $(document).trigger(JIT.events.zoom, [event]) }, zoomOut: function (event) { - Metamaps.Visualize.mGraph.canvas.scale(0.8, 0.8) + Visualize.mGraph.canvas.scale(0.8, 0.8) $(document).trigger(JIT.events.zoom, [event]) }, centerMap: function (canvas) { @@ -1743,12 +1768,12 @@ const JIT = { canvas.translate(-1 * offsetX, -1 * offsetY) }, zoomToBox: function (event) { - var sX = Metamaps.Mouse.boxStartCoordinates.x, - sY = Metamaps.Mouse.boxStartCoordinates.y, - eX = Metamaps.Mouse.boxEndCoordinates.x, - eY = Metamaps.Mouse.boxEndCoordinates.y + var sX = Mouse.boxStartCoordinates.x, + sY = Mouse.boxStartCoordinates.y, + eX = Mouse.boxEndCoordinates.x, + eY = Mouse.boxEndCoordinates.y - var canvas = Metamaps.Visualize.mGraph.canvas + var canvas = Visualize.mGraph.canvas JIT.centerMap(canvas) var height = $(document).height(), @@ -1778,9 +1803,9 @@ const JIT = { canvas.translate(-1 * cogX, -1 * cogY) $(document).trigger(JIT.events.zoom, [event]) - Metamaps.Mouse.boxStartCoordinates = false - Metamaps.Mouse.boxEndCoordinates = false - Metamaps.Visualize.mGraph.plot() + Mouse.boxStartCoordinates = false + Mouse.boxEndCoordinates = false + Visualize.mGraph.plot() }, zoomExtents: function (event, canvas, denySelected) { JIT.centerMap(canvas) @@ -1788,10 +1813,10 @@ const JIT = { width = canvas.getSize().width, maxX, minX, maxY, minY, counter = 0 - if (!denySelected && Metamaps.Selected.Nodes.length > 0) { - var nodes = Metamaps.Selected.Nodes + if (!denySelected && Selected.Nodes.length > 0) { + var nodes = Selected.Nodes } else { - var nodes = _.values(Metamaps.Visualize.mGraph.graph.nodes) + var nodes = _.values(Visualize.mGraph.graph.nodes) } if (nodes.length > 1) { @@ -1806,7 +1831,7 @@ const JIT = { minY = y } - var arrayOfLabelLines = Metamaps.Util.splitLine(n.name, 30).split('\n'), + var arrayOfLabelLines = Util.splitLine(n.name, 30).split('\n'), dim = n.getData('dim'), ctx = canvas.getCtx() diff --git a/frontend/src/Metamaps/Listeners.js b/frontend/src/Metamaps/Listeners.js index 1c56b679..78e881d4 100644 --- a/frontend/src/Metamaps/Listeners.js +++ b/frontend/src/Metamaps/Listeners.js @@ -1,57 +1,59 @@ -/* global Metamaps, $ */ +/* global $ */ + +import Active from './Active' +import Control from './Control' +import JIT from './JIT' +import Mobile from './Mobile' +import Realtime from './Realtime' +import Selected from './Selected' +import Topic from './Topic' +import Visualize from './Visualize' -/* - * Dependencies: - * - Metamaps.Active - * - Metamaps.Control - * - Metamaps.JIT - * - Metamaps.Visualize - */ const Listeners = { init: function () { var self = this $(document).on('keydown', function (e) { - if (!(Metamaps.Active.Map || Metamaps.Active.Topic)) return + if (!(Active.Map || Active.Topic)) return switch (e.which) { case 13: // if enter key is pressed - Metamaps.JIT.enterKeyHandler() + JIT.enterKeyHandler() e.preventDefault() break case 27: // if esc key is pressed - Metamaps.JIT.escKeyHandler() + JIT.escKeyHandler() break case 65: // if a or A is pressed if (e.ctrlKey) { - Metamaps.Control.deselectAllNodes() - Metamaps.Control.deselectAllEdges() + Control.deselectAllNodes() + Control.deselectAllEdges() e.preventDefault() - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { - Metamaps.Control.selectNode(n, e) + Visualize.mGraph.graph.eachNode(function (n) { + Control.selectNode(n, e) }) - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } break case 68: // if d or D is pressed if (e.ctrlKey) { e.preventDefault() - Metamaps.Control.deleteSelected() + Control.deleteSelected() } break case 69: // if e or E is pressed - if (e.ctrlKey && Metamaps.Active.Map) { + if (e.ctrlKey && Active.Map) { e.preventDefault() - Metamaps.JIT.zoomExtents(null, Metamaps.Visualize.mGraph.canvas) + JIT.zoomExtents(null, Visualize.mGraph.canvas) break } - if (e.altKey && Metamaps.Active.Topic) { + if (e.altKey && Active.Topic) { e.preventDefault() - if (Metamaps.Active.Topic) { - self.centerAndReveal(Metamaps.Selected.Nodes, { + if (Active.Topic) { + self.centerAndReveal(Selected.Nodes, { center: true, reveal: false }) @@ -62,30 +64,30 @@ const Listeners = { case 72: // if h or H is pressed if (e.ctrlKey) { e.preventDefault() - Metamaps.Control.hideSelectedNodes() - Metamaps.Control.hideSelectedEdges() + Control.hideSelectedNodes() + Control.hideSelectedEdges() } break case 77: // if m or M is pressed if (e.ctrlKey) { e.preventDefault() - Metamaps.Control.removeSelectedNodes() - Metamaps.Control.removeSelectedEdges() + Control.removeSelectedNodes() + Control.removeSelectedEdges() } break case 82: // if r or R is pressed - if (e.altKey && Metamaps.Active.Topic) { + if (e.altKey && Active.Topic) { e.preventDefault() - self.centerAndReveal(Metamaps.Selected.Nodes, { + self.centerAndReveal(Selected.Nodes, { center: false, reveal: true }) } break case 84: // if t or T is pressed - if (e.altKey && Metamaps.Active.Topic) { + if (e.altKey && Active.Topic) { e.preventDefault() - self.centerAndReveal(Metamaps.Selected.Nodes, { + self.centerAndReveal(Selected.Nodes, { center: true, reveal: true }) @@ -98,23 +100,22 @@ const Listeners = { }) $(window).resize(function () { - if (Metamaps.Visualize && Metamaps.Visualize.mGraph) Metamaps.Visualize.mGraph.canvas.resize($(window).width(), $(window).height()) - if ((Metamaps.Active.Map || Metamaps.Active.Topic) && Metamaps.Famous && Metamaps.Famous.maps.surf) Metamaps.Famous.maps.reposition() - if (Metamaps.Active.Map && Metamaps.Realtime.inConversation) Metamaps.Realtime.positionVideos() - Metamaps.Mobile.resizeTitle() + if (Visualize && Visualize.mGraph) Visualize.mGraph.canvas.resize($(window).width(), $(window).height()) + if (Active.Map && Realtime.inConversation) Realtime.positionVideos() + Mobile.resizeTitle() }) }, centerAndReveal: function(nodes, opts) { if (nodes.length < 1) return var node = nodes[nodes.length - 1] if (opts.center && opts.reveal) { - Metamaps.Topic.centerOn(node.id, function() { - Metamaps.Topic.fetchRelatives(nodes) + Topic.centerOn(node.id, function() { + Topic.fetchRelatives(nodes) }) } else if (opts.center) { - Metamaps.Topic.centerOn(node.id) + Topic.centerOn(node.id) } else if (opts.reveal) { - Metamaps.Topic.fetchRelatives(nodes) + Topic.fetchRelatives(nodes) } } } diff --git a/frontend/src/Metamaps/Map.js b/frontend/src/Metamaps/Map.js index 690c2a6d..cd2c3d2e 100644 --- a/frontend/src/Metamaps/Map.js +++ b/frontend/src/Metamaps/Map.js @@ -1,30 +1,29 @@ -window.Metamaps = window.Metamaps || {} - /* global Metamaps, $ */ +import Active from './Active' +import AutoLayout from './AutoLayout' +import Create from './Create' +import Filter from './Filter' +import GlobalUI from './GlobalUI' +import JIT from './JIT' +import Realtime from './Realtime' +import Selected from './Selected' +import SynapseCard from './SynapseCard' +import TopicCard from './TopicCard' +import Visualize from './Visualize' + /* * Metamaps.Map.js.erb * * Dependencies: - * - Metamaps.AutoLayout - * - Metamaps.Create - * - Metamaps.Erb - * - Metamaps.Filter - * - Metamaps.JIT - * - Metamaps.Loading - * - Metamaps.Maps - * - Metamaps.Realtime - * - Metamaps.Router - * - Metamaps.Selected - * - Metamaps.SynapseCard - * - Metamaps.TopicCard - * - Metamaps.Visualize - * - Metamaps.Active * - Metamaps.Backbone - * - Metamaps.GlobalUI + * - Metamaps.Erb + * - Metamaps.Loading * - Metamaps.Mappers * - Metamaps.Mappings + * - Metamaps.Maps * - Metamaps.Messages + * - Metamaps.Router * - Metamaps.Synapses * - Metamaps.Topics * @@ -33,6 +32,7 @@ window.Metamaps = window.Metamaps || {} * - Metamaps.Map.InfoBox */ +window.Metamaps = window.Metamaps || {} Metamaps.Map = { events: { editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper' @@ -54,7 +54,7 @@ Metamaps.Map = { self.fork() }) - Metamaps.GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html() + GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html() self.updateStar() self.InfoBox.init() @@ -65,7 +65,7 @@ Metamaps.Map = { launch: function (id) { var bb = Metamaps.Backbone var start = function (data) { - Metamaps.Active.Map = new bb.Map(data.map) + Active.Map = new bb.Map(data.map) Metamaps.Mappers = new bb.MapperCollection(data.mappers) Metamaps.Collaborators = new bb.MapperCollection(data.collaborators) Metamaps.Topics = new bb.TopicCollection(data.topics) @@ -75,8 +75,8 @@ Metamaps.Map = { Metamaps.Stars = data.stars Metamaps.Backbone.attachCollectionEvents() - var map = Metamaps.Active.Map - var mapper = Metamaps.Active.Mapper + var map = Active.Map + var mapper = Active.Mapper // add class to .wrapper for specifying whether you can edit the map if (map.authorizeToEdit(mapper)) { @@ -95,24 +95,24 @@ Metamaps.Map = { $('#filter_by_mapper h3').html('MAPPERS') // build and render the visualization - Metamaps.Visualize.type = 'ForceDirected' - Metamaps.JIT.prepareVizData() + Visualize.type = 'ForceDirected' + JIT.prepareVizData() // update filters - Metamaps.Filter.reset() + Filter.reset() // reset selected arrays - Metamaps.Selected.reset() + Selected.reset() // set the proper mapinfobox content Metamaps.Map.InfoBox.load() // these three update the actual filter box with the right list items - Metamaps.Filter.checkMetacodes() - Metamaps.Filter.checkSynapses() - Metamaps.Filter.checkMappers() + Filter.checkMetacodes() + Filter.checkSynapses() + Filter.checkMappers() - Metamaps.Realtime.startActiveMap() + Realtime.startActiveMap() Metamaps.Loading.hide() // for mobile @@ -125,24 +125,24 @@ Metamaps.Map = { }) }, end: function () { - if (Metamaps.Active.Map) { + if (Active.Map) { $('.wrapper').removeClass('canEditMap commonsMap') - Metamaps.AutoLayout.resetSpiral() + AutoLayout.resetSpiral() $('.rightclickmenu').remove() - Metamaps.TopicCard.hideCard() - Metamaps.SynapseCard.hideCard() - Metamaps.Create.newTopic.hide(true) // true means force (and override pinned) - Metamaps.Create.newSynapse.hide() - Metamaps.Filter.close() + TopicCard.hideCard() + SynapseCard.hideCard() + Create.newTopic.hide(true) // true means force (and override pinned) + Create.newSynapse.hide() + Filter.close() Metamaps.Map.InfoBox.close() - Metamaps.Realtime.endActiveMap() + Realtime.endActiveMap() } }, updateStar: function () { - if (!Metamaps.Active.Mapper || !Metamaps.Stars) return + if (!Active.Mapper || !Metamaps.Stars) return // update the star/unstar icon - if (Metamaps.Stars.find(function (s) { return s.user_id === Metamaps.Active.Mapper.id })) { + if (Metamaps.Stars.find(function (s) { return s.user_id === Active.Mapper.id })) { $('.starMap').addClass('starred') $('.starMap .tooltipsAbove').html('Unstar') } else { @@ -153,31 +153,31 @@ Metamaps.Map = { star: function () { var self = Metamaps.Map - if (!Metamaps.Active.Map) return - $.post('/maps/' + Metamaps.Active.Map.id + '/star') - Metamaps.Stars.push({ user_id: Metamaps.Active.Mapper.id, map_id: Metamaps.Active.Map.id }) - Metamaps.Maps.Starred.add(Metamaps.Active.Map) - Metamaps.GlobalUI.notifyUser('Map is now starred') + if (!Active.Map) return + $.post('/maps/' + Active.Map.id + '/star') + Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id }) + Metamaps.Maps.Starred.add(Active.Map) + GlobalUI.notifyUser('Map is now starred') self.updateStar() }, unstar: function () { var self = Metamaps.Map - if (!Metamaps.Active.Map) return - $.post('/maps/' + Metamaps.Active.Map.id + '/unstar') - Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Metamaps.Active.Mapper.id }) - Metamaps.Maps.Starred.remove(Metamaps.Active.Map) + if (!Active.Map) return + $.post('/maps/' + Active.Map.id + '/unstar') + Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Active.Mapper.id }) + Metamaps.Maps.Starred.remove(Active.Map) self.updateStar() }, fork: function () { - Metamaps.GlobalUI.openLightbox('forkmap') + GlobalUI.openLightbox('forkmap') var nodes_data = '', synapses_data = '' var nodes_array = [] var synapses_array = [] // collect the unfiltered topics - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + Visualize.mGraph.graph.eachNode(function (n) { // if the opacity is less than 1 then it's filtered if (n.getData('alpha') === 1) { var id = n.getData('topic').id @@ -197,7 +197,7 @@ Metamaps.Map = { Metamaps.Synapses.each(function (synapse) { var desc = synapse.get('desc') - var descNotFiltered = Metamaps.Filter.visible.synapses.indexOf(desc) > -1 + var descNotFiltered = Filter.visible.synapses.indexOf(desc) > -1 // make sure that both topics are being added, otherwise, it // doesn't make sense to add the synapse var topicsNotFiltered = nodes_array.indexOf(synapse.get('node1_id')) > -1 @@ -210,32 +210,32 @@ Metamaps.Map = { synapses_data = synapses_array.join() nodes_data = nodes_data.slice(0, -1) - Metamaps.GlobalUI.CreateMap.topicsToMap = nodes_data - Metamaps.GlobalUI.CreateMap.synapsesToMap = synapses_data + GlobalUI.CreateMap.topicsToMap = nodes_data + GlobalUI.CreateMap.synapsesToMap = synapses_data }, leavePrivateMap: function () { - var map = Metamaps.Active.Map + var map = Active.Map Metamaps.Maps.Active.remove(map) Metamaps.Maps.Featured.remove(map) Metamaps.Router.home() - Metamaps.GlobalUI.notifyUser('Sorry! That map has been changed to Private.') + GlobalUI.notifyUser('Sorry! That map has been changed to Private.') }, cantEditNow: function () { - Metamaps.Realtime.turnOff(true); // true is for 'silence' - Metamaps.GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.') - Metamaps.Active.Map.trigger('changeByOther') + Realtime.turnOff(true); // true is for 'silence' + GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.') + Active.Map.trigger('changeByOther') }, canEditNow: function () { var confirmString = "You've been granted permission to edit this map. " confirmString += 'Do you want to reload and enable realtime collaboration?' var c = confirm(confirmString) if (c) { - Metamaps.Router.maps(Metamaps.Active.Map.id) + Metamaps.Router.maps(Active.Map.id) } }, editedByActiveMapper: function () { - if (Metamaps.Active.Mapper) { - Metamaps.Mappers.add(Metamaps.Active.Mapper) + if (Active.Mapper) { + Metamaps.Mappers.add(Active.Mapper) } }, exportImage: function () { @@ -282,14 +282,14 @@ Metamaps.Map = { // center it canvas.getCtx().translate(1880 / 2, 1260 / 2) - var mGraph = Metamaps.Visualize.mGraph + var mGraph = Visualize.mGraph var id = mGraph.root var root = mGraph.graph.getNode(id) var T = !!root.visited // pass true to avoid basing it on a selection - Metamaps.JIT.zoomExtents(null, canvas, true) + JIT.zoomExtents(null, canvas, true) var c = canvas.canvas, ctx = canvas.getCtx(), @@ -327,7 +327,7 @@ Metamaps.Map = { encoded_image: canvas.canvas.toDataURL() } - var map = Metamaps.Active.Map + var map = Active.Map var today = new Date() var dd = today.getDate() @@ -346,12 +346,12 @@ Metamaps.Map = { downloadMessage += 'Captured map screenshot! ' downloadMessage += "DOWNLOAD" - Metamaps.GlobalUI.notifyUser(downloadMessage) + GlobalUI.notifyUser(downloadMessage) $.ajax({ type: 'POST', dataType: 'json', - url: '/maps/' + Metamaps.Active.Map.id + '/upload_screenshot', + url: '/maps/' + Active.Map.id + '/upload_screenshot', data: imageData, success: function (data) { console.log('successfully uploaded map screenshot') @@ -461,12 +461,12 @@ Metamaps.Map.InfoBox = { load: function () { var self = Metamaps.Map.InfoBox - var map = Metamaps.Active.Map + var map = Active.Map var obj = map.pick('permission', 'topic_count', 'synapse_count') - var isCreator = map.authorizePermissionChange(Metamaps.Active.Mapper) - var canEdit = map.authorizeToEdit(Metamaps.Active.Mapper) + var isCreator = map.authorizePermissionChange(Active.Mapper) + var canEdit = map.authorizeToEdit(Active.Mapper) var relevantPeople = map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators var shareable = map.get('permission') !== 'private' @@ -519,8 +519,8 @@ Metamaps.Map.InfoBox = { $('.mapInfoName .best_in_place_name').unbind('ajax:success').bind('ajax:success', function () { var name = $(this).html() - Metamaps.Active.Map.set('name', name) - Metamaps.Active.Map.trigger('saved') + Active.Map.set('name', name) + Active.Map.trigger('saved') // mobile menu $('#header_content').html(name) $('.mapInfoBox').removeClass('mapRequestTitle') @@ -529,8 +529,8 @@ Metamaps.Map.InfoBox = { $('.mapInfoDesc .best_in_place_desc').unbind('ajax:success').bind('ajax:success', function () { var desc = $(this).html() - Metamaps.Active.Map.set('desc', desc) - Metamaps.Active.Map.trigger('saved') + Active.Map.set('desc', desc) + Active.Map.trigger('saved') }) $('.yourMap .mapPermission').unbind().click(self.onPermissionClick) @@ -558,7 +558,7 @@ Metamaps.Map.InfoBox = { addTypeahead: function () { var self = Metamaps.Map.InfoBox - if (!Metamaps.Active.Map) return + if (!Active.Map) return // for autocomplete var collaborators = { @@ -589,7 +589,7 @@ Metamaps.Map.InfoBox = { } // for adding map collaborators, who will have edit rights - if (Metamaps.Active.Mapper && Metamaps.Active.Mapper.id === Metamaps.Active.Map.get('user_id')) { + if (Active.Mapper && Active.Mapper.id === Active.Map.get('user_id')) { $('.collaboratorSearchField').typeahead( { highlight: false, @@ -606,23 +606,23 @@ Metamaps.Map.InfoBox = { var self = Metamaps.Map.InfoBox Metamaps.Collaborators.remove(Metamaps.Collaborators.get(collaboratorId)) var mapperIds = Metamaps.Collaborators.models.map(function (mapper) { return mapper.id }) - $.post('/maps/' + Metamaps.Active.Map.id + '/access', { access: mapperIds }) + $.post('/maps/' + Active.Map.id + '/access', { access: mapperIds }) self.updateNumbers() }, addCollaborator: function (newCollaboratorId) { var self = Metamaps.Map.InfoBox if (Metamaps.Collaborators.get(newCollaboratorId)) { - Metamaps.GlobalUI.notifyUser('That user already has access') + GlobalUI.notifyUser('That user already has access') return } function callback(mapper) { Metamaps.Collaborators.add(mapper) var mapperIds = Metamaps.Collaborators.models.map(function (mapper) { return mapper.id }) - $.post('/maps/' + Metamaps.Active.Map.id + '/access', { access: mapperIds }) + $.post('/maps/' + Active.Map.id + '/access', { access: mapperIds }) var name = Metamaps.Collaborators.get(newCollaboratorId).get('name') - Metamaps.GlobalUI.notifyUser(name + ' will be notified by email') + GlobalUI.notifyUser(name + ' will be notified by email') self.updateNumbers() } @@ -642,13 +642,13 @@ Metamaps.Map.InfoBox = { }, createContributorList: function () { var self = Metamaps.Map.InfoBox - var relevantPeople = Metamaps.Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators - var activeMapperIsCreator = Metamaps.Active.Mapper && Metamaps.Active.Mapper.id === Metamaps.Active.Map.get('user_id') + var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators + var activeMapperIsCreator = Active.Mapper && Active.Mapper.id === Active.Map.get('user_id') var string = '' string += '
              ' relevantPeople.each(function (m) { - var isCreator = Metamaps.Active.Map.get('user_id') === m.get('id') + var isCreator = Active.Map.get('user_id') === m.get('id') string += '
            • ' + '' + m.get('name') if (isCreator) string += ' (creator)' string += '' @@ -664,11 +664,11 @@ Metamaps.Map.InfoBox = { return string }, updateNumbers: function () { - if (!Metamaps.Active.Map) return + if (!Active.Map) return var self = Metamaps.Map.InfoBox - var mapper = Metamaps.Active.Mapper - var relevantPeople = Metamaps.Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators + var mapper = Active.Mapper + var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators var contributors_class = '' if (relevantPeople.length === 2) contributors_class = 'multiple mTwo' @@ -720,10 +720,10 @@ Metamaps.Map.InfoBox = { self.selectingPermission = false var permission = $(this).attr('class') - Metamaps.Active.Map.save({ + Active.Map.save({ permission: permission }) - Metamaps.Active.Map.updateMapWrapper() + Active.Map.updateMapWrapper() shareable = permission === 'private' ? '' : 'shareable' $('.mapPermission').removeClass('commons public private minimize').addClass(permission) $('.mapPermission .permissionSelect').remove() @@ -735,8 +735,8 @@ Metamaps.Map.InfoBox = { confirmString += 'This action is irreversible. It will not delete the topics and synapses on the map.' var doIt = confirm(confirmString) - var map = Metamaps.Active.Map - var mapper = Metamaps.Active.Mapper + var map = Active.Map + var mapper = Active.Mapper var authorized = map.authorizePermissionChange(mapper) if (doIt && authorized) { @@ -747,7 +747,7 @@ Metamaps.Map.InfoBox = { Metamaps.Maps.Shared.remove(map) map.destroy() Metamaps.Router.home() - Metamaps.GlobalUI.notifyUser('Map eliminated!') + GlobalUI.notifyUser('Map eliminated!') } else if (!authorized) { alert("Hey now. We can't just go around willy nilly deleting other people's maps now can we? Run off and find something constructive to do, eh?") diff --git a/frontend/src/Metamaps/Mapper.js b/frontend/src/Metamaps/Mapper.js index ac93c34d..3858101d 100644 --- a/frontend/src/Metamaps/Mapper.js +++ b/frontend/src/Metamaps/Mapper.js @@ -1,4 +1,6 @@ -import Backbone from './Backbone' +/* + * Metamaps.Backbone + */ const Mapper = { // this function is to retrieve a mapper JSON object from the database @@ -9,7 +11,7 @@ const Mapper = { if (!response.ok) throw response return response.json() }).then(payload => { - callback(new Backbone.Mapper(payload)) + callback(new Metamaps.Backbone.Mapper(payload)) }) } } diff --git a/frontend/src/Metamaps/PasteInput.js b/frontend/src/Metamaps/PasteInput.js index ebe1d944..e0620329 100644 --- a/frontend/src/Metamaps/PasteInput.js +++ b/frontend/src/Metamaps/PasteInput.js @@ -2,6 +2,8 @@ import AutoLayout from './AutoLayout' import Import from './Import' +import TopicCard from './TopicCard' +import Util from './Util' const PasteInput = { // thanks to https://github.com/kevva/url-regex @@ -19,7 +21,7 @@ const PasteInput = { window.addEventListener("drop", function(e) { e = e || event; e.preventDefault(); - var coords = Metamaps.Util.pixelsToCoords({ x: e.clientX, y: e.clientY }) + var coords = Util.pixelsToCoords({ x: e.clientX, y: e.clientY }) if (e.dataTransfer.files.length > 0) { var fileReader = new FileReader() var text = fileReader.readAsText(e.dataTransfer.files[0]) @@ -86,7 +88,7 @@ const PasteInput = { import_id, { success: function(topic) { - Metamaps.TopicCard.showCard(topic.get('node'), function() { + TopicCard.showCard(topic.get('node'), function() { $('#showcard #titleActivator').click() .find('textarea, input').focus() }) diff --git a/frontend/src/Metamaps/Realtime.js b/frontend/src/Metamaps/Realtime.js index 35d00f06..1eef6408 100644 --- a/frontend/src/Metamaps/Realtime.js +++ b/frontend/src/Metamaps/Realtime.js @@ -1,27 +1,27 @@ /* global Metamaps, $ */ +import Active from './Active' +import Control from './Control' +import GlobalUI from './GlobalUI' +import JIT from './JIT' +import Map from './Map' +import Mapper from './Mapper' +import Topic from './Topic' +import Util from './Util' +import Views from './Views' +import Visualize from './Visualize' + /* * Metamaps.Realtime.js * * Dependencies: - * - Metamaps.Active * - Metamaps.Backbone - * - Metamaps.Backbone - * - Metamaps.Control * - Metamaps.Erb - * - Metamaps.GlobalUI - * - Metamaps.JIT - * - Metamaps.Map - * - Metamaps.Mapper * - Metamaps.Mappers * - Metamaps.Mappings * - Metamaps.Messages * - Metamaps.Synapses - * - Metamaps.Topic * - Metamaps.Topics - * - Metamaps.Util - * - Metamaps.Views - * - Metamaps.Visualize */ const Realtime = { @@ -52,7 +52,7 @@ const Realtime = { self.disconnected = true }) - if (Metamaps.Active.Mapper) { + if (Active.Mapper) { self.webrtc = new SimpleWebRTC({ connection: self.socket, localVideoEl: self.videoId, @@ -69,23 +69,23 @@ const Realtime = { video: true, audio: true }, - nick: Metamaps.Active.Mapper.id + nick: Active.Mapper.id }) var $video = $('').attr('id', self.videoId) self.localVideo = { $video: $video, - view: new Metamaps.Views.videoView($video[0], $('body'), 'me', true, { + view: new Views.videoView($video[0], $('body'), 'me', true, { DOUBLE_CLICK_TOLERANCE: 200, - avatar: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('image') : '' + avatar: Active.Mapper ? Active.Mapper.get('image') : '' }) } - self.room = new Metamaps.Views.room({ + self.room = new Views.room({ webrtc: self.webrtc, socket: self.socket, - username: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('name') : '', - image: Metamaps.Active.Mapper ? Metamaps.Active.Mapper.get('image') : '', + username: Active.Mapper ? Active.Mapper.get('name') : '', + image: Active.Mapper ? Active.Mapper.get('image') : '', room: 'global', $video: self.localVideo.$video, myVideoView: self.localVideo.view, @@ -93,35 +93,35 @@ const Realtime = { }) self.room.videoAdded(self.handleVideoAdded) - if (!Metamaps.Active.Map) { + if (!Active.Map) { self.room.chat.$container.hide() } $('body').prepend(self.room.chat.$container) - } // if Metamaps.Active.Mapper + } // if Active.Mapper }, addJuntoListeners: function () { var self = Realtime - $(document).on(Metamaps.Views.chatView.events.openTray, function () { + $(document).on(Views.chatView.events.openTray, function () { $('.main').addClass('compressed') self.chatOpen = true self.positionPeerIcons() }) - $(document).on(Metamaps.Views.chatView.events.closeTray, function () { + $(document).on(Views.chatView.events.closeTray, function () { $('.main').removeClass('compressed') self.chatOpen = false self.positionPeerIcons() }) - $(document).on(Metamaps.Views.chatView.events.videosOn, function () { + $(document).on(Views.chatView.events.videosOn, function () { $('#wrapper').removeClass('hideVideos') }) - $(document).on(Metamaps.Views.chatView.events.videosOff, function () { + $(document).on(Views.chatView.events.videosOff, function () { $('#wrapper').addClass('hideVideos') }) - $(document).on(Metamaps.Views.chatView.events.cursorsOn, function () { + $(document).on(Views.chatView.events.cursorsOn, function () { $('#wrapper').removeClass('hideCursors') }) - $(document).on(Metamaps.Views.chatView.events.cursorsOff, function () { + $(document).on(Views.chatView.events.cursorsOff, function () { $('#wrapper').addClass('hideCursors') }) }, @@ -187,8 +187,8 @@ const Realtime = { startActiveMap: function () { var self = Realtime - if (Metamaps.Active.Map && Metamaps.Active.Mapper) { - if (Metamaps.Active.Map.authorizeToEdit(Metamaps.Active.Mapper)) { + if (Active.Map && Active.Mapper) { + if (Active.Map.authorizeToEdit(Active.Mapper)) { self.turnOn() self.setupSocket() } else { @@ -219,15 +219,15 @@ const Realtime = { self.status = true $('.collabCompass').show() self.room.chat.$container.show() - self.room.room = 'map-' + Metamaps.Active.Map.id + self.room.room = 'map-' + Active.Map.id self.checkForACallToJoin() self.activeMapper = { - id: Metamaps.Active.Mapper.id, - name: Metamaps.Active.Mapper.get('name'), - username: Metamaps.Active.Mapper.get('name'), - image: Metamaps.Active.Mapper.get('image'), - color: Metamaps.Util.getPastelColor(), + id: Active.Mapper.id, + name: Active.Mapper.get('name'), + username: Active.Mapper.get('name'), + image: Active.Mapper.get('image'), + color: Util.getPastelColor(), self: true } self.localVideo.view.$container.find('.video-cutoff').css({ @@ -237,7 +237,7 @@ const Realtime = { }, checkForACallToJoin: function () { var self = Realtime - self.socket.emit('checkForCall', { room: self.room.room, mapid: Metamaps.Active.Map.id }) + self.socket.emit('checkForCall', { room: self.room.room, mapid: Active.Map.id }) }, promptToJoin: function () { var self = Realtime @@ -245,7 +245,7 @@ const Realtime = { var notifyText = "There's a conversation happening, want to join?" notifyText += ' ' notifyText += ' ' - Metamaps.GlobalUI.notifyUser(notifyText, true) + GlobalUI.notifyUser(notifyText, true) self.room.conversationInProgress() }, conversationHasBegun: function () { @@ -255,7 +255,7 @@ const Realtime = { var notifyText = "There's a conversation starting, want to join?" notifyText += ' ' notifyText += ' ' - Metamaps.GlobalUI.notifyUser(notifyText, true) + GlobalUI.notifyUser(notifyText, true) self.room.conversationInProgress() }, countOthersInConversation: function () { @@ -275,7 +275,7 @@ const Realtime = { if (self.inConversation) { var username = mapper.name var notifyText = username + ' joined the call' - Metamaps.GlobalUI.notifyUser(notifyText) + GlobalUI.notifyUser(notifyText) } mapper.inConversation = true @@ -290,7 +290,7 @@ const Realtime = { if (self.inConversation) { var username = mapper.name var notifyText = username + ' left the call' - Metamaps.GlobalUI.notifyUser(notifyText) + GlobalUI.notifyUser(notifyText) } mapper.inConversation = false @@ -332,7 +332,7 @@ const Realtime = { notifyText += username + ' is inviting you to a conversation. Join live?' notifyText += ' ' notifyText += ' ' - Metamaps.GlobalUI.notifyUser(notifyText, true) + GlobalUI.notifyUser(notifyText, true) }, invitedToJoin: function (inviter) { var self = Realtime @@ -344,55 +344,55 @@ const Realtime = { var notifyText = username + ' is inviting you to the conversation. Join?' notifyText += ' ' notifyText += ' ' - Metamaps.GlobalUI.notifyUser(notifyText, true) + GlobalUI.notifyUser(notifyText, true) }, acceptCall: function (userid) { var self = Realtime self.room.chat.sound.stop('sessioninvite') self.socket.emit('callAccepted', { - mapid: Metamaps.Active.Map.id, - invited: Metamaps.Active.Mapper.id, + mapid: Active.Map.id, + invited: Active.Mapper.id, inviter: userid }) - $.post('/maps/' + Metamaps.Active.Map.id + '/events/conversation') + $.post('/maps/' + Active.Map.id + '/events/conversation') self.joinCall() - Metamaps.GlobalUI.clearNotify() + GlobalUI.clearNotify() }, denyCall: function (userid) { var self = Realtime self.room.chat.sound.stop('sessioninvite') self.socket.emit('callDenied', { - mapid: Metamaps.Active.Map.id, - invited: Metamaps.Active.Mapper.id, + mapid: Active.Map.id, + invited: Active.Mapper.id, inviter: userid }) - Metamaps.GlobalUI.clearNotify() + GlobalUI.clearNotify() }, denyInvite: function (userid) { var self = Realtime self.room.chat.sound.stop('sessioninvite') self.socket.emit('inviteDenied', { - mapid: Metamaps.Active.Map.id, - invited: Metamaps.Active.Mapper.id, + mapid: Active.Map.id, + invited: Active.Mapper.id, inviter: userid }) - Metamaps.GlobalUI.clearNotify() + GlobalUI.clearNotify() }, inviteACall: function (userid) { var self = Realtime self.socket.emit('inviteACall', { - mapid: Metamaps.Active.Map.id, - inviter: Metamaps.Active.Mapper.id, + mapid: Active.Map.id, + inviter: Active.Mapper.id, invited: userid }) self.room.chat.invitationPending(userid) - Metamaps.GlobalUI.clearNotify() + GlobalUI.clearNotify() }, inviteToJoin: function (userid) { var self = Realtime self.socket.emit('inviteToJoin', { - mapid: Metamaps.Active.Map.id, - inviter: Metamaps.Active.Mapper.id, + mapid: Active.Map.id, + inviter: Active.Mapper.id, invited: userid }) self.room.chat.invitationPending(userid) @@ -401,7 +401,7 @@ const Realtime = { var self = Realtime var username = self.mappersOnMap[userid].name - Metamaps.GlobalUI.notifyUser('Conversation starting...') + GlobalUI.notifyUser('Conversation starting...') self.joinCall() self.room.chat.invitationAnswered(userid) }, @@ -409,14 +409,14 @@ const Realtime = { var self = Realtime var username = self.mappersOnMap[userid].name - Metamaps.GlobalUI.notifyUser(username + " didn't accept your invitation") + GlobalUI.notifyUser(username + " didn't accept your invitation") self.room.chat.invitationAnswered(userid) }, inviteDenied: function (userid) { var self = Realtime var username = self.mappersOnMap[userid].name - Metamaps.GlobalUI.notifyUser(username + " didn't accept your invitation") + GlobalUI.notifyUser(username + " didn't accept your invitation") self.room.chat.invitationAnswered(userid) }, joinCall: function () { @@ -436,22 +436,22 @@ const Realtime = { }) self.inConversation = true self.socket.emit('mapperJoinedCall', { - mapid: Metamaps.Active.Map.id, - id: Metamaps.Active.Mapper.id + mapid: Active.Map.id, + id: Active.Mapper.id }) self.webrtc.startLocalVideo() - Metamaps.GlobalUI.clearNotify() - self.room.chat.mapperJoinedCall(Metamaps.Active.Mapper.id) + GlobalUI.clearNotify() + self.room.chat.mapperJoinedCall(Active.Mapper.id) }, leaveCall: function () { var self = Realtime self.socket.emit('mapperLeftCall', { - mapid: Metamaps.Active.Map.id, - id: Metamaps.Active.Mapper.id + mapid: Active.Map.id, + id: Active.Mapper.id }) - self.room.chat.mapperLeftCall(Metamaps.Active.Mapper.id) + self.room.chat.mapperLeftCall(Active.Mapper.id) self.room.leaveVideoOnly() self.inConversation = false self.localVideo.view.$container.hide() @@ -479,63 +479,63 @@ const Realtime = { setupSocket: function () { var self = Realtime var socket = Realtime.socket - var myId = Metamaps.Active.Mapper.id + var myId = Active.Mapper.id socket.emit('newMapperNotify', { userid: myId, - username: Metamaps.Active.Mapper.get('name'), - userimage: Metamaps.Active.Mapper.get('image'), - mapid: Metamaps.Active.Map.id + username: Active.Mapper.get('name'), + userimage: Active.Mapper.get('image'), + mapid: Active.Map.id }) - socket.on(myId + '-' + Metamaps.Active.Map.id + '-invitedToCall', self.invitedToCall) // new call - socket.on(myId + '-' + Metamaps.Active.Map.id + '-invitedToJoin', self.invitedToJoin) // call already in progress - socket.on(myId + '-' + Metamaps.Active.Map.id + '-callAccepted', self.callAccepted) - socket.on(myId + '-' + Metamaps.Active.Map.id + '-callDenied', self.callDenied) - socket.on(myId + '-' + Metamaps.Active.Map.id + '-inviteDenied', self.inviteDenied) + socket.on(myId + '-' + Active.Map.id + '-invitedToCall', self.invitedToCall) // new call + socket.on(myId + '-' + Active.Map.id + '-invitedToJoin', self.invitedToJoin) // call already in progress + socket.on(myId + '-' + Active.Map.id + '-callAccepted', self.callAccepted) + socket.on(myId + '-' + Active.Map.id + '-callDenied', self.callDenied) + socket.on(myId + '-' + Active.Map.id + '-inviteDenied', self.inviteDenied) // receive word that there's a conversation in progress - socket.on('maps-' + Metamaps.Active.Map.id + '-callInProgress', self.promptToJoin) - socket.on('maps-' + Metamaps.Active.Map.id + '-callStarting', self.conversationHasBegun) + socket.on('maps-' + Active.Map.id + '-callInProgress', self.promptToJoin) + socket.on('maps-' + Active.Map.id + '-callStarting', self.conversationHasBegun) - socket.on('maps-' + Metamaps.Active.Map.id + '-mapperJoinedCall', self.mapperJoinedCall) - socket.on('maps-' + Metamaps.Active.Map.id + '-mapperLeftCall', self.mapperLeftCall) + socket.on('maps-' + Active.Map.id + '-mapperJoinedCall', self.mapperJoinedCall) + socket.on('maps-' + Active.Map.id + '-mapperLeftCall', self.mapperLeftCall) // if you're the 'new guy' update your list with who's already online - socket.on(myId + '-' + Metamaps.Active.Map.id + '-UpdateMapperList', self.updateMapperList) + socket.on(myId + '-' + Active.Map.id + '-UpdateMapperList', self.updateMapperList) // receive word that there's a new mapper on the map - socket.on('maps-' + Metamaps.Active.Map.id + '-newmapper', self.newPeerOnMap) + socket.on('maps-' + Active.Map.id + '-newmapper', self.newPeerOnMap) // receive word that a mapper left the map - socket.on('maps-' + Metamaps.Active.Map.id + '-lostmapper', self.lostPeerOnMap) + socket.on('maps-' + Active.Map.id + '-lostmapper', self.lostPeerOnMap) // receive word that there's a mapper turned on realtime - socket.on('maps-' + Metamaps.Active.Map.id + '-newrealtime', self.newCollaborator) + socket.on('maps-' + Active.Map.id + '-newrealtime', self.newCollaborator) // receive word that there's a mapper turned on realtime - socket.on('maps-' + Metamaps.Active.Map.id + '-lostrealtime', self.lostCollaborator) + socket.on('maps-' + Active.Map.id + '-lostrealtime', self.lostCollaborator) // - socket.on('maps-' + Metamaps.Active.Map.id + '-topicDrag', self.topicDrag) + socket.on('maps-' + Active.Map.id + '-topicDrag', self.topicDrag) // - socket.on('maps-' + Metamaps.Active.Map.id + '-newTopic', self.newTopic) + socket.on('maps-' + Active.Map.id + '-newTopic', self.newTopic) // - socket.on('maps-' + Metamaps.Active.Map.id + '-newMessage', self.newMessage) + socket.on('maps-' + Active.Map.id + '-newMessage', self.newMessage) // - socket.on('maps-' + Metamaps.Active.Map.id + '-removeTopic', self.removeTopic) + socket.on('maps-' + Active.Map.id + '-removeTopic', self.removeTopic) // - socket.on('maps-' + Metamaps.Active.Map.id + '-newSynapse', self.newSynapse) + socket.on('maps-' + Active.Map.id + '-newSynapse', self.newSynapse) // - socket.on('maps-' + Metamaps.Active.Map.id + '-removeSynapse', self.removeSynapse) + socket.on('maps-' + Active.Map.id + '-removeSynapse', self.removeSynapse) // update mapper compass position - socket.on('maps-' + Metamaps.Active.Map.id + '-updatePeerCoords', self.updatePeerCoords) + socket.on('maps-' + Active.Map.id + '-updatePeerCoords', self.updatePeerCoords) // deletions socket.on('deleteTopicFromServer', self.removeTopic) @@ -551,7 +551,7 @@ const Realtime = { x: event.pageX, y: event.pageY } - var coords = Metamaps.Util.pixelsToCoords(pixels) + var coords = Util.pixelsToCoords(pixels) self.sendCoords(coords) } $(document).on('mousemove.map', sendCoords) @@ -562,54 +562,54 @@ const Realtime = { x: e.pageX, y: e.pageY } - var coords = Metamaps.Util.pixelsToCoords(pixels) + var coords = Util.pixelsToCoords(pixels) self.sendCoords(coords) } self.positionPeerIcons() } - $(document).on(Metamaps.JIT.events.zoom + '.map', zoom) + $(document).on(JIT.events.zoom + '.map', zoom) - $(document).on(Metamaps.JIT.events.pan + '.map', self.positionPeerIcons) + $(document).on(JIT.events.pan + '.map', self.positionPeerIcons) var sendTopicDrag = function (event, positions) { self.sendTopicDrag(positions) } - $(document).on(Metamaps.JIT.events.topicDrag + '.map', sendTopicDrag) + $(document).on(JIT.events.topicDrag + '.map', sendTopicDrag) var sendNewTopic = function (event, data) { self.sendNewTopic(data) } - $(document).on(Metamaps.JIT.events.newTopic + '.map', sendNewTopic) + $(document).on(JIT.events.newTopic + '.map', sendNewTopic) var sendDeleteTopic = function (event, data) { self.sendDeleteTopic(data) } - $(document).on(Metamaps.JIT.events.deleteTopic + '.map', sendDeleteTopic) + $(document).on(JIT.events.deleteTopic + '.map', sendDeleteTopic) var sendRemoveTopic = function (event, data) { self.sendRemoveTopic(data) } - $(document).on(Metamaps.JIT.events.removeTopic + '.map', sendRemoveTopic) + $(document).on(JIT.events.removeTopic + '.map', sendRemoveTopic) var sendNewSynapse = function (event, data) { self.sendNewSynapse(data) } - $(document).on(Metamaps.JIT.events.newSynapse + '.map', sendNewSynapse) + $(document).on(JIT.events.newSynapse + '.map', sendNewSynapse) var sendDeleteSynapse = function (event, data) { self.sendDeleteSynapse(data) } - $(document).on(Metamaps.JIT.events.deleteSynapse + '.map', sendDeleteSynapse) + $(document).on(JIT.events.deleteSynapse + '.map', sendDeleteSynapse) var sendRemoveSynapse = function (event, data) { self.sendRemoveSynapse(data) } - $(document).on(Metamaps.JIT.events.removeSynapse + '.map', sendRemoveSynapse) + $(document).on(JIT.events.removeSynapse + '.map', sendRemoveSynapse) var sendNewMessage = function (event, data) { self.sendNewMessage(data) } - $(document).on(Metamaps.Views.room.events.newMessage + '.map', sendNewMessage) + $(document).on(Views.room.events.newMessage + '.map', sendNewMessage) }, attachMapListener: function () { var self = Realtime @@ -623,9 +623,9 @@ const Realtime = { // send this new mapper back your details, and the awareness that you're online var update = { - username: Metamaps.Active.Mapper.get('name'), - userid: Metamaps.Active.Mapper.id, - mapid: Metamaps.Active.Map.id + username: Active.Mapper.get('name'), + userid: Active.Mapper.id, + mapid: Active.Map.id } socket.emit('notifyStartRealtime', update) }, @@ -635,9 +635,9 @@ const Realtime = { // send this new mapper back your details, and the awareness that you're online var update = { - username: Metamaps.Active.Mapper.get('name'), - userid: Metamaps.Active.Mapper.id, - mapid: Metamaps.Active.Map.id + username: Active.Mapper.get('name'), + userid: Active.Mapper.id, + mapid: Active.Map.id } socket.emit('notifyStopRealtime', update) }, @@ -655,7 +655,7 @@ const Realtime = { name: data.username, username: data.username, image: data.userimage, - color: Metamaps.Util.getPastelColor(), + color: Util.getPastelColor(), realtime: data.userrealtime, inConversation: data.userinconversation, coords: { @@ -664,7 +664,7 @@ const Realtime = { } } - if (data.userid !== Metamaps.Active.Mapper.id) { + if (data.userid !== Active.Mapper.id) { self.room.chat.addParticipant(self.mappersOnMap[data.userid]) if (data.userinconversation) self.room.chat.mapperJoinedCall(data.userid) @@ -687,7 +687,7 @@ const Realtime = { name: data.username, username: data.username, image: data.userimage, - color: Metamaps.Util.getPastelColor(), + color: Util.getPastelColor(), realtime: true, coords: { x: 0, @@ -696,7 +696,7 @@ const Realtime = { } // create an item for them in the realtime box - if (data.userid !== Metamaps.Active.Mapper.id && self.status) { + if (data.userid !== Active.Mapper.id && self.status) { self.room.chat.sound.play('joinmap') self.room.chat.addParticipant(self.mappersOnMap[data.userid]) @@ -707,17 +707,17 @@ const Realtime = { if (firstOtherPerson) { notifyMessage += ' ' } - Metamaps.GlobalUI.notifyUser(notifyMessage) + GlobalUI.notifyUser(notifyMessage) // send this new mapper back your details, and the awareness that you've loaded the map var update = { userToNotify: data.userid, - username: Metamaps.Active.Mapper.get('name'), - userimage: Metamaps.Active.Mapper.get('image'), - userid: Metamaps.Active.Mapper.id, + username: Active.Mapper.get('name'), + userimage: Active.Mapper.get('image'), + userid: Active.Mapper.id, userrealtime: self.status, userinconversation: self.inConversation, - mapid: Metamaps.Active.Map.id + mapid: Active.Map.id } socket.emit('updateNewMapperList', update) } @@ -753,7 +753,7 @@ const Realtime = { $('#compass' + data.userid).remove() self.room.chat.removeParticipant(data.username) - Metamaps.GlobalUI.notifyUser(data.username + ' just left the map') + GlobalUI.notifyUser(data.username + ' just left the map') if ((self.inConversation && self.countOthersInConversation() === 0) || (!self.inConversation && self.countOthersInConversation() === 1)) { @@ -772,7 +772,7 @@ const Realtime = { // $('#mapper' + data.userid).removeClass('littleRtOff').addClass('littleRtOn') $('#compass' + data.userid).show() - Metamaps.GlobalUI.notifyUser(data.username + ' just turned on realtime') + GlobalUI.notifyUser(data.username + ' just turned on realtime') }, lostCollaborator: function (data) { var self = Realtime @@ -786,7 +786,7 @@ const Realtime = { // $('#mapper' + data.userid).removeClass('littleRtOn').addClass('littleRtOff') $('#compass' + data.userid).hide() - Metamaps.GlobalUI.notifyUser(data.username + ' just turned off realtime') + GlobalUI.notifyUser(data.username + ' just turned off realtime') }, updatePeerCoords: function (data) { var self = Realtime @@ -819,7 +819,7 @@ const Realtime = { var compassDiameter = 56 var compassArrowSize = 24 - var origPixels = Metamaps.Util.coordsToPixels(mapper.coords) + var origPixels = Util.coordsToPixels(mapper.coords) var pixels = self.limitPixelsToScreen(origPixels) $('#compass' + id).css({ left: pixels.x + 'px', @@ -867,14 +867,14 @@ const Realtime = { var self = Realtime var socket = Realtime.socket - var map = Metamaps.Active.Map - var mapper = Metamaps.Active.Mapper + var map = Active.Map + var mapper = Active.Mapper if (self.status && map.authorizeToEdit(mapper) && socket) { var update = { usercoords: coords, - userid: Metamaps.Active.Mapper.id, - mapid: Metamaps.Active.Map.id + userid: Active.Mapper.id, + mapid: Active.Map.id } socket.emit('updateMapperCoords', update) } @@ -883,8 +883,8 @@ const Realtime = { var self = Realtime var socket = self.socket - if (Metamaps.Active.Map && self.status) { - positions.mapid = Metamaps.Active.Map.id + if (Active.Map && self.status) { + positions.mapid = Active.Map.id socket.emit('topicDrag', positions) } }, @@ -895,13 +895,13 @@ const Realtime = { var topic var node - if (Metamaps.Active.Map && self.status) { + if (Active.Map && self.status) { for (var key in positions) { topic = Metamaps.Topics.get(key) if (topic) node = topic.get('node') if (node) node.pos.setc(positions[key].x, positions[key].y) } // for - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } }, sendTopicChange: function (topic) { @@ -960,23 +960,23 @@ const Realtime = { socket.emit('mapChangeFromClient', data) }, mapChange: function (data) { - var map = Metamaps.Active.Map + var map = Active.Map var isActiveMap = map && data.mapId === map.id if (isActiveMap) { - var couldEditBefore = map.authorizeToEdit(Metamaps.Active.Mapper) + var couldEditBefore = map.authorizeToEdit(Active.Mapper) var idBefore = map.id map.fetch({ success: function (model, response) { var idNow = model.id - var canEditNow = model.authorizeToEdit(Metamaps.Active.Mapper) + var canEditNow = model.authorizeToEdit(Active.Mapper) if (idNow !== idBefore) { - Metamaps.Map.leavePrivateMap() // this means the map has been changed to private + Map.leavePrivateMap() // this means the map has been changed to private } else if (couldEditBefore && !canEditNow) { - Metamaps.Map.cantEditNow() + Map.cantEditNow() } else if (!couldEditBefore && canEditNow) { - Metamaps.Map.canEditNow() + Map.canEditNow() } else { model.fetchContained() model.trigger('changeByOther') @@ -991,7 +991,7 @@ const Realtime = { var socket = self.socket var message = data.attributes - message.mapid = Metamaps.Active.Map.id + message.mapid = Active.Map.id socket.emit('newMessage', message) }, newMessage: function (data) { @@ -1005,14 +1005,14 @@ const Realtime = { var self = Realtime var socket = self.socket - if (Metamaps.Active.Map && self.status) { - data.mapperid = Metamaps.Active.Mapper.id - data.mapid = Metamaps.Active.Map.id + if (Active.Map && self.status) { + data.mapperid = Active.Mapper.id + data.mapid = Active.Map.id socket.emit('newTopic', data) } }, newTopic: function (data) { - var topic, mapping, mapper, mapperCallback, cancel + var topic, mapping, mapper, cancel var self = Realtime var socket = self.socket @@ -1021,7 +1021,7 @@ const Realtime = { function waitThenRenderTopic () { if (topic && mapping && mapper) { - Metamaps.Topic.renderTopic(mapping, topic, false, false) + Topic.renderTopic(mapping, topic, false, false) } else if (!cancel) { setTimeout(waitThenRenderTopic, 10) @@ -1030,11 +1030,10 @@ const Realtime = { mapper = Metamaps.Mappers.get(data.mapperid) if (mapper === undefined) { - mapperCallback = function (m) { + Mapper.get(data.mapperid, function(m) { Metamaps.Mappers.add(m) mapper = m - } - Metamaps.Mapper.get(data.mapperid, mapperCallback) + }) } $.ajax({ url: '/topics/' + data.mappableid + '.json', @@ -1064,7 +1063,7 @@ const Realtime = { var self = Realtime var socket = self.socket - if (Metamaps.Active.Map) { + if (Active.Map) { socket.emit('deleteTopicFromClient', data) } }, @@ -1073,8 +1072,8 @@ const Realtime = { var self = Realtime var socket = self.socket - if (Metamaps.Active.Map) { - data.mapid = Metamaps.Active.Map.id + if (Active.Map) { + data.mapid = Active.Map.id socket.emit('removeTopic', data) } }, @@ -1088,7 +1087,7 @@ const Realtime = { if (topic) { var node = topic.get('node') var mapping = topic.getMapping() - Metamaps.Control.hideNode(node.id) + Control.hideNode(node.id) Metamaps.Topics.remove(topic) Metamaps.Mappings.remove(mapping) } @@ -1098,9 +1097,9 @@ const Realtime = { var self = Realtime var socket = self.socket - if (Metamaps.Active.Map) { - data.mapperid = Metamaps.Active.Mapper.id - data.mapid = Metamaps.Active.Map.id + if (Active.Map) { + data.mapperid = Active.Mapper.id + data.mapid = Active.Map.id socket.emit('newSynapse', data) } }, @@ -1119,7 +1118,7 @@ const Realtime = { topic2 = synapse.getTopic2() node2 = topic2.get('node') - Metamaps.Synapse.renderSynapse(mapping, synapse, node1, node2, false) + Synapse.renderSynapse(mapping, synapse, node1, node2, false) } else if (!cancel) { setTimeout(waitThenRenderSynapse, 10) @@ -1128,11 +1127,10 @@ const Realtime = { mapper = Metamaps.Mappers.get(data.mapperid) if (mapper === undefined) { - mapperCallback = function (m) { + Mapper.get(data.mapperid, function(m) { Metamaps.Mappers.add(m) mapper = m - } - Metamaps.Mapper.get(data.mapperid, mapperCallback) + }) } $.ajax({ url: '/synapses/' + data.mappableid + '.json', @@ -1161,8 +1159,8 @@ const Realtime = { var self = Realtime var socket = self.socket - if (Metamaps.Active.Map) { - data.mapid = Metamaps.Active.Map.id + if (Active.Map) { + data.mapid = Active.Map.id socket.emit('deleteSynapseFromClient', data) } }, @@ -1171,8 +1169,8 @@ const Realtime = { var self = Realtime var socket = self.socket - if (Metamaps.Active.Map) { - data.mapid = Metamaps.Active.Map.id + if (Active.Map) { + data.mapid = Active.Map.id socket.emit('removeSynapse', data) } }, @@ -1187,7 +1185,7 @@ const Realtime = { var edge = synapse.get('edge') var mapping = synapse.getMapping() if (edge.getData('mappings').length - 1 === 0) { - Metamaps.Control.hideEdge(edge) + Control.hideEdge(edge) } var index = _.indexOf(edge.getData('synapses'), synapse) diff --git a/frontend/src/Metamaps/Router.js b/frontend/src/Metamaps/Router.js index 8aacadd1..d5c07e12 100644 --- a/frontend/src/Metamaps/Router.js +++ b/frontend/src/Metamaps/Router.js @@ -1,19 +1,19 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, Backbone, $ */ +import Active from './Active' +import GlobalUI from './GlobalUI' +import JIT from './JIT' +import Map from './Map' +import Topic from './Topic' +import Views from './Views' +import Visualize from './Visualize' + /* * Metamaps.Router.js.erb * * Dependencies: - * - Metamaps.Active - * - Metamaps.GlobalUI - * - Metamaps.JIT * - Metamaps.Loading - * - Metamaps.Map * - Metamaps.Maps - * - Metamaps.Topic - * - Metamaps.Views - * - Metamaps.Visualize */ const _Router = Backbone.Router.extend({ @@ -24,53 +24,53 @@ const _Router = Backbone.Router.extend({ 'maps/:id': 'maps' // #maps/7 }, home: function () { - clearTimeout(Metamaps.Router.timeoutId) + clearTimeout(this.timeoutId) - if (Metamaps.Active.Mapper) document.title = 'Explore Active Maps | Metamaps' + if (Active.Mapper) document.title = 'Explore Active Maps | Metamaps' else document.title = 'Home | Metamaps' - Metamaps.Router.currentSection = '' - Metamaps.Router.currentPage = '' + this.currentSection = '' + this.currentPage = '' $('.wrapper').removeClass('mapPage topicPage') - var classes = Metamaps.Active.Mapper ? 'homePage explorePage' : 'homePage' + var classes = Active.Mapper ? 'homePage explorePage' : 'homePage' $('.wrapper').addClass(classes) var navigate = function () { - Metamaps.Router.timeoutId = setTimeout(function () { - Metamaps.Router.navigate('') + this.timeoutId = setTimeout(function () { + this.navigate('') }, 300) } // all this only for the logged in home page - if (Metamaps.Active.Mapper) { + if (Active.Mapper) { $('.homeButton a').attr('href', '/') - Metamaps.GlobalUI.hideDiv('#yield') + GlobalUI.hideDiv('#yield') - Metamaps.GlobalUI.showDiv('#explore') + GlobalUI.showDiv('#explore') - Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) + Views.exploreMaps.setCollection(Metamaps.Maps.Active) if (Metamaps.Maps.Active.length === 0) { Metamaps.Maps.Active.getMaps(navigate) // this will trigger an explore maps render } else { - Metamaps.Views.exploreMaps.render(navigate) + Views.exploreMaps.render(navigate) } } else { // logged out home page - Metamaps.GlobalUI.hideDiv('#explore') - Metamaps.GlobalUI.showDiv('#yield') - Metamaps.Router.timeoutId = setTimeout(navigate, 500) + GlobalUI.hideDiv('#explore') + GlobalUI.showDiv('#yield') + this.timeoutId = setTimeout(navigate, 500) } - Metamaps.GlobalUI.hideDiv('#infovis') - Metamaps.GlobalUI.hideDiv('#instructions') - Metamaps.Map.end() - Metamaps.Topic.end() - Metamaps.Active.Map = null - Metamaps.Active.Topic = null + GlobalUI.hideDiv('#infovis') + GlobalUI.hideDiv('#instructions') + Map.end() + Topic.end() + Active.Map = null + Active.Topic = null }, explore: function (section, id) { - clearTimeout(Metamaps.Router.timeoutId) + clearTimeout(this.timeoutId) // just capitalize the variable section // either 'featured', 'mapper', or 'active' @@ -90,12 +90,12 @@ const _Router = Backbone.Router.extend({ document.title = 'Explore My Maps | Metamaps' } - if (Metamaps.Active.Mapper && section != 'mapper') $('.homeButton a').attr('href', '/explore/' + section) + if (Active.Mapper && section != 'mapper') $('.homeButton a').attr('href', '/explore/' + section) $('.wrapper').removeClass('homePage mapPage topicPage') $('.wrapper').addClass('explorePage') - Metamaps.Router.currentSection = 'explore' - Metamaps.Router.currentPage = section + this.currentSection = 'explore' + this.currentPage = section // this will mean it's a mapper page being loaded if (id) { @@ -108,20 +108,20 @@ const _Router = Backbone.Router.extend({ Metamaps.Maps.Mapper.mapperId = id } - Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps[capitalize]) + Views.exploreMaps.setCollection(Metamaps.Maps[capitalize]) var navigate = function () { - var path = '/explore/' + Metamaps.Router.currentPage + var path = '/explore/' + this.currentPage // alter url if for mapper profile page - if (Metamaps.Router.currentPage === 'mapper') { + if (this.currentPage === 'mapper') { path += '/' + Metamaps.Maps.Mapper.mapperId } - Metamaps.Router.navigate(path) + this.navigate(path) } var navigateTimeout = function () { - Metamaps.Router.timeoutId = setTimeout(navigate, 300) + this.timeoutId = setTimeout(navigate, 300) } if (Metamaps.Maps[capitalize].length === 0) { Metamaps.Loading.show() @@ -130,77 +130,77 @@ const _Router = Backbone.Router.extend({ }, 300) // wait 300 milliseconds till the other animations are done to do the fetch } else { if (id) { - Metamaps.Views.exploreMaps.fetchUserThenRender(navigateTimeout) + Views.exploreMaps.fetchUserThenRender(navigateTimeout) } else { - Metamaps.Views.exploreMaps.render(navigateTimeout) + Views.exploreMaps.render(navigateTimeout) } } - Metamaps.GlobalUI.showDiv('#explore') - Metamaps.GlobalUI.hideDiv('#yield') - Metamaps.GlobalUI.hideDiv('#infovis') - Metamaps.GlobalUI.hideDiv('#instructions') - Metamaps.Map.end() - Metamaps.Topic.end() - Metamaps.Active.Map = null - Metamaps.Active.Topic = null + GlobalUI.showDiv('#explore') + GlobalUI.hideDiv('#yield') + GlobalUI.hideDiv('#infovis') + GlobalUI.hideDiv('#instructions') + Map.end() + Topic.end() + Active.Map = null + Active.Topic = null }, maps: function (id) { - clearTimeout(Metamaps.Router.timeoutId) + clearTimeout(this.timeoutId) document.title = 'Map ' + id + ' | Metamaps' - Metamaps.Router.currentSection = 'map' - Metamaps.Router.currentPage = id + this.currentSection = 'map' + this.currentPage = id $('.wrapper').removeClass('homePage explorePage topicPage') $('.wrapper').addClass('mapPage') // another class will be added to wrapper if you // can edit this map '.canEditMap' - Metamaps.GlobalUI.hideDiv('#yield') - Metamaps.GlobalUI.hideDiv('#explore') + GlobalUI.hideDiv('#yield') + GlobalUI.hideDiv('#explore') // clear the visualization, if there was one, before showing its div again - if (Metamaps.Visualize.mGraph) { - Metamaps.Visualize.mGraph.graph.empty() - Metamaps.Visualize.mGraph.plot() - Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas) + if (Visualize.mGraph) { + Visualize.mGraph.graph.empty() + Visualize.mGraph.plot() + JIT.centerMap(Visualize.mGraph.canvas) } - Metamaps.GlobalUI.showDiv('#infovis') - Metamaps.Topic.end() - Metamaps.Active.Topic = null + GlobalUI.showDiv('#infovis') + Topic.end() + Active.Topic = null Metamaps.Loading.show() - Metamaps.Map.end() - Metamaps.Map.launch(id) + Map.end() + Map.launch(id) }, topics: function (id) { - clearTimeout(Metamaps.Router.timeoutId) + clearTimeout(this.timeoutId) document.title = 'Topic ' + id + ' | Metamaps' - Metamaps.Router.currentSection = 'topic' - Metamaps.Router.currentPage = id + this.currentSection = 'topic' + this.currentPage = id $('.wrapper').removeClass('homePage explorePage mapPage') $('.wrapper').addClass('topicPage') - Metamaps.GlobalUI.hideDiv('#yield') - Metamaps.GlobalUI.hideDiv('#explore') + GlobalUI.hideDiv('#yield') + GlobalUI.hideDiv('#explore') // clear the visualization, if there was one, before showing its div again - if (Metamaps.Visualize.mGraph) { - Metamaps.Visualize.mGraph.graph.empty() - Metamaps.Visualize.mGraph.plot() - Metamaps.JIT.centerMap(Metamaps.Visualize.mGraph.canvas) + if (Visualize.mGraph) { + Visualize.mGraph.graph.empty() + Visualize.mGraph.plot() + JIT.centerMap(Visualize.mGraph.canvas) } - Metamaps.GlobalUI.showDiv('#infovis') - Metamaps.Map.end() - Metamaps.Active.Map = null + GlobalUI.showDiv('#infovis') + Map.end() + Active.Map = null - Metamaps.Topic.end() - Metamaps.Topic.launch(id) + Topic.end() + Topic.launch(id) } }) @@ -227,9 +227,9 @@ Router.intercept = function (evt) { segments.splice(0, 1) // pop off the element created by the first / if (href.attr === '') { - Metamaps.Router.home() + Router.home() } else { - Metamaps.Router[segments[0]](segments[1], segments[2]) + Router[segments[0]](segments[1], segments[2]) } } } @@ -240,7 +240,7 @@ Router.init = function () { pushState: true, root: '/' }) - $(document).on('click', 'a[data-router="true"]', Metamaps.Router.intercept) + $(document).on('click', 'a[data-router="true"]', Router.intercept) } export default Router diff --git a/frontend/src/Metamaps/Synapse.js b/frontend/src/Metamaps/Synapse.js index 5258de3b..b50e50e6 100644 --- a/frontend/src/Metamaps/Synapse.js +++ b/frontend/src/Metamaps/Synapse.js @@ -1,20 +1,22 @@ /* global Metamaps, $ */ +import Active from './Active' +import Control from './Control' +import Create from './Create' +import JIT from './JIT' +import Map from './Map' +import Selected from './Selected' +import Settings from './Settings' +import Visualize from './Visualize' + /* * Metamaps.Synapse.js.erb * * Dependencies: * - Metamaps.Backbone - * - Metamaps.Control - * - Metamaps.Create - * - Metamaps.JIT - * - Metamaps.Map * - Metamaps.Mappings - * - Metamaps.Selected - * - Metamaps.Settings * - Metamaps.Synapses * - Metamaps.Topics - * - Metamaps.Visualize */ const Synapse = { @@ -52,18 +54,18 @@ const Synapse = { * */ renderSynapse: function (mapping, synapse, node1, node2, createNewInDB) { - var self = Metamaps.Synapse + var self = Synapse var edgeOnViz var newedge = synapse.createEdge(mapping) - Metamaps.Visualize.mGraph.graph.addAdjacence(node1, node2, newedge.data) - edgeOnViz = Metamaps.Visualize.mGraph.graph.getAdjacence(node1.id, node2.id) + Visualize.mGraph.graph.addAdjacence(node1, node2, newedge.data) + edgeOnViz = Visualize.mGraph.graph.getAdjacence(node1.id, node2.id) synapse.set('edge', edgeOnViz) synapse.updateEdge() // links the synapse and the mapping to the edge - Metamaps.Control.selectEdge(edgeOnViz) + Control.selectEdge(edgeOnViz) var mappingSuccessCallback = function (mappingModel, response) { var newSynapseData = { @@ -71,17 +73,17 @@ const Synapse = { mappableid: mappingModel.get('mappable_id') } - $(document).trigger(Metamaps.JIT.events.newSynapse, [newSynapseData]) + $(document).trigger(JIT.events.newSynapse, [newSynapseData]) } var synapseSuccessCallback = function (synapseModel, response) { - if (Metamaps.Active.Map) { + if (Active.Map) { mapping.save({ mappable_id: synapseModel.id }, { success: mappingSuccessCallback }) } } - if (!Metamaps.Settings.sandbox && createNewInDB) { + if (!Settings.sandbox && createNewInDB) { if (synapse.isNew()) { synapse.save(null, { success: synapseSuccessCallback, @@ -89,7 +91,7 @@ const Synapse = { console.log('error saving synapse to database') } }) - } else if (!synapse.isNew() && Metamaps.Active.Map) { + } else if (!synapse.isNew() && Active.Map) { mapping.save(null, { success: mappingSuccessCallback }) @@ -105,27 +107,27 @@ const Synapse = { synapse, mapping - $(document).trigger(Metamaps.Map.events.editedByActiveMapper) + $(document).trigger(Map.events.editedByActiveMapper) // for each node in this array we will create a synapse going to the position2 node. var synapsesToCreate = [] - topic2 = Metamaps.Topics.get(Metamaps.Create.newSynapse.topic2id) + topic2 = Metamaps.Topics.get(Create.newSynapse.topic2id) node2 = topic2.get('node') - var len = Metamaps.Selected.Nodes.length + var len = Selected.Nodes.length if (len == 0) { - topic1 = Metamaps.Topics.get(Metamaps.Create.newSynapse.topic1id) + topic1 = Metamaps.Topics.get(Create.newSynapse.topic1id) synapsesToCreate[0] = topic1.get('node') } else if (len > 0) { - synapsesToCreate = Metamaps.Selected.Nodes + synapsesToCreate = Selected.Nodes } for (var i = 0; i < synapsesToCreate.length; i++) { node1 = synapsesToCreate[i] topic1 = node1.getData('topic') synapse = new Metamaps.Backbone.Synapse({ - desc: Metamaps.Create.newSynapse.description, + desc: Create.newSynapse.description, node1_id: topic1.isNew() ? topic1.cid : topic1.id, node2_id: topic2.isNew() ? topic2.cid : topic2.id, }) @@ -141,7 +143,7 @@ const Synapse = { self.renderSynapse(mapping, synapse, node1, node2, true) } // for each in synapsesToCreate - Metamaps.Create.newSynapse.hide() + Create.newSynapse.hide() }, getSynapseFromAutocomplete: function (id) { var self = Synapse, @@ -158,11 +160,11 @@ const Synapse = { }) Metamaps.Mappings.add(mapping) - topic1 = Metamaps.Topics.get(Metamaps.Create.newSynapse.topic1id) + topic1 = Metamaps.Topics.get(Create.newSynapse.topic1id) node1 = topic1.get('node') - topic2 = Metamaps.Topics.get(Metamaps.Create.newSynapse.topic2id) + topic2 = Metamaps.Topics.get(Create.newSynapse.topic2id) node2 = topic2.get('node') - Metamaps.Create.newSynapse.hide() + Create.newSynapse.hide() self.renderSynapse(mapping, synapse, node1, node2, true) } diff --git a/frontend/src/Metamaps/SynapseCard.js b/frontend/src/Metamaps/SynapseCard.js index e0315486..28ff1e32 100644 --- a/frontend/src/Metamaps/SynapseCard.js +++ b/frontend/src/Metamaps/SynapseCard.js @@ -1,4 +1,4 @@ -/* global Metamaps, $ */ +/* global $ */ import Active from './Active' import Control from './Control' import Mapper from './Mapper' diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index ab93e419..412f7ef2 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -1,26 +1,29 @@ /* global Metamaps, $ */ import Active from './Active' +import AutoLayout from './AutoLayout' +import Create from './Create' +import Filter from './Filter' +import GlobalUI from './GlobalUI' import JIT from './JIT' +import Map from './Map' +import Router from './Router' import Selected from './Selected' import Settings from './Settings' +import SynapseCard from './SynapseCard' +import TopicCard from './TopicCard' import Util from './Util' +import Visualize from './Visualize' /* * Metamaps.Topic.js.erb * * Dependencies: * - Metamaps.Backbone - * - Metamaps.Create * - Metamaps.Creators - * - Metamaps.Filter - * - Metamaps.GlobalUI * - Metamaps.Mappings - * - Metamaps.SynapseCard * - Metamaps.Synapses - * - Metamaps.TopicCard * - Metamaps.Topics - * - Metamaps.Visualize */ const Topic = { @@ -67,19 +70,19 @@ const Topic = { $('#filter_by_mapper h3').html('CREATORS') // build and render the visualization - Metamaps.Visualize.type = 'RGraph' + Visualize.type = 'RGraph' JIT.prepareVizData() // update filters - Metamaps.Filter.reset() + Filter.reset() // reset selected arrays Selected.reset() // these three update the actual filter box with the right list items - Metamaps.Filter.checkMetacodes() - Metamaps.Filter.checkSynapses() - Metamaps.Filter.checkMappers() + Filter.checkMetacodes() + Filter.checkSynapses() + Filter.checkMappers() // for mobile $('#header_content').html(Active.Topic.get('name')) @@ -93,22 +96,22 @@ const Topic = { end: function () { if (Active.Topic) { $('.rightclickmenu').remove() - Metamaps.TopicCard.hideCard() - Metamaps.SynapseCard.hideCard() - Metamaps.Filter.close() + TopicCard.hideCard() + SynapseCard.hideCard() + Filter.close() } }, centerOn: function (nodeid, callback) { // don't clash with fetchRelatives - if (!Metamaps.Visualize.mGraph.busy) { - Metamaps.Visualize.mGraph.onClick(nodeid, { + if (!Visualize.mGraph.busy) { + Visualize.mGraph.onClick(nodeid, { hideLabels: false, duration: 1000, onComplete: function () { if (callback) callback() } }) - Metamaps.Router.navigate('/topics/' + nodeid) + Router.navigate('/topics/' + nodeid) Active.Topic = Metamaps.Topics.get(nodeid) } }, @@ -127,7 +130,7 @@ const Topic = { var successCallback; successCallback = function (data) { - if (Metamaps.Visualize.mGraph.busy) { + if (Visualize.mGraph.busy) { // don't clash with centerOn window.setTimeout(function() { successCallback(data) }, 100) return @@ -141,7 +144,7 @@ const Topic = { var synapseColl = new Metamaps.Backbone.SynapseCollection(data.synapses) var graph = JIT.convertModelsToJIT(topicColl, synapseColl)[0] - Metamaps.Visualize.mGraph.op.sum(graph, { + Visualize.mGraph.op.sum(graph, { type: 'fade', duration: 500, hideLabels: false @@ -149,7 +152,7 @@ const Topic = { var i, l, t, s - Metamaps.Visualize.mGraph.graph.eachNode(function (n) { + Visualize.mGraph.graph.eachNode(function (n) { t = Metamaps.Topics.get(n.id) t.set({ node: n }, { silent: true }) t.updateNode() @@ -186,7 +189,7 @@ const Topic = { // opts is additional options in a hash // TODO: move createNewInDB and permitCerateSYnapseAfter into opts renderTopic: function (mapping, topic, createNewInDB, permitCreateSynapseAfter, opts) { - var self = Metamaps.Topic + var self = Topic var nodeOnViz, tempPos @@ -194,37 +197,37 @@ const Topic = { var midpoint = {}, pixelPos - if (!$.isEmptyObject(Metamaps.Visualize.mGraph.graph.nodes)) { - Metamaps.Visualize.mGraph.graph.addNode(newnode) - nodeOnViz = Metamaps.Visualize.mGraph.graph.getNode(newnode.id) + if (!$.isEmptyObject(Visualize.mGraph.graph.nodes)) { + Visualize.mGraph.graph.addNode(newnode) + nodeOnViz = Visualize.mGraph.graph.getNode(newnode.id) topic.set('node', nodeOnViz, {silent: true}) topic.updateNode() // links the topic and the mapping to the node nodeOnViz.setData('dim', 1, 'start') nodeOnViz.setData('dim', 25, 'end') - if (Metamaps.Visualize.type === 'RGraph') { + if (Visualize.type === 'RGraph') { tempPos = new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')) tempPos = tempPos.toPolar() nodeOnViz.setPos(tempPos, 'current') nodeOnViz.setPos(tempPos, 'start') nodeOnViz.setPos(tempPos, 'end') - } else if (Metamaps.Visualize.type === 'ForceDirected') { + } else if (Visualize.type === 'ForceDirected') { nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'current') nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'start') nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'end') } - if (Metamaps.Create.newTopic.addSynapse && permitCreateSynapseAfter) { - Metamaps.Create.newSynapse.topic1id = JIT.tempNode.getData('topic').id + if (Create.newTopic.addSynapse && permitCreateSynapseAfter) { + Create.newSynapse.topic1id = JIT.tempNode.getData('topic').id // position the form midpoint.x = JIT.tempNode.pos.getc().x + (nodeOnViz.pos.getc().x - JIT.tempNode.pos.getc().x) / 2 midpoint.y = JIT.tempNode.pos.getc().y + (nodeOnViz.pos.getc().y - JIT.tempNode.pos.getc().y) / 2 - pixelPos = Metamaps.Util.coordsToPixels(midpoint) + pixelPos = Util.coordsToPixels(midpoint) $('#new_synapse').css('left', pixelPos.x + 'px') $('#new_synapse').css('top', pixelPos.y + 'px') // show the form - Metamaps.Create.newSynapse.open() - Metamaps.Visualize.mGraph.fx.animate({ + Create.newSynapse.open() + Visualize.mGraph.fx.animate({ modes: ['node-property:dim'], duration: 500, onComplete: function () { @@ -234,16 +237,16 @@ const Topic = { } }) } else { - Metamaps.Visualize.mGraph.fx.plotNode(nodeOnViz, Metamaps.Visualize.mGraph.canvas) - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.plotNode(nodeOnViz, Visualize.mGraph.canvas) + Visualize.mGraph.fx.animate({ modes: ['node-property:dim'], duration: 500, onComplete: function () {} }) } } else { - Metamaps.Visualize.mGraph.loadJSON(newnode) - nodeOnViz = Metamaps.Visualize.mGraph.graph.getNode(newnode.id) + Visualize.mGraph.loadJSON(newnode) + nodeOnViz = Visualize.mGraph.graph.getNode(newnode.id) topic.set('node', nodeOnViz, {silent: true}) topic.updateNode() // links the topic and the mapping to the node @@ -252,8 +255,8 @@ const Topic = { nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'current') nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'start') nodeOnViz.setPos(new $jit.Complex(mapping.get('xloc'), mapping.get('yloc')), 'end') - Metamaps.Visualize.mGraph.fx.plotNode(nodeOnViz, Metamaps.Visualize.mGraph.canvas) - Metamaps.Visualize.mGraph.fx.animate({ + Visualize.mGraph.fx.plotNode(nodeOnViz, Visualize.mGraph.canvas) + Visualize.mGraph.fx.animate({ modes: ['node-property:dim'], duration: 500, onComplete: function () {} @@ -284,8 +287,8 @@ const Topic = { }) } - if (Metamaps.Create.newTopic.addSynapse) { - Metamaps.Create.newSynapse.topic2id = topicModel.id + if (Create.newTopic.addSynapse) { + Create.newSynapse.topic2id = topicModel.id } } @@ -305,58 +308,58 @@ const Topic = { } }, createTopicLocally: function () { - var self = Metamaps.Topic + var self = Topic - if (Metamaps.Create.newTopic.name === '') { - Metamaps.GlobalUI.notifyUser('Please enter a topic title...') + if (Create.newTopic.name === '') { + GlobalUI.notifyUser('Please enter a topic title...') return } // hide the 'double-click to add a topic' message - Metamaps.GlobalUI.hideDiv('#instructions') + GlobalUI.hideDiv('#instructions') - $(document).trigger(Metamaps.Map.events.editedByActiveMapper) + $(document).trigger(Map.events.editedByActiveMapper) - var metacode = Metamaps.Metacodes.get(Metamaps.Create.newTopic.metacode) + var metacode = Metamaps.Metacodes.get(Create.newTopic.metacode) var topic = new Metamaps.Backbone.Topic({ - name: Metamaps.Create.newTopic.name, + name: Create.newTopic.name, metacode_id: metacode.id, defer_to_map_id: Active.Map.id }) Metamaps.Topics.add(topic) - if (Metamaps.Create.newTopic.pinned) { - var nextCoords = Metamaps.AutoLayout.getNextCoord() + if (Create.newTopic.pinned) { + var nextCoords = AutoLayout.getNextCoord() } var mapping = new Metamaps.Backbone.Mapping({ - xloc: nextCoords ? nextCoords.x : Metamaps.Create.newTopic.x, - yloc: nextCoords ? nextCoords.y : Metamaps.Create.newTopic.y, + xloc: nextCoords ? nextCoords.x : Create.newTopic.x, + yloc: nextCoords ? nextCoords.y : Create.newTopic.y, mappable_id: topic.cid, mappable_type: 'Topic', }) Metamaps.Mappings.add(mapping) // these can't happen until the value is retrieved, which happens in the line above - Metamaps.Create.newTopic.hide() + Create.newTopic.hide() self.renderTopic(mapping, topic, true, true) // this function also includes the creation of the topic in the database }, getTopicFromAutocomplete: function (id) { - var self = Metamaps.Topic + var self = Topic - $(document).trigger(Metamaps.Map.events.editedByActiveMapper) + $(document).trigger(Map.events.editedByActiveMapper) - Metamaps.Create.newTopic.hide() + Create.newTopic.hide() var topic = self.get(id) - if (Metamaps.Create.newTopic.pinned) { - var nextCoords = Metamaps.AutoLayout.getNextCoord() + if (Create.newTopic.pinned) { + var nextCoords = AutoLayout.getNextCoord() } var mapping = new Metamaps.Backbone.Mapping({ - xloc: nextCoords ? nextCoords.x : Metamaps.Create.newTopic.x, - yloc: nextCoords ? nextCoords.y : Metamaps.Create.newTopic.y, + xloc: nextCoords ? nextCoords.x : Create.newTopic.x, + yloc: nextCoords ? nextCoords.y : Create.newTopic.y, mappable_type: 'Topic', mappable_id: topic.id, }) @@ -365,13 +368,13 @@ const Topic = { self.renderTopic(mapping, topic, true, true) }, getTopicFromSearch: function (event, id) { - var self = Metamaps.Topic + var self = Topic - $(document).trigger(Metamaps.Map.events.editedByActiveMapper) + $(document).trigger(Map.events.editedByActiveMapper) var topic = self.get(id) - var nextCoords = Metamaps.AutoLayout.getNextCoord() + var nextCoords = AutoLayout.getNextCoord() var mapping = new Metamaps.Backbone.Mapping({ xloc: nextCoords.x, yloc: nextCoords.y, @@ -382,7 +385,7 @@ const Topic = { self.renderTopic(mapping, topic, true, true) - Metamaps.GlobalUI.notifyUser('Topic was added to your map!') + GlobalUI.notifyUser('Topic was added to your map!') event.stopPropagation() event.preventDefault() diff --git a/frontend/src/Metamaps/TopicCard.js b/frontend/src/Metamaps/TopicCard.js index ebc79575..7320d285 100644 --- a/frontend/src/Metamaps/TopicCard.js +++ b/frontend/src/Metamaps/TopicCard.js @@ -1,7 +1,9 @@ /* global Metamaps, $ */ import Active from './Active' +import GlobalUI from './GlobalUI' import Mapper from './Mapper' +import Router from './Router' import Util from './Util' import Visualize from './Visualize' @@ -9,9 +11,7 @@ import Visualize from './Visualize' * Metamaps.TopicCard.js * * Dependencies: - * - Metamaps.GlobalUI * - Metamaps.Metacodes - * - Metamaps.Router */ const TopicCard = { openTopicCard: null, // stores the topic that's currently open @@ -332,7 +332,7 @@ const TopicCard = { $('.showcard .hoverTip').removeClass('hide') }) - $('.mapCount .tip li a').click(Metamaps.Router.intercept) + $('.mapCount .tip li a').click(Router.intercept) var originalText = $('.showMore').html() $('.mapCount .tip .showMore').unbind().toggle( @@ -353,7 +353,7 @@ const TopicCard = { var self = TopicCard self.removeLink() - Metamaps.GlobalUI.notifyUser('Invalid link') + GlobalUI.notifyUser('Invalid link') }, populateShowCard: function (topic) { var self = TopicCard diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index 9e44e8e8..678c7c64 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -2,6 +2,8 @@ import Active from './Active' import JIT from './JIT' +import Router from './Router' +import TopicCard from './TopicCard' /* * Metamaps.Visualize @@ -9,9 +11,7 @@ import JIT from './JIT' * Dependencies: * - Metamaps.Loading * - Metamaps.Metacodes - * - Metamaps.Router * - Metamaps.Synapses - * - Metamaps.TopicCard * - Metamaps.Topics */ @@ -42,7 +42,7 @@ const Visualize = { // prevent touch events on the canvas from default behaviour $('#infovis-canvas').bind('touchend touchcancel', function (event) { lastDist = 0 - if (!self.mGraph.events.touchMoved && !Visualize.touchDragNode) Metamaps.TopicCard.hideCurrentCard() + if (!self.mGraph.events.touchMoved && !Visualize.touchDragNode) TopicCard.hideCurrentCard() self.mGraph.events.touched = self.mGraph.events.touchMoved = false Visualize.touchDragNode = false }) @@ -204,16 +204,16 @@ const Visualize = { hold() // update the url now that the map is ready - clearTimeout(Metamaps.Router.timeoutId) - Metamaps.Router.timeoutId = setTimeout(function () { + clearTimeout(Router.timeoutId) + Router.timeoutId = setTimeout(function () { var m = Active.Map var t = Active.Topic if (m && window.location.pathname !== '/maps/' + m.id) { - Metamaps.Router.navigate('/maps/' + m.id) + Router.navigate('/maps/' + m.id) } else if (t && window.location.pathname !== '/topics/' + t.id) { - Metamaps.Router.navigate('/topics/' + t.id) + Router.navigate('/topics/' + t.id) } }, 800) } diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 37e93492..9fe8925b 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -83,22 +83,22 @@ document.addEventListener("DOMContentLoaded", function() { Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ) if (Metamaps.currentPage === "mapper") { - Metamaps.Views.exploreMaps.fetchUserThenRender() + Views.exploreMaps.fetchUserThenRender() } else { - Metamaps.Views.exploreMaps.render() + Views.exploreMaps.render() } - Metamaps.GlobalUI.showDiv('#explore') + GlobalUI.showDiv('#explore') } - else if (Metamaps.currentSection === "" && Metamaps.Active.Mapper) { - Metamaps.Views.exploreMaps.setCollection(Metamaps.Maps.Active) - Metamaps.Views.exploreMaps.render() - Metamaps.GlobalUI.showDiv('#explore') + else if (Metamaps.currentSection === "" && Active.Mapper) { + Views.exploreMaps.setCollection(Metamaps.Maps.Active) + Views.exploreMaps.render() + GlobalUI.showDiv('#explore') } - else if (Metamaps.Active.Map || Metamaps.Active.Topic) { + else if (Active.Map || Active.Topic) { Metamaps.Loading.show() - Metamaps.JIT.prepareVizData() - Metamaps.GlobalUI.showDiv('#infovis') + JIT.prepareVizData() + GlobalUI.showDiv('#infovis') } }); From 59b471ac62a75da175a8a17bee11c9f4b22f8624 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 23:51:13 +0800 Subject: [PATCH 14/26] break Map into three files --- frontend/src/Metamaps/Map/CheatSheet.js | 27 ++ .../src/Metamaps/{Map.js => Map/InfoBox.js} | 446 ++---------------- frontend/src/Metamaps/Map/index.js | 365 ++++++++++++++ frontend/src/Metamaps/index.js | 4 +- 4 files changed, 425 insertions(+), 417 deletions(-) create mode 100644 frontend/src/Metamaps/Map/CheatSheet.js rename frontend/src/Metamaps/{Map.js => Map/InfoBox.js} (51%) create mode 100644 frontend/src/Metamaps/Map/index.js diff --git a/frontend/src/Metamaps/Map/CheatSheet.js b/frontend/src/Metamaps/Map/CheatSheet.js new file mode 100644 index 00000000..969ee159 --- /dev/null +++ b/frontend/src/Metamaps/Map/CheatSheet.js @@ -0,0 +1,27 @@ +const CheatSheet = { + init: function () { + // tab the cheatsheet + $('#cheatSheet').tabs() + $('#quickReference').tabs().addClass('ui-tabs-vertical ui-helper-clearfix') + $('#quickReference .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left') + + // id = the id of a vimeo video + var switchVideo = function (element, id) { + $('.tutorialItem').removeClass('active') + $(element).addClass('active') + $('#tutorialVideo').attr('src', '//player.vimeo.com/video/' + id) + } + + $('#gettingStarted').click(function () { + // switchVideo(this,'88334167') + }) + $('#upYourSkillz').click(function () { + // switchVideo(this,'100118167') + }) + $('#advancedMapping').click(function () { + // switchVideo(this,'88334167') + }) + } +} + +export default CheatSheet diff --git a/frontend/src/Metamaps/Map.js b/frontend/src/Metamaps/Map/InfoBox.js similarity index 51% rename from frontend/src/Metamaps/Map.js rename to frontend/src/Metamaps/Map/InfoBox.js index cd2c3d2e..eaceba29 100644 --- a/frontend/src/Metamaps/Map.js +++ b/frontend/src/Metamaps/Map/InfoBox.js @@ -1,405 +1,19 @@ /* global Metamaps, $ */ import Active from './Active' -import AutoLayout from './AutoLayout' -import Create from './Create' -import Filter from './Filter' -import GlobalUI from './GlobalUI' -import JIT from './JIT' -import Realtime from './Realtime' -import Selected from './Selected' -import SynapseCard from './SynapseCard' -import TopicCard from './TopicCard' -import Visualize from './Visualize' +import GlobalUI from '../GlobalUI' +import Router from '../Router' /* - * Metamaps.Map.js.erb - * - * Dependencies: - * - Metamaps.Backbone - * - Metamaps.Erb - * - Metamaps.Loading - * - Metamaps.Mappers - * - Metamaps.Mappings - * - Metamaps.Maps - * - Metamaps.Messages - * - Metamaps.Router - * - Metamaps.Synapses - * - Metamaps.Topics - * - * Major sub-modules: - * - Metamaps.Map.CheatSheet - * - Metamaps.Map.InfoBox + * Metamaps.Collaborators + * Metamaps.Erb + * Metamaps.Mappers + * Metamaps.Maps + * Metamaps.Synapses + * Metamaps.Topics */ -window.Metamaps = window.Metamaps || {} -Metamaps.Map = { - events: { - editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper' - }, - init: function () { - var self = Metamaps.Map - - // prevent right clicks on the main canvas, so as to not get in the way of our right clicks - $('#center-container').bind('contextmenu', function (e) { - return false - }) - - $('.starMap').click(function () { - if ($(this).is('.starred')) self.unstar() - else self.star() - }) - - $('.sidebarFork').click(function () { - self.fork() - }) - - GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html() - - self.updateStar() - self.InfoBox.init() - self.CheatSheet.init() - - $(document).on(Metamaps.Map.events.editedByActiveMapper, self.editedByActiveMapper) - }, - launch: function (id) { - var bb = Metamaps.Backbone - var start = function (data) { - Active.Map = new bb.Map(data.map) - Metamaps.Mappers = new bb.MapperCollection(data.mappers) - Metamaps.Collaborators = new bb.MapperCollection(data.collaborators) - Metamaps.Topics = new bb.TopicCollection(data.topics) - Metamaps.Synapses = new bb.SynapseCollection(data.synapses) - Metamaps.Mappings = new bb.MappingCollection(data.mappings) - Metamaps.Messages = data.messages - Metamaps.Stars = data.stars - Metamaps.Backbone.attachCollectionEvents() - - var map = Active.Map - var mapper = Active.Mapper - - // add class to .wrapper for specifying whether you can edit the map - if (map.authorizeToEdit(mapper)) { - $('.wrapper').addClass('canEditMap') - } - - // add class to .wrapper for specifying if the map can - // be collaborated on - if (map.get('permission') === 'commons') { - $('.wrapper').addClass('commonsMap') - } - - Metamaps.Map.updateStar() - - // set filter mapper H3 text - $('#filter_by_mapper h3').html('MAPPERS') - - // build and render the visualization - Visualize.type = 'ForceDirected' - JIT.prepareVizData() - - // update filters - Filter.reset() - - // reset selected arrays - Selected.reset() - - // set the proper mapinfobox content - Metamaps.Map.InfoBox.load() - - // these three update the actual filter box with the right list items - Filter.checkMetacodes() - Filter.checkSynapses() - Filter.checkMappers() - - Realtime.startActiveMap() - Metamaps.Loading.hide() - - // for mobile - $('#header_content').html(map.get('name')) - } - - $.ajax({ - url: '/maps/' + id + '/contains.json', - success: start - }) - }, - end: function () { - if (Active.Map) { - $('.wrapper').removeClass('canEditMap commonsMap') - AutoLayout.resetSpiral() - - $('.rightclickmenu').remove() - TopicCard.hideCard() - SynapseCard.hideCard() - Create.newTopic.hide(true) // true means force (and override pinned) - Create.newSynapse.hide() - Filter.close() - Metamaps.Map.InfoBox.close() - Realtime.endActiveMap() - } - }, - updateStar: function () { - if (!Active.Mapper || !Metamaps.Stars) return - // update the star/unstar icon - if (Metamaps.Stars.find(function (s) { return s.user_id === Active.Mapper.id })) { - $('.starMap').addClass('starred') - $('.starMap .tooltipsAbove').html('Unstar') - } else { - $('.starMap').removeClass('starred') - $('.starMap .tooltipsAbove').html('Star') - } - }, - star: function () { - var self = Metamaps.Map - - if (!Active.Map) return - $.post('/maps/' + Active.Map.id + '/star') - Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id }) - Metamaps.Maps.Starred.add(Active.Map) - GlobalUI.notifyUser('Map is now starred') - self.updateStar() - }, - unstar: function () { - var self = Metamaps.Map - - if (!Active.Map) return - $.post('/maps/' + Active.Map.id + '/unstar') - Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Active.Mapper.id }) - Metamaps.Maps.Starred.remove(Active.Map) - self.updateStar() - }, - fork: function () { - GlobalUI.openLightbox('forkmap') - - var nodes_data = '', - synapses_data = '' - var nodes_array = [] - var synapses_array = [] - // collect the unfiltered topics - Visualize.mGraph.graph.eachNode(function (n) { - // if the opacity is less than 1 then it's filtered - if (n.getData('alpha') === 1) { - var id = n.getData('topic').id - nodes_array.push(id) - var x, y - if (n.pos.x && n.pos.y) { - x = n.pos.x - y = n.pos.y - } else { - var x = Math.cos(n.pos.theta) * n.pos.rho - var y = Math.sin(n.pos.theta) * n.pos.rho - } - nodes_data += id + '/' + x + '/' + y + ',' - } - }) - // collect the unfiltered synapses - Metamaps.Synapses.each(function (synapse) { - var desc = synapse.get('desc') - - var descNotFiltered = Filter.visible.synapses.indexOf(desc) > -1 - // make sure that both topics are being added, otherwise, it - // doesn't make sense to add the synapse - var topicsNotFiltered = nodes_array.indexOf(synapse.get('node1_id')) > -1 - topicsNotFiltered = topicsNotFiltered && nodes_array.indexOf(synapse.get('node2_id')) > -1 - if (descNotFiltered && topicsNotFiltered) { - synapses_array.push(synapse.id) - } - }) - - synapses_data = synapses_array.join() - nodes_data = nodes_data.slice(0, -1) - - GlobalUI.CreateMap.topicsToMap = nodes_data - GlobalUI.CreateMap.synapsesToMap = synapses_data - }, - leavePrivateMap: function () { - var map = Active.Map - Metamaps.Maps.Active.remove(map) - Metamaps.Maps.Featured.remove(map) - Metamaps.Router.home() - GlobalUI.notifyUser('Sorry! That map has been changed to Private.') - }, - cantEditNow: function () { - Realtime.turnOff(true); // true is for 'silence' - GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.') - Active.Map.trigger('changeByOther') - }, - canEditNow: function () { - var confirmString = "You've been granted permission to edit this map. " - confirmString += 'Do you want to reload and enable realtime collaboration?' - var c = confirm(confirmString) - if (c) { - Metamaps.Router.maps(Active.Map.id) - } - }, - editedByActiveMapper: function () { - if (Active.Mapper) { - Metamaps.Mappers.add(Active.Mapper) - } - }, - exportImage: function () { - var canvas = {} - - canvas.canvas = document.createElement('canvas') - canvas.canvas.width = 1880 // 960 - canvas.canvas.height = 1260 // 630 - - canvas.scaleOffsetX = 1 - canvas.scaleOffsetY = 1 - canvas.translateOffsetY = 0 - canvas.translateOffsetX = 0 - canvas.denySelected = true - - canvas.getSize = function () { - if (this.size) return this.size - var canvas = this.canvas - return this.size = { - width: canvas.width, - height: canvas.height - } - } - canvas.scale = function (x, y) { - var px = this.scaleOffsetX * x, - py = this.scaleOffsetY * y - var dx = this.translateOffsetX * (x - 1) / px, - dy = this.translateOffsetY * (y - 1) / py - this.scaleOffsetX = px - this.scaleOffsetY = py - this.getCtx().scale(x, y) - this.translate(dx, dy) - } - canvas.translate = function (x, y) { - var sx = this.scaleOffsetX, - sy = this.scaleOffsetY - this.translateOffsetX += x * sx - this.translateOffsetY += y * sy - this.getCtx().translate(x, y) - } - canvas.getCtx = function () { - return this.canvas.getContext('2d') - } - // center it - canvas.getCtx().translate(1880 / 2, 1260 / 2) - - var mGraph = Visualize.mGraph - - var id = mGraph.root - var root = mGraph.graph.getNode(id) - var T = !!root.visited - - // pass true to avoid basing it on a selection - JIT.zoomExtents(null, canvas, true) - - var c = canvas.canvas, - ctx = canvas.getCtx(), - scale = canvas.scaleOffsetX - - // draw a grey background - ctx.fillStyle = '#d8d9da' - var xPoint = (-(c.width / scale) / 2) - (canvas.translateOffsetX / scale), - yPoint = (-(c.height / scale) / 2) - (canvas.translateOffsetY / scale) - ctx.fillRect(xPoint, yPoint, c.width / scale, c.height / scale) - - // draw the graph - mGraph.graph.eachNode(function (node) { - var nodeAlpha = node.getData('alpha') - node.eachAdjacency(function (adj) { - var nodeTo = adj.nodeTo - if (!!nodeTo.visited === T && node.drawn && nodeTo.drawn) { - mGraph.fx.plotLine(adj, canvas) - } - }) - if (node.drawn) { - mGraph.fx.plotNode(node, canvas) - } - if (!mGraph.labelsHidden) { - if (node.drawn && nodeAlpha >= 0.95) { - mGraph.labels.plotLabel(canvas, node) - } else { - mGraph.labels.hideLabel(node, false) - } - } - node.visited = !T - }) - - var imageData = { - encoded_image: canvas.canvas.toDataURL() - } - - var map = Active.Map - - var today = new Date() - var dd = today.getDate() - var mm = today.getMonth() + 1; // January is 0! - var yyyy = today.getFullYear() - if (dd < 10) { - dd = '0' + dd - } - if (mm < 10) { - mm = '0' + mm - } - today = mm + '/' + dd + '/' + yyyy - - var mapName = map.get('name').split(' ').join([separator = '-']) - var downloadMessage = '' - downloadMessage += 'Captured map screenshot! ' - downloadMessage += "DOWNLOAD" - GlobalUI.notifyUser(downloadMessage) - - $.ajax({ - type: 'POST', - dataType: 'json', - url: '/maps/' + Active.Map.id + '/upload_screenshot', - data: imageData, - success: function (data) { - console.log('successfully uploaded map screenshot') - }, - error: function () { - console.log('failed to save map screenshot') - } - }) - } -} - -/* - * - * CHEATSHEET - * - */ -Metamaps.Map.CheatSheet = { - init: function () { - // tab the cheatsheet - $('#cheatSheet').tabs() - $('#quickReference').tabs().addClass('ui-tabs-vertical ui-helper-clearfix') - $('#quickReference .ui-tabs-nav li').removeClass('ui-corner-top').addClass('ui-corner-left') - - // id = the id of a vimeo video - var switchVideo = function (element, id) { - $('.tutorialItem').removeClass('active') - $(element).addClass('active') - $('#tutorialVideo').attr('src', '//player.vimeo.com/video/' + id) - } - - $('#gettingStarted').click(function () { - // switchVideo(this,'88334167') - }) - $('#upYourSkillz').click(function () { - // switchVideo(this,'100118167') - }) - $('#advancedMapping').click(function () { - // switchVideo(this,'88334167') - }) - } -}; // end Metamaps.Map.CheatSheet - -/* - * - * INFOBOX - * - */ -Metamaps.Map.InfoBox = { +const InfoBox = { isOpen: false, changing: false, selectingPermission: false, @@ -407,7 +21,7 @@ Metamaps.Map.InfoBox = { nameHTML: '{{name}}', descHTML: '{{desc}}', init: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoIcon').click(self.toggleBox) $('.mapInfoBox').click(function (event) { @@ -426,7 +40,7 @@ Metamaps.Map.InfoBox = { } }, toggleBox: function (event) { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (self.isOpen) self.close() else self.open() @@ -434,7 +48,7 @@ Metamaps.Map.InfoBox = { event.stopPropagation() }, open: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoIcon div').addClass('hide') if (!self.isOpen && !self.changing) { self.changing = true @@ -445,7 +59,7 @@ Metamaps.Map.InfoBox = { } }, close: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoIcon div').removeClass('hide') if (!self.changing) { @@ -459,7 +73,7 @@ Metamaps.Map.InfoBox = { } }, load: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox var map = Active.Map @@ -494,7 +108,7 @@ Metamaps.Map.InfoBox = { self.attachEventListeners() }, attachEventListeners: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox $('.mapInfoBox.canEdit .best_in_place').best_in_place() @@ -547,7 +161,7 @@ Metamaps.Map.InfoBox = { $('.mapContributors .tip').unbind().click(function (event) { event.stopPropagation() }) - $('.mapContributors .tip li a').click(Metamaps.Router.intercept) + $('.mapContributors .tip li a').click(Router.intercept) $('.mapInfoBox').unbind('.hideTip').bind('click.hideTip', function () { $('.mapContributors .tip').hide() @@ -556,7 +170,7 @@ Metamaps.Map.InfoBox = { self.addTypeahead() }, addTypeahead: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (!Active.Map) return @@ -603,14 +217,14 @@ Metamaps.Map.InfoBox = { } }, removeCollaborator: function (collaboratorId) { - var self = Metamaps.Map.InfoBox + var self = InfoBox Metamaps.Collaborators.remove(Metamaps.Collaborators.get(collaboratorId)) var mapperIds = Metamaps.Collaborators.models.map(function (mapper) { return mapper.id }) $.post('/maps/' + Active.Map.id + '/access', { access: mapperIds }) self.updateNumbers() }, addCollaborator: function (newCollaboratorId) { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (Metamaps.Collaborators.get(newCollaboratorId)) { GlobalUI.notifyUser('That user already has access') @@ -629,7 +243,7 @@ Metamaps.Map.InfoBox = { $.getJSON('/users/' + newCollaboratorId + '.json', callback) }, handleResultClick: function (event, item) { - var self = Metamaps.Map.InfoBox + var self = InfoBox self.addCollaborator(item.id) $('.collaboratorSearchField').typeahead('val', '') @@ -641,7 +255,7 @@ Metamaps.Map.InfoBox = { $('.mapInfoBox .mapPermission').removeClass('commons public private').addClass(perm) }, createContributorList: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators var activeMapperIsCreator = Active.Mapper && Active.Mapper.id === Active.Map.get('user_id') var string = '' @@ -666,7 +280,7 @@ Metamaps.Map.InfoBox = { updateNumbers: function () { if (!Active.Map) return - var self = Metamaps.Map.InfoBox + var self = InfoBox var mapper = Active.Mapper var relevantPeople = Active.Map.get('permission') === 'commons' ? Metamaps.Mappers : Metamaps.Collaborators @@ -689,10 +303,10 @@ Metamaps.Map.InfoBox = { $('.mapTopics').text(Metamaps.Topics.length) $('.mapSynapses').text(Metamaps.Synapses.length) - $('.mapEditedAt').html('Last edited: ' + Metamaps.Util.nowDateFormatted()) + $('.mapEditedAt').html('Last edited: ' + Util.nowDateFormatted()) }, onPermissionClick: function (event) { - var self = Metamaps.Map.InfoBox + var self = InfoBox if (!self.selectingPermission) { self.selectingPermission = true @@ -709,14 +323,14 @@ Metamaps.Map.InfoBox = { } }, hidePermissionSelect: function () { - var self = Metamaps.Map.InfoBox + var self = InfoBox self.selectingPermission = false $('.mapPermission').removeClass('minimize') // this line flips the pull up arrow to a drop down arrow $('.mapPermission .permissionSelect').remove() }, selectPermission: function (event) { - var self = Metamaps.Map.InfoBox + var self = InfoBox self.selectingPermission = false var permission = $(this).attr('class') @@ -740,19 +354,19 @@ Metamaps.Map.InfoBox = { var authorized = map.authorizePermissionChange(mapper) if (doIt && authorized) { - Metamaps.Map.InfoBox.close() + InfoBox.close() Metamaps.Maps.Active.remove(map) Metamaps.Maps.Featured.remove(map) Metamaps.Maps.Mine.remove(map) Metamaps.Maps.Shared.remove(map) map.destroy() - Metamaps.Router.home() + Router.home() GlobalUI.notifyUser('Map eliminated!') } else if (!authorized) { alert("Hey now. We can't just go around willy nilly deleting other people's maps now can we? Run off and find something constructive to do, eh?") } } -}; // end Metamaps.Map.InfoBox +} -export default Metamaps.Map +export default InfoBox diff --git a/frontend/src/Metamaps/Map/index.js b/frontend/src/Metamaps/Map/index.js new file mode 100644 index 00000000..84ee8b39 --- /dev/null +++ b/frontend/src/Metamaps/Map/index.js @@ -0,0 +1,365 @@ +/* global Metamaps, $ */ + +import Active from './Active' +import AutoLayout from './AutoLayout' +import Create from './Create' +import Filter from './Filter' +import GlobalUI from './GlobalUI' +import JIT from './JIT' +import Realtime from './Realtime' +import Router from './Router' +import Selected from './Selected' +import SynapseCard from './SynapseCard' +import TopicCard from './TopicCard' +import Visualize from './Visualize' + +import CheatSheet from './CheatSheet' +import InfoBox from './InfoBox' + +/* + * Metamaps.Map.js.erb + * + * Dependencies: + * - Metamaps.Backbone + * - Metamaps.Erb + * - Metamaps.Loading + * - Metamaps.Mappers + * - Metamaps.Mappings + * - Metamaps.Maps + * - Metamaps.Messages + * - Metamaps.Synapses + * - Metamaps.Topics + */ + +const Map = { + events: { + editedByActiveMapper: 'Metamaps:Map:events:editedByActiveMapper' + }, + init: function () { + var self = Map + + // prevent right clicks on the main canvas, so as to not get in the way of our right clicks + $('#center-container').bind('contextmenu', function (e) { + return false + }) + + $('.starMap').click(function () { + if ($(this).is('.starred')) self.unstar() + else self.star() + }) + + $('.sidebarFork').click(function () { + self.fork() + }) + + GlobalUI.CreateMap.emptyForkMapForm = $('#fork_map').html() + + self.updateStar() + self.InfoBox.init() + CheatSheet.init() + + $(document).on(Map.events.editedByActiveMapper, self.editedByActiveMapper) + }, + launch: function (id) { + var bb = Metamaps.Backbone + var start = function (data) { + Active.Map = new bb.Map(data.map) + Metamaps.Mappers = new bb.MapperCollection(data.mappers) + Metamaps.Collaborators = new bb.MapperCollection(data.collaborators) + Metamaps.Topics = new bb.TopicCollection(data.topics) + Metamaps.Synapses = new bb.SynapseCollection(data.synapses) + Metamaps.Mappings = new bb.MappingCollection(data.mappings) + Metamaps.Messages = data.messages + Metamaps.Stars = data.stars + Metamaps.Backbone.attachCollectionEvents() + + var map = Active.Map + var mapper = Active.Mapper + + // add class to .wrapper for specifying whether you can edit the map + if (map.authorizeToEdit(mapper)) { + $('.wrapper').addClass('canEditMap') + } + + // add class to .wrapper for specifying if the map can + // be collaborated on + if (map.get('permission') === 'commons') { + $('.wrapper').addClass('commonsMap') + } + + Map.updateStar() + + // set filter mapper H3 text + $('#filter_by_mapper h3').html('MAPPERS') + + // build and render the visualization + Visualize.type = 'ForceDirected' + JIT.prepareVizData() + + // update filters + Filter.reset() + + // reset selected arrays + Selected.reset() + + // set the proper mapinfobox content + Map.InfoBox.load() + + // these three update the actual filter box with the right list items + Filter.checkMetacodes() + Filter.checkSynapses() + Filter.checkMappers() + + Realtime.startActiveMap() + Metamaps.Loading.hide() + + // for mobile + $('#header_content').html(map.get('name')) + } + + $.ajax({ + url: '/maps/' + id + '/contains.json', + success: start + }) + }, + end: function () { + if (Active.Map) { + $('.wrapper').removeClass('canEditMap commonsMap') + AutoLayout.resetSpiral() + + $('.rightclickmenu').remove() + TopicCard.hideCard() + SynapseCard.hideCard() + Create.newTopic.hide(true) // true means force (and override pinned) + Create.newSynapse.hide() + Filter.close() + Map.InfoBox.close() + Realtime.endActiveMap() + } + }, + updateStar: function () { + if (!Active.Mapper || !Metamaps.Stars) return + // update the star/unstar icon + if (Metamaps.Stars.find(function (s) { return s.user_id === Active.Mapper.id })) { + $('.starMap').addClass('starred') + $('.starMap .tooltipsAbove').html('Unstar') + } else { + $('.starMap').removeClass('starred') + $('.starMap .tooltipsAbove').html('Star') + } + }, + star: function () { + var self = Map + + if (!Active.Map) return + $.post('/maps/' + Active.Map.id + '/star') + Metamaps.Stars.push({ user_id: Active.Mapper.id, map_id: Active.Map.id }) + Metamaps.Maps.Starred.add(Active.Map) + GlobalUI.notifyUser('Map is now starred') + self.updateStar() + }, + unstar: function () { + var self = Map + + if (!Active.Map) return + $.post('/maps/' + Active.Map.id + '/unstar') + Metamaps.Stars = Metamaps.Stars.filter(function (s) { return s.user_id != Active.Mapper.id }) + Metamaps.Maps.Starred.remove(Active.Map) + self.updateStar() + }, + fork: function () { + GlobalUI.openLightbox('forkmap') + + var nodes_data = '', + synapses_data = '' + var nodes_array = [] + var synapses_array = [] + // collect the unfiltered topics + Visualize.mGraph.graph.eachNode(function (n) { + // if the opacity is less than 1 then it's filtered + if (n.getData('alpha') === 1) { + var id = n.getData('topic').id + nodes_array.push(id) + var x, y + if (n.pos.x && n.pos.y) { + x = n.pos.x + y = n.pos.y + } else { + var x = Math.cos(n.pos.theta) * n.pos.rho + var y = Math.sin(n.pos.theta) * n.pos.rho + } + nodes_data += id + '/' + x + '/' + y + ',' + } + }) + // collect the unfiltered synapses + Metamaps.Synapses.each(function (synapse) { + var desc = synapse.get('desc') + + var descNotFiltered = Filter.visible.synapses.indexOf(desc) > -1 + // make sure that both topics are being added, otherwise, it + // doesn't make sense to add the synapse + var topicsNotFiltered = nodes_array.indexOf(synapse.get('node1_id')) > -1 + topicsNotFiltered = topicsNotFiltered && nodes_array.indexOf(synapse.get('node2_id')) > -1 + if (descNotFiltered && topicsNotFiltered) { + synapses_array.push(synapse.id) + } + }) + + synapses_data = synapses_array.join() + nodes_data = nodes_data.slice(0, -1) + + GlobalUI.CreateMap.topicsToMap = nodes_data + GlobalUI.CreateMap.synapsesToMap = synapses_data + }, + leavePrivateMap: function () { + var map = Active.Map + Metamaps.Maps.Active.remove(map) + Metamaps.Maps.Featured.remove(map) + Router.home() + GlobalUI.notifyUser('Sorry! That map has been changed to Private.') + }, + cantEditNow: function () { + Realtime.turnOff(true); // true is for 'silence' + GlobalUI.notifyUser('Map was changed to Public. Editing is disabled.') + Active.Map.trigger('changeByOther') + }, + canEditNow: function () { + var confirmString = "You've been granted permission to edit this map. " + confirmString += 'Do you want to reload and enable realtime collaboration?' + var c = confirm(confirmString) + if (c) { + Router.maps(Active.Map.id) + } + }, + editedByActiveMapper: function () { + if (Active.Mapper) { + Metamaps.Mappers.add(Active.Mapper) + } + }, + exportImage: function () { + var canvas = {} + + canvas.canvas = document.createElement('canvas') + canvas.canvas.width = 1880 // 960 + canvas.canvas.height = 1260 // 630 + + canvas.scaleOffsetX = 1 + canvas.scaleOffsetY = 1 + canvas.translateOffsetY = 0 + canvas.translateOffsetX = 0 + canvas.denySelected = true + + canvas.getSize = function () { + if (this.size) return this.size + var canvas = this.canvas + return this.size = { + width: canvas.width, + height: canvas.height + } + } + canvas.scale = function (x, y) { + var px = this.scaleOffsetX * x, + py = this.scaleOffsetY * y + var dx = this.translateOffsetX * (x - 1) / px, + dy = this.translateOffsetY * (y - 1) / py + this.scaleOffsetX = px + this.scaleOffsetY = py + this.getCtx().scale(x, y) + this.translate(dx, dy) + } + canvas.translate = function (x, y) { + var sx = this.scaleOffsetX, + sy = this.scaleOffsetY + this.translateOffsetX += x * sx + this.translateOffsetY += y * sy + this.getCtx().translate(x, y) + } + canvas.getCtx = function () { + return this.canvas.getContext('2d') + } + // center it + canvas.getCtx().translate(1880 / 2, 1260 / 2) + + var mGraph = Visualize.mGraph + + var id = mGraph.root + var root = mGraph.graph.getNode(id) + var T = !!root.visited + + // pass true to avoid basing it on a selection + JIT.zoomExtents(null, canvas, true) + + var c = canvas.canvas, + ctx = canvas.getCtx(), + scale = canvas.scaleOffsetX + + // draw a grey background + ctx.fillStyle = '#d8d9da' + var xPoint = (-(c.width / scale) / 2) - (canvas.translateOffsetX / scale), + yPoint = (-(c.height / scale) / 2) - (canvas.translateOffsetY / scale) + ctx.fillRect(xPoint, yPoint, c.width / scale, c.height / scale) + + // draw the graph + mGraph.graph.eachNode(function (node) { + var nodeAlpha = node.getData('alpha') + node.eachAdjacency(function (adj) { + var nodeTo = adj.nodeTo + if (!!nodeTo.visited === T && node.drawn && nodeTo.drawn) { + mGraph.fx.plotLine(adj, canvas) + } + }) + if (node.drawn) { + mGraph.fx.plotNode(node, canvas) + } + if (!mGraph.labelsHidden) { + if (node.drawn && nodeAlpha >= 0.95) { + mGraph.labels.plotLabel(canvas, node) + } else { + mGraph.labels.hideLabel(node, false) + } + } + node.visited = !T + }) + + var imageData = { + encoded_image: canvas.canvas.toDataURL() + } + + var map = Active.Map + + var today = new Date() + var dd = today.getDate() + var mm = today.getMonth() + 1; // January is 0! + var yyyy = today.getFullYear() + if (dd < 10) { + dd = '0' + dd + } + if (mm < 10) { + mm = '0' + mm + } + today = mm + '/' + dd + '/' + yyyy + + var mapName = map.get('name').split(' ').join([separator = '-']) + var downloadMessage = '' + downloadMessage += 'Captured map screenshot! ' + downloadMessage += "DOWNLOAD" + GlobalUI.notifyUser(downloadMessage) + + $.ajax({ + type: 'POST', + dataType: 'json', + url: '/maps/' + Active.Map.id + '/upload_screenshot', + data: imageData, + success: function (data) { + console.log('successfully uploaded map screenshot') + }, + error: function () { + console.log('failed to save map screenshot') + } + }) + } +} + +export CheatSheet, InfoBox +export default Map diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 9fe8925b..7b431d1f 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -13,7 +13,7 @@ import GlobalUI from './GlobalUI' import Import from './Import' import JIT from './JIT' import Listeners from './Listeners' -import Map from './Map' +import Map, { CheatSheet, InfoBox } from './Map' import Mapper from './Mapper' import Mobile from './Mobile' import Mouse from './Mouse' @@ -46,6 +46,8 @@ Metamaps.Import = Import Metamaps.JIT = JIT Metamaps.Listeners = Listeners Metamaps.Map = Map +Metamaps.Map.CheatSheet = CheatSheet +Metamaps.Map.InfoBox = InfoBox Metamaps.Maps = {} Metamaps.Mapper = Mapper Metamaps.Mobile = Mobile From fe3012136da1a674d87cd0cb0bb48d73dd33c08c Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Thu, 22 Sep 2016 23:51:33 +0800 Subject: [PATCH 15/26] import _ --- frontend/src/Metamaps/Backbone.js | 3 ++- frontend/src/Metamaps/Control.js | 2 ++ frontend/src/Metamaps/Filter.js | 2 ++ frontend/src/Metamaps/JIT.js | 2 ++ frontend/src/Metamaps/Organize.js | 2 ++ frontend/src/Metamaps/Realtime.js | 2 ++ frontend/src/Metamaps/Visualize.js | 2 ++ 7 files changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/src/Metamaps/Backbone.js b/frontend/src/Metamaps/Backbone.js index 9f18ef32..bc303df4 100644 --- a/frontend/src/Metamaps/Backbone.js +++ b/frontend/src/Metamaps/Backbone.js @@ -1,6 +1,7 @@ -window.Metamaps = window.Metamaps || {} /* global Metamaps, Backbone, _, $ */ +import _ from 'lodash' + /* * Metamaps.Backbone.js.erb * diff --git a/frontend/src/Metamaps/Control.js b/frontend/src/Metamaps/Control.js index 9e13e40c..2c14cfca 100644 --- a/frontend/src/Metamaps/Control.js +++ b/frontend/src/Metamaps/Control.js @@ -1,5 +1,7 @@ /* global Metamaps, $ */ +import _ from 'lodash' + import Active from './Active' import Filter from './Filter' import GlobalUI from './GlobalUI' diff --git a/frontend/src/Metamaps/Filter.js b/frontend/src/Metamaps/Filter.js index 38c4f369..f67c6ec8 100644 --- a/frontend/src/Metamaps/Filter.js +++ b/frontend/src/Metamaps/Filter.js @@ -1,5 +1,7 @@ /* global Metamaps, $ */ +import _ from 'lodash' + import Active from './Active' import Control from './Control' import GlobalUI from './GlobalUI' diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index 50c48985..0fe5a224 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -1,5 +1,7 @@ /* global Metamaps */ +import _ from 'lodash' + import Active from './Active' import Control from './Control' import Create from './Create' diff --git a/frontend/src/Metamaps/Organize.js b/frontend/src/Metamaps/Organize.js index ee29c2b8..c05f870e 100644 --- a/frontend/src/Metamaps/Organize.js +++ b/frontend/src/Metamaps/Organize.js @@ -1,5 +1,7 @@ /* global $ */ +import _ from 'lodash' + import Visualize from './Visualize' import JIT from './JIT' diff --git a/frontend/src/Metamaps/Realtime.js b/frontend/src/Metamaps/Realtime.js index 1eef6408..80143f25 100644 --- a/frontend/src/Metamaps/Realtime.js +++ b/frontend/src/Metamaps/Realtime.js @@ -1,5 +1,7 @@ /* global Metamaps, $ */ +import _ from 'lodash' + import Active from './Active' import Control from './Control' import GlobalUI from './GlobalUI' diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index 678c7c64..047cb81d 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -1,5 +1,7 @@ /* global Metamaps, $ */ +import _ from 'lodash' + import Active from './Active' import JIT from './JIT' import Router from './Router' From 30894a313fbde92faabcc5ed37124cf995a34967 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 00:07:30 +0800 Subject: [PATCH 16/26] move views to their own frontend folder --- .../javascripts/src/Metamaps.Erb.js.erb | 2 + .../javascripts/src/views/chatView.js.erb | 343 ------------------ app/assets/javascripts/src/views/room.js | 195 ---------- app/assets/javascripts/src/views/videoView.js | 207 ----------- frontend/src/Metamaps/Realtime.js | 18 +- frontend/src/Metamaps/Router.js | 10 +- frontend/src/Metamaps/Views.js | 91 ----- frontend/src/Metamaps/Views/ChatView.js | 337 +++++++++++++++++ frontend/src/Metamaps/Views/ExploreMaps.js | 86 +++++ frontend/src/Metamaps/Views/Room.js | 198 ++++++++++ frontend/src/Metamaps/Views/VideoView.js | 202 +++++++++++ frontend/src/Metamaps/Views/index.js | 6 + frontend/src/Metamaps/index.js | 12 +- 13 files changed, 851 insertions(+), 856 deletions(-) delete mode 100644 app/assets/javascripts/src/views/chatView.js.erb delete mode 100644 app/assets/javascripts/src/views/room.js delete mode 100644 app/assets/javascripts/src/views/videoView.js delete mode 100644 frontend/src/Metamaps/Views.js create mode 100644 frontend/src/Metamaps/Views/ChatView.js create mode 100644 frontend/src/Metamaps/Views/ExploreMaps.js create mode 100644 frontend/src/Metamaps/Views/Room.js create mode 100644 frontend/src/Metamaps/Views/VideoView.js create mode 100644 frontend/src/Metamaps/Views/index.js diff --git a/app/assets/javascripts/src/Metamaps.Erb.js.erb b/app/assets/javascripts/src/Metamaps.Erb.js.erb index 90eba5e5..60b64e46 100644 --- a/app/assets/javascripts/src/Metamaps.Erb.js.erb +++ b/app/assets/javascripts/src/Metamaps.Erb.js.erb @@ -14,5 +14,7 @@ Metamaps.Erb['icons/wildcard.png'] = '<%= asset_path('icons/wildcard.png') %>' Metamaps.Erb['topic_description_signifier.png'] = '<%= asset_path('topic_description_signifier.png') %>' Metamaps.Erb['topic_link_signifier.png'] = '<%= asset_path('topic_link_signifier.png') %>' Metamaps.Erb['synapse16.png'] = '<%= asset_path('synapse16.png') %>' +Metamaps.Erb['sounds/MM_sounds.mp3'] = '<%= asset_path 'sounds/MM_sounds.mp3' %>' +Metamaps.Erb['sounds/MM_sounds.ogg'] = '<%= asset_path 'sounds/MM_sounds.ogg' %>' Metamaps.Metacodes = <%= Metacode.all.to_json.gsub(%r[(icon.*?)(\"},)], '\1?purple=stupid\2').html_safe %> Metamaps.VERSION = '<%= METAMAPS_VERSION %>' diff --git a/app/assets/javascripts/src/views/chatView.js.erb b/app/assets/javascripts/src/views/chatView.js.erb deleted file mode 100644 index 7a1e7f8e..00000000 --- a/app/assets/javascripts/src/views/chatView.js.erb +++ /dev/null @@ -1,343 +0,0 @@ -Metamaps.Views = Metamaps.Views || {}; - -Metamaps.Views.chatView = (function () { - var - chatView, - linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false }); - - var Private = { - messageHTML: "
              " + - "
              " + - "
              {{ message }}
              " + - "
              {{ timestamp }}
              " + - "
              " + - "
              ", - participantHTML: "
              " + - "
              " + - "
              {{ username }} {{ selfName }}
              " + - "" + - "" + - "
              " + - "
              " + - "
              ", - templates: function() { - _.templateSettings = { - interpolate: /\{\{(.+?)\}\}/g - }; - this.messageTemplate = _.template(Private.messageHTML); - - this.participantTemplate = _.template(Private.participantHTML); - }, - createElements: function() { - this.$unread = $('
              '); - this.$button = $('
              Chat
              '); - this.$messageInput = $(''); - this.$juntoHeader = $('
              PARTICIPANTS
              '); - this.$videoToggle = $('
              '); - this.$cursorToggle = $('
              '); - this.$participants = $('
              '); - this.$conversationInProgress = $('
              LIVE LEAVEJOIN
              '); - this.$chatHeader = $('
              CHAT
              '); - this.$soundToggle = $('
              '); - this.$messages = $('
              '); - this.$container = $('
              '); - }, - attachElements: function() { - this.$button.append(this.$unread); - - this.$juntoHeader.append(this.$videoToggle); - this.$juntoHeader.append(this.$cursorToggle); - - this.$chatHeader.append(this.$soundToggle); - - this.$participants.append(this.$conversationInProgress); - - this.$container.append(this.$juntoHeader); - this.$container.append(this.$participants); - this.$container.append(this.$chatHeader); - this.$container.append(this.$button); - this.$container.append(this.$messages); - this.$container.append(this.$messageInput); - }, - addEventListeners: function() { - var self = this; - - this.participants.on('add', function (participant) { - Private.addParticipant.call(self, participant); - }); - - this.participants.on('remove', function (participant) { - Private.removeParticipant.call(self, participant); - }); - - this.$button.on('click', function () { - Handlers.buttonClick.call(self); - }); - this.$videoToggle.on('click', function () { - Handlers.videoToggleClick.call(self); - }); - this.$cursorToggle.on('click', function () { - Handlers.cursorToggleClick.call(self); - }); - this.$soundToggle.on('click', function () { - Handlers.soundToggleClick.call(self); - }); - this.$messageInput.on('keyup', function (event) { - Handlers.keyUp.call(self, event); - }); - this.$messageInput.on('focus', function () { - Handlers.inputFocus.call(self); - }); - this.$messageInput.on('blur', function () { - Handlers.inputBlur.call(self); - }); - }, - initializeSounds: function() { - this.sound = new Howl({ - urls: ["<%= asset_path 'sounds/MM_sounds.mp3' %>", "<%= asset_path 'sounds/MM_sounds.ogg' %>"], - sprite: { - joinmap: [0, 561], - leavemap: [1000, 592], - receivechat: [2000, 318], - sendchat: [3000, 296], - sessioninvite: [4000, 5393, true] - } - }); - }, - incrementUnread: function() { - this.unreadMessages++; - this.$unread.html(this.unreadMessages); - this.$unread.show(); - }, - addMessage: function(message, isInitial, wasMe) { - - if (!this.isOpen && !isInitial) Private.incrementUnread.call(this); - - function addZero(i) { - if (i < 10) { - i = "0" + i; - } - return i; - } - var m = _.clone(message.attributes); - - var today = new Date(); - m.timestamp = new Date(m.created_at); - - var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate(); - date += " " + addZero(m.timestamp.getHours()) + ":" + addZero(m.timestamp.getMinutes()); - m.timestamp = date; - m.image = m.user_image || 'http://www.hotpepper.ca/wp-content/uploads/2014/11/default_profile_1_200x200.png'; // TODO: remove - m.message = linker.link(m.message); - var $html = $(this.messageTemplate(m)); - this.$messages.append($html); - if (!isInitial) this.scrollMessages(200); - - if (!wasMe && !isInitial && this.alertSound) this.sound.play('receivechat'); - }, - initialMessages: function() { - var messages = this.messages.models; - for (var i = 0; i < messages.length; i++) { - Private.addMessage.call(this, messages[i], true); - } - }, - handleInputMessage: function() { - var message = { - message: this.$messageInput.val(), - }; - this.$messageInput.val(''); - $(document).trigger(chatView.events.message + '-' + this.room, [message]); - }, - addParticipant: function(participant) { - var p = _.clone(participant.attributes); - if (p.self) { - p.selfClass = 'is-self'; - p.selfName = '(me)'; - } else { - p.selfClass = ''; - p.selfName = ''; - } - var html = this.participantTemplate(p); - this.$participants.append(html); - }, - removeParticipant: function(participant) { - this.$container.find('.participant-' + participant.get('id')).remove(); - } - }; - - var Handlers = { - buttonClick: function() { - if (this.isOpen) this.close(); - else if (!this.isOpen) this.open(); - }, - videoToggleClick: function() { - this.$videoToggle.toggleClass('active'); - this.videosShowing = !this.videosShowing; - $(document).trigger(this.videosShowing ? chatView.events.videosOn : chatView.events.videosOff); - }, - cursorToggleClick: function() { - this.$cursorToggle.toggleClass('active'); - this.cursorsShowing = !this.cursorsShowing; - $(document).trigger(this.cursorsShowing ? chatView.events.cursorsOn : chatView.events.cursorsOff); - }, - soundToggleClick: function() { - this.alertSound = !this.alertSound; - this.$soundToggle.toggleClass('active'); - }, - keyUp: function(event) { - switch(event.which) { - case 13: // enter - Private.handleInputMessage.call(this); - break; - } - }, - inputFocus: function() { - $(document).trigger(chatView.events.inputFocus); - }, - inputBlur: function() { - $(document).trigger(chatView.events.inputBlur); - } - }; - - chatView = function(messages, mapper, room) { - var self = this; - - this.room = room; - this.mapper = mapper; - this.messages = messages; // backbone collection - - this.isOpen = false; - this.alertSound = true; // whether to play sounds on arrival of new messages or not - this.cursorsShowing = true; - this.videosShowing = true; - this.unreadMessages = 0; - this.participants = new Backbone.Collection(); - - Private.templates.call(this); - Private.createElements.call(this); - Private.attachElements.call(this); - Private.addEventListeners.call(this); - Private.initialMessages.call(this); - Private.initializeSounds.call(this); - this.$container.css({ - right: '-300px' - }); - }; - - chatView.prototype.conversationInProgress = function (participating) { - this.$conversationInProgress.show(); - this.$participants.addClass('is-live'); - if (participating) this.$participants.addClass('is-participating'); - this.$button.addClass('active'); - - // hide invite to call buttons - } - - chatView.prototype.conversationEnded = function () { - this.$conversationInProgress.hide(); - this.$participants.removeClass('is-live'); - this.$participants.removeClass('is-participating'); - this.$button.removeClass('active'); - this.$participants.find('.participant').removeClass('active'); - this.$participants.find('.participant').removeClass('pending'); - } - - chatView.prototype.leaveConversation = function () { - this.$participants.removeClass('is-participating'); - } - - chatView.prototype.mapperJoinedCall = function (id) { - this.$participants.find('.participant-' + id).addClass('active'); - } - - chatView.prototype.mapperLeftCall = function (id) { - this.$participants.find('.participant-' + id).removeClass('active'); - } - - chatView.prototype.invitationPending = function (id) { - this.$participants.find('.participant-' + id).addClass('pending'); - } - - chatView.prototype.invitationAnswered = function (id) { - this.$participants.find('.participant-' + id).removeClass('pending'); - } - - chatView.prototype.addParticipant = function (participant) { - this.participants.add(participant); - } - - chatView.prototype.removeParticipant = function (username) { - var p = this.participants.find(function (p) { return p.get('username') === username; }); - if (p) { - this.participants.remove(p); - } - } - - chatView.prototype.removeParticipants = function () { - this.participants.remove(this.participants.models); - } - - chatView.prototype.open = function () { - this.$container.css({ - right: '0' - }); - this.$messageInput.focus(); - this.isOpen = true; - this.unreadMessages = 0; - this.$unread.hide(); - this.scrollMessages(0); - $(document).trigger(chatView.events.openTray); - } - - chatView.prototype.addMessage = function(message, isInitial, wasMe) { - this.messages.add(message); - Private.addMessage.call(this, message, isInitial, wasMe); - } - - chatView.prototype.scrollMessages = function(duration) { - duration = duration || 0; - - this.$messages.animate({ - scrollTop: this.$messages[0].scrollHeight - }, duration); - } - - chatView.prototype.clearMessages = function () { - this.unreadMessages = 0; - this.$unread.hide(); - this.$messages.empty(); - } - - chatView.prototype.close = function () { - this.$container.css({ - right: '-300px' - }); - this.$messageInput.blur(); - this.isOpen = false; - $(document).trigger(chatView.events.closeTray); - } - - chatView.prototype.remove = function () { - this.$button.off(); - this.$container.remove(); - } - - /** - * @class - * @static - */ - chatView.events = { - message: 'ChatView:message', - openTray: 'ChatView:openTray', - closeTray: 'ChatView:closeTray', - inputFocus: 'ChatView:inputFocus', - inputBlur: 'ChatView:inputBlur', - cursorsOff: 'ChatView:cursorsOff', - cursorsOn: 'ChatView:cursorsOn', - videosOff: 'ChatView:videosOff', - videosOn: 'ChatView:videosOn' - }; - - return chatView; - -})(); diff --git a/app/assets/javascripts/src/views/room.js b/app/assets/javascripts/src/views/room.js deleted file mode 100644 index 4595c3cb..00000000 --- a/app/assets/javascripts/src/views/room.js +++ /dev/null @@ -1,195 +0,0 @@ -Metamaps.Views = Metamaps.Views || {}; - -Metamaps.Views.room = (function () { - - var ChatView = Metamaps.Views.chatView; - var VideoView = Metamaps.Views.videoView; - - var room = function(opts) { - var self = this; - - this.isActiveRoom = false; - this.socket = opts.socket; - this.webrtc = opts.webrtc; - //this.roomRef = opts.firebase; - this.room = opts.room; - this.config = opts.config; - this.peopleCount = 0; - - this.$myVideo = opts.$video; - this.myVideo = opts.myVideoView; - - this.messages = new Backbone.Collection(); - this.currentMapper = new Backbone.Model({ name: opts.username, image: opts.image }); - this.chat = new ChatView(this.messages, this.currentMapper, this.room); - - this.videos = {}; - - this.init(); - }; - - room.prototype.join = function(cb) { - this.isActiveRoom = true; - this.webrtc.joinRoom(this.room, cb); - this.chat.conversationInProgress(true); // true indicates participation - } - - room.prototype.conversationInProgress = function() { - this.chat.conversationInProgress(false); // false indicates not participating - } - - room.prototype.conversationEnding = function() { - this.chat.conversationEnded(); - } - - room.prototype.leaveVideoOnly = function() { - this.chat.leaveConversation(); // the conversation will carry on without you - for (var id in this.videos) { - this.removeVideo(id); - } - this.isActiveRoom = false; - this.webrtc.leaveRoom(); - } - - room.prototype.leave = function() { - for (var id in this.videos) { - this.removeVideo(id); - } - this.isActiveRoom = false; - this.webrtc.leaveRoom(); - this.chat.conversationEnded(); - this.chat.removeParticipants(); - this.chat.clearMessages(); - this.messages.reset(); - } - - room.prototype.setPeopleCount = function(count) { - this.peopleCount = count; - } - - room.prototype.init = function () { - var self = this; - - $(document).on(VideoView.events.audioControlClick, function (event, videoView) { - if (!videoView.audioStatus) self.webrtc.mute(); - else if (videoView.audioStatus) self.webrtc.unmute(); - }); - $(document).on(VideoView.events.videoControlClick, function (event, videoView) { - if (!videoView.videoStatus) self.webrtc.pauseVideo(); - else if (videoView.videoStatus) self.webrtc.resumeVideo(); - }); - - this.webrtc.webrtc.off('peerStreamAdded'); - this.webrtc.webrtc.off('peerStreamRemoved'); - this.webrtc.on('peerStreamAdded', function (peer) { - var mapper = Metamaps.Realtime.mappersOnMap[peer.nick]; - peer.avatar = mapper.image; - peer.username = mapper.name; - if (self.isActiveRoom) { - self.addVideo(peer); - } - }); - - this.webrtc.on('peerStreamRemoved', function (peer) { - if (self.isActiveRoom) { - self.removeVideo(peer); - } - }); - - this.webrtc.on('mute', function (data) { - var v = self.videos[data.id]; - if (!v) return; - - if (data.name === 'audio') { - v.audioStatus = false; - } - else if (data.name === 'video') { - v.videoStatus = false; - v.$avatar.show(); - } - if (!v.audioStatus && !v.videoStatus) v.$container.hide(); - }); - this.webrtc.on('unmute', function (data) { - var v = self.videos[data.id]; - if (!v) return; - - if (data.name === 'audio') { - v.audioStatus = true; - } - else if (data.name === 'video') { - v.videoStatus = true; - v.$avatar.hide(); - } - v.$container.show(); - }); - - var sendChatMessage = function (event, data) { - self.sendChatMessage(data); - }; - $(document).on(ChatView.events.message + '-' + this.room, sendChatMessage); - } - - room.prototype.videoAdded = function (callback) { - this._videoAdded = callback; - } - - room.prototype.addVideo = function (peer) { - var - id = this.webrtc.getDomId(peer), - video = attachMediaStream(peer.stream); - - var - v = new VideoView(video, null, id, false, { DOUBLE_CLICK_TOLERANCE: 200, avatar: peer.avatar, username: peer.username }); - - this.videos[peer.id] = v; - if (this._videoAdded) this._videoAdded(v, peer.nick); - } - - room.prototype.removeVideo = function (peer) { - var id = typeof peer == 'string' ? peer : peer.id; - if (this.videos[id]) { - this.videos[id].remove(); - delete this.videos[id]; - } - } - - room.prototype.sendChatMessage = function (data) { - var self = this; - //this.roomRef.child('messages').push(data); - if (self.chat.alertSound) self.chat.sound.play('sendchat'); - var m = new Metamaps.Backbone.Message({ - message: data.message, - resource_id: Metamaps.Active.Map.id, - resource_type: "Map" - }); - m.save(null, { - success: function (model, response) { - self.addMessages(new Metamaps.Backbone.MessageCollection(model), false, true); - $(document).trigger(room.events.newMessage, [model]); - }, - error: function (model, response) { - console.log('error!', response); - } - }); - } - - // they should be instantiated as backbone models before they get - // passed to this function - room.prototype.addMessages = function (messages, isInitial, wasMe) { - var self = this; - - messages.models.forEach(function (message) { - self.chat.addMessage(message, isInitial, wasMe); - }); - } - - /** - * @class - * @static - */ - room.events = { - newMessage: "Room:newMessage" - }; - - return room; -})(); diff --git a/app/assets/javascripts/src/views/videoView.js b/app/assets/javascripts/src/views/videoView.js deleted file mode 100644 index b9d39c06..00000000 --- a/app/assets/javascripts/src/views/videoView.js +++ /dev/null @@ -1,207 +0,0 @@ -Metamaps.Views = Metamaps.Views || {}; - -Metamaps.Views.videoView = (function () { - - var videoView; - - var Private = { - addControls: function() { - var self = this; - - this.$audioControl = $('
              '); - this.$videoControl = $('
              '); - - this.$audioControl.on('click', function () { - Handlers.audioControlClick.call(self); - }); - - this.$videoControl.on('click', function () { - Handlers.videoControlClick.call(self); - }); - - this.$container.append(this.$audioControl); - this.$container.append(this.$videoControl); - }, - cancelClick: function() { - this.mouseIsDown = false; - - if (this.hasMoved) { - - } - - $(document).trigger(videoView.events.dragEnd); - } - }; - - var Handlers = { - mousedown: function(event) { - this.mouseIsDown = true; - this.hasMoved = false; - this.mouseMoveStart = { - x: event.pageX, - y: event.pageY - }; - this.posStart = { - x: parseInt(this.$container.css('left'), '10'), - y: parseInt(this.$container.css('top'), '10') - } - - $(document).trigger(videoView.events.mousedown); - }, - mouseup: function(event) { - $(document).trigger(videoView.events.mouseup, [this]); - - var storedTime = this.lastClick; - var now = Date.now(); - this.lastClick = now; - - if (now - storedTime < this.config.DOUBLE_CLICK_TOLERANCE) { - $(document).trigger(videoView.events.doubleClick, [this]); - } - }, - mousemove: function(event) { - var - diffX, - diffY, - newX, - newY; - - if (this.$parent && this.mouseIsDown) { - this.manuallyPositioned = true; - this.hasMoved = true; - diffX = event.pageX - this.mouseMoveStart.x; - diffY = this.mouseMoveStart.y - event.pageY; - newX = this.posStart.x + diffX; - newY = this.posStart.y - diffY; - this.$container.css({ - top: newY, - left: newX - }); - } - }, - audioControlClick: function() { - if (this.audioStatus) { - this.audioOff(); - } else { - this.audioOn(); - } - $(document).trigger(videoView.events.audioControlClick, [this]); - }, - videoControlClick: function() { - if (this.videoStatus) { - this.videoOff(); - } else { - this.videoOn(); - } - $(document).trigger(videoView.events.videoControlClick, [this]); - }, - }; - - var videoView = function(video, $parent, id, isMyself, config) { - var self = this; - - this.$parent = $parent; // mapView - - this.video = video; - this.id = id; - - this.config = config; - - this.mouseIsDown = false; - this.mouseDownOffset = { x: 0, y: 0 }; - this.lastClick = null; - this.hasMoved = false; - - this.audioStatus = true; - this.videoStatus = true; - - this.$container = $('
              '); - this.$container.addClass('collaborator-video' + (isMyself ? ' my-video' : '')); - this.$container.attr('id', 'container_' + id); - - - var $vidContainer = $('
              '); - $vidContainer.addClass('video-cutoff'); - $vidContainer.append(this.video); - - this.avatar = config.avatar; - this.$avatar = $(''); - $vidContainer.append(this.$avatar); - - this.$container.append($vidContainer); - - this.$container.on('mousedown', function (event) { - Handlers.mousedown.call(self, event); - }); - - if (isMyself) { - Private.addControls.call(this); - } - - // suppress contextmenu - this.video.oncontextmenu = function () { return false; }; - - if (this.$parent) this.setParent(this.$parent); - }; - - videoView.prototype.setParent = function($parent) { - var self = this; - this.$parent = $parent; - this.$parent.off('.video' + this.id); - this.$parent.on('mouseup.video' + this.id, function (event) { - Handlers.mouseup.call(self, event); - Private.cancelClick.call(self); - }); - this.$parent.on('mousemove.video' + this.id, function (event) { - Handlers.mousemove.call(self, event); - }); - } - - videoView.prototype.setAvatar = function (src) { - this.$avatar.attr('src', src); - this.avatar = src; - } - - videoView.prototype.remove = function () { - this.$container.off(); - if (this.$parent) this.$parent.off('.video' + this.id); - this.$container.remove(); - } - - videoView.prototype.videoOff = function () { - this.$videoControl.addClass('active'); - this.$avatar.show(); - this.videoStatus = false; - } - - videoView.prototype.videoOn = function () { - this.$videoControl.removeClass('active'); - this.$avatar.hide(); - this.videoStatus = true; - } - - videoView.prototype.audioOff = function () { - this.$audioControl.addClass('active'); - this.audioStatus = false; - } - - videoView.prototype.audioOn = function () { - this.$audioControl.removeClass('active'); - this.audioStatus = true; - } - - /** - * @class - * @static - */ - videoView.events = { - mousedown: "VideoView:mousedown", - mouseup: "VideoView:mouseup", - doubleClick: "VideoView:doubleClick", - dragEnd: "VideoView:dragEnd", - audioControlClick: "VideoView:audioControlClick", - videoControlClick: "VideoView:videoControlClick", - }; - - return videoView; -})(); diff --git a/frontend/src/Metamaps/Realtime.js b/frontend/src/Metamaps/Realtime.js index 80143f25..355e73f8 100644 --- a/frontend/src/Metamaps/Realtime.js +++ b/frontend/src/Metamaps/Realtime.js @@ -77,13 +77,13 @@ const Realtime = { var $video = $('').attr('id', self.videoId) self.localVideo = { $video: $video, - view: new Views.videoView($video[0], $('body'), 'me', true, { + view: new Views.VideoView($video[0], $('body'), 'me', true, { DOUBLE_CLICK_TOLERANCE: 200, avatar: Active.Mapper ? Active.Mapper.get('image') : '' }) } - self.room = new Views.room({ + self.room = new Views.Room({ webrtc: self.webrtc, socket: self.socket, username: Active.Mapper ? Active.Mapper.get('name') : '', @@ -104,26 +104,26 @@ const Realtime = { addJuntoListeners: function () { var self = Realtime - $(document).on(Views.chatView.events.openTray, function () { + $(document).on(Views.ChatView.events.openTray, function () { $('.main').addClass('compressed') self.chatOpen = true self.positionPeerIcons() }) - $(document).on(Views.chatView.events.closeTray, function () { + $(document).on(Views.ChatView.events.closeTray, function () { $('.main').removeClass('compressed') self.chatOpen = false self.positionPeerIcons() }) - $(document).on(Views.chatView.events.videosOn, function () { + $(document).on(Views.ChatView.events.videosOn, function () { $('#wrapper').removeClass('hideVideos') }) - $(document).on(Views.chatView.events.videosOff, function () { + $(document).on(Views.ChatView.events.videosOff, function () { $('#wrapper').addClass('hideVideos') }) - $(document).on(Views.chatView.events.cursorsOn, function () { + $(document).on(Views.ChatView.events.cursorsOn, function () { $('#wrapper').removeClass('hideCursors') }) - $(document).on(Views.chatView.events.cursorsOff, function () { + $(document).on(Views.ChatView.events.cursorsOff, function () { $('#wrapper').addClass('hideCursors') }) }, @@ -611,7 +611,7 @@ const Realtime = { var sendNewMessage = function (event, data) { self.sendNewMessage(data) } - $(document).on(Views.room.events.newMessage + '.map', sendNewMessage) + $(document).on(Views.Room.events.newMessage + '.map', sendNewMessage) }, attachMapListener: function () { var self = Realtime diff --git a/frontend/src/Metamaps/Router.js b/frontend/src/Metamaps/Router.js index d5c07e12..6760edcc 100644 --- a/frontend/src/Metamaps/Router.js +++ b/frontend/src/Metamaps/Router.js @@ -49,11 +49,11 @@ const _Router = Backbone.Router.extend({ GlobalUI.showDiv('#explore') - Views.exploreMaps.setCollection(Metamaps.Maps.Active) + Views.ExploreMaps.setCollection(Metamaps.Maps.Active) if (Metamaps.Maps.Active.length === 0) { Metamaps.Maps.Active.getMaps(navigate) // this will trigger an explore maps render } else { - Views.exploreMaps.render(navigate) + Views.ExploreMaps.render(navigate) } } else { // logged out home page @@ -108,7 +108,7 @@ const _Router = Backbone.Router.extend({ Metamaps.Maps.Mapper.mapperId = id } - Views.exploreMaps.setCollection(Metamaps.Maps[capitalize]) + Views.ExploreMaps.setCollection(Metamaps.Maps[capitalize]) var navigate = function () { var path = '/explore/' + this.currentPage @@ -130,9 +130,9 @@ const _Router = Backbone.Router.extend({ }, 300) // wait 300 milliseconds till the other animations are done to do the fetch } else { if (id) { - Views.exploreMaps.fetchUserThenRender(navigateTimeout) + Views.ExploreMaps.fetchUserThenRender(navigateTimeout) } else { - Views.exploreMaps.render(navigateTimeout) + Views.ExploreMaps.render(navigateTimeout) } } diff --git a/frontend/src/Metamaps/Views.js b/frontend/src/Metamaps/Views.js deleted file mode 100644 index aee0fdf0..00000000 --- a/frontend/src/Metamaps/Views.js +++ /dev/null @@ -1,91 +0,0 @@ -/* global Metamaps, $ */ - -import Active from './Active' -import ReactComponents from './ReactComponents' -import ReactDOM from 'react-dom' // TODO ensure this isn't a double import - -/* - * Metamaps.Views.js.erb - * - * Dependencies: - * - Metamaps.Loading - */ - -const Views = { - exploreMaps: { - setCollection: function (collection) { - var self = Views.exploreMaps - - if (self.collection) { - self.collection.off('add', self.render) - self.collection.off('successOnFetch', self.handleSuccess) - self.collection.off('errorOnFetch', self.handleError) - } - self.collection = collection - self.collection.on('add', self.render) - self.collection.on('successOnFetch', self.handleSuccess) - self.collection.on('errorOnFetch', self.handleError) - }, - render: function (mapperObj, cb) { - var self = Views.exploreMaps - - if (typeof mapperObj === 'function') { - cb = mapperObj - mapperObj = null - } - - var exploreObj = { - currentUser: Active.Mapper, - section: self.collection.id, - displayStyle: 'grid', - maps: self.collection, - moreToLoad: self.collection.page != 'loadedAll', - user: mapperObj, - loadMore: self.loadMore - } - ReactDOM.render( - React.createElement(ReactComponents.Maps, exploreObj), - document.getElementById('explore') - ) - - if (cb) cb() - Metamaps.Loading.hide() - }, - loadMore: function () { - var self = Views.exploreMaps - - if (self.collection.page != "loadedAll") { - self.collection.getMaps() - } - else self.render() - }, - handleSuccess: function (cb) { - var self = Views.exploreMaps - - if (self.collection && self.collection.id === 'mapper') { - self.fetchUserThenRender(cb) - } else { - self.render(cb) - } - }, - handleError: function () { - console.log('error loading maps!') // TODO - }, - fetchUserThenRender: function (cb) { - var self = Views.exploreMaps - - // first load the mapper object and then call the render function - $.ajax({ - url: '/users/' + self.collection.mapperId + '/details.json', - success: function (response) { - self.render(response, cb) - }, - error: function () { - self.render(cb) - } - }) - } - } -} - -export default Views diff --git a/frontend/src/Metamaps/Views/ChatView.js b/frontend/src/Metamaps/Views/ChatView.js new file mode 100644 index 00000000..5d8f5f65 --- /dev/null +++ b/frontend/src/Metamaps/Views/ChatView.js @@ -0,0 +1,337 @@ +/* global Autolinker, $ */ +var linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false }); + +var Private = { + messageHTML: "
              " + + "
              " + + "
              {{ message }}
              " + + "
              {{ timestamp }}
              " + + "
              " + + "
              ", + participantHTML: "
              " + + "
              " + + "
              {{ username }} {{ selfName }}
              " + + "" + + "" + + "
              " + + "
              " + + "
              ", + templates: function() { + _.templateSettings = { + interpolate: /\{\{(.+?)\}\}/g + }; + this.messageTemplate = _.template(Private.messageHTML); + + this.participantTemplate = _.template(Private.participantHTML); + }, + createElements: function() { + this.$unread = $('
              '); + this.$button = $('
              Chat
              '); + this.$messageInput = $(''); + this.$juntoHeader = $('
              PARTICIPANTS
              '); + this.$videoToggle = $('
              '); + this.$cursorToggle = $('
              '); + this.$participants = $('
              '); + this.$conversationInProgress = $('
              LIVE LEAVEJOIN
              '); + this.$chatHeader = $('
              CHAT
              '); + this.$soundToggle = $('
              '); + this.$messages = $('
              '); + this.$container = $('
              '); + }, + attachElements: function() { + this.$button.append(this.$unread); + + this.$juntoHeader.append(this.$videoToggle); + this.$juntoHeader.append(this.$cursorToggle); + + this.$chatHeader.append(this.$soundToggle); + + this.$participants.append(this.$conversationInProgress); + + this.$container.append(this.$juntoHeader); + this.$container.append(this.$participants); + this.$container.append(this.$chatHeader); + this.$container.append(this.$button); + this.$container.append(this.$messages); + this.$container.append(this.$messageInput); + }, + addEventListeners: function() { + var self = this; + + this.participants.on('add', function (participant) { + Private.addParticipant.call(self, participant); + }); + + this.participants.on('remove', function (participant) { + Private.removeParticipant.call(self, participant); + }); + + this.$button.on('click', function () { + Handlers.buttonClick.call(self); + }); + this.$videoToggle.on('click', function () { + Handlers.videoToggleClick.call(self); + }); + this.$cursorToggle.on('click', function () { + Handlers.cursorToggleClick.call(self); + }); + this.$soundToggle.on('click', function () { + Handlers.soundToggleClick.call(self); + }); + this.$messageInput.on('keyup', function (event) { + Handlers.keyUp.call(self, event); + }); + this.$messageInput.on('focus', function () { + Handlers.inputFocus.call(self); + }); + this.$messageInput.on('blur', function () { + Handlers.inputBlur.call(self); + }); + }, + initializeSounds: function() { + this.sound = new Howl({ + urls: [Metamaps.Erb['sounds/MM_sounds.mp3'], Metamaps.Erb['sounds/MM_sounds.ogg'], + sprite: { + joinmap: [0, 561], + leavemap: [1000, 592], + receivechat: [2000, 318], + sendchat: [3000, 296], + sessioninvite: [4000, 5393, true] + } + }); + }, + incrementUnread: function() { + this.unreadMessages++; + this.$unread.html(this.unreadMessages); + this.$unread.show(); + }, + addMessage: function(message, isInitial, wasMe) { + + if (!this.isOpen && !isInitial) Private.incrementUnread.call(this); + + function addZero(i) { + if (i < 10) { + i = "0" + i; + } + return i; + } + var m = _.clone(message.attributes); + + var today = new Date(); + m.timestamp = new Date(m.created_at); + + var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate(); + date += " " + addZero(m.timestamp.getHours()) + ":" + addZero(m.timestamp.getMinutes()); + m.timestamp = date; + m.image = m.user_image || 'http://www.hotpepper.ca/wp-content/uploads/2014/11/default_profile_1_200x200.png'; // TODO: remove + m.message = linker.link(m.message); + var $html = $(this.messageTemplate(m)); + this.$messages.append($html); + if (!isInitial) this.scrollMessages(200); + + if (!wasMe && !isInitial && this.alertSound) this.sound.play('receivechat'); + }, + initialMessages: function() { + var messages = this.messages.models; + for (var i = 0; i < messages.length; i++) { + Private.addMessage.call(this, messages[i], true); + } + }, + handleInputMessage: function() { + var message = { + message: this.$messageInput.val(), + }; + this.$messageInput.val(''); + $(document).trigger(chatView.events.message + '-' + this.room, [message]); + }, + addParticipant: function(participant) { + var p = _.clone(participant.attributes); + if (p.self) { + p.selfClass = 'is-self'; + p.selfName = '(me)'; + } else { + p.selfClass = ''; + p.selfName = ''; + } + var html = this.participantTemplate(p); + this.$participants.append(html); + }, + removeParticipant: function(participant) { + this.$container.find('.participant-' + participant.get('id')).remove(); + } +}; + +var Handlers = { + buttonClick: function() { + if (this.isOpen) this.close(); + else if (!this.isOpen) this.open(); + }, + videoToggleClick: function() { + this.$videoToggle.toggleClass('active'); + this.videosShowing = !this.videosShowing; + $(document).trigger(this.videosShowing ? chatView.events.videosOn : chatView.events.videosOff); + }, + cursorToggleClick: function() { + this.$cursorToggle.toggleClass('active'); + this.cursorsShowing = !this.cursorsShowing; + $(document).trigger(this.cursorsShowing ? chatView.events.cursorsOn : chatView.events.cursorsOff); + }, + soundToggleClick: function() { + this.alertSound = !this.alertSound; + this.$soundToggle.toggleClass('active'); + }, + keyUp: function(event) { + switch(event.which) { + case 13: // enter + Private.handleInputMessage.call(this); + break; + } + }, + inputFocus: function() { + $(document).trigger(chatView.events.inputFocus); + }, + inputBlur: function() { + $(document).trigger(chatView.events.inputBlur); + } +}; + +const ChatView = function(messages, mapper, room) { + var self = this; + + this.room = room; + this.mapper = mapper; + this.messages = messages; // backbone collection + + this.isOpen = false; + this.alertSound = true; // whether to play sounds on arrival of new messages or not + this.cursorsShowing = true; + this.videosShowing = true; + this.unreadMessages = 0; + this.participants = new Backbone.Collection(); + + Private.templates.call(this); + Private.createElements.call(this); + Private.attachElements.call(this); + Private.addEventListeners.call(this); + Private.initialMessages.call(this); + Private.initializeSounds.call(this); + this.$container.css({ + right: '-300px' + }); +}; + +ChatView.prototype.conversationInProgress = function (participating) { + this.$conversationInProgress.show(); + this.$participants.addClass('is-live'); + if (participating) this.$participants.addClass('is-participating'); + this.$button.addClass('active'); + + // hide invite to call buttons +} + +ChatView.prototype.conversationEnded = function () { + this.$conversationInProgress.hide(); + this.$participants.removeClass('is-live'); + this.$participants.removeClass('is-participating'); + this.$button.removeClass('active'); + this.$participants.find('.participant').removeClass('active'); + this.$participants.find('.participant').removeClass('pending'); +} + +ChatView.prototype.leaveConversation = function () { + this.$participants.removeClass('is-participating'); +} + +ChatView.prototype.mapperJoinedCall = function (id) { + this.$participants.find('.participant-' + id).addClass('active'); +} + +ChatView.prototype.mapperLeftCall = function (id) { + this.$participants.find('.participant-' + id).removeClass('active'); +} + +ChatView.prototype.invitationPending = function (id) { + this.$participants.find('.participant-' + id).addClass('pending'); +} + +ChatView.prototype.invitationAnswered = function (id) { + this.$participants.find('.participant-' + id).removeClass('pending'); +} + +ChatView.prototype.addParticipant = function (participant) { + this.participants.add(participant); +} + +ChatView.prototype.removeParticipant = function (username) { + var p = this.participants.find(function (p) { return p.get('username') === username; }); + if (p) { + this.participants.remove(p); + } +} + +ChatView.prototype.removeParticipants = function () { + this.participants.remove(this.participants.models); +} + +ChatView.prototype.open = function () { + this.$container.css({ + right: '0' + }); + this.$messageInput.focus(); + this.isOpen = true; + this.unreadMessages = 0; + this.$unread.hide(); + this.scrollMessages(0); + $(document).trigger(ChatView.events.openTray); +} + +ChatView.prototype.addMessage = function(message, isInitial, wasMe) { + this.messages.add(message); + Private.addMessage.call(this, message, isInitial, wasMe); +} + +ChatView.prototype.scrollMessages = function(duration) { + duration = duration || 0; + + this.$messages.animate({ + scrollTop: this.$messages[0].scrollHeight + }, duration); +} + +ChatView.prototype.clearMessages = function () { + this.unreadMessages = 0; + this.$unread.hide(); + this.$messages.empty(); +} + +ChatView.prototype.close = function () { + this.$container.css({ + right: '-300px' + }); + this.$messageInput.blur(); + this.isOpen = false; + $(document).trigger(ChatView.events.closeTray); +} + +ChatView.prototype.remove = function () { + this.$button.off(); + this.$container.remove(); +} + +/** + * @class + * @static + */ +ChatView.events = { + message: 'ChatView:message', + openTray: 'ChatView:openTray', + closeTray: 'ChatView:closeTray', + inputFocus: 'ChatView:inputFocus', + inputBlur: 'ChatView:inputBlur', + cursorsOff: 'ChatView:cursorsOff', + cursorsOn: 'ChatView:cursorsOn', + videosOff: 'ChatView:videosOff', + videosOn: 'ChatView:videosOn' +}; + +export default ChatView diff --git a/frontend/src/Metamaps/Views/ExploreMaps.js b/frontend/src/Metamaps/Views/ExploreMaps.js new file mode 100644 index 00000000..4ffbf9fb --- /dev/null +++ b/frontend/src/Metamaps/Views/ExploreMaps.js @@ -0,0 +1,86 @@ +/* global Metamaps, $ */ + +import Active from './Active' +import ReactComponents from './ReactComponents' +import ReactDOM from 'react-dom' // TODO ensure this isn't a double import + +/* + * - Metamaps.Loading + */ + +const ExploreMaps = { + setCollection: function (collection) { + var self = ExploreMaps + + if (self.collection) { + self.collection.off('add', self.render) + self.collection.off('successOnFetch', self.handleSuccess) + self.collection.off('errorOnFetch', self.handleError) + } + self.collection = collection + self.collection.on('add', self.render) + self.collection.on('successOnFetch', self.handleSuccess) + self.collection.on('errorOnFetch', self.handleError) + }, + render: function (mapperObj, cb) { + var self = ExploreMaps + + if (typeof mapperObj === 'function') { + cb = mapperObj + mapperObj = null + } + + var exploreObj = { + currentUser: Active.Mapper, + section: self.collection.id, + displayStyle: 'grid', + maps: self.collection, + moreToLoad: self.collection.page != 'loadedAll', + user: mapperObj, + loadMore: self.loadMore + } + ReactDOM.render( + React.createElement(ReactComponents.Maps, exploreObj), + document.getElementById('explore') + ) + + if (cb) cb() + Metamaps.Loading.hide() + }, + loadMore: function () { + var self = ExploreMaps + + if (self.collection.page != "loadedAll") { + self.collection.getMaps() + } + else self.render() + }, + handleSuccess: function (cb) { + var self = ExploreMaps + + if (self.collection && self.collection.id === 'mapper') { + self.fetchUserThenRender(cb) + } else { + self.render(cb) + } + }, + handleError: function () { + console.log('error loading maps!') // TODO + }, + fetchUserThenRender: function (cb) { + var self = ExploreMaps + + // first load the mapper object and then call the render function + $.ajax({ + url: '/users/' + self.collection.mapperId + '/details.json', + success: function (response) { + self.render(response, cb) + }, + error: function () { + self.render(cb) + } + }) + } +} + +export default ExploreMaps diff --git a/frontend/src/Metamaps/Views/Room.js b/frontend/src/Metamaps/Views/Room.js new file mode 100644 index 00000000..014df61b --- /dev/null +++ b/frontend/src/Metamaps/Views/Room.js @@ -0,0 +1,198 @@ +/* global Metamaps, $ */ +import Active from '../Active' +import Realtime from '../Realtime' + +import ChatView from './ChatView' +import VideoView from './VideoView' + +/* + * Metamaps.Backbone + */ + +const Room = function(opts) { + var self = this + + this.isActiveRoom = false + this.socket = opts.socket + this.webrtc = opts.webrtc + //this.roomRef = opts.firebase + this.room = opts.room + this.config = opts.config + this.peopleCount = 0 + + this.$myVideo = opts.$video + this.myVideo = opts.myVideoView + + this.messages = new Backbone.Collection() + this.currentMapper = new Backbone.Model({ name: opts.username, image: opts.image }) + this.chat = new ChatView(this.messages, this.currentMapper, this.room) + + this.videos = {} + + this.init() +} + +Room.prototype.join = function(cb) { + this.isActiveRoom = true + this.webrtc.joinRoom(this.room, cb) + this.chat.conversationInProgress(true) // true indicates participation +} + +Room.prototype.conversationInProgress = function() { + this.chat.conversationInProgress(false) // false indicates not participating +} + +Room.prototype.conversationEnding = function() { + this.chat.conversationEnded() +} + +Room.prototype.leaveVideoOnly = function() { + this.chat.leaveConversation() // the conversation will carry on without you + for (var id in this.videos) { + this.removeVideo(id) + } + this.isActiveRoom = false + this.webrtc.leaveRoom() +} + +Room.prototype.leave = function() { + for (var id in this.videos) { + this.removeVideo(id) + } + this.isActiveRoom = false + this.webrtc.leaveRoom() + this.chat.conversationEnded() + this.chat.removeParticipants() + this.chat.clearMessages() + this.messages.reset() +} + +Room.prototype.setPeopleCount = function(count) { + this.peopleCount = count +} + +Room.prototype.init = function () { + var self = this + + $(document).on(VideoView.events.audioControlClick, function (event, videoView) { + if (!videoView.audioStatus) self.webrtc.mute() + else if (videoView.audioStatus) self.webrtc.unmute() + }) + $(document).on(VideoView.events.videoControlClick, function (event, videoView) { + if (!videoView.videoStatus) self.webrtc.pauseVideo() + else if (videoView.videoStatus) self.webrtc.resumeVideo() + }) + + this.webrtc.webrtc.off('peerStreamAdded') + this.webrtc.webrtc.off('peerStreamRemoved') + this.webrtc.on('peerStreamAdded', function (peer) { + var mapper = Realtime.mappersOnMap[peer.nick] + peer.avatar = mapper.image + peer.username = mapper.name + if (self.isActiveRoom) { + self.addVideo(peer) + } + }) + + this.webrtc.on('peerStreamRemoved', function (peer) { + if (self.isActiveRoom) { + self.removeVideo(peer) + } + }) + + this.webrtc.on('mute', function (data) { + var v = self.videos[data.id] + if (!v) return + + if (data.name === 'audio') { + v.audioStatus = false + } + else if (data.name === 'video') { + v.videoStatus = false + v.$avatar.show() + } + if (!v.audioStatus && !v.videoStatus) v.$container.hide() + }) + this.webrtc.on('unmute', function (data) { + var v = self.videos[data.id] + if (!v) return + + if (data.name === 'audio') { + v.audioStatus = true + } + else if (data.name === 'video') { + v.videoStatus = true + v.$avatar.hide() + } + v.$container.show() + }) + + var sendChatMessage = function (event, data) { + self.sendChatMessage(data) + } + $(document).on(ChatView.events.message + '-' + this.room, sendChatMessage) + } + + Room.prototype.videoAdded = function (callback) { + this._videoAdded = callback + } + + Room.prototype.addVideo = function (peer) { + var + id = this.webrtc.getDomId(peer), + video = attachMediaStream(peer.stream) + + var + v = new VideoView(video, null, id, false, { DOUBLE_CLICK_TOLERANCE: 200, avatar: peer.avatar, username: peer.username }) + + this.videos[peer.id] = v + if (this._videoAdded) this._videoAdded(v, peer.nick) + } + + Room.prototype.removeVideo = function (peer) { + var id = typeof peer == 'string' ? peer : peer.id + if (this.videos[id]) { + this.videos[id].remove() + delete this.videos[id] + } + } + + Room.prototype.sendChatMessage = function (data) { + var self = this + //this.roomRef.child('messages').push(data) + if (self.chat.alertSound) self.chat.sound.play('sendchat') + var m = new Metamaps.Backbone.Message({ + message: data.message, + resource_id: Active.Map.id, + resource_type: "Map" + }) + m.save(null, { + success: function (model, response) { + self.addMessages(new Metamaps.Backbone.MessageCollection(model), false, true) + $(document).trigger(Room.events.newMessage, [model]) + }, + error: function (model, response) { + console.log('error!', response) + } + }) + } + + // they should be instantiated as backbone models before they get + // passed to this function + Room.prototype.addMessages = function (messages, isInitial, wasMe) { + var self = this + + messages.models.forEach(function (message) { + self.chat.addMessage(message, isInitial, wasMe) + }) + } + +/** + * @class + * @static + */ +Room.events = { + newMessage: "Room:newMessage" +} + +export default Room diff --git a/frontend/src/Metamaps/Views/VideoView.js b/frontend/src/Metamaps/Views/VideoView.js new file mode 100644 index 00000000..401ece54 --- /dev/null +++ b/frontend/src/Metamaps/Views/VideoView.js @@ -0,0 +1,202 @@ +/* global $ */ + +var Private = { + addControls: function() { + var self = this; + + this.$audioControl = $('
              '); + this.$videoControl = $('
              '); + + this.$audioControl.on('click', function () { + Handlers.audioControlClick.call(self); + }); + + this.$videoControl.on('click', function () { + Handlers.videoControlClick.call(self); + }); + + this.$container.append(this.$audioControl); + this.$container.append(this.$videoControl); + }, + cancelClick: function() { + this.mouseIsDown = false; + + if (this.hasMoved) { + + } + + $(document).trigger(VideoView.events.dragEnd); + } +}; + +var Handlers = { + mousedown: function(event) { + this.mouseIsDown = true; + this.hasMoved = false; + this.mouseMoveStart = { + x: event.pageX, + y: event.pageY + }; + this.posStart = { + x: parseInt(this.$container.css('left'), '10'), + y: parseInt(this.$container.css('top'), '10') + } + + $(document).trigger(VideoView.events.mousedown); + }, + mouseup: function(event) { + $(document).trigger(VideoView.events.mouseup, [this]); + + var storedTime = this.lastClick; + var now = Date.now(); + this.lastClick = now; + + if (now - storedTime < this.config.DOUBLE_CLICK_TOLERANCE) { + $(document).trigger(VideoView.events.doubleClick, [this]); + } + }, + mousemove: function(event) { + var + diffX, + diffY, + newX, + newY; + + if (this.$parent && this.mouseIsDown) { + this.manuallyPositioned = true; + this.hasMoved = true; + diffX = event.pageX - this.mouseMoveStart.x; + diffY = this.mouseMoveStart.y - event.pageY; + newX = this.posStart.x + diffX; + newY = this.posStart.y - diffY; + this.$container.css({ + top: newY, + left: newX + }); + } + }, + audioControlClick: function() { + if (this.audioStatus) { + this.audioOff(); + } else { + this.audioOn(); + } + $(document).trigger(VideoView.events.audioControlClick, [this]); + }, + videoControlClick: function() { + if (this.videoStatus) { + this.videoOff(); + } else { + this.videoOn(); + } + $(document).trigger(VideoView.events.videoControlClick, [this]); + }, +}; + +var VideoView = function(video, $parent, id, isMyself, config) { + var self = this; + + this.$parent = $parent; // mapView + + this.video = video; + this.id = id; + + this.config = config; + + this.mouseIsDown = false; + this.mouseDownOffset = { x: 0, y: 0 }; + this.lastClick = null; + this.hasMoved = false; + + this.audioStatus = true; + this.videoStatus = true; + + this.$container = $('
              '); + this.$container.addClass('collaborator-video' + (isMyself ? ' my-video' : '')); + this.$container.attr('id', 'container_' + id); + + + var $vidContainer = $('
              '); + $vidContainer.addClass('video-cutoff'); + $vidContainer.append(this.video); + + this.avatar = config.avatar; + this.$avatar = $(''); + $vidContainer.append(this.$avatar); + + this.$container.append($vidContainer); + + this.$container.on('mousedown', function (event) { + Handlers.mousedown.call(self, event); + }); + + if (isMyself) { + Private.addControls.call(this); + } + + // suppress contextmenu + this.video.oncontextmenu = function () { return false; }; + + if (this.$parent) this.setParent(this.$parent); +}; + +VideoView.prototype.setParent = function($parent) { + var self = this; + this.$parent = $parent; + this.$parent.off('.video' + this.id); + this.$parent.on('mouseup.video' + this.id, function (event) { + Handlers.mouseup.call(self, event); + Private.cancelClick.call(self); + }); + this.$parent.on('mousemove.video' + this.id, function (event) { + Handlers.mousemove.call(self, event); + }); +} + +VideoView.prototype.setAvatar = function (src) { + this.$avatar.attr('src', src); + this.avatar = src; +} + +VideoView.prototype.remove = function () { + this.$container.off(); + if (this.$parent) this.$parent.off('.video' + this.id); + this.$container.remove(); +} + +VideoView.prototype.videoOff = function () { + this.$videoControl.addClass('active'); + this.$avatar.show(); + this.videoStatus = false; +} + +VideoView.prototype.videoOn = function () { + this.$videoControl.removeClass('active'); + this.$avatar.hide(); + this.videoStatus = true; +} + +VideoView.prototype.audioOff = function () { + this.$audioControl.addClass('active'); + this.audioStatus = false; +} + +VideoView.prototype.audioOn = function () { + this.$audioControl.removeClass('active'); + this.audioStatus = true; +} + +/** + * @class + * @static + */ +VideoView.events = { + mousedown: "VideoView:mousedown", + mouseup: "VideoView:mouseup", + doubleClick: "VideoView:doubleClick", + dragEnd: "VideoView:dragEnd", + audioControlClick: "VideoView:audioControlClick", + videoControlClick: "VideoView:videoControlClick", +}; + +export default VideoView diff --git a/frontend/src/Metamaps/Views/index.js b/frontend/src/Metamaps/Views/index.js new file mode 100644 index 00000000..ca0e751a --- /dev/null +++ b/frontend/src/Metamaps/Views/index.js @@ -0,0 +1,6 @@ +import ExploreMaps from './ExploreMaps' +import ChatView from './ChatView' +import VideoView from './VideoView' +import Room from './Room' + +export ExploreMaps, ChatView, VideoView, Room diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 7b431d1f..45283c89 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -28,7 +28,7 @@ import SynapseCard from './SynapseCard' import Topic from './Topic' import TopicCard from './TopicCard' import Util from './Util' -import Views from './Views' +import * as Views from './Views' import Visualize from './Visualize' import ReactComponents from './ReactComponents' @@ -83,18 +83,18 @@ document.addEventListener("DOMContentLoaded", function() { if (Metamaps.currentSection === "explore") { const capitalize = Metamaps.currentPage.charAt(0).toUpperCase() + Metamaps.currentPage.slice(1) - Metamaps.Views.exploreMaps.setCollection( Metamaps.Maps[capitalize] ) + Metamaps.Views.ExploreMaps.setCollection( Metamaps.Maps[capitalize] ) if (Metamaps.currentPage === "mapper") { - Views.exploreMaps.fetchUserThenRender() + Views.ExploreMaps.fetchUserThenRender() } else { - Views.exploreMaps.render() + Views.ExploreMaps.render() } GlobalUI.showDiv('#explore') } else if (Metamaps.currentSection === "" && Active.Mapper) { - Views.exploreMaps.setCollection(Metamaps.Maps.Active) - Views.exploreMaps.render() + Views.ExploreMaps.setCollection(Metamaps.Maps.Active) + Views.ExploreMaps.render() GlobalUI.showDiv('#explore') } else if (Active.Map || Active.Topic) { From a996734c793aebd75eea8031e4a328f3e5a5a2b5 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 00:16:15 +0800 Subject: [PATCH 17/26] remove Backbone from window --- .../src/Metamaps/{Backbone.js => Backbone/index.js} | 4 +++- frontend/src/Metamaps/Router.js | 6 +++++- frontend/src/Metamaps/Views/ChatView.js | 5 +++++ frontend/src/Metamaps/Views/Room.js | 8 +++++++- frontend/src/index.js | 11 ++--------- 5 files changed, 22 insertions(+), 12 deletions(-) rename frontend/src/Metamaps/{Backbone.js => Backbone/index.js} (99%) diff --git a/frontend/src/Metamaps/Backbone.js b/frontend/src/Metamaps/Backbone/index.js similarity index 99% rename from frontend/src/Metamaps/Backbone.js rename to frontend/src/Metamaps/Backbone/index.js index bc303df4..7e6878b3 100644 --- a/frontend/src/Metamaps/Backbone.js +++ b/frontend/src/Metamaps/Backbone/index.js @@ -1,6 +1,8 @@ -/* global Metamaps, Backbone, _, $ */ +/* global Metamaps, Backbone, $ */ import _ from 'lodash' +import Backbone from 'backbone' +Backbone.$ = window.$ /* * Metamaps.Backbone.js.erb diff --git a/frontend/src/Metamaps/Router.js b/frontend/src/Metamaps/Router.js index 6760edcc..0ad88efd 100644 --- a/frontend/src/Metamaps/Router.js +++ b/frontend/src/Metamaps/Router.js @@ -1,4 +1,8 @@ -/* global Metamaps, Backbone, $ */ +/* global Metamaps, $ */ + +import Backbone from 'backbone' +//TODO is this line good or bad? +//Backbone.$ = window.$ import Active from './Active' import GlobalUI from './GlobalUI' diff --git a/frontend/src/Metamaps/Views/ChatView.js b/frontend/src/Metamaps/Views/ChatView.js index 5d8f5f65..d1efdf74 100644 --- a/frontend/src/Metamaps/Views/ChatView.js +++ b/frontend/src/Metamaps/Views/ChatView.js @@ -1,4 +1,9 @@ /* global Autolinker, $ */ + +import Backbone from 'backbone' +// TODO is this line good or bad +// Backbone.$ = window.$ + var linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false }); var Private = { diff --git a/frontend/src/Metamaps/Views/Room.js b/frontend/src/Metamaps/Views/Room.js index 014df61b..5b70ee7c 100644 --- a/frontend/src/Metamaps/Views/Room.js +++ b/frontend/src/Metamaps/Views/Room.js @@ -1,4 +1,9 @@ /* global Metamaps, $ */ + +import Backbone from 'backbone' +// TODO is this line good or bad +// Backbone.$ = window.$ + import Active from '../Active' import Realtime from '../Realtime' @@ -6,7 +11,8 @@ import ChatView from './ChatView' import VideoView from './VideoView' /* - * Metamaps.Backbone + * Dependencies: + * Metamaps.Backbone */ const Room = function(opts) { diff --git a/frontend/src/index.js b/frontend/src/index.js index e5705512..176ac329 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -1,15 +1,8 @@ -import React from 'react' +// create global references to some utility libraries import ReactDOM from 'react-dom' -import Backbone from 'backbone' import _ from 'underscore' - -import Metamaps from './Metamaps' - -// create global references to some libraries -window.React = React window.ReactDOM = ReactDOM -Backbone.$ = window.$ // jquery from rails -window.Backbone = Backbone window._ = _ +import Metamaps from './Metamaps' window.Metamaps = Metamaps From 30fc9438331620b9b27a0edf897581ccbf51e19a Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 00:20:05 +0800 Subject: [PATCH 18/26] clean up backbone file imports --- frontend/src/Metamaps/Backbone/index.js | 141 ++++++++++++------------ 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/frontend/src/Metamaps/Backbone/index.js b/frontend/src/Metamaps/Backbone/index.js index 7e6878b3..2c7ae530 100644 --- a/frontend/src/Metamaps/Backbone/index.js +++ b/frontend/src/Metamaps/Backbone/index.js @@ -4,29 +4,30 @@ import _ from 'lodash' import Backbone from 'backbone' Backbone.$ = window.$ +import Active from '../Active' +import Filter from '../Filter' +import JIT from '../JIT' +import Map, { InfoBox } from '../Map' +import Mapper from '../Mapper' +import Realtime from '../Realtime' +import Synapse from '../Synapse' +import SynapseCard from '../SynapseCard' +import Topic from '../Topic' +import TopicCard from '../TopicCard' +import Visualize from '../Visualize' + /* * Metamaps.Backbone.js.erb * * Dependencies: - * - Metamaps.Active * - Metamaps.Collaborators * - Metamaps.Creators - * - Metamaps.Filter - * - Metamaps.JIT * - Metamaps.Loading - * - Metamaps.Map - * - Metamaps.Mapper * - Metamaps.Mappers * - Metamaps.Mappings * - Metamaps.Metacodes - * - Metamaps.Realtime - * - Metamaps.Synapse - * - Metamaps.SynapseCard * - Metamaps.Synapses - * - Metamaps.Topic - * - Metamaps.TopicCard * - Metamaps.Topics - * - Metamaps.Visualize */ const _Backbone = {} @@ -62,7 +63,7 @@ _Backbone.Map = Backbone.Model.extend({ this.on('saved', this.savedEvent) }, savedEvent: function () { - Metamaps.Realtime.sendMapChange(this) + Realtime.sendMapChange(this) }, authorizeToEdit: function (mapper) { if (mapper && ( @@ -82,7 +83,7 @@ _Backbone.Map = Backbone.Model.extend({ } }, getUser: function () { - return Metamaps.Mapper.get(this.get('user_id')) + return Mapper.get(this.get('user_id')) }, fetchContained: function () { var bb = _Backbone @@ -126,10 +127,10 @@ _Backbone.Map = Backbone.Model.extend({ return this.get('mappers') }, updateView: function () { - var map = Metamaps.Active.Map + var map = Active.Map var isActiveMap = this.id === map.id if (isActiveMap) { - Metamaps.Map.InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission')) + InfoBox.updateNameDescPerm(this.get('name'), this.get('desc'), this.get('permission')) this.updateMapWrapper() // mobile menu $('#header_content').html(this.get('name')) @@ -137,9 +138,9 @@ _Backbone.Map = Backbone.Model.extend({ } }, updateMapWrapper: function () { - var map = Metamaps.Active.Map + var map = Active.Map var isActiveMap = this.id === map.id - var authorized = map && map.authorizeToEdit(Metamaps.Active.Mapper) ? 'canEditMap' : '' + var authorized = map && map.authorizeToEdit(Active.Mapper) ? 'canEditMap' : '' var commonsMap = map && map.get('permission') === 'commons' ? 'commonsMap' : '' if (isActiveMap) { $('.wrapper').removeClass('canEditMap commonsMap').addClass(authorized + ' ' + commonsMap) @@ -324,10 +325,10 @@ _Backbone.init = function () { initialize: function () { if (this.isNew()) { this.set({ - 'user_id': Metamaps.Active.Mapper.id, + 'user_id': Active.Mapper.id, 'desc': this.get('desc') || '', 'link': this.get('link') || '', - 'permission': Metamaps.Active.Map ? Metamaps.Active.Map.get('permission') : 'commons' + 'permission': Active.Map ? Active.Map.get('permission') : 'commons' }) } @@ -339,7 +340,7 @@ _Backbone.init = function () { mappableid: this.id } - $(document).trigger(Metamaps.JIT.events.removeTopic, [removeTopicData]) + $(document).trigger(JIT.events.removeTopic, [removeTopicData]) }) this.on('noLongerPrivate', function () { var newTopicData = { @@ -347,10 +348,10 @@ _Backbone.init = function () { mappableid: this.id } - $(document).trigger(Metamaps.JIT.events.newTopic, [newTopicData]) + $(document).trigger(JIT.events.newTopic, [newTopicData]) }) - this.on('change:metacode_id', Metamaps.Filter.checkMetacodes, this) + this.on('change:metacode_id', Filter.checkMetacodes, this) }, authorizeToEdit: function (mapper) { if (mapper && @@ -371,10 +372,10 @@ _Backbone.init = function () { return Metamaps.Metacodes.get(this.get('metacode_id')) }, getMapping: function () { - if (!Metamaps.Active.Map) return false + if (!Active.Map) return false return Metamaps.Mappings.findWhere({ - map_id: Metamaps.Active.Map.id, + map_id: Active.Map.id, mappable_type: 'Topic', mappable_id: this.isNew() ? this.cid : this.id }) @@ -387,7 +388,7 @@ _Backbone.init = function () { name: this.get('name') } - if (Metamaps.Active.Map) { + if (Active.Map) { mapping = this.getMapping() node.data = { $mapping: null, @@ -402,7 +403,7 @@ _Backbone.init = function () { var node = this.get('node') node.setData('topic', this) - if (Metamaps.Active.Map) { + if (Active.Map) { mapping = this.getMapping() node.setData('mapping', mapping) } @@ -410,38 +411,38 @@ _Backbone.init = function () { return node }, savedEvent: function () { - Metamaps.Realtime.sendTopicChange(this) + Realtime.sendTopicChange(this) }, updateViews: function () { - var onPageWithTopicCard = Metamaps.Active.Map || Metamaps.Active.Topic + var onPageWithTopicCard = Active.Map || Active.Topic var node = this.get('node') // update topic card, if this topic is the one open there - if (onPageWithTopicCard && this == Metamaps.TopicCard.openTopicCard) { - Metamaps.TopicCard.showCard(node) + if (onPageWithTopicCard && this == TopicCard.openTopicCard) { + TopicCard.showCard(node) } // update the node on the map if (onPageWithTopicCard && node) { node.name = this.get('name') - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } }, updateCardView: function () { - var onPageWithTopicCard = Metamaps.Active.Map || Metamaps.Active.Topic + var onPageWithTopicCard = Active.Map || Active.Topic var node = this.get('node') // update topic card, if this topic is the one open there - if (onPageWithTopicCard && this == Metamaps.TopicCard.openTopicCard) { - Metamaps.TopicCard.showCard(node) + if (onPageWithTopicCard && this == TopicCard.openTopicCard) { + TopicCard.showCard(node) } }, updateNodeView: function () { - var onPageWithTopicCard = Metamaps.Active.Map || Metamaps.Active.Topic + var onPageWithTopicCard = Active.Map || Active.Topic var node = this.get('node') // update the node on the map if (onPageWithTopicCard && node) { node.name = this.get('name') - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } } }) @@ -489,8 +490,8 @@ _Backbone.init = function () { initialize: function () { if (this.isNew()) { this.set({ - 'user_id': Metamaps.Active.Mapper.id, - 'permission': Metamaps.Active.Map ? Metamaps.Active.Map.get('permission') : 'commons', + 'user_id': Active.Mapper.id, + 'permission': Active.Map ? Active.Map.get('permission') : 'commons', 'category': 'from-to' }) } @@ -504,15 +505,15 @@ _Backbone.init = function () { mappableid: this.id } - $(document).trigger(Metamaps.JIT.events.newSynapse, [newSynapseData]) + $(document).trigger(JIT.events.newSynapse, [newSynapseData]) }) this.on('nowPrivate', function () { - $(document).trigger(Metamaps.JIT.events.removeSynapse, [{ + $(document).trigger(JIT.events.removeSynapse, [{ mappableid: this.id }]) }) - this.on('change:desc', Metamaps.Filter.checkSynapses, this) + this.on('change:desc', Filter.checkSynapses, this) }, prepareLiForFilter: function () { var li = '' @@ -546,10 +547,10 @@ _Backbone.init = function () { ] : false }, getMapping: function () { - if (!Metamaps.Active.Map) return false + if (!Active.Map) return false return Metamaps.Mappings.findWhere({ - map_id: Metamaps.Active.Map.id, + map_id: Active.Map.id, mappable_type: 'Synapse', mappable_id: this.isNew() ? this.cid : this.id }) @@ -567,7 +568,7 @@ _Backbone.init = function () { } } - if (Metamaps.Active.Map) { + if (Active.Map) { mapping = providedMapping || this.getMapping() mappingID = mapping.isNew() ? mapping.cid : mapping.id edge.data.$mappings = [] @@ -581,7 +582,7 @@ _Backbone.init = function () { var edge = this.get('edge') edge.getData('synapses').push(this) - if (Metamaps.Active.Map) { + if (Active.Map) { mapping = this.getMapping() edge.getData('mappings').push(mapping) } @@ -589,28 +590,28 @@ _Backbone.init = function () { return edge }, savedEvent: function () { - Metamaps.Realtime.sendSynapseChange(this) + Realtime.sendSynapseChange(this) }, updateViews: function () { this.updateCardView() this.updateEdgeView() }, updateCardView: function () { - var onPageWithSynapseCard = Metamaps.Active.Map || Metamaps.Active.Topic + var onPageWithSynapseCard = Active.Map || Active.Topic var edge = this.get('edge') // update synapse card, if this synapse is the one open there - if (onPageWithSynapseCard && edge == Metamaps.SynapseCard.openSynapseCard) { - Metamaps.SynapseCard.showCard(edge) + if (onPageWithSynapseCard && edge == SynapseCard.openSynapseCard) { + SynapseCard.showCard(edge) } }, updateEdgeView: function () { - var onPageWithSynapseCard = Metamaps.Active.Map || Metamaps.Active.Topic + var onPageWithSynapseCard = Active.Map || Active.Topic var edge = this.get('edge') // update the edge on the map if (onPageWithSynapseCard && edge) { - Metamaps.Visualize.mGraph.plot() + Visualize.mGraph.plot() } } }) @@ -629,20 +630,20 @@ _Backbone.init = function () { initialize: function () { if (this.isNew()) { this.set({ - 'user_id': Metamaps.Active.Mapper.id, - 'map_id': Metamaps.Active.Map ? Metamaps.Active.Map.id : null + 'user_id': Active.Mapper.id, + 'map_id': Active.Map ? Active.Map.id : null }) } }, getMap: function () { - return Metamaps.Map.get(this.get('map_id')) + return Map.get(this.get('map_id')) }, getTopic: function () { - if (this.get('mappable_type') === 'Topic') return Metamaps.Topic.get(this.get('mappable_id')) + if (this.get('mappable_type') === 'Topic') return Topic.get(this.get('mappable_id')) else return false }, getSynapse: function () { - if (this.get('mappable_type') === 'Synapse') return Metamaps.Synapse.get(this.get('mappable_id')) + if (this.get('mappable_type') === 'Synapse') return Synapse.get(this.get('mappable_id')) else return false } }) @@ -665,34 +666,34 @@ _Backbone.init = function () { // this is for topic view Metamaps.Creators = Metamaps.Creators ? new self.MapperCollection(Metamaps.Creators) : new self.MapperCollection() - if (Metamaps.Active.Map) { + if (Active.Map) { Metamaps.Mappings = Metamaps.Mappings ? new self.MappingCollection(Metamaps.Mappings) : new self.MappingCollection() - Metamaps.Active.Map = new self.Map(Metamaps.Active.Map) + Active.Map = new self.Map(Active.Map) } - if (Metamaps.Active.Topic) Metamaps.Active.Topic = new self.Topic(Metamaps.Active.Topic) + if (Active.Topic) Active.Topic = new self.Topic(Active.Topic) // attach collection event listeners self.attachCollectionEvents = function () { Metamaps.Topics.on('add remove', function (topic) { - Metamaps.Map.InfoBox.updateNumbers() - Metamaps.Filter.checkMetacodes() - Metamaps.Filter.checkMappers() + InfoBox.updateNumbers() + Filter.checkMetacodes() + Filter.checkMappers() }) Metamaps.Synapses.on('add remove', function (synapse) { - Metamaps.Map.InfoBox.updateNumbers() - Metamaps.Filter.checkSynapses() - Metamaps.Filter.checkMappers() + InfoBox.updateNumbers() + Filter.checkSynapses() + Filter.checkMappers() }) - if (Metamaps.Active.Map) { + if (Active.Map) { Metamaps.Mappings.on('add remove', function (mapping) { - Metamaps.Map.InfoBox.updateNumbers() - Metamaps.Filter.checkSynapses() - Metamaps.Filter.checkMetacodes() - Metamaps.Filter.checkMappers() + InfoBox.updateNumbers() + Filter.checkSynapses() + Filter.checkMetacodes() + Filter.checkMappers() }) } } From 73e7c38873c21551f718478eedf8a40a81a831fc Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 08:05:26 +0800 Subject: [PATCH 19/26] syntax fixes --- frontend/src/Metamaps/Map/InfoBox.js | 2 +- frontend/src/Metamaps/Map/index.js | 26 +++++++++++----------- frontend/src/Metamaps/Views/ChatView.js | 2 +- frontend/src/Metamaps/Views/ExploreMaps.js | 5 +++-- frontend/src/Metamaps/Views/index.js | 2 +- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/frontend/src/Metamaps/Map/InfoBox.js b/frontend/src/Metamaps/Map/InfoBox.js index eaceba29..a2cc5de2 100644 --- a/frontend/src/Metamaps/Map/InfoBox.js +++ b/frontend/src/Metamaps/Map/InfoBox.js @@ -1,6 +1,6 @@ /* global Metamaps, $ */ -import Active from './Active' +import Active from '../Active' import GlobalUI from '../GlobalUI' import Router from '../Router' diff --git a/frontend/src/Metamaps/Map/index.js b/frontend/src/Metamaps/Map/index.js index 84ee8b39..3dd1c531 100644 --- a/frontend/src/Metamaps/Map/index.js +++ b/frontend/src/Metamaps/Map/index.js @@ -1,17 +1,17 @@ /* global Metamaps, $ */ -import Active from './Active' -import AutoLayout from './AutoLayout' -import Create from './Create' -import Filter from './Filter' -import GlobalUI from './GlobalUI' -import JIT from './JIT' -import Realtime from './Realtime' -import Router from './Router' -import Selected from './Selected' -import SynapseCard from './SynapseCard' -import TopicCard from './TopicCard' -import Visualize from './Visualize' +import Active from '../Active' +import AutoLayout from '../AutoLayout' +import Create from '../Create' +import Filter from '../Filter' +import GlobalUI from '../GlobalUI' +import JIT from '../JIT' +import Realtime from '../Realtime' +import Router from '../Router' +import Selected from '../Selected' +import SynapseCard from '../SynapseCard' +import TopicCard from '../TopicCard' +import Visualize from '../Visualize' import CheatSheet from './CheatSheet' import InfoBox from './InfoBox' @@ -361,5 +361,5 @@ const Map = { } } -export CheatSheet, InfoBox +export { CheatSheet, InfoBox } export default Map diff --git a/frontend/src/Metamaps/Views/ChatView.js b/frontend/src/Metamaps/Views/ChatView.js index d1efdf74..9f800c4e 100644 --- a/frontend/src/Metamaps/Views/ChatView.js +++ b/frontend/src/Metamaps/Views/ChatView.js @@ -95,7 +95,7 @@ var Private = { }, initializeSounds: function() { this.sound = new Howl({ - urls: [Metamaps.Erb['sounds/MM_sounds.mp3'], Metamaps.Erb['sounds/MM_sounds.ogg'], + urls: [Metamaps.Erb['sounds/MM_sounds.mp3'], Metamaps.Erb['sounds/MM_sounds.ogg']], sprite: { joinmap: [0, 561], leavemap: [1000, 592], diff --git a/frontend/src/Metamaps/Views/ExploreMaps.js b/frontend/src/Metamaps/Views/ExploreMaps.js index 4ffbf9fb..d8ba5360 100644 --- a/frontend/src/Metamaps/Views/ExploreMaps.js +++ b/frontend/src/Metamaps/Views/ExploreMaps.js @@ -1,9 +1,10 @@ /* global Metamaps, $ */ -import Active from './Active' -import ReactComponents from './ReactComponents' import ReactDOM from 'react-dom' // TODO ensure this isn't a double import +import Active from '../Active' +import ReactComponents from '../ReactComponents' + /* * - Metamaps.Loading */ diff --git a/frontend/src/Metamaps/Views/index.js b/frontend/src/Metamaps/Views/index.js index ca0e751a..9663ba98 100644 --- a/frontend/src/Metamaps/Views/index.js +++ b/frontend/src/Metamaps/Views/index.js @@ -3,4 +3,4 @@ import ChatView from './ChatView' import VideoView from './VideoView' import Room from './Room' -export ExploreMaps, ChatView, VideoView, Room +export { ExploreMaps, ChatView, VideoView, Room } From f59a5775ae6136a2bb274170204176da018e325e Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Thu, 22 Sep 2016 20:16:18 -0400 Subject: [PATCH 20/26] tweaks to import/exports --- app/assets/javascripts/application.js | 3 --- frontend/src/Metamaps/Views/ExploreMaps.js | 1 + frontend/src/Metamaps/Views/index.js | 3 ++- frontend/src/Metamaps/index.js | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 03dac4fb..68f2179b 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -17,7 +17,4 @@ //= require ./src/JIT //= require ./src/Metamaps.Erb //= require ./webpacked/metamaps.bundle -//= require ./src/views/chatView -//= require ./src/views/videoView -//= require ./src/views/room //= require ./src/check-canvas-support diff --git a/frontend/src/Metamaps/Views/ExploreMaps.js b/frontend/src/Metamaps/Views/ExploreMaps.js index d8ba5360..155e8453 100644 --- a/frontend/src/Metamaps/Views/ExploreMaps.js +++ b/frontend/src/Metamaps/Views/ExploreMaps.js @@ -1,5 +1,6 @@ /* global Metamaps, $ */ +import React from 'react' import ReactDOM from 'react-dom' // TODO ensure this isn't a double import import Active from '../Active' diff --git a/frontend/src/Metamaps/Views/index.js b/frontend/src/Metamaps/Views/index.js index 9663ba98..d13482d0 100644 --- a/frontend/src/Metamaps/Views/index.js +++ b/frontend/src/Metamaps/Views/index.js @@ -3,4 +3,5 @@ import ChatView from './ChatView' import VideoView from './VideoView' import Room from './Room' -export { ExploreMaps, ChatView, VideoView, Room } +const Views = { ExploreMaps, ChatView, VideoView, Room } +export default Views diff --git a/frontend/src/Metamaps/index.js b/frontend/src/Metamaps/index.js index 45283c89..5d15559c 100644 --- a/frontend/src/Metamaps/index.js +++ b/frontend/src/Metamaps/index.js @@ -28,7 +28,7 @@ import SynapseCard from './SynapseCard' import Topic from './Topic' import TopicCard from './TopicCard' import Util from './Util' -import * as Views from './Views' +import Views from './Views' import Visualize from './Visualize' import ReactComponents from './ReactComponents' From 499593fc82f7c8338ad2c9dbead7511829f8aef4 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Thu, 22 Sep 2016 21:40:49 -0400 Subject: [PATCH 21/26] fixing references --- frontend/src/Metamaps/Router.js | 20 +++++++++++--------- frontend/src/Metamaps/Views/ChatView.js | 10 +++++----- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/frontend/src/Metamaps/Router.js b/frontend/src/Metamaps/Router.js index 0ad88efd..c5f1c9a7 100644 --- a/frontend/src/Metamaps/Router.js +++ b/frontend/src/Metamaps/Router.js @@ -21,6 +21,9 @@ import Visualize from './Visualize' */ const _Router = Backbone.Router.extend({ + currentPage: '', + currentSection: '', + timeoutId: undefined, routes: { '': 'home', // #home 'explore/:section': 'explore', // #explore/active @@ -28,6 +31,7 @@ const _Router = Backbone.Router.extend({ 'maps/:id': 'maps' // #maps/7 }, home: function () { + let self = this clearTimeout(this.timeoutId) if (Active.Mapper) document.title = 'Explore Active Maps | Metamaps' @@ -41,8 +45,8 @@ const _Router = Backbone.Router.extend({ $('.wrapper').addClass(classes) var navigate = function () { - this.timeoutId = setTimeout(function () { - this.navigate('') + self.timeoutId = setTimeout(function () { + self.navigate('') }, 300) } @@ -74,6 +78,7 @@ const _Router = Backbone.Router.extend({ Active.Topic = null }, explore: function (section, id) { + var self = this clearTimeout(this.timeoutId) // just capitalize the variable section @@ -115,17 +120,17 @@ const _Router = Backbone.Router.extend({ Views.ExploreMaps.setCollection(Metamaps.Maps[capitalize]) var navigate = function () { - var path = '/explore/' + this.currentPage + var path = '/explore/' + self.currentPage // alter url if for mapper profile page - if (this.currentPage === 'mapper') { + if (self.currentPage === 'mapper') { path += '/' + Metamaps.Maps.Mapper.mapperId } - this.navigate(path) + self.navigate(path) } var navigateTimeout = function () { - this.timeoutId = setTimeout(navigate, 300) + self.timeoutId = setTimeout(navigate, 300) } if (Metamaps.Maps[capitalize].length === 0) { Metamaps.Loading.show() @@ -209,9 +214,6 @@ const _Router = Backbone.Router.extend({ }) const Router = new _Router() -Router.currentPage = '' -Router.currentSection = undefined -Router.timeoutId = undefined Router.intercept = function (evt) { var segments diff --git a/frontend/src/Metamaps/Views/ChatView.js b/frontend/src/Metamaps/Views/ChatView.js index 9f800c4e..cdcda4e5 100644 --- a/frontend/src/Metamaps/Views/ChatView.js +++ b/frontend/src/Metamaps/Views/ChatView.js @@ -147,7 +147,7 @@ var Private = { message: this.$messageInput.val(), }; this.$messageInput.val(''); - $(document).trigger(chatView.events.message + '-' + this.room, [message]); + $(document).trigger(ChatView.events.message + '-' + this.room, [message]); }, addParticipant: function(participant) { var p = _.clone(participant.attributes); @@ -174,12 +174,12 @@ var Handlers = { videoToggleClick: function() { this.$videoToggle.toggleClass('active'); this.videosShowing = !this.videosShowing; - $(document).trigger(this.videosShowing ? chatView.events.videosOn : chatView.events.videosOff); + $(document).trigger(this.videosShowing ? ChatView.events.videosOn : ChatView.events.videosOff); }, cursorToggleClick: function() { this.$cursorToggle.toggleClass('active'); this.cursorsShowing = !this.cursorsShowing; - $(document).trigger(this.cursorsShowing ? chatView.events.cursorsOn : chatView.events.cursorsOff); + $(document).trigger(this.cursorsShowing ? ChatView.events.cursorsOn : ChatView.events.cursorsOff); }, soundToggleClick: function() { this.alertSound = !this.alertSound; @@ -193,10 +193,10 @@ var Handlers = { } }, inputFocus: function() { - $(document).trigger(chatView.events.inputFocus); + $(document).trigger(ChatView.events.inputFocus); }, inputBlur: function() { - $(document).trigger(chatView.events.inputBlur); + $(document).trigger(ChatView.events.inputBlur); } }; From 07e4ac386530694ff2b185bb9231dd3893ad76c3 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 10:37:59 +0800 Subject: [PATCH 22/26] attempt to get npm testing working; fail --- .travis.yml | 2 +- app/assets/javascripts/lib/Autolinker.js | 2756 ----------------- .../javascripts/src/{JIT.js.erb => JIT.js} | 2 +- frontend/src/Metamaps/JIT.js | 4 +- frontend/src/Metamaps/Views/ChatView.js | 5 +- frontend/test/Metamaps.Import.spec.js | 6 +- package.json | 2 + 7 files changed, 15 insertions(+), 2762 deletions(-) delete mode 100644 app/assets/javascripts/lib/Autolinker.js rename app/assets/javascripts/src/{JIT.js.erb => JIT.js} (99%) diff --git a/.travis.yml b/.travis.yml index 28559996..99c917c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,4 +18,4 @@ before_script: - nvm use stable - npm install script: - - bundle exec rspec && npm test && bundle exec brakeman -q -z + - bundle exec rspec && bundle exec brakeman -q -z || npm test diff --git a/app/assets/javascripts/lib/Autolinker.js b/app/assets/javascripts/lib/Autolinker.js deleted file mode 100644 index 6f363d4c..00000000 --- a/app/assets/javascripts/lib/Autolinker.js +++ /dev/null @@ -1,2756 +0,0 @@ -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module unless amdModuleId is set - define([], function () { - return (root['Autolinker'] = factory()); - }); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - root['Autolinker'] = factory(); - } -}(this, function () { - -/*! - * Autolinker.js - * 0.17.1 - * - * Copyright(c) 2015 Gregory Jacobs - * MIT Licensed. http://www.opensource.org/licenses/mit-license.php - * - * https://github.com/gregjacobs/Autolinker.js - */ -/** - * @class Autolinker - * @extends Object - * - * Utility class used to process a given string of text, and wrap the matches in - * the appropriate anchor (<a>) tags to turn them into links. - * - * Any of the configuration options may be provided in an Object (map) provided - * to the Autolinker constructor, which will configure how the {@link #link link()} - * method will process the links. - * - * For example: - * - * var autolinker = new Autolinker( { - * newWindow : false, - * truncate : 30 - * } ); - * - * var html = autolinker.link( "Joe went to www.yahoo.com" ); - * // produces: 'Joe went to yahoo.com' - * - * - * The {@link #static-link static link()} method may also be used to inline options into a single call, which may - * be more convenient for one-off uses. For example: - * - * var html = Autolinker.link( "Joe went to www.yahoo.com", { - * newWindow : false, - * truncate : 30 - * } ); - * // produces: 'Joe went to yahoo.com' - * - * - * ## Custom Replacements of Links - * - * If the configuration options do not provide enough flexibility, a {@link #replaceFn} - * may be provided to fully customize the output of Autolinker. This function is - * called once for each URL/Email/Phone#/Twitter Handle/Hashtag match that is - * encountered. - * - * For example: - * - * var input = "..."; // string with URLs, Email Addresses, Phone #s, Twitter Handles, and Hashtags - * - * var linkedText = Autolinker.link( input, { - * replaceFn : function( autolinker, match ) { - * console.log( "href = ", match.getAnchorHref() ); - * console.log( "text = ", match.getAnchorText() ); - * - * switch( match.getType() ) { - * case 'url' : - * console.log( "url: ", match.getUrl() ); - * - * if( match.getUrl().indexOf( 'mysite.com' ) === -1 ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an `Autolinker.HtmlTag` instance, which provides mutator methods for easy changes - * tag.setAttr( 'rel', 'nofollow' ); - * tag.addClass( 'external-link' ); - * - * return tag; - * - * } else { - * return true; // let Autolinker perform its normal anchor tag replacement - * } - * - * case 'email' : - * var email = match.getEmail(); - * console.log( "email: ", email ); - * - * if( email === "my@own.address" ) { - * return false; // don't auto-link this particular email address; leave as-is - * } else { - * return; // no return value will have Autolinker perform its normal anchor tag replacement (same as returning `true`) - * } - * - * case 'phone' : - * var phoneNumber = match.getPhoneNumber(); - * console.log( phoneNumber ); - * - * return '' + phoneNumber + ''; - * - * case 'twitter' : - * var twitterHandle = match.getTwitterHandle(); - * console.log( twitterHandle ); - * - * return '' + twitterHandle + ''; - * - * case 'hashtag' : - * var hashtag = match.getHashtag(); - * console.log( hashtag ); - * - * return '' + hashtag + ''; - * } - * } - * } ); - * - * - * The function may return the following values: - * - * - `true` (Boolean): Allow Autolinker to replace the match as it normally would. - * - `false` (Boolean): Do not replace the current match at all - leave as-is. - * - Any String: If a string is returned from the function, the string will be used directly as the replacement HTML for - * the match. - * - An {@link Autolinker.HtmlTag} instance, which can be used to build/modify an HTML tag before writing out its HTML text. - * - * @constructor - * @param {Object} [config] The configuration options for the Autolinker instance, specified in an Object (map). - */ -var Autolinker = function( cfg ) { - Autolinker.Util.assign( this, cfg ); // assign the properties of `cfg` onto the Autolinker instance. Prototype properties will be used for missing configs. - - // Validate the value of the `hashtag` cfg. - var hashtag = this.hashtag; - if( hashtag !== false && hashtag !== 'twitter' && hashtag !== 'facebook' ) { - throw new Error( "invalid `hashtag` cfg - see docs" ); - } -}; - -Autolinker.prototype = { - constructor : Autolinker, // fix constructor property - - /** - * @cfg {Boolean} urls - * - * `true` if miscellaneous URLs should be automatically linked, `false` if they should not be. - */ - urls : true, - - /** - * @cfg {Boolean} email - * - * `true` if email addresses should be automatically linked, `false` if they should not be. - */ - email : true, - - /** - * @cfg {Boolean} twitter - * - * `true` if Twitter handles ("@example") should be automatically linked, `false` if they should not be. - */ - twitter : true, - - /** - * @cfg {Boolean} phone - * - * `true` if Phone numbers ("(555)555-5555") should be automatically linked, `false` if they should not be. - */ - phone: true, - - /** - * @cfg {Boolean/String} hashtag - * - * A string for the service name to have hashtags (ex: "#myHashtag") - * auto-linked to. The currently-supported values are: - * - * - 'twitter' - * - 'facebook' - * - * Pass `false` to skip auto-linking of hashtags. - */ - hashtag : false, - - /** - * @cfg {Boolean} newWindow - * - * `true` if the links should open in a new window, `false` otherwise. - */ - newWindow : true, - - /** - * @cfg {Boolean} stripPrefix - * - * `true` if 'http://' or 'https://' and/or the 'www.' should be stripped - * from the beginning of URL links' text, `false` otherwise. - */ - stripPrefix : true, - - /** - * @cfg {Number} truncate - * - * A number for how many characters long matched text should be truncated to inside the text of - * a link. If the matched text is over this number of characters, it will be truncated to this length by - * adding a two period ellipsis ('..') to the end of the string. - * - * For example: A url like 'http://www.yahoo.com/some/long/path/to/a/file' truncated to 25 characters might look - * something like this: 'yahoo.com/some/long/pat..' - */ - truncate : undefined, - - /** - * @cfg {String} className - * - * A CSS class name to add to the generated links. This class will be added to all links, as well as this class - * plus match suffixes for styling url/email/phone/twitter/hashtag links differently. - * - * For example, if this config is provided as "myLink", then: - * - * - URL links will have the CSS classes: "myLink myLink-url" - * - Email links will have the CSS classes: "myLink myLink-email", and - * - Twitter links will have the CSS classes: "myLink myLink-twitter" - * - Phone links will have the CSS classes: "myLink myLink-phone" - * - Hashtag links will have the CSS classes: "myLink myLink-hashtag" - */ - className : "", - - /** - * @cfg {Function} replaceFn - * - * A function to individually process each match found in the input string. - * - * See the class's description for usage. - * - * This function is called with the following parameters: - * - * @cfg {Autolinker} replaceFn.autolinker The Autolinker instance, which may be used to retrieve child objects from (such - * as the instance's {@link #getTagBuilder tag builder}). - * @cfg {Autolinker.match.Match} replaceFn.match The Match instance which can be used to retrieve information about the - * match that the `replaceFn` is currently processing. See {@link Autolinker.match.Match} subclasses for details. - */ - - - /** - * @private - * @property {Autolinker.htmlParser.HtmlParser} htmlParser - * - * The HtmlParser instance used to skip over HTML tags, while finding text nodes to process. This is lazily instantiated - * in the {@link #getHtmlParser} method. - */ - htmlParser : undefined, - - /** - * @private - * @property {Autolinker.matchParser.MatchParser} matchParser - * - * The MatchParser instance used to find matches in the text nodes of an input string passed to - * {@link #link}. This is lazily instantiated in the {@link #getMatchParser} method. - */ - matchParser : undefined, - - /** - * @private - * @property {Autolinker.AnchorTagBuilder} tagBuilder - * - * The AnchorTagBuilder instance used to build match replacement anchor tags. Note: this is lazily instantiated - * in the {@link #getTagBuilder} method. - */ - tagBuilder : undefined, - - /** - * Automatically links URLs, Email addresses, Phone numbers, Twitter - * handles, and Hashtags found in the given chunk of HTML. Does not link - * URLs found within HTML tags. - * - * For instance, if given the text: `You should go to http://www.yahoo.com`, - * then the result will be `You should go to - * <a href="http://www.yahoo.com">http://www.yahoo.com</a>` - * - * This method finds the text around any HTML elements in the input - * `textOrHtml`, which will be the text that is processed. Any original HTML - * elements will be left as-is, as well as the text that is already wrapped - * in anchor (<a>) tags. - * - * @param {String} textOrHtml The HTML or text to autolink matches within - * (depending on if the {@link #urls}, {@link #email}, {@link #phone}, - * {@link #twitter}, and {@link #hashtag} options are enabled). - * @return {String} The HTML, with matches automatically linked. - */ - link : function( textOrHtml ) { - var htmlParser = this.getHtmlParser(), - htmlNodes = htmlParser.parse( textOrHtml ), - anchorTagStackCount = 0, // used to only process text around anchor tags, and any inner text/html they may have - resultHtml = []; - - for( var i = 0, len = htmlNodes.length; i < len; i++ ) { - var node = htmlNodes[ i ], - nodeType = node.getType(), - nodeText = node.getText(); - - if( nodeType === 'element' ) { - // Process HTML nodes in the input `textOrHtml` - if( node.getTagName() === 'a' ) { - if( !node.isClosing() ) { // it's the start tag - anchorTagStackCount++; - } else { // it's the end tag - anchorTagStackCount = Math.max( anchorTagStackCount - 1, 0 ); // attempt to handle extraneous tags by making sure the stack count never goes below 0 - } - } - resultHtml.push( nodeText ); // now add the text of the tag itself verbatim - - } else if( nodeType === 'entity' || nodeType === 'comment' ) { - resultHtml.push( nodeText ); // append HTML entity nodes (such as ' ') or HTML comments (such as '') verbatim - - } else { - // Process text nodes in the input `textOrHtml` - if( anchorTagStackCount === 0 ) { - // If we're not within an tag, process the text node to linkify - var linkifiedStr = this.linkifyStr( nodeText ); - resultHtml.push( linkifiedStr ); - - } else { - // `text` is within an tag, simply append the text - we do not want to autolink anything - // already within an ... tag - resultHtml.push( nodeText ); - } - } - } - - return resultHtml.join( "" ); - }, - - /** - * Process the text that lies in between HTML tags, performing the anchor - * tag replacements for the matches, and returns the string with the - * replacements made. - * - * This method does the actual wrapping of matches with anchor tags. - * - * @private - * @param {String} str The string of text to auto-link. - * @return {String} The text with anchor tags auto-filled. - */ - linkifyStr : function( str ) { - return this.getMatchParser().replace( str, this.createMatchReturnVal, this ); - }, - - - /** - * Creates the return string value for a given match in the input string, - * for the {@link #linkifyStr} method. - * - * This method handles the {@link #replaceFn}, if one was provided. - * - * @private - * @param {Autolinker.match.Match} match The Match object that represents the match. - * @return {String} The string that the `match` should be replaced with. This is usually the anchor tag string, but - * may be the `matchStr` itself if the match is not to be replaced. - */ - createMatchReturnVal : function( match ) { - // Handle a custom `replaceFn` being provided - var replaceFnResult; - if( this.replaceFn ) { - replaceFnResult = this.replaceFn.call( this, this, match ); // Autolinker instance is the context, and the first arg - } - - if( typeof replaceFnResult === 'string' ) { - return replaceFnResult; // `replaceFn` returned a string, use that - - } else if( replaceFnResult === false ) { - return match.getMatchedText(); // no replacement for the match - - } else if( replaceFnResult instanceof Autolinker.HtmlTag ) { - return replaceFnResult.toAnchorString(); - - } else { // replaceFnResult === true, or no/unknown return value from function - // Perform Autolinker's default anchor tag generation - var tagBuilder = this.getTagBuilder(), - anchorTag = tagBuilder.build( match ); // returns an Autolinker.HtmlTag instance - - return anchorTag.toAnchorString(); - } - }, - - - /** - * Lazily instantiates and returns the {@link #htmlParser} instance for this Autolinker instance. - * - * @protected - * @return {Autolinker.htmlParser.HtmlParser} - */ - getHtmlParser : function() { - var htmlParser = this.htmlParser; - - if( !htmlParser ) { - htmlParser = this.htmlParser = new Autolinker.htmlParser.HtmlParser(); - } - - return htmlParser; - }, - - - /** - * Lazily instantiates and returns the {@link #matchParser} instance for this Autolinker instance. - * - * @protected - * @return {Autolinker.matchParser.MatchParser} - */ - getMatchParser : function() { - var matchParser = this.matchParser; - - if( !matchParser ) { - matchParser = this.matchParser = new Autolinker.matchParser.MatchParser( { - urls : this.urls, - email : this.email, - twitter : this.twitter, - phone : this.phone, - hashtag : this.hashtag, - stripPrefix : this.stripPrefix - } ); - } - - return matchParser; - }, - - - /** - * Returns the {@link #tagBuilder} instance for this Autolinker instance, lazily instantiating it - * if it does not yet exist. - * - * This method may be used in a {@link #replaceFn} to generate the {@link Autolinker.HtmlTag HtmlTag} instance that - * Autolinker would normally generate, and then allow for modifications before returning it. For example: - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance - * tag.setAttr( 'rel', 'nofollow' ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test google.com - * - * @return {Autolinker.AnchorTagBuilder} - */ - getTagBuilder : function() { - var tagBuilder = this.tagBuilder; - - if( !tagBuilder ) { - tagBuilder = this.tagBuilder = new Autolinker.AnchorTagBuilder( { - newWindow : this.newWindow, - truncate : this.truncate, - className : this.className - } ); - } - - return tagBuilder; - } - -}; - - -/** - * Automatically links URLs, Email addresses, Phone Numbers, Twitter handles, - * and Hashtags found in the given chunk of HTML. Does not link URLs found - * within HTML tags. - * - * For instance, if given the text: `You should go to http://www.yahoo.com`, - * then the result will be `You should go to <a href="http://www.yahoo.com">http://www.yahoo.com</a>` - * - * Example: - * - * var linkedText = Autolinker.link( "Go to google.com", { newWindow: false } ); - * // Produces: "Go to google.com" - * - * @static - * @param {String} textOrHtml The HTML or text to find matches within (depending - * on if the {@link #urls}, {@link #email}, {@link #phone}, {@link #twitter}, - * and {@link #hashtag} options are enabled). - * @param {Object} [options] Any of the configuration options for the Autolinker - * class, specified in an Object (map). See the class description for an - * example call. - * @return {String} The HTML text, with matches automatically linked. - */ -Autolinker.link = function( textOrHtml, options ) { - var autolinker = new Autolinker( options ); - return autolinker.link( textOrHtml ); -}; - - -// Autolinker Namespaces -Autolinker.match = {}; -Autolinker.htmlParser = {}; -Autolinker.matchParser = {}; - -/*global Autolinker */ -/*jshint eqnull:true, boss:true */ -/** - * @class Autolinker.Util - * @singleton - * - * A few utility methods for Autolinker. - */ -Autolinker.Util = { - - /** - * @property {Function} abstractMethod - * - * A function object which represents an abstract method. - */ - abstractMethod : function() { throw "abstract"; }, - - - /** - * @private - * @property {RegExp} trimRegex - * - * The regular expression used to trim the leading and trailing whitespace - * from a string. - */ - trimRegex : /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - - /** - * Assigns (shallow copies) the properties of `src` onto `dest`. - * - * @param {Object} dest The destination object. - * @param {Object} src The source object. - * @return {Object} The destination object (`dest`) - */ - assign : function( dest, src ) { - for( var prop in src ) { - if( src.hasOwnProperty( prop ) ) { - dest[ prop ] = src[ prop ]; - } - } - - return dest; - }, - - - /** - * Extends `superclass` to create a new subclass, adding the `protoProps` to the new subclass's prototype. - * - * @param {Function} superclass The constructor function for the superclass. - * @param {Object} protoProps The methods/properties to add to the subclass's prototype. This may contain the - * special property `constructor`, which will be used as the new subclass's constructor function. - * @return {Function} The new subclass function. - */ - extend : function( superclass, protoProps ) { - var superclassProto = superclass.prototype; - - var F = function() {}; - F.prototype = superclassProto; - - var subclass; - if( protoProps.hasOwnProperty( 'constructor' ) ) { - subclass = protoProps.constructor; - } else { - subclass = function() { superclassProto.constructor.apply( this, arguments ); }; - } - - var subclassProto = subclass.prototype = new F(); // set up prototype chain - subclassProto.constructor = subclass; // fix constructor property - subclassProto.superclass = superclassProto; - - delete protoProps.constructor; // don't re-assign constructor property to the prototype, since a new function may have been created (`subclass`), which is now already there - Autolinker.Util.assign( subclassProto, protoProps ); - - return subclass; - }, - - - /** - * Truncates the `str` at `len - ellipsisChars.length`, and adds the `ellipsisChars` to the - * end of the string (by default, two periods: '..'). If the `str` length does not exceed - * `len`, the string will be returned unchanged. - * - * @param {String} str The string to truncate and add an ellipsis to. - * @param {Number} truncateLen The length to truncate the string at. - * @param {String} [ellipsisChars=..] The ellipsis character(s) to add to the end of `str` - * when truncated. Defaults to '..' - */ - ellipsis : function( str, truncateLen, ellipsisChars ) { - if( str.length > truncateLen ) { - ellipsisChars = ( ellipsisChars == null ) ? '..' : ellipsisChars; - str = str.substring( 0, truncateLen - ellipsisChars.length ) + ellipsisChars; - } - return str; - }, - - - /** - * Supports `Array.prototype.indexOf()` functionality for old IE (IE8 and below). - * - * @param {Array} arr The array to find an element of. - * @param {*} element The element to find in the array, and return the index of. - * @return {Number} The index of the `element`, or -1 if it was not found. - */ - indexOf : function( arr, element ) { - if( Array.prototype.indexOf ) { - return arr.indexOf( element ); - - } else { - for( var i = 0, len = arr.length; i < len; i++ ) { - if( arr[ i ] === element ) return i; - } - return -1; - } - }, - - - - /** - * Performs the functionality of what modern browsers do when `String.prototype.split()` is called - * with a regular expression that contains capturing parenthesis. - * - * For example: - * - * // Modern browsers: - * "a,b,c".split( /(,)/ ); // --> [ 'a', ',', 'b', ',', 'c' ] - * - * // Old IE (including IE8): - * "a,b,c".split( /(,)/ ); // --> [ 'a', 'b', 'c' ] - * - * This method emulates the functionality of modern browsers for the old IE case. - * - * @param {String} str The string to split. - * @param {RegExp} splitRegex The regular expression to split the input `str` on. The splitting - * character(s) will be spliced into the array, as in the "modern browsers" example in the - * description of this method. - * Note #1: the supplied regular expression **must** have the 'g' flag specified. - * Note #2: for simplicity's sake, the regular expression does not need - * to contain capturing parenthesis - it will be assumed that any match has them. - * @return {String[]} The split array of strings, with the splitting character(s) included. - */ - splitAndCapture : function( str, splitRegex ) { - if( !splitRegex.global ) throw new Error( "`splitRegex` must have the 'g' flag set" ); - - var result = [], - lastIdx = 0, - match; - - while( match = splitRegex.exec( str ) ) { - result.push( str.substring( lastIdx, match.index ) ); - result.push( match[ 0 ] ); // push the splitting char(s) - - lastIdx = match.index + match[ 0 ].length; - } - result.push( str.substring( lastIdx ) ); - - return result; - }, - - - /** - * Trims the leading and trailing whitespace from a string. - * - * @param {String} str The string to trim. - * @return {String} - */ - trim : function( str ) { - return str.replace( this.trimRegex, '' ); - } - -}; -/*global Autolinker */ -/*jshint boss:true */ -/** - * @class Autolinker.HtmlTag - * @extends Object - * - * Represents an HTML tag, which can be used to easily build/modify HTML tags programmatically. - * - * Autolinker uses this abstraction to create HTML tags, and then write them out as strings. You may also use - * this class in your code, especially within a {@link Autolinker#replaceFn replaceFn}. - * - * ## Examples - * - * Example instantiation: - * - * var tag = new Autolinker.HtmlTag( { - * tagName : 'a', - * attrs : { 'href': 'http://google.com', 'class': 'external-link' }, - * innerHtml : 'Google' - * } ); - * - * tag.toAnchorString(); // Google - * - * // Individual accessor methods - * tag.getTagName(); // 'a' - * tag.getAttr( 'href' ); // 'http://google.com' - * tag.hasClass( 'external-link' ); // true - * - * - * Using mutator methods (which may be used in combination with instantiation config properties): - * - * var tag = new Autolinker.HtmlTag(); - * tag.setTagName( 'a' ); - * tag.setAttr( 'href', 'http://google.com' ); - * tag.addClass( 'external-link' ); - * tag.setInnerHtml( 'Google' ); - * - * tag.getTagName(); // 'a' - * tag.getAttr( 'href' ); // 'http://google.com' - * tag.hasClass( 'external-link' ); // true - * - * tag.toAnchorString(); // Google - * - * - * ## Example use within a {@link Autolinker#replaceFn replaceFn} - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance, configured with the Match's href and anchor text - * tag.setAttr( 'rel', 'nofollow' ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test google.com - * - * - * ## Example use with a new tag for the replacement - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = new Autolinker.HtmlTag( { - * tagName : 'button', - * attrs : { 'title': 'Load URL: ' + match.getAnchorHref() }, - * innerHtml : 'Load URL: ' + match.getAnchorText() - * } ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test - */ -Autolinker.HtmlTag = Autolinker.Util.extend( Object, { - - /** - * @cfg {String} tagName - * - * The tag name. Ex: 'a', 'button', etc. - * - * Not required at instantiation time, but should be set using {@link #setTagName} before {@link #toAnchorString} - * is executed. - */ - - /** - * @cfg {Object.} attrs - * - * An key/value Object (map) of attributes to create the tag with. The keys are the attribute names, and the - * values are the attribute values. - */ - - /** - * @cfg {String} innerHtml - * - * The inner HTML for the tag. - * - * Note the camel case name on `innerHtml`. Acronyms are camelCased in this utility (such as not to run into the acronym - * naming inconsistency that the DOM developers created with `XMLHttpRequest`). You may alternatively use {@link #innerHTML} - * if you prefer, but this one is recommended. - */ - - /** - * @cfg {String} innerHTML - * - * Alias of {@link #innerHtml}, accepted for consistency with the browser DOM api, but prefer the camelCased version - * for acronym names. - */ - - - /** - * @protected - * @property {RegExp} whitespaceRegex - * - * Regular expression used to match whitespace in a string of CSS classes. - */ - whitespaceRegex : /\s+/, - - - /** - * @constructor - * @param {Object} [cfg] The configuration properties for this class, in an Object (map) - */ - constructor : function( cfg ) { - Autolinker.Util.assign( this, cfg ); - - this.innerHtml = this.innerHtml || this.innerHTML; // accept either the camelCased form or the fully capitalized acronym - }, - - - /** - * Sets the tag name that will be used to generate the tag with. - * - * @param {String} tagName - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setTagName : function( tagName ) { - this.tagName = tagName; - return this; - }, - - - /** - * Retrieves the tag name. - * - * @return {String} - */ - getTagName : function() { - return this.tagName || ""; - }, - - - /** - * Sets an attribute on the HtmlTag. - * - * @param {String} attrName The attribute name to set. - * @param {String} attrValue The attribute value to set. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setAttr : function( attrName, attrValue ) { - var tagAttrs = this.getAttrs(); - tagAttrs[ attrName ] = attrValue; - - return this; - }, - - - /** - * Retrieves an attribute from the HtmlTag. If the attribute does not exist, returns `undefined`. - * - * @param {String} name The attribute name to retrieve. - * @return {String} The attribute's value, or `undefined` if it does not exist on the HtmlTag. - */ - getAttr : function( attrName ) { - return this.getAttrs()[ attrName ]; - }, - - - /** - * Sets one or more attributes on the HtmlTag. - * - * @param {Object.} attrs A key/value Object (map) of the attributes to set. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setAttrs : function( attrs ) { - var tagAttrs = this.getAttrs(); - Autolinker.Util.assign( tagAttrs, attrs ); - - return this; - }, - - - /** - * Retrieves the attributes Object (map) for the HtmlTag. - * - * @return {Object.} A key/value object of the attributes for the HtmlTag. - */ - getAttrs : function() { - return this.attrs || ( this.attrs = {} ); - }, - - - /** - * Sets the provided `cssClass`, overwriting any current CSS classes on the HtmlTag. - * - * @param {String} cssClass One or more space-separated CSS classes to set (overwrite). - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setClass : function( cssClass ) { - return this.setAttr( 'class', cssClass ); - }, - - - /** - * Convenience method to add one or more CSS classes to the HtmlTag. Will not add duplicate CSS classes. - * - * @param {String} cssClass One or more space-separated CSS classes to add. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - addClass : function( cssClass ) { - var classAttr = this.getClass(), - whitespaceRegex = this.whitespaceRegex, - indexOf = Autolinker.Util.indexOf, // to support IE8 and below - classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ), - newClasses = cssClass.split( whitespaceRegex ), - newClass; - - while( newClass = newClasses.shift() ) { - if( indexOf( classes, newClass ) === -1 ) { - classes.push( newClass ); - } - } - - this.getAttrs()[ 'class' ] = classes.join( " " ); - return this; - }, - - - /** - * Convenience method to remove one or more CSS classes from the HtmlTag. - * - * @param {String} cssClass One or more space-separated CSS classes to remove. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - removeClass : function( cssClass ) { - var classAttr = this.getClass(), - whitespaceRegex = this.whitespaceRegex, - indexOf = Autolinker.Util.indexOf, // to support IE8 and below - classes = ( !classAttr ) ? [] : classAttr.split( whitespaceRegex ), - removeClasses = cssClass.split( whitespaceRegex ), - removeClass; - - while( classes.length && ( removeClass = removeClasses.shift() ) ) { - var idx = indexOf( classes, removeClass ); - if( idx !== -1 ) { - classes.splice( idx, 1 ); - } - } - - this.getAttrs()[ 'class' ] = classes.join( " " ); - return this; - }, - - - /** - * Convenience method to retrieve the CSS class(es) for the HtmlTag, which will each be separated by spaces when - * there are multiple. - * - * @return {String} - */ - getClass : function() { - return this.getAttrs()[ 'class' ] || ""; - }, - - - /** - * Convenience method to check if the tag has a CSS class or not. - * - * @param {String} cssClass The CSS class to check for. - * @return {Boolean} `true` if the HtmlTag has the CSS class, `false` otherwise. - */ - hasClass : function( cssClass ) { - return ( ' ' + this.getClass() + ' ' ).indexOf( ' ' + cssClass + ' ' ) !== -1; - }, - - - /** - * Sets the inner HTML for the tag. - * - * @param {String} html The inner HTML to set. - * @return {Autolinker.HtmlTag} This HtmlTag instance, so that method calls may be chained. - */ - setInnerHtml : function( html ) { - this.innerHtml = html; - - return this; - }, - - - /** - * Retrieves the inner HTML for the tag. - * - * @return {String} - */ - getInnerHtml : function() { - return this.innerHtml || ""; - }, - - - /** - * Override of superclass method used to generate the HTML string for the tag. - * - * @return {String} - */ - toAnchorString : function() { - var tagName = this.getTagName(), - attrsStr = this.buildAttrsStr(); - - attrsStr = ( attrsStr ) ? ' ' + attrsStr : ''; // prepend a space if there are actually attributes - - return [ '<', tagName, attrsStr, '>', this.getInnerHtml(), '' ].join( "" ); - }, - - - /** - * Support method for {@link #toAnchorString}, returns the string space-separated key="value" pairs, used to populate - * the stringified HtmlTag. - * - * @protected - * @return {String} Example return: `attr1="value1" attr2="value2"` - */ - buildAttrsStr : function() { - if( !this.attrs ) return ""; // no `attrs` Object (map) has been set, return empty string - - var attrs = this.getAttrs(), - attrsArr = []; - - for( var prop in attrs ) { - if( attrs.hasOwnProperty( prop ) ) { - attrsArr.push( prop + '="' + attrs[ prop ] + '"' ); - } - } - return attrsArr.join( " " ); - } - -} ); - -/*global Autolinker */ -/*jshint sub:true */ -/** - * @protected - * @class Autolinker.AnchorTagBuilder - * @extends Object - * - * Builds anchor (<a>) tags for the Autolinker utility when a match is found. - * - * Normally this class is instantiated, configured, and used internally by an {@link Autolinker} instance, but may - * actually be retrieved in a {@link Autolinker#replaceFn replaceFn} to create {@link Autolinker.HtmlTag HtmlTag} instances - * which may be modified before returning from the {@link Autolinker#replaceFn replaceFn}. For example: - * - * var html = Autolinker.link( "Test google.com", { - * replaceFn : function( autolinker, match ) { - * var tag = autolinker.getTagBuilder().build( match ); // returns an {@link Autolinker.HtmlTag} instance - * tag.setAttr( 'rel', 'nofollow' ); - * - * return tag; - * } - * } ); - * - * // generated html: - * // Test google.com - */ -Autolinker.AnchorTagBuilder = Autolinker.Util.extend( Object, { - - /** - * @cfg {Boolean} newWindow - * @inheritdoc Autolinker#newWindow - */ - - /** - * @cfg {Number} truncate - * @inheritdoc Autolinker#truncate - */ - - /** - * @cfg {String} className - * @inheritdoc Autolinker#className - */ - - - /** - * @constructor - * @param {Object} [cfg] The configuration options for the AnchorTagBuilder instance, specified in an Object (map). - */ - constructor : function( cfg ) { - Autolinker.Util.assign( this, cfg ); - }, - - - /** - * Generates the actual anchor (<a>) tag to use in place of the - * matched text, via its `match` object. - * - * @param {Autolinker.match.Match} match The Match instance to generate an - * anchor tag from. - * @return {Autolinker.HtmlTag} The HtmlTag instance for the anchor tag. - */ - build : function( match ) { - var tag = new Autolinker.HtmlTag( { - tagName : 'a', - attrs : this.createAttrs( match.getType(), match.getAnchorHref() ), - innerHtml : this.processAnchorText( match.getAnchorText() ) - } ); - - return tag; - }, - - - /** - * Creates the Object (map) of the HTML attributes for the anchor (<a>) - * tag being generated. - * - * @protected - * @param {"url"/"email"/"phone"/"twitter"/"hashtag"} matchType The type of - * match that an anchor tag is being generated for. - * @param {String} href The href for the anchor tag. - * @return {Object} A key/value Object (map) of the anchor tag's attributes. - */ - createAttrs : function( matchType, anchorHref ) { - var attrs = { - 'href' : anchorHref // we'll always have the `href` attribute - }; - - var cssClass = this.createCssClass( matchType ); - if( cssClass ) { - attrs[ 'class' ] = cssClass; - } - if( this.newWindow ) { - attrs[ 'target' ] = "_blank"; - } - - return attrs; - }, - - - /** - * Creates the CSS class that will be used for a given anchor tag, based on - * the `matchType` and the {@link #className} config. - * - * @private - * @param {"url"/"email"/"phone"/"twitter"/"hashtag"} matchType The type of - * match that an anchor tag is being generated for. - * @return {String} The CSS class string for the link. Example return: - * "myLink myLink-url". If no {@link #className} was configured, returns - * an empty string. - */ - createCssClass : function( matchType ) { - var className = this.className; - - if( !className ) - return ""; - else - return className + " " + className + "-" + matchType; // ex: "myLink myLink-url", "myLink myLink-email", "myLink myLink-phone", "myLink myLink-twitter", or "myLink myLink-hashtag" - }, - - - /** - * Processes the `anchorText` by truncating the text according to the - * {@link #truncate} config. - * - * @private - * @param {String} anchorText The anchor tag's text (i.e. what will be - * displayed). - * @return {String} The processed `anchorText`. - */ - processAnchorText : function( anchorText ) { - anchorText = this.doTruncate( anchorText ); - - return anchorText; - }, - - - /** - * Performs the truncation of the `anchorText`, if the `anchorText` is - * longer than the {@link #truncate} option. Truncates the text to 2 - * characters fewer than the {@link #truncate} option, and adds ".." to the - * end. - * - * @private - * @param {String} text The anchor tag's text (i.e. what will be displayed). - * @return {String} The truncated anchor text. - */ - doTruncate : function( anchorText ) { - return Autolinker.Util.ellipsis( anchorText, this.truncate || Number.POSITIVE_INFINITY ); - } - -} ); -/*global Autolinker */ -/** - * @private - * @class Autolinker.htmlParser.HtmlParser - * @extends Object - * - * An HTML parser implementation which simply walks an HTML string and returns an array of - * {@link Autolinker.htmlParser.HtmlNode HtmlNodes} that represent the basic HTML structure of the input string. - * - * Autolinker uses this to only link URLs/emails/Twitter handles within text nodes, effectively ignoring / "walking - * around" HTML tags. - */ -Autolinker.htmlParser.HtmlParser = Autolinker.Util.extend( Object, { - - /** - * @private - * @property {RegExp} htmlRegex - * - * The regular expression used to pull out HTML tags from a string. Handles namespaced HTML tags and - * attribute names, as specified by http://www.w3.org/TR/html-markup/syntax.html. - * - * Capturing groups: - * - * 1. The "!DOCTYPE" tag name, if a tag is a <!DOCTYPE> tag. - * 2. If it is an end tag, this group will have the '/'. - * 3. If it is a comment tag, this group will hold the comment text (i.e. - * the text inside the `<!--` and `-->`. - * 4. The tag name for all tags (other than the <!DOCTYPE> tag) - */ - htmlRegex : (function() { - var commentTagRegex = /!--([\s\S]+?)--/, - tagNameRegex = /[0-9a-zA-Z][0-9a-zA-Z:]*/, - attrNameRegex = /[^\s\0"'>\/=\x01-\x1F\x7F]+/, // the unicode range accounts for excluding control chars, and the delete char - attrValueRegex = /(?:"[^"]*?"|'[^']*?'|[^'"=<>`\s]+)/, // double quoted, single quoted, or unquoted attribute values - nameEqualsValueRegex = attrNameRegex.source + '(?:\\s*=\\s*' + attrValueRegex.source + ')?'; // optional '=[value]' - - return new RegExp( [ - // for tag. Ex: ) - '(?:', - '<(!DOCTYPE)', // *** Capturing Group 1 - If it's a doctype tag - - // Zero or more attributes following the tag name - '(?:', - '\\s+', // one or more whitespace chars before an attribute - - // Either: - // A. attr="value", or - // B. "value" alone (To cover example doctype tag: ) - '(?:', nameEqualsValueRegex, '|', attrValueRegex.source + ')', - ')*', - '>', - ')', - - '|', - - // All other HTML tags (i.e. tags that are not ) - '(?:', - '<(/)?', // Beginning of a tag or comment. Either '<' for a start tag, or '' - - ')', - ')', - '>', - ')' - ].join( "" ), 'gi' ); - } )(), - - /** - * @private - * @property {RegExp} htmlCharacterEntitiesRegex - * - * The regular expression that matches common HTML character entities. - * - * Ignoring & as it could be part of a query string -- handling it separately. - */ - htmlCharacterEntitiesRegex: /( | |<|<|>|>|"|"|')/gi, - - - /** - * Parses an HTML string and returns a simple array of {@link Autolinker.htmlParser.HtmlNode HtmlNodes} - * to represent the HTML structure of the input string. - * - * @param {String} html The HTML to parse. - * @return {Autolinker.htmlParser.HtmlNode[]} - */ - parse : function( html ) { - var htmlRegex = this.htmlRegex, - currentResult, - lastIndex = 0, - textAndEntityNodes, - nodes = []; // will be the result of the method - - while( ( currentResult = htmlRegex.exec( html ) ) !== null ) { - var tagText = currentResult[ 0 ], - commentText = currentResult[ 3 ], // if we've matched a comment - tagName = currentResult[ 1 ] || currentResult[ 4 ], // The tag (ex: "!DOCTYPE"), or another tag (ex: "a" or "img") - isClosingTag = !!currentResult[ 2 ], - inBetweenTagsText = html.substring( lastIndex, currentResult.index ); - - // Push TextNodes and EntityNodes for any text found between tags - if( inBetweenTagsText ) { - textAndEntityNodes = this.parseTextAndEntityNodes( inBetweenTagsText ); - nodes.push.apply( nodes, textAndEntityNodes ); - } - - // Push the CommentNode or ElementNode - if( commentText ) { - nodes.push( this.createCommentNode( tagText, commentText ) ); - } else { - nodes.push( this.createElementNode( tagText, tagName, isClosingTag ) ); - } - - lastIndex = currentResult.index + tagText.length; - } - - // Process any remaining text after the last HTML element. Will process all of the text if there were no HTML elements. - if( lastIndex < html.length ) { - var text = html.substring( lastIndex ); - - // Push TextNodes and EntityNodes for any text found between tags - if( text ) { - textAndEntityNodes = this.parseTextAndEntityNodes( text ); - nodes.push.apply( nodes, textAndEntityNodes ); - } - } - - return nodes; - }, - - - /** - * Parses text and HTML entity nodes from a given string. The input string - * should not have any HTML tags (elements) within it. - * - * @private - * @param {String} text The text to parse. - * @return {Autolinker.htmlParser.HtmlNode[]} An array of HtmlNodes to - * represent the {@link Autolinker.htmlParser.TextNode TextNodes} and - * {@link Autolinker.htmlParser.EntityNode EntityNodes} found. - */ - parseTextAndEntityNodes : function( text ) { - var nodes = [], - textAndEntityTokens = Autolinker.Util.splitAndCapture( text, this.htmlCharacterEntitiesRegex ); // split at HTML entities, but include the HTML entities in the results array - - // Every even numbered token is a TextNode, and every odd numbered token is an EntityNode - // For example: an input `text` of "Test "this" today" would turn into the - // `textAndEntityTokens`: [ 'Test ', '"', 'this', '"', ' today' ] - for( var i = 0, len = textAndEntityTokens.length; i < len; i += 2 ) { - var textToken = textAndEntityTokens[ i ], - entityToken = textAndEntityTokens[ i + 1 ]; - - if( textToken ) nodes.push( this.createTextNode( textToken ) ); - if( entityToken ) nodes.push( this.createEntityNode( entityToken ) ); - } - return nodes; - }, - - - /** - * Factory method to create an {@link Autolinker.htmlParser.CommentNode CommentNode}. - * - * @private - * @param {String} tagText The full text of the tag (comment) that was - * matched, including its <!-- and -->. - * @param {String} comment The full text of the comment that was matched. - */ - createCommentNode : function( tagText, commentText ) { - return new Autolinker.htmlParser.CommentNode( { - text: tagText, - comment: Autolinker.Util.trim( commentText ) - } ); - }, - - - /** - * Factory method to create an {@link Autolinker.htmlParser.ElementNode ElementNode}. - * - * @private - * @param {String} tagText The full text of the tag (element) that was - * matched, including its attributes. - * @param {String} tagName The name of the tag. Ex: An <img> tag would - * be passed to this method as "img". - * @param {Boolean} isClosingTag `true` if it's a closing tag, false - * otherwise. - * @return {Autolinker.htmlParser.ElementNode} - */ - createElementNode : function( tagText, tagName, isClosingTag ) { - return new Autolinker.htmlParser.ElementNode( { - text : tagText, - tagName : tagName.toLowerCase(), - closing : isClosingTag - } ); - }, - - - /** - * Factory method to create a {@link Autolinker.htmlParser.EntityNode EntityNode}. - * - * @private - * @param {String} text The text that was matched for the HTML entity (such - * as '&nbsp;'). - * @return {Autolinker.htmlParser.EntityNode} - */ - createEntityNode : function( text ) { - return new Autolinker.htmlParser.EntityNode( { text: text } ); - }, - - - /** - * Factory method to create a {@link Autolinker.htmlParser.TextNode TextNode}. - * - * @private - * @param {String} text The text that was matched. - * @return {Autolinker.htmlParser.TextNode} - */ - createTextNode : function( text ) { - return new Autolinker.htmlParser.TextNode( { text: text } ); - } - -} ); -/*global Autolinker */ -/** - * @abstract - * @class Autolinker.htmlParser.HtmlNode - * - * Represents an HTML node found in an input string. An HTML node is one of the following: - * - * 1. An {@link Autolinker.htmlParser.ElementNode ElementNode}, which represents HTML tags. - * 2. A {@link Autolinker.htmlParser.TextNode TextNode}, which represents text outside or within HTML tags. - * 3. A {@link Autolinker.htmlParser.EntityNode EntityNode}, which represents one of the known HTML - * entities that Autolinker looks for. This includes common ones such as &quot; and &nbsp; - */ -Autolinker.htmlParser.HtmlNode = Autolinker.Util.extend( Object, { - - /** - * @cfg {String} text (required) - * - * The original text that was matched for the HtmlNode. - * - * - In the case of an {@link Autolinker.htmlParser.ElementNode ElementNode}, this will be the tag's - * text. - * - In the case of a {@link Autolinker.htmlParser.TextNode TextNode}, this will be the text itself. - * - In the case of a {@link Autolinker.htmlParser.EntityNode EntityNode}, this will be the text of - * the HTML entity. - */ - text : "", - - - /** - * @constructor - * @param {Object} cfg The configuration properties for the Match instance, specified in an Object (map). - */ - constructor : function( cfg ) { - Autolinker.Util.assign( this, cfg ); - }, - - - /** - * Returns a string name for the type of node that this class represents. - * - * @abstract - * @return {String} - */ - getType : Autolinker.Util.abstractMethod, - - - /** - * Retrieves the {@link #text} for the HtmlNode. - * - * @return {String} - */ - getText : function() { - return this.text; - } - -} ); -/*global Autolinker */ -/** - * @class Autolinker.htmlParser.CommentNode - * @extends Autolinker.htmlParser.HtmlNode - * - * Represents an HTML comment node that has been parsed by the - * {@link Autolinker.htmlParser.HtmlParser}. - * - * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more - * details. - */ -Autolinker.htmlParser.CommentNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { - - /** - * @cfg {String} comment (required) - * - * The text inside the comment tag. This text is stripped of any leading or - * trailing whitespace. - */ - comment : '', - - - /** - * Returns a string name for the type of node that this class represents. - * - * @return {String} - */ - getType : function() { - return 'comment'; - }, - - - /** - * Returns the comment inside the comment tag. - * - * @return {String} - */ - getComment : function() { - return this.comment; - } - -} ); -/*global Autolinker */ -/** - * @class Autolinker.htmlParser.ElementNode - * @extends Autolinker.htmlParser.HtmlNode - * - * Represents an HTML element node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}. - * - * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more details. - */ -Autolinker.htmlParser.ElementNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { - - /** - * @cfg {String} tagName (required) - * - * The name of the tag that was matched. - */ - tagName : '', - - /** - * @cfg {Boolean} closing (required) - * - * `true` if the element (tag) is a closing tag, `false` if its an opening tag. - */ - closing : false, - - - /** - * Returns a string name for the type of node that this class represents. - * - * @return {String} - */ - getType : function() { - return 'element'; - }, - - - /** - * Returns the HTML element's (tag's) name. Ex: for an <img> tag, returns "img". - * - * @return {String} - */ - getTagName : function() { - return this.tagName; - }, - - - /** - * Determines if the HTML element (tag) is a closing tag. Ex: <div> returns - * `false`, while </div> returns `true`. - * - * @return {Boolean} - */ - isClosing : function() { - return this.closing; - } - -} ); -/*global Autolinker */ -/** - * @class Autolinker.htmlParser.EntityNode - * @extends Autolinker.htmlParser.HtmlNode - * - * Represents a known HTML entity node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}. - * Ex: '&nbsp;', or '&#160;' (which will be retrievable from the {@link #getText} method. - * - * Note that this class will only be returned from the HtmlParser for the set of checked HTML entity nodes - * defined by the {@link Autolinker.htmlParser.HtmlParser#htmlCharacterEntitiesRegex}. - * - * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more details. - */ -Autolinker.htmlParser.EntityNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { - - /** - * Returns a string name for the type of node that this class represents. - * - * @return {String} - */ - getType : function() { - return 'entity'; - } - -} ); -/*global Autolinker */ -/** - * @class Autolinker.htmlParser.TextNode - * @extends Autolinker.htmlParser.HtmlNode - * - * Represents a text node that has been parsed by the {@link Autolinker.htmlParser.HtmlParser}. - * - * See this class's superclass ({@link Autolinker.htmlParser.HtmlNode}) for more details. - */ -Autolinker.htmlParser.TextNode = Autolinker.Util.extend( Autolinker.htmlParser.HtmlNode, { - - /** - * Returns a string name for the type of node that this class represents. - * - * @return {String} - */ - getType : function() { - return 'text'; - } - -} ); -/*global Autolinker */ -/** - * @private - * @class Autolinker.matchParser.MatchParser - * @extends Object - * - * Used by Autolinker to parse potential matches, given an input string of text. - * - * The MatchParser is fed a non-HTML string in order to search for matches. - * Autolinker first uses the {@link Autolinker.htmlParser.HtmlParser} to "walk - * around" HTML tags, and then the text around the HTML tags is passed into the - * MatchParser in order to find the actual matches. - */ -Autolinker.matchParser.MatchParser = Autolinker.Util.extend( Object, { - - /** - * @cfg {Boolean} urls - * @inheritdoc Autolinker#urls - */ - urls : true, - - /** - * @cfg {Boolean} email - * @inheritdoc Autolinker#email - */ - email : true, - - /** - * @cfg {Boolean} twitter - * @inheritdoc Autolinker#twitter - */ - twitter : true, - - /** - * @cfg {Boolean} phone - * @inheritdoc Autolinker#phone - */ - phone: true, - - /** - * @cfg {Boolean/String} hashtag - * @inheritdoc Autolinker#hashtag - */ - hashtag : false, - - /** - * @cfg {Boolean} stripPrefix - * @inheritdoc Autolinker#stripPrefix - */ - stripPrefix : true, - - - /** - * @private - * @property {RegExp} matcherRegex - * - * The regular expression that matches URLs, email addresses, phone #s, - * Twitter handles, and Hashtags. - * - * This regular expression has the following capturing groups: - * - * 1. Group that is used to determine if there is a Twitter handle match - * (i.e. \@someTwitterUser). Simply check for its existence to determine - * if there is a Twitter handle match. The next couple of capturing - * groups give information about the Twitter handle match. - * 2. The whitespace character before the \@sign in a Twitter handle. This - * is needed because there are no lookbehinds in JS regular expressions, - * and can be used to reconstruct the original string in a replace(). - * 3. The Twitter handle itself in a Twitter match. If the match is - * '@someTwitterUser', the handle is 'someTwitterUser'. - * 4. Group that matches an email address. Used to determine if the match - * is an email address, as well as holding the full address. Ex: - * 'me@my.com' - * 5. Group that matches a URL in the input text. Ex: 'http://google.com', - * 'www.google.com', or just 'google.com'. This also includes a path, - * url parameters, or hash anchors. Ex: google.com/path/to/file?q1=1&q2=2#myAnchor - * 6. Group that matches a protocol URL (i.e. 'http://google.com'). This is - * used to match protocol URLs with just a single word, like 'http://localhost', - * where we won't double check that the domain name has at least one '.' - * in it. - * 7. A protocol-relative ('//') match for the case of a 'www.' prefixed - * URL. Will be an empty string if it is not a protocol-relative match. - * We need to know the character before the '//' in order to determine - * if it is a valid match or the // was in a string we don't want to - * auto-link. - * 8. A protocol-relative ('//') match for the case of a known TLD prefixed - * URL. Will be an empty string if it is not a protocol-relative match. - * See #6 for more info. - * 9. Group that is used to determine if there is a phone number match. The - * next 3 groups give segments of the phone number. - * 10. Group that is used to determine if there is a Hashtag match - * (i.e. \#someHashtag). Simply check for its existence to determine if - * there is a Hashtag match. The next couple of capturing groups give - * information about the Hashtag match. - * 11. The whitespace character before the #sign in a Hashtag handle. This - * is needed because there are no look-behinds in JS regular - * expressions, and can be used to reconstruct the original string in a - * replace(). - * 12. The Hashtag itself in a Hashtag match. If the match is - * '#someHashtag', the hashtag is 'someHashtag'. - */ - matcherRegex : (function() { - var twitterRegex = /(^|[^\w])@(\w{1,15})/, // For matching a twitter handle. Ex: @gregory_jacobs - - hashtagRegex = /(^|[^\w])#(\w{1,15})/, // For matching a Hashtag. Ex: #games - - emailRegex = /(?:[\-;:&=\+\$,\w\.]+@)/, // something@ for email addresses (a.k.a. local-part) - phoneRegex = /(?:\+?\d{1,3}[-\s.])?\(?\d{3}\)?[-\s.]?\d{3}[-\s.]\d{4}/, // ex: (123) 456-7890, 123 456 7890, 123-456-7890, etc. - protocolRegex = /(?:[A-Za-z][-.+A-Za-z0-9]+:(?![A-Za-z][-.+A-Za-z0-9]+:\/\/)(?!\d+\/?)(?:\/\/)?)/, // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex) - wwwRegex = /(?:www\.)/, // starting with 'www.' - domainNameRegex = /[A-Za-z0-9\.\-]*[A-Za-z0-9\-]/, // anything looking at all like a domain, non-unicode domains, not ending in a period - tldRegex = /\.(?:international|construction|contractors|enterprises|photography|productions|foundation|immobilien|industries|management|properties|technology|christmas|community|directory|education|equipment|institute|marketing|solutions|vacations|bargains|boutique|builders|catering|cleaning|clothing|computer|democrat|diamonds|graphics|holdings|lighting|partners|plumbing|supplies|training|ventures|academy|careers|company|cruises|domains|exposed|flights|florist|gallery|guitars|holiday|kitchen|neustar|okinawa|recipes|rentals|reviews|shiksha|singles|support|systems|agency|berlin|camera|center|coffee|condos|dating|estate|events|expert|futbol|kaufen|luxury|maison|monash|museum|nagoya|photos|repair|report|social|supply|tattoo|tienda|travel|viajes|villas|vision|voting|voyage|actor|build|cards|cheap|codes|dance|email|glass|house|mango|ninja|parts|photo|shoes|solar|today|tokyo|tools|watch|works|aero|arpa|asia|best|bike|blue|buzz|camp|club|cool|coop|farm|fish|gift|guru|info|jobs|kiwi|kred|land|limo|link|menu|mobi|moda|name|pics|pink|post|qpon|rich|ruhr|sexy|tips|vote|voto|wang|wien|wiki|zone|bar|bid|biz|cab|cat|ceo|com|edu|gov|int|kim|mil|net|onl|org|pro|pub|red|tel|uno|wed|xxx|xyz|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/, // match our known top level domains (TLDs) - - // Allow optional path, query string, and hash anchor, not ending in the following characters: "?!:,.;" - // http://blog.codinghorror.com/the-problem-with-urls/ - urlSuffixRegex = /[\-A-Za-z0-9+&@#\/%=~_()|'$*\[\]?!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|'$*\[\]]/; - - return new RegExp( [ - '(', // *** Capturing group $1, which can be used to check for a twitter handle match. Use group $3 for the actual twitter handle though. $2 may be used to reconstruct the original string in a replace() - // *** Capturing group $2, which matches the whitespace character before the '@' sign (needed because of no lookbehinds), and - // *** Capturing group $3, which matches the actual twitter handle - twitterRegex.source, - ')', - - '|', - - '(', // *** Capturing group $4, which is used to determine an email match - emailRegex.source, - domainNameRegex.source, - tldRegex.source, - ')', - - '|', - - '(', // *** Capturing group $5, which is used to match a URL - '(?:', // parens to cover match for protocol (optional), and domain - '(', // *** Capturing group $6, for a protocol-prefixed url (ex: http://google.com) - protocolRegex.source, - domainNameRegex.source, - ')', - - '|', - - '(?:', // non-capturing paren for a 'www.' prefixed url (ex: www.google.com) - '(.?//)?', // *** Capturing group $7 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character - wwwRegex.source, - domainNameRegex.source, - ')', - - '|', - - '(?:', // non-capturing paren for known a TLD url (ex: google.com) - '(.?//)?', // *** Capturing group $8 for an optional protocol-relative URL. Must be at the beginning of the string or start with a non-word character - domainNameRegex.source, - tldRegex.source, - ')', - ')', - - '(?:' + urlSuffixRegex.source + ')?', // match for path, query string, and/or hash anchor - optional - ')', - - '|', - - // this setup does not scale well for open extension :( Need to rethink design of autolinker... - // *** Capturing group $9, which matches a (USA for now) phone number - '(', - phoneRegex.source, - ')', - - '|', - - '(', // *** Capturing group $10, which can be used to check for a Hashtag match. Use group $12 for the actual Hashtag though. $11 may be used to reconstruct the original string in a replace() - // *** Capturing group $11, which matches the whitespace character before the '#' sign (needed because of no lookbehinds), and - // *** Capturing group $12, which matches the actual Hashtag - hashtagRegex.source, - ')' - ].join( "" ), 'gi' ); - } )(), - - /** - * @private - * @property {RegExp} charBeforeProtocolRelMatchRegex - * - * The regular expression used to retrieve the character before a - * protocol-relative URL match. - * - * This is used in conjunction with the {@link #matcherRegex}, which needs - * to grab the character before a protocol-relative '//' due to the lack of - * a negative look-behind in JavaScript regular expressions. The character - * before the match is stripped from the URL. - */ - charBeforeProtocolRelMatchRegex : /^(.)?\/\//, - - /** - * @private - * @property {Autolinker.MatchValidator} matchValidator - * - * The MatchValidator object, used to filter out any false positives from - * the {@link #matcherRegex}. See {@link Autolinker.MatchValidator} for details. - */ - - - /** - * @constructor - * @param {Object} [cfg] The configuration options for the AnchorTagBuilder - * instance, specified in an Object (map). - */ - constructor : function( cfg ) { - Autolinker.Util.assign( this, cfg ); - - this.matchValidator = new Autolinker.MatchValidator(); - }, - - - /** - * Parses the input `text` to search for matches, and calls the `replaceFn` - * to allow replacements of the matches. Returns the `text` with matches - * replaced. - * - * @param {String} text The text to search and repace matches in. - * @param {Function} replaceFn The iterator function to handle the - * replacements. The function takes a single argument, a {@link Autolinker.match.Match} - * object, and should return the text that should make the replacement. - * @param {Object} [contextObj=window] The context object ("scope") to run - * the `replaceFn` in. - * @return {String} - */ - replace : function( text, replaceFn, contextObj ) { - var me = this; // for closure - - return text.replace( this.matcherRegex, function( matchStr, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 ) { - var matchDescObj = me.processCandidateMatch( matchStr, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 ); // "match description" object - - // Return out with no changes for match types that are disabled (url, - // email, phone, etc.), or for matches that are invalid (false - // positives from the matcherRegex, which can't use look-behinds - // since they are unavailable in JS). - if( !matchDescObj ) { - return matchStr; - - } else { - // Generate replacement text for the match from the `replaceFn` - var replaceStr = replaceFn.call( contextObj, matchDescObj.match ); - return matchDescObj.prefixStr + replaceStr + matchDescObj.suffixStr; - } - } ); - }, - - - /** - * Processes a candidate match from the {@link #matcherRegex}. - * - * Not all matches found by the regex are actual URL/Email/Phone/Twitter/Hashtag - * matches, as determined by the {@link #matchValidator}. In this case, the - * method returns `null`. Otherwise, a valid Object with `prefixStr`, - * `match`, and `suffixStr` is returned. - * - * @private - * @param {String} matchStr The full match that was found by the - * {@link #matcherRegex}. - * @param {String} twitterMatch The matched text of a Twitter handle, if the - * match is a Twitter match. - * @param {String} twitterHandlePrefixWhitespaceChar The whitespace char - * before the @ sign in a Twitter handle match. This is needed because of - * no lookbehinds in JS regexes, and is need to re-include the character - * for the anchor tag replacement. - * @param {String} twitterHandle The actual Twitter user (i.e the word after - * the @ sign in a Twitter match). - * @param {String} emailAddressMatch The matched email address for an email - * address match. - * @param {String} urlMatch The matched URL string for a URL match. - * @param {String} protocolUrlMatch The match URL string for a protocol - * match. Ex: 'http://yahoo.com'. This is used to match something like - * 'http://localhost', where we won't double check that the domain name - * has at least one '.' in it. - * @param {String} wwwProtocolRelativeMatch The '//' for a protocol-relative - * match from a 'www' url, with the character that comes before the '//'. - * @param {String} tldProtocolRelativeMatch The '//' for a protocol-relative - * match from a TLD (top level domain) match, with the character that - * comes before the '//'. - * @param {String} phoneMatch The matched text of a phone number - * @param {String} hashtagMatch The matched text of a Twitter - * Hashtag, if the match is a Hashtag match. - * @param {String} hashtagPrefixWhitespaceChar The whitespace char - * before the # sign in a Hashtag match. This is needed because of no - * lookbehinds in JS regexes, and is need to re-include the character for - * the anchor tag replacement. - * @param {String} hashtag The actual Hashtag (i.e the word - * after the # sign in a Hashtag match). - * - * @return {Object} A "match description object". This will be `null` if the - * match was invalid, or if a match type is disabled. Otherwise, this will - * be an Object (map) with the following properties: - * @return {String} return.prefixStr The char(s) that should be prepended to - * the replacement string. These are char(s) that were needed to be - * included from the regex match that were ignored by processing code, and - * should be re-inserted into the replacement stream. - * @return {String} return.suffixStr The char(s) that should be appended to - * the replacement string. These are char(s) that were needed to be - * included from the regex match that were ignored by processing code, and - * should be re-inserted into the replacement stream. - * @return {Autolinker.match.Match} return.match The Match object that - * represents the match that was found. - */ - processCandidateMatch : function( - matchStr, twitterMatch, twitterHandlePrefixWhitespaceChar, twitterHandle, - emailAddressMatch, urlMatch, protocolUrlMatch, wwwProtocolRelativeMatch, - tldProtocolRelativeMatch, phoneMatch, hashtagMatch, - hashtagPrefixWhitespaceChar, hashtag - ) { - // Note: The `matchStr` variable wil be fixed up to remove characters that are no longer needed (which will - // be added to `prefixStr` and `suffixStr`). - - var protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch, - match, // Will be an Autolinker.match.Match object - - prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter and Hashtag matches. - suffixStr = ""; // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked. - - // Return out with `null` for match types that are disabled (url, email, - // twitter, hashtag), or for matches that are invalid (false positives - // from the matcherRegex, which can't use look-behinds since they are - // unavailable in JS). - if( - ( urlMatch && !this.urls ) || - ( emailAddressMatch && !this.email ) || - ( phoneMatch && !this.phone ) || - ( twitterMatch && !this.twitter ) || - ( hashtagMatch && !this.hashtag ) || - !this.matchValidator.isValidMatch( urlMatch, protocolUrlMatch, protocolRelativeMatch ) - ) { - return null; - } - - // Handle a closing parenthesis at the end of the match, and exclude it - // if there is not a matching open parenthesis - // in the match itself. - if( this.matchHasUnbalancedClosingParen( matchStr ) ) { - matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")" - suffixStr = ")"; // this will be added after the generated tag - } - - if( emailAddressMatch ) { - match = new Autolinker.match.Email( { matchedText: matchStr, email: emailAddressMatch } ); - - } else if( twitterMatch ) { - // fix up the `matchStr` if there was a preceding whitespace char, - // which was needed to determine the match itself (since there are - // no look-behinds in JS regexes) - if( twitterHandlePrefixWhitespaceChar ) { - prefixStr = twitterHandlePrefixWhitespaceChar; - matchStr = matchStr.slice( 1 ); // remove the prefixed whitespace char from the match - } - match = new Autolinker.match.Twitter( { matchedText: matchStr, twitterHandle: twitterHandle } ); - - } else if( phoneMatch ) { - // remove non-numeric values from phone number string - var cleanNumber = matchStr.replace( /\D/g, '' ); - match = new Autolinker.match.Phone( { matchedText: matchStr, number: cleanNumber } ); - - } else if( hashtagMatch ) { - // fix up the `matchStr` if there was a preceding whitespace char, - // which was needed to determine the match itself (since there are - // no look-behinds in JS regexes) - if( hashtagPrefixWhitespaceChar ) { - prefixStr = hashtagPrefixWhitespaceChar; - matchStr = matchStr.slice( 1 ); // remove the prefixed whitespace char from the match - } - match = new Autolinker.match.Hashtag( { matchedText: matchStr, serviceName: this.hashtag, hashtag: hashtag } ); - - } else { // url match - // If it's a protocol-relative '//' match, remove the character - // before the '//' (which the matcherRegex needed to match due to - // the lack of a negative look-behind in JavaScript regular - // expressions) - if( protocolRelativeMatch ) { - var charBeforeMatch = protocolRelativeMatch.match( this.charBeforeProtocolRelMatchRegex )[ 1 ] || ""; - - if( charBeforeMatch ) { // fix up the `matchStr` if there was a preceding char before a protocol-relative match, which was needed to determine the match itself (since there are no look-behinds in JS regexes) - prefixStr = charBeforeMatch; - matchStr = matchStr.slice( 1 ); // remove the prefixed char from the match - } - } - - match = new Autolinker.match.Url( { - matchedText : matchStr, - url : matchStr, - protocolUrlMatch : !!protocolUrlMatch, - protocolRelativeMatch : !!protocolRelativeMatch, - stripPrefix : this.stripPrefix - } ); - } - - return { - prefixStr : prefixStr, - suffixStr : suffixStr, - match : match - }; - }, - - - /** - * Determines if a match found has an unmatched closing parenthesis. If so, - * this parenthesis will be removed from the match itself, and appended - * after the generated anchor tag in {@link #processCandidateMatch}. - * - * A match may have an extra closing parenthesis at the end of the match - * because the regular expression must include parenthesis for URLs such as - * "wikipedia.com/something_(disambiguation)", which should be auto-linked. - * - * However, an extra parenthesis *will* be included when the URL itself is - * wrapped in parenthesis, such as in the case of "(wikipedia.com/something_(disambiguation))". - * In this case, the last closing parenthesis should *not* be part of the - * URL itself, and this method will return `true`. - * - * @private - * @param {String} matchStr The full match string from the {@link #matcherRegex}. - * @return {Boolean} `true` if there is an unbalanced closing parenthesis at - * the end of the `matchStr`, `false` otherwise. - */ - matchHasUnbalancedClosingParen : function( matchStr ) { - var lastChar = matchStr.charAt( matchStr.length - 1 ); - - if( lastChar === ')' ) { - var openParensMatch = matchStr.match( /\(/g ), - closeParensMatch = matchStr.match( /\)/g ), - numOpenParens = ( openParensMatch && openParensMatch.length ) || 0, - numCloseParens = ( closeParensMatch && closeParensMatch.length ) || 0; - - if( numOpenParens < numCloseParens ) { - return true; - } - } - - return false; - } - -} ); -/*global Autolinker */ -/*jshint scripturl:true */ -/** - * @private - * @class Autolinker.MatchValidator - * @extends Object - * - * Used by Autolinker to filter out false positives from the - * {@link Autolinker.matchParser.MatchParser#matcherRegex}. - * - * Due to the limitations of regular expressions (including the missing feature - * of look-behinds in JS regular expressions), we cannot always determine the - * validity of a given match. This class applies a bit of additional logic to - * filter out any false positives that have been matched by the - * {@link Autolinker.matchParser.MatchParser#matcherRegex}. - */ -Autolinker.MatchValidator = Autolinker.Util.extend( Object, { - - /** - * @private - * @property {RegExp} invalidProtocolRelMatchRegex - * - * The regular expression used to check a potential protocol-relative URL - * match, coming from the {@link Autolinker.matchParser.MatchParser#matcherRegex}. - * A protocol-relative URL is, for example, "//yahoo.com" - * - * This regular expression checks to see if there is a word character before - * the '//' match in order to determine if we should actually autolink a - * protocol-relative URL. This is needed because there is no negative - * look-behind in JavaScript regular expressions. - * - * For instance, we want to autolink something like "Go to: //google.com", - * but we don't want to autolink something like "abc//google.com" - */ - invalidProtocolRelMatchRegex : /^[\w]\/\//, - - /** - * Regex to test for a full protocol, with the two trailing slashes. Ex: 'http://' - * - * @private - * @property {RegExp} hasFullProtocolRegex - */ - hasFullProtocolRegex : /^[A-Za-z][-.+A-Za-z0-9]+:\/\//, - - /** - * Regex to find the URI scheme, such as 'mailto:'. - * - * This is used to filter out 'javascript:' and 'vbscript:' schemes. - * - * @private - * @property {RegExp} uriSchemeRegex - */ - uriSchemeRegex : /^[A-Za-z][-.+A-Za-z0-9]+:/, - - /** - * Regex to determine if at least one word char exists after the protocol (i.e. after the ':') - * - * @private - * @property {RegExp} hasWordCharAfterProtocolRegex - */ - hasWordCharAfterProtocolRegex : /:[^\s]*?[A-Za-z]/, - - - /** - * Determines if a given match found by the {@link Autolinker.matchParser.MatchParser} - * is valid. Will return `false` for: - * - * 1) URL matches which do not have at least have one period ('.') in the - * domain name (effectively skipping over matches like "abc:def"). - * However, URL matches with a protocol will be allowed (ex: 'http://localhost') - * 2) URL matches which do not have at least one word character in the - * domain name (effectively skipping over matches like "git:1.0"). - * 3) A protocol-relative url match (a URL beginning with '//') whose - * previous character is a word character (effectively skipping over - * strings like "abc//google.com") - * - * Otherwise, returns `true`. - * - * @param {String} urlMatch The matched URL, if there was one. Will be an - * empty string if the match is not a URL match. - * @param {String} protocolUrlMatch The match URL string for a protocol - * match. Ex: 'http://yahoo.com'. This is used to match something like - * 'http://localhost', where we won't double check that the domain name - * has at least one '.' in it. - * @param {String} protocolRelativeMatch The protocol-relative string for a - * URL match (i.e. '//'), possibly with a preceding character (ex, a - * space, such as: ' //', or a letter, such as: 'a//'). The match is - * invalid if there is a word character preceding the '//'. - * @return {Boolean} `true` if the match given is valid and should be - * processed, or `false` if the match is invalid and/or should just not be - * processed. - */ - isValidMatch : function( urlMatch, protocolUrlMatch, protocolRelativeMatch ) { - if( - ( protocolUrlMatch && !this.isValidUriScheme( protocolUrlMatch ) ) || - this.urlMatchDoesNotHaveProtocolOrDot( urlMatch, protocolUrlMatch ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost') - this.urlMatchDoesNotHaveAtLeastOneWordChar( urlMatch, protocolUrlMatch ) || // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" - this.isInvalidProtocolRelativeMatch( protocolRelativeMatch ) // A protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com") - ) { - return false; - } - - return true; - }, - - - /** - * Determines if the URI scheme is a valid scheme to be autolinked. Returns - * `false` if the scheme is 'javascript:' or 'vbscript:' - * - * @private - * @param {String} uriSchemeMatch The match URL string for a full URI scheme - * match. Ex: 'http://yahoo.com' or 'mailto:a@a.com'. - * @return {Boolean} `true` if the scheme is a valid one, `false` otherwise. - */ - isValidUriScheme : function( uriSchemeMatch ) { - var uriScheme = uriSchemeMatch.match( this.uriSchemeRegex )[ 0 ].toLowerCase(); - - return ( uriScheme !== 'javascript:' && uriScheme !== 'vbscript:' ); - }, - - - /** - * Determines if a URL match does not have either: - * - * a) a full protocol (i.e. 'http://'), or - * b) at least one dot ('.') in the domain name (for a non-full-protocol - * match). - * - * Either situation is considered an invalid URL (ex: 'git:d' does not have - * either the '://' part, or at least one dot in the domain name. If the - * match was 'git:abc.com', we would consider this valid.) - * - * @private - * @param {String} urlMatch The matched URL, if there was one. Will be an - * empty string if the match is not a URL match. - * @param {String} protocolUrlMatch The match URL string for a protocol - * match. Ex: 'http://yahoo.com'. This is used to match something like - * 'http://localhost', where we won't double check that the domain name - * has at least one '.' in it. - * @return {Boolean} `true` if the URL match does not have a full protocol, - * or at least one dot ('.') in a non-full-protocol match. - */ - urlMatchDoesNotHaveProtocolOrDot : function( urlMatch, protocolUrlMatch ) { - return ( !!urlMatch && ( !protocolUrlMatch || !this.hasFullProtocolRegex.test( protocolUrlMatch ) ) && urlMatch.indexOf( '.' ) === -1 ); - }, - - - /** - * Determines if a URL match does not have at least one word character after - * the protocol (i.e. in the domain name). - * - * At least one letter character must exist in the domain name after a - * protocol match. Ex: skip over something like "git:1.0" - * - * @private - * @param {String} urlMatch The matched URL, if there was one. Will be an - * empty string if the match is not a URL match. - * @param {String} protocolUrlMatch The match URL string for a protocol - * match. Ex: 'http://yahoo.com'. This is used to know whether or not we - * have a protocol in the URL string, in order to check for a word - * character after the protocol separator (':'). - * @return {Boolean} `true` if the URL match does not have at least one word - * character in it after the protocol, `false` otherwise. - */ - urlMatchDoesNotHaveAtLeastOneWordChar : function( urlMatch, protocolUrlMatch ) { - if( urlMatch && protocolUrlMatch ) { - return !this.hasWordCharAfterProtocolRegex.test( urlMatch ); - } else { - return false; - } - }, - - - /** - * Determines if a protocol-relative match is an invalid one. This method - * returns `true` if there is a `protocolRelativeMatch`, and that match - * contains a word character before the '//' (i.e. it must contain - * whitespace or nothing before the '//' in order to be considered valid). - * - * @private - * @param {String} protocolRelativeMatch The protocol-relative string for a - * URL match (i.e. '//'), possibly with a preceding character (ex, a - * space, such as: ' //', or a letter, such as: 'a//'). The match is - * invalid if there is a word character preceding the '//'. - * @return {Boolean} `true` if it is an invalid protocol-relative match, - * `false` otherwise. - */ - isInvalidProtocolRelativeMatch : function( protocolRelativeMatch ) { - return ( !!protocolRelativeMatch && this.invalidProtocolRelMatchRegex.test( protocolRelativeMatch ) ); - } - -} ); -/*global Autolinker */ -/** - * @abstract - * @class Autolinker.match.Match - * - * Represents a match found in an input string which should be Autolinked. A Match object is what is provided in a - * {@link Autolinker#replaceFn replaceFn}, and may be used to query for details about the match. - * - * For example: - * - * var input = "..."; // string with URLs, Email Addresses, and Twitter Handles - * - * var linkedText = Autolinker.link( input, { - * replaceFn : function( autolinker, match ) { - * console.log( "href = ", match.getAnchorHref() ); - * console.log( "text = ", match.getAnchorText() ); - * - * switch( match.getType() ) { - * case 'url' : - * console.log( "url: ", match.getUrl() ); - * - * case 'email' : - * console.log( "email: ", match.getEmail() ); - * - * case 'twitter' : - * console.log( "twitter: ", match.getTwitterHandle() ); - * } - * } - * } ); - * - * See the {@link Autolinker} class for more details on using the {@link Autolinker#replaceFn replaceFn}. - */ -Autolinker.match.Match = Autolinker.Util.extend( Object, { - - /** - * @cfg {String} matchedText (required) - * - * The original text that was matched. - */ - - - /** - * @constructor - * @param {Object} cfg The configuration properties for the Match instance, specified in an Object (map). - */ - constructor : function( cfg ) { - Autolinker.Util.assign( this, cfg ); - }, - - - /** - * Returns a string name for the type of match that this class represents. - * - * @abstract - * @return {String} - */ - getType : Autolinker.Util.abstractMethod, - - - /** - * Returns the original text that was matched. - * - * @return {String} - */ - getMatchedText : function() { - return this.matchedText; - }, - - - /** - * Returns the anchor href that should be generated for the match. - * - * @abstract - * @return {String} - */ - getAnchorHref : Autolinker.Util.abstractMethod, - - - /** - * Returns the anchor text that should be generated for the match. - * - * @abstract - * @return {String} - */ - getAnchorText : Autolinker.Util.abstractMethod - -} ); -/*global Autolinker */ -/** - * @class Autolinker.match.Email - * @extends Autolinker.match.Match - * - * Represents a Email match found in an input string which should be Autolinked. - * - * See this class's superclass ({@link Autolinker.match.Match}) for more details. - */ -Autolinker.match.Email = Autolinker.Util.extend( Autolinker.match.Match, { - - /** - * @cfg {String} email (required) - * - * The email address that was matched. - */ - - - /** - * Returns a string name for the type of match that this class represents. - * - * @return {String} - */ - getType : function() { - return 'email'; - }, - - - /** - * Returns the email address that was matched. - * - * @return {String} - */ - getEmail : function() { - return this.email; - }, - - - /** - * Returns the anchor href that should be generated for the match. - * - * @return {String} - */ - getAnchorHref : function() { - return 'mailto:' + this.email; - }, - - - /** - * Returns the anchor text that should be generated for the match. - * - * @return {String} - */ - getAnchorText : function() { - return this.email; - } - -} ); -/*global Autolinker */ -/** - * @class Autolinker.match.Hashtag - * @extends Autolinker.match.Match - * - * Represents a Hashtag match found in an input string which should be - * Autolinked. - * - * See this class's superclass ({@link Autolinker.match.Match}) for more - * details. - */ -Autolinker.match.Hashtag = Autolinker.Util.extend( Autolinker.match.Match, { - - /** - * @cfg {String} serviceName (required) - * - * The service to point hashtag matches to. See {@link Autolinker#hashtag} - * for available values. - */ - - /** - * @cfg {String} hashtag (required) - * - * The Hashtag that was matched, without the '#'. - */ - - - /** - * Returns the type of match that this class represents. - * - * @return {String} - */ - getType : function() { - return 'hashtag'; - }, - - - /** - * Returns the matched hashtag. - * - * @return {String} - */ - getHashtag : function() { - return this.hashtag; - }, - - - /** - * Returns the anchor href that should be generated for the match. - * - * @return {String} - */ - getAnchorHref : function() { - var serviceName = this.serviceName, - hashtag = this.hashtag; - - switch( serviceName ) { - case 'twitter' : - return 'https://twitter.com/hashtag/' + hashtag; - case 'facebook' : - return 'https://www.facebook.com/hashtag/' + hashtag; - - default : // Shouldn't happen because Autolinker's constructor should block any invalid values, but just in case. - throw new Error( 'Unknown service name to point hashtag to: ', serviceName ); - } - }, - - - /** - * Returns the anchor text that should be generated for the match. - * - * @return {String} - */ - getAnchorText : function() { - return '#' + this.hashtag; - } - -} ); -/*global Autolinker */ -/** - * @class Autolinker.match.Phone - * @extends Autolinker.match.Match - * - * Represents a Phone number match found in an input string which should be - * Autolinked. - * - * See this class's superclass ({@link Autolinker.match.Match}) for more - * details. - */ -Autolinker.match.Phone = Autolinker.Util.extend( Autolinker.match.Match, { - - /** - * @cfg {String} number (required) - * - * The phone number that was matched. - */ - - - /** - * Returns a string name for the type of match that this class represents. - * - * @return {String} - */ - getType : function() { - return 'phone'; - }, - - - /** - * Returns the phone number that was matched. - * - * @return {String} - */ - getNumber: function() { - return this.number; - }, - - - /** - * Returns the anchor href that should be generated for the match. - * - * @return {String} - */ - getAnchorHref : function() { - return 'tel:' + this.number; - }, - - - /** - * Returns the anchor text that should be generated for the match. - * - * @return {String} - */ - getAnchorText : function() { - return this.matchedText; - } - -} ); - -/*global Autolinker */ -/** - * @class Autolinker.match.Twitter - * @extends Autolinker.match.Match - * - * Represents a Twitter match found in an input string which should be Autolinked. - * - * See this class's superclass ({@link Autolinker.match.Match}) for more details. - */ -Autolinker.match.Twitter = Autolinker.Util.extend( Autolinker.match.Match, { - - /** - * @cfg {String} twitterHandle (required) - * - * The Twitter handle that was matched. - */ - - - /** - * Returns the type of match that this class represents. - * - * @return {String} - */ - getType : function() { - return 'twitter'; - }, - - - /** - * Returns a string name for the type of match that this class represents. - * - * @return {String} - */ - getTwitterHandle : function() { - return this.twitterHandle; - }, - - - /** - * Returns the anchor href that should be generated for the match. - * - * @return {String} - */ - getAnchorHref : function() { - return 'https://twitter.com/' + this.twitterHandle; - }, - - - /** - * Returns the anchor text that should be generated for the match. - * - * @return {String} - */ - getAnchorText : function() { - return '@' + this.twitterHandle; - } - -} ); -/*global Autolinker */ -/** - * @class Autolinker.match.Url - * @extends Autolinker.match.Match - * - * Represents a Url match found in an input string which should be Autolinked. - * - * See this class's superclass ({@link Autolinker.match.Match}) for more details. - */ -Autolinker.match.Url = Autolinker.Util.extend( Autolinker.match.Match, { - - /** - * @cfg {String} url (required) - * - * The url that was matched. - */ - - /** - * @cfg {Boolean} protocolUrlMatch (required) - * - * `true` if the URL is a match which already has a protocol (i.e. 'http://'), `false` if the match was from a 'www' or - * known TLD match. - */ - - /** - * @cfg {Boolean} protocolRelativeMatch (required) - * - * `true` if the URL is a protocol-relative match. A protocol-relative match is a URL that starts with '//', - * and will be either http:// or https:// based on the protocol that the site is loaded under. - */ - - /** - * @cfg {Boolean} stripPrefix (required) - * @inheritdoc Autolinker#stripPrefix - */ - - - /** - * @private - * @property {RegExp} urlPrefixRegex - * - * A regular expression used to remove the 'http://' or 'https://' and/or the 'www.' from URLs. - */ - urlPrefixRegex: /^(https?:\/\/)?(www\.)?/i, - - /** - * @private - * @property {RegExp} protocolRelativeRegex - * - * The regular expression used to remove the protocol-relative '//' from the {@link #url} string, for purposes - * of {@link #getAnchorText}. A protocol-relative URL is, for example, "//yahoo.com" - */ - protocolRelativeRegex : /^\/\//, - - /** - * @private - * @property {Boolean} protocolPrepended - * - * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the - * {@link #url} did not have a protocol) - */ - protocolPrepended : false, - - - /** - * Returns a string name for the type of match that this class represents. - * - * @return {String} - */ - getType : function() { - return 'url'; - }, - - - /** - * Returns the url that was matched, assuming the protocol to be 'http://' if the original - * match was missing a protocol. - * - * @return {String} - */ - getUrl : function() { - var url = this.url; - - // if the url string doesn't begin with a protocol, assume 'http://' - if( !this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended ) { - url = this.url = 'http://' + url; - - this.protocolPrepended = true; - } - - return url; - }, - - - /** - * Returns the anchor href that should be generated for the match. - * - * @return {String} - */ - getAnchorHref : function() { - var url = this.getUrl(); - - return url.replace( /&/g, '&' ); // any &'s in the URL should be converted back to '&' if they were displayed as & in the source html - }, - - - /** - * Returns the anchor text that should be generated for the match. - * - * @return {String} - */ - getAnchorText : function() { - var anchorText = this.getUrl(); - - if( this.protocolRelativeMatch ) { - // Strip off any protocol-relative '//' from the anchor text - anchorText = this.stripProtocolRelativePrefix( anchorText ); - } - if( this.stripPrefix ) { - anchorText = this.stripUrlPrefix( anchorText ); - } - anchorText = this.removeTrailingSlash( anchorText ); // remove trailing slash, if there is one - - return anchorText; - }, - - - // --------------------------------------- - - // Utility Functionality - - /** - * Strips the URL prefix (such as "http://" or "https://") from the given text. - * - * @private - * @param {String} text The text of the anchor that is being generated, for which to strip off the - * url prefix (such as stripping off "http://") - * @return {String} The `anchorText`, with the prefix stripped. - */ - stripUrlPrefix : function( text ) { - return text.replace( this.urlPrefixRegex, '' ); - }, - - - /** - * Strips any protocol-relative '//' from the anchor text. - * - * @private - * @param {String} text The text of the anchor that is being generated, for which to strip off the - * protocol-relative prefix (such as stripping off "//") - * @return {String} The `anchorText`, with the protocol-relative prefix stripped. - */ - stripProtocolRelativePrefix : function( text ) { - return text.replace( this.protocolRelativeRegex, '' ); - }, - - - /** - * Removes any trailing slash from the given `anchorText`, in preparation for the text to be displayed. - * - * @private - * @param {String} anchorText The text of the anchor that is being generated, for which to remove any trailing - * slash ('/') that may exist. - * @return {String} The `anchorText`, with the trailing slash removed. - */ - removeTrailingSlash : function( anchorText ) { - if( anchorText.charAt( anchorText.length - 1 ) === '/' ) { - anchorText = anchorText.slice( 0, -1 ); - } - return anchorText; - } - -} ); -return Autolinker; - -})); diff --git a/app/assets/javascripts/src/JIT.js.erb b/app/assets/javascripts/src/JIT.js similarity index 99% rename from app/assets/javascripts/src/JIT.js.erb rename to app/assets/javascripts/src/JIT.js index 2cb202dc..4754871e 100644 --- a/app/assets/javascripts/src/JIT.js.erb +++ b/app/assets/javascripts/src/JIT.js @@ -3232,7 +3232,7 @@ var Canvas; ctx = base.getCtx(), scale = base.scaleOffsetX; //var pattern = new Image(); - //pattern.src = "<%= asset_path('cubes.png') %>"; + //pattern.src = Metamaps.Erb['cubes.png'] //var ptrn = ctx.createPattern(pattern, 'repeat'); //ctx.fillStyle = ptrn; ctx.fillStyle = Metamaps.Settings.colors.background; diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index 0fe5a224..ae9e9293 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -1,4 +1,6 @@ -/* global Metamaps */ +/* global Metamaps, $jit */ + +const $jit = $jit || {} import _ from 'lodash' diff --git a/frontend/src/Metamaps/Views/ChatView.js b/frontend/src/Metamaps/Views/ChatView.js index cdcda4e5..a49aaa4d 100644 --- a/frontend/src/Metamaps/Views/ChatView.js +++ b/frontend/src/Metamaps/Views/ChatView.js @@ -1,10 +1,11 @@ -/* global Autolinker, $ */ +/* global $ */ import Backbone from 'backbone' +import Autolinker from 'autolinker' // TODO is this line good or bad // Backbone.$ = window.$ -var linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false }); +const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false }); var Private = { messageHTML: "
              " + diff --git a/frontend/test/Metamaps.Import.spec.js b/frontend/test/Metamaps.Import.spec.js index 68946bea..ae482c46 100644 --- a/frontend/test/Metamaps.Import.spec.js +++ b/frontend/test/Metamaps.Import.spec.js @@ -1,7 +1,11 @@ /* global describe, it */ import chai from 'chai' -import Import from '../src/Metamaps/Import' + +// JIT needs window.$jit +require('../../app/assets/javascripts/src/JIT.js') + +const Import = require('../src/Metamaps/Import') const { expect } = chai diff --git a/package.json b/package.json index 925323ac..d15d248e 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ }, "homepage": "https://github.com/metamaps/metamaps#readme", "dependencies": { + "autolinker": "^0.17.1", "babel-cli": "^6.11.4", "babel-loader": "^6.2.4", "babel-plugin-transform-class-properties": "^6.11.5", @@ -27,6 +28,7 @@ "chai": "^3.5.0", "jquery": "1.12.1", "mocha": "^3.0.2", + "mocha-jsdom": "^1.1.0", "node-uuid": "1.2.0", "react": "^15.3.0", "react-dom": "^15.3.0", From 700119cc9efdfd887a4fefe758c2e3eb931a9341 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Thu, 22 Sep 2016 23:04:46 -0400 Subject: [PATCH 23/26] opts can be undefined and throw error --- Gemfile.lock | 3 --- frontend/src/Metamaps/TopicCard.js | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index c2fd0d28..79638ae7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -332,8 +332,5 @@ DEPENDENCIES uglifier uservoice-ruby -RUBY VERSION - ruby 2.3.0p0 - BUNDLED WITH 1.12.5 diff --git a/frontend/src/Metamaps/TopicCard.js b/frontend/src/Metamaps/TopicCard.js index 7320d285..b92d7edd 100644 --- a/frontend/src/Metamaps/TopicCard.js +++ b/frontend/src/Metamaps/TopicCard.js @@ -40,7 +40,7 @@ const TopicCard = { */ showCard: function (node, opts) { var self = TopicCard - + if (!opts) opts = {} var topic = node.getData('topic') self.openTopicCard = topic From bda740491c532a907cba06750c4d50a2b3e9756f Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 11:47:40 +0800 Subject: [PATCH 24/26] moved JIT to npm. tests pass. whoop whoop --- app/assets/javascripts/application.js | 1 - frontend/src/Metamaps/JIT.js | 14 +++++++++----- frontend/src/Metamaps/Organize.js | 2 ++ frontend/src/Metamaps/Topic.js | 3 +++ frontend/src/Metamaps/Visualize.js | 2 ++ .../src => frontend/src/patched}/JIT.js | 12 ++++++------ frontend/test/Metamaps.Import.spec.js | 5 +---- 7 files changed, 23 insertions(+), 16 deletions(-) rename {app/assets/javascripts/src => frontend/src/patched}/JIT.js (99%) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 68f2179b..df086157 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,7 +14,6 @@ //= require jquery-ui //= require jquery_ujs //= require_directory ./lib -//= require ./src/JIT //= require ./src/Metamaps.Erb //= require ./webpacked/metamaps.bundle //= require ./src/check-canvas-support diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index ae9e9293..7145bf9c 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -1,9 +1,9 @@ /* global Metamaps, $jit */ -const $jit = $jit || {} - import _ from 'lodash' +import $jit from '../patched/JIT' + import Active from './Active' import Control from './Control' import Create from './Create' @@ -21,6 +21,7 @@ import TopicCard from './TopicCard' import Util from './Util' import Visualize from './Visualize' + /* * Metamaps.Erb * Metamaps.Mappings @@ -284,7 +285,8 @@ const JIT = { ForceDirected: { animateSavedLayout: { modes: ['linear'], - transition: $jit.Trans.Quad.easeInOut, + // TODO fix tests so we don't need _.get + transition: _.get($jit, 'Trans.Quad.easeInOut'), duration: 800, onComplete: function () { Visualize.mGraph.busy = false @@ -293,7 +295,8 @@ const JIT = { }, animateFDLayout: { modes: ['linear'], - transition: $jit.Trans.Elastic.easeOut, + // TODO fix tests so we don't need _.get + transition: _.get($jit, 'Trans.Elastic.easeOut'), duration: 800, onComplete: function () { Visualize.mGraph.busy = false @@ -554,7 +557,8 @@ const JIT = { ForceDirected3D: { animate: { modes: ['linear'], - transition: $jit.Trans.Elastic.easeOut, + // TODO fix tests so we don't need _.get + transition: _.get($jit, 'Trans.Elastic.easeOut'), duration: 2500, onComplete: function () { Visualize.mGraph.busy = false diff --git a/frontend/src/Metamaps/Organize.js b/frontend/src/Metamaps/Organize.js index c05f870e..ed005d39 100644 --- a/frontend/src/Metamaps/Organize.js +++ b/frontend/src/Metamaps/Organize.js @@ -2,6 +2,8 @@ import _ from 'lodash' +import $jit from '../patched/JIT' + import Visualize from './Visualize' import JIT from './JIT' diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index 412f7ef2..3e8743b6 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -1,5 +1,7 @@ /* global Metamaps, $ */ +import $jit from '../patched/JIT' + import Active from './Active' import AutoLayout from './AutoLayout' import Create from './Create' @@ -15,6 +17,7 @@ import TopicCard from './TopicCard' import Util from './Util' import Visualize from './Visualize' + /* * Metamaps.Topic.js.erb * diff --git a/frontend/src/Metamaps/Visualize.js b/frontend/src/Metamaps/Visualize.js index 047cb81d..df5bab99 100644 --- a/frontend/src/Metamaps/Visualize.js +++ b/frontend/src/Metamaps/Visualize.js @@ -2,6 +2,8 @@ import _ from 'lodash' +import $jit from '../patched/JIT' + import Active from './Active' import JIT from './JIT' import Router from './Router' diff --git a/app/assets/javascripts/src/JIT.js b/frontend/src/patched/JIT.js similarity index 99% rename from app/assets/javascripts/src/JIT.js rename to frontend/src/patched/JIT.js index 4754871e..7814ecbe 100644 --- a/app/assets/javascripts/src/JIT.js +++ b/frontend/src/patched/JIT.js @@ -20,7 +20,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - (function () { /* File: Core.js @@ -34,7 +33,11 @@ THE SOFTWARE. This variable is the *only* global variable defined in the Toolkit. There are also other interesting properties attached to this variable described below. */ -window.$jit = function(w) { +// START METAMAPS CODE +const $jit = function(w) { +// ORIGINAL: +// window.$jit = function(w) { +// END METAMAPS CODE w = w || window; for(var k in $jit) { if($jit[k].$extend) { @@ -11312,7 +11315,4 @@ $jit.ForceDirected3D.$extend = true; })($jit.ForceDirected3D); - - - - })(); +export default $jit diff --git a/frontend/test/Metamaps.Import.spec.js b/frontend/test/Metamaps.Import.spec.js index ae482c46..c8ee33b1 100644 --- a/frontend/test/Metamaps.Import.spec.js +++ b/frontend/test/Metamaps.Import.spec.js @@ -2,10 +2,7 @@ import chai from 'chai' -// JIT needs window.$jit -require('../../app/assets/javascripts/src/JIT.js') - -const Import = require('../src/Metamaps/Import') +import Import from '../src/Metamaps/Import' const { expect } = chai From e65a5e2d1c6dc05f3703b9cf2bd7d6fa6a09d0a6 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 12:00:47 +0800 Subject: [PATCH 25/26] whoops, reenable travis npm test --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 99c917c7..d607a7a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,4 +18,4 @@ before_script: - nvm use stable - npm install script: - - bundle exec rspec && bundle exec brakeman -q -z || npm test + - bundle exec rspec && bundle exec brakeman -q -z && npm test From 6f91ce5ff52fb622a154e9fb6c2cfbab15ee4df4 Mon Sep 17 00:00:00 2001 From: Devin Howard Date: Fri, 23 Sep 2016 14:12:27 +0800 Subject: [PATCH 26/26] fix a few more errors --- frontend/src/Metamaps/JIT.js | 4 ++-- frontend/src/Metamaps/Map/InfoBox.js | 1 + frontend/src/Metamaps/Topic.js | 2 +- frontend/src/Metamaps/TopicCard.js | 24 ++++++++---------------- frontend/src/patched/JIT.js | 24 +++++++++++++++++++----- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/frontend/src/Metamaps/JIT.js b/frontend/src/Metamaps/JIT.js index 7145bf9c..5eccbc6c 100644 --- a/frontend/src/Metamaps/JIT.js +++ b/frontend/src/Metamaps/JIT.js @@ -99,11 +99,11 @@ const JIT = { synapsesToRemove.push(s) } else if (nodes[edge.nodeFrom] && nodes[edge.nodeTo]) { - existingEdge = _.findWhere(edges, { + existingEdge = _.find(edges, { nodeFrom: edge.nodeFrom, nodeTo: edge.nodeTo }) || - _.findWhere(edges, { + _.find(edges, { nodeFrom: edge.nodeTo, nodeTo: edge.nodeFrom }) diff --git a/frontend/src/Metamaps/Map/InfoBox.js b/frontend/src/Metamaps/Map/InfoBox.js index a2cc5de2..ec5c1405 100644 --- a/frontend/src/Metamaps/Map/InfoBox.js +++ b/frontend/src/Metamaps/Map/InfoBox.js @@ -3,6 +3,7 @@ import Active from '../Active' import GlobalUI from '../GlobalUI' import Router from '../Router' +import Util from '../Util' /* * Metamaps.Collaborators diff --git a/frontend/src/Metamaps/Topic.js b/frontend/src/Metamaps/Topic.js index 3e8743b6..c2f3ff29 100644 --- a/frontend/src/Metamaps/Topic.js +++ b/frontend/src/Metamaps/Topic.js @@ -191,7 +191,7 @@ const Topic = { // opts is additional options in a hash // TODO: move createNewInDB and permitCerateSYnapseAfter into opts - renderTopic: function (mapping, topic, createNewInDB, permitCreateSynapseAfter, opts) { + renderTopic: function (mapping, topic, createNewInDB, permitCreateSynapseAfter, opts = {}) { var self = Topic var nodeOnViz, tempPos diff --git a/frontend/src/Metamaps/TopicCard.js b/frontend/src/Metamaps/TopicCard.js index b92d7edd..dad58565 100644 --- a/frontend/src/Metamaps/TopicCard.js +++ b/frontend/src/Metamaps/TopicCard.js @@ -187,17 +187,9 @@ const TopicCard = { } var openMetacodeSelect = function (event) { - var windowWidth - var showcardLeft var TOPICCARD_WIDTH = 300 var METACODESELECT_WIDTH = 404 - var distanceFromEdge - var MAX_METACODELIST_HEIGHT = 270 - var windowHeight - var showcardTop - var topicTitleHeight - var distanceFromBottom if (!selectingMetacode) { selectingMetacode = true @@ -206,9 +198,9 @@ const TopicCard = { // select is accessible onscreen, when opened // while topic card is close to the right // edge of the screen - windowWidth = $(window).width() - showcardLeft = parseInt($('.showcard').css('left')) - distanceFromEdge = windowWidth - (showcardLeft + TOPICCARD_WIDTH) + var windowWidth = $(window).width() + var showcardLeft = parseInt($('.showcard').css('left')) + var distanceFromEdge = windowWidth - (showcardLeft + TOPICCARD_WIDTH) if (distanceFromEdge < METACODESELECT_WIDTH) { $('.metacodeSelect').addClass('onRightEdge') } @@ -217,11 +209,11 @@ const TopicCard = { // select is accessible onscreen, when opened // while topic card is close to the bottom // edge of the screen - windowHeight = $(window).height() - showcardTop = parseInt($('.showcard').css('top')) - topicTitleHeight = $('.showcard .title').height() + parseInt($('.showcard .title').css('padding-top')) + parseInt($('.showcard .title').css('padding-bottom')) - heightOfSetList = $('.showcard .metacodeSelect').height() - distanceFromBottom = windowHeight - (showcardTop + topicTitleHeight) + var windowHeight = $(window).height() + var showcardTop = parseInt($('.showcard').css('top')) + var topicTitleHeight = $('.showcard .title').height() + parseInt($('.showcard .title').css('padding-top')) + parseInt($('.showcard .title').css('padding-bottom')) + var heightOfSetList = $('.showcard .metacodeSelect').height() + var distanceFromBottom = windowHeight - (showcardTop + topicTitleHeight) if (distanceFromBottom < MAX_METACODELIST_HEIGHT) { $('.metacodeSelect').addClass('onBottomEdge') } diff --git a/frontend/src/patched/JIT.js b/frontend/src/patched/JIT.js index 7814ecbe..af7311be 100644 --- a/frontend/src/patched/JIT.js +++ b/frontend/src/patched/JIT.js @@ -3125,9 +3125,15 @@ var Canvas; }; }, translateToCenter: function(ps) { - var size = this.getSize(), - width = ps? (size.width - ps.width - this.translateOffsetX*2) : size.width; - height = ps? (size.height - ps.height - this.translateOffsetY*2) : size.height; + // START METAMAPS CODE + var size = this.getSize(); + var width = ps ? (size.width - ps.width - this.translateOffsetX*2) : size.width; + var height = ps ? (size.height - ps.height - this.translateOffsetY*2) : size.height; + // ORIGINAL CODE + // var size = this.getSize(), + // width = ps? (size.width - ps.width - this.translateOffsetX*2) : size.width; + // height = ps? (size.height - ps.height - this.translateOffsetY*2) : size.height; + // END METAMAPS CODE var ctx = this.getCtx(); ps && ctx.scale(1/this.scaleOffsetX, 1/this.scaleOffsetY); ctx.translate(width/2, height/2); @@ -5637,7 +5643,11 @@ Graph.Op = { break; case 'fade:seq': case 'fade': case 'fade:con': - that = this; + // START METAMAPS CODE + var that = this; + // ORIGINAL CODE: + // that = this; + // END METAMAPS CODE graph = viz.construct(json); //set alpha to 0 for nodes to add. @@ -5773,7 +5783,11 @@ Graph.Op = { break; case 'fade:seq': case 'fade': case 'fade:con': - that = this; + // START METAMAPS CODE + var that = this; + // ORIGINAL CODE: + // that = this; + // END METAMAPS CODE graph = viz.construct(json); //preprocessing for nodes to delete. //get node property modes to interpolate