diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 6ed8278d..14f565fa 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -43,5 +43,7 @@ //= 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.Import.js b/app/assets/javascripts/src/Metamaps.Import.js index d7771988..7ebadb37 100644 --- a/app/assets/javascripts/src/Metamaps.Import.js +++ b/app/assets/javascripts/src/Metamaps.Import.js @@ -6,7 +6,6 @@ * Dependencies: * - Metamaps.Active * - Metamaps.Backbone - * - Metamaps.Famous // TODO remove dependency * - Metamaps.Map * - Metamaps.Mappings * - Metamaps.Metacodes @@ -24,38 +23,30 @@ Metamaps.Import = { ], cidMappings: {}, // to be filled by import_id => cid mappings - init: function () { + handleTSV: function (text) { var self = Metamaps.Import + results = self.parseTabbedString(text) + self.handle(results) + }, - $('body').bind('paste', function (e) { - if (e.target.tagName === 'INPUT') return - if (e.target.tagName === 'TEXTAREA') return + handleJSON: function (text) { + var self = Metamaps.Import + results = JSON.parse(text) + self.handle(results) + }, - var text = e.originalEvent.clipboardData.getData('text/plain') + handle: function(results) { + var self = Metamaps.Import + var topics = results.topics + var synapses = results.synapses - var results - if (text.trimLeft()[0] === '{') { - try { - results = JSON.parse(text) - } catch (e) { - results = false - } - } else { - results = self.parseTabbedString(text) - } - if (results === false) return - - var topics = results.topics - var synapses = results.synapses - - if (topics.length > 0 || synapses.length > 0) { - if (window.confirm('Are you sure you want to create ' + topics.length + - ' new topics and ' + synapses.length + ' new synapses?')) { - self.importTopics(topics) - self.importSynapses(synapses) - } // if + if (topics.length > 0 || synapses.length > 0) { + if (window.confirm('Are you sure you want to create ' + topics.length + + ' new topics and ' + synapses.length + ' new synapses?')) { + self.importTopics(topics) + self.importSynapses(synapses) } // if - }) + } // if }, abort: function (message) { @@ -272,15 +263,22 @@ Metamaps.Import = { 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 = new Metamaps.Backbone.Topic({ name: name, metacode_id: metacode.id, - permission: permission || Metamaps.Active.Map.get('permission'), - desc: desc || "", - link: link + permission: topic_permission, + defer_to_map_id: defer_to_map_id, + desc: desc || "" }) + topic.set('desc', desc || '') // TODO why is this necessary? + topic.set('link', link) // TODO why is this necessary? Metamaps.Topics.add(topic) - self.cidMappings[import_id] = topic.cid + + if (import_id !== null && import_id !== undefined) { + self.cidMappings[import_id] = topic.cid + } var mapping = new Metamaps.Backbone.Mapping({ xloc: xloc, @@ -293,7 +291,7 @@ Metamaps.Import = { // this function also includes the creation of the topic in the database Metamaps.Topic.renderTopic(mapping, topic, true, true) - Metamaps.Famous.viz.hideInstructions() + Metamaps.GlobalUI.hideDiv('#instructions') }, createSynapseWithParameters: function (desc, category, permission, diff --git a/app/assets/javascripts/src/Metamaps.PasteInput.js b/app/assets/javascripts/src/Metamaps.PasteInput.js new file mode 100644 index 00000000..1b89b0af --- /dev/null +++ b/app/assets/javascripts/src/Metamaps.PasteInput.js @@ -0,0 +1,120 @@ +/* global Metamaps, $ */ + +/* + * Metamaps.PasteInput.js.erb + * + * Dependencies: + * - Metamaps.Import + * - Metamaps.AutoLayout + */ + +Metamaps.PasteInput = { + init: function () { + var self = Metamaps.PasteInput + + // intercept dragged files + // see http://stackoverflow.com/questions/6756583 + window.addEventListener("dragover", function(e){ + e = e || event; + e.preventDefault(); + }, false); + window.addEventListener("drop", function(e){ + e = e || event; + e.preventDefault(); + var coords = Metamaps.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]) + fileReader.onload = function(e) { + var text = e.currentTarget.result + if (text.substring(0,5) === '(.*)<\/string>[\s\S]*/m, '$1') + } + self.handle(text, coords) + } + } + }, false); + + // allow pasting onto canvas (but don't break existing inputs/textareas) + $('body').bind('paste', function (e) { + if (e.target.tagName === 'INPUT') return + if (e.target.tagName === 'TEXTAREA') return + + var text = e.originalEvent.clipboardData.getData('text/plain').trim() + self.handle(text) + }) + }, + + handle: function(text, coords) { + var self = Metamaps.PasteInput + // thanks to https://github.com/kevva/url-regex + const 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"]*)?$') + + if (text.match(URL_REGEX)) { + self.handleURL(text, coords) + } else if (text[0] === '{') { + self.handleJSON(text) + } else if (text.match(/\t/)) { + self.handleTSV(text) + } else { + // fail silently + } + }, + + handleURL: function (text, coords) { + var title = 'Link' + if (!coords || !coords.x || !coords.y) { + coords = Metamaps.AutoLayout.getNextCoord() + } + + var import_id = null // don't store a cidMapping + var permission = null // use default + + // try { + // // fetch title in 150ms or less + // Promise.race([ + // new Promise(function(resolve, reject) { + // fetch(text).then(function(response) { + // return response.text() + // }).then(function(html) { + // title = html.replace(/[\s\S]*(.*)<\/title>[\s\S]*/m, '$1') + // resolve() + // }) + // }), new Promise(function(resolve, reject) { + // window.setTimeout(function() { + // resolve() + // }, 150) + // }) + // ]).then(function() { + // finish() + // }).catch(function(error) { + // throw error + // }) + // } catch (err) { + // console.warn("Your browser can't fetch the title") // TODO move to webpack to avoid this error + // } + finish() + + function finish() { + Metamaps.Import.createTopicWithParameters( + title, + 'Reference', // metacode - todo fix + permission, + text, // desc - todo load from url? + text, // link - todo fix because this isn't being POSTed + coords.x, + coords.y, + import_id + ) + } + }, + + handleJSON: function (text) { + Metamaps.Import.handleJSON(text) + }, + + handleTSV: function (text) { + Metamaps.Import.handleTSV(text) + } +}