diff --git a/article/nodes/composite/composite_view.js b/article/nodes/composite/composite_view.js index 9fbb9ee..cb4cb8d 100644 --- a/article/nodes/composite/composite_view.js +++ b/article/nodes/composite/composite_view.js @@ -16,6 +16,10 @@ CompositeView.Prototype = function() { // ============================= // + // Render Markup + // -------- + // + this.render = function() { NodeView.prototype.render.call(this); diff --git a/article/nodes/cover/cover_view.js b/article/nodes/cover/cover_view.js index 5b82e08..a099bb9 100644 --- a/article/nodes/cover/cover_view.js +++ b/article/nodes/cover/cover_view.js @@ -14,6 +14,7 @@ var CoverView = function(node, viewFactory) { CoverView.Prototype = function() { + // Render it // -------- // @@ -85,7 +86,6 @@ CoverView.Prototype = function() { if (pubInfo) { var pubDate = pubInfo.published_on; - console.log("pubDate",pubDate); var articleType = pubInfo.article_type; if (pubDate) { var items = [articleUtil.formatDate(pubDate)]; diff --git a/article/nodes/footnote/footnote.css b/article/nodes/footnote/footnote.css index 2099440..3ff4242 100644 --- a/article/nodes/footnote/footnote.css +++ b/article/nodes/footnote/footnote.css @@ -28,4 +28,14 @@ Footnotes .lens-article .content-node.footnote .content .footnote-urls .url { padding-right: 20px; +} + +.lens-article .content-node.footnote .content .table { + + border-collapse: collapse; + width: 100%; +} +.lens-article .content-node.footnote .content .table th, td { + padding: 1px; + } \ No newline at end of file diff --git a/article/nodes/footnote/footnote_view.js b/article/nodes/footnote/footnote_view.js index 5466339..b694054 100644 --- a/article/nodes/footnote/footnote_view.js +++ b/article/nodes/footnote/footnote_view.js @@ -5,7 +5,7 @@ var $$ = require("../../../substance/application").$$; var NodeView = require("../node").View; var ResourceView = require('../../resource_view'); var util = require("../../../substance/util"); -var TableView = require('../table/table_view'); + // Lens.Citation.View @@ -93,9 +93,9 @@ CitationView.Prototype = function () { if (children[0]) { var table = document.createElement('table'); table.innerHTML =children[0].innerHTML; - div.appendChild(table); + table.className="table"; + frag.appendChild(table); - //div.appendChild(children[0]); } } diff --git a/article/nodes/html_table/html_table.js b/article/nodes/html_table/html_table.js new file mode 100644 index 0000000..b485c2c --- /dev/null +++ b/article/nodes/html_table/html_table.js @@ -0,0 +1,84 @@ +var _ = require('underscore'); +var Document = require('../../../substance/document'); + +// Lens.HTMLTable +// ----------------- +// + +var HTMLTable = function(node, doc) { + Document.Node.call(this, node, doc); +}; + +// Type definition +// ----------------- +// + +HTMLTable.type = { + "id": "html_table", + "parent": "content", + "properties": { + "source_id": "string", + "label": "string", + "content": "string", + "footers": ["array", "string"], + "caption": "caption" + } +}; + +HTMLTable.config = { + "zoomable": true +}; + + +// This is used for the auto-generated docs +// ----------------- +// + +HTMLTable.description = { + "name": "HTMLTable", + "remarks": [ + "A table figure which is expressed in HTML notation" + ], + "properties": { + "source_id": "string", + "label": "Label shown in the resource header.", + "title": "Full table title", + "content": "HTML data", + "footers": "HTMLTable footers expressed as an array strings", + "caption": "References a caption node, that has all the content" + } +}; + + +// Example HTMLTable +// ----------------- +// + +HTMLTable.example = { + "id": "html_table_1", + "type": "html_table", + "label": "HTMLTable 1.", + "title": "Lorem ipsum table", + "content": "...
", + "footers": [], + "caption": "caption_1" +}; + +HTMLTable.Prototype = function() { + + this.getCaption = function() { + if (this.properties.caption) return this.document.get(this.properties.caption); + }; + + this.getHeader = function() { + return this.properties.label; + }; +}; + +HTMLTable.Prototype.prototype = Document.Node.prototype; +HTMLTable.prototype = new HTMLTable.Prototype(); +HTMLTable.prototype.constructor = HTMLTable; + +Document.Node.defineProperties(HTMLTable); + +module.exports = HTMLTable; diff --git a/article/nodes/html_table/html_table_view.js b/article/nodes/html_table/html_table_view.js new file mode 100644 index 0000000..9ad5d97 --- /dev/null +++ b/article/nodes/html_table/html_table_view.js @@ -0,0 +1,64 @@ +"use strict"; + +var _ = require("underscore"); +var NodeView = require("../node").View; +var $$ = require("../../../substance/application").$$; +var ResourceView = require('../../resource_view'); + +// Substance.Paragraph.View +// ========================================================================== + +var HTMLTableView = function(node, viewFactory, options) { + NodeView.call(this, node, viewFactory); + + // Mix-in + ResourceView.call(this, options); + +}; + +HTMLTableView.Prototype = function() { + + // Mix-in + _.extend(this, ResourceView.prototype); + + this.isZoomable = true; + + this.renderBody = function() { + + // The actual content + // -------- + // + + var tableWrapper = $$('.table-wrapper', { + html: this.node.content // HTML table content + }); + + this.content.appendChild(tableWrapper); + + // Display footers (optional) + // -------- + // + + var footers = $$('.footers', { + children: _.map(this.node.footers, function(footer) { + return $$('.footer', { html: ""+footer.label+" " + footer.content }); + }) + }); + + // Display caption + + + if (this.node.caption) { + var captionView = this.createView(this.node.caption); + this.content.appendChild(captionView.render().el); + } + + this.content.appendChild(footers); + }; + +}; + +HTMLTableView.Prototype.prototype = NodeView.prototype; +HTMLTableView.prototype = new HTMLTableView.Prototype(); + +module.exports = HTMLTableView; diff --git a/article/nodes/html_table/index.js b/article/nodes/html_table/index.js new file mode 100644 index 0000000..2537ae6 --- /dev/null +++ b/article/nodes/html_table/index.js @@ -0,0 +1,6 @@ +"use strict"; + +module.exports = { + Model: require('./html_table'), + View: require('./html_table_view') +}; diff --git a/article/nodes/paragraph/paragraph.css b/article/nodes/paragraph/paragraph.css index 48dbb07..5a7ce9e 100644 --- a/article/nodes/paragraph/paragraph.css +++ b/article/nodes/paragraph/paragraph.css @@ -57,6 +57,12 @@ margin-right: 2ex; } +.content-node.paragraph.margin-left-2 { + margin-left: 4ex; } + +.content-node.paragraph.margin-right-2 { + margin-right: 4ex; } + .content-node.paragraph.centered { text-align: center; } @@ -214,3 +220,17 @@ display: block !important; line-height: 28px !important; } + +/*** Abstand zw. zwei aufeinanderfolgenden Paragrafen im Fließtext sowie Unterdrückung dieses Abstands für

innerhalb von Tabellen und Zitaten 7.12.18 voe***/ +.content-node.paragraph + .content-node.paragraph { + margin-top: 0.7em; + } + +td > .content-node.paragraph + .content-node.paragraph { + margin-top: 0; + } +/*.quote > .content .content-node.paragraph + .quote > .content .content-node.paragraph*/ +.quote > .content > .paragraph + .paragraph { + margin-top: 0 !important; + } + diff --git a/article/nodes/quote/quote.css b/article/nodes/quote/quote.css index 0ff271d..33e6248 100644 --- a/article/nodes/quote/quote.css +++ b/article/nodes/quote/quote.css @@ -5,8 +5,8 @@ } .document .content-node.quote .content-node.paragraph { - padding: 10px 40px 10px 40px; - border-left: 3px solid #ccc; + padding: 0px 20px 0px 20px; + /*border-left: 3px solid #ccc; doppelte Ausgabe von Rändern bei Zitaten in Stille, Scholz ... 416/416-69-83162-1-10-20181203.xml*/ } .surface.content .content-node.quote { diff --git a/article/nodes/table/table.css b/article/nodes/table/table.css index 84b3cf8..4caae3a 100644 --- a/article/nodes/table/table.css +++ b/article/nodes/table/table.css @@ -1,122 +1,51 @@ -.lens-article .content-node.html-table > .content { - padding: 20px; -} -.lens-article .content-node.html-table > .content img { - width: 100%; -} - -.lens-article .content-node.html-table .table-wrapper { - width: 100%; - overflow: auto; -} - -.lens-article .content-node.html-table .caption { - padding-top: 20px; -} - -.lens-article .content-node.html-table table { - position: relative; - border-collapse: collapse; - border-spacing: 0; - margin-bottom: 20px; - margin: 0 auto; - width: 100%; -} - -.lens-article .content-node.html-table thead tr { - background: #eee; -} - -.lens-article .content-node.html-table thead td { - font-weight: bold; -} - -/* Table sub tags */ -.lens-article .content-node.html-table table sub { - vertical-align: baseline; - position: relative; - top: 0.4em; - font-size: 11px; -} - -.lens-article .content-node.html-table table td { - padding: 5px; - /**font-size: 12px;**/ - border: 0px solid lightgrey; - /* Enable white-space: nowrap; if author controls wrapping (
in HTML) - /* white-space: nowrap; */ -} - -.lens-article .content-node.html-table .footers { +.lens-article .content-node.table .footers { padding: 0 20px; padding-top: 10px; font-size: 12px; - background: #fff; -} + background: #fff; } /** Formatierung der Klasse "layout-tabelle" - Layout-Tabelle - , die nur zur Anordnung von Elementen verwendet wird **/ -.lens-article .content-node.html-table .layout-tabelle { +.layout-tabelle { border: 0; width: auto; - margin-left: 0; -} + margin-left: 0; } -.lens-article .content-node.html-table .layout-tabelle td { +.layout-tabelle td { border: 0; font-size: 1em; - padding: 3px; -} + padding: 3px; } /** Formatierung der Klasse "gitter-tabelle" - Gitter-Tabelle **/ -.lens-article .content-node.html-table .gitter-tabelle { +.gitter-tabelle { border: 1px solid lightgray; border-collapse: collapse; width: auto; - margin-left: 0; -} + margin-left: 0; } -.lens-article .content-node.html-table .gitter-tabelle td { +.gitter-tabelle td { border: 1px solid lightgray; border-collapse: collapse; - padding: 3px; -} - - + padding: 3px; } /** Layout Daten-Tabelle Issue Nr. 58 - für heiUP auskommentiert, um mehrspaltigen Satz ohne Färbung zu ermöglichen, To do: HTML/CSS-Konstruktion für mehrspaltigen Satz - 09.03. voe - neues default ist layout-tabelle, deshalb testweise wieder einkommentiert - 07.08. voe**/ - -.lens-article .content-node.html-table > .content { /* Wie wirkt sich diese klassenunabhängige Anweisung aus? Test! 07.08.. - wenn bis 07.11. keine Verschiebungen bekannt werden, kann Hinweis entfernt werden.*/ - padding-left: 0; -} + für heiUP auskommentiert, um mehrspaltigen Satz ohne Färbung zu ermöglichen, - neues default ist layout-tabelle, deshalb testweise wieder einkommentiert - 07.08. voe**/ +.lens-article .content-node.table > .content { + padding-left: 0; } -.lens-article .content-node.html-table .daten-tabelle { +.daten-tabelle { border: 1px solid #f8f8f8; - overflow-x: scroll; -} + overflow-x: scroll; } -.lens-article .content-node.html-table .daten-tabelle tr { - vertical-align: top; -} +.daten-tabelle tr { + vertical-align: top; } -.lens-article .content-node.html-table .daten-tabelle tr:nth-child(odd) { - background-color: #f8f8f8; -} +.daten-tabelle tr:nth-child(odd) { + background-color: #f8f8f8; } -.lens-article .content-node.html-table .daten-tabelle tr:nth-child(odd) td:empty { - background-color: #f8f8f8; -} +.daten-tabelle tr:nth-child(odd) td:empty { + background-color: #f8f8f8; } - -.lens-article .content-node.html-table .daten-tabelle td { +.daten-tabelle td { border-right: 1px solid #f8f8f8; - padding: 10px; -} -.lens-article .content-node.html-table table td { - font-size: 0.75em; - line-height: 1.7em; -} - - - + padding: 10px; } \ No newline at end of file diff --git a/article/nodes/text/text.css b/article/nodes/text/text.css index 53001c8..15d367e 100644 --- a/article/nodes/text/text.css +++ b/article/nodes/text/text.css @@ -21,4 +21,9 @@ .content-node.text.title { padding-left: 0; -} \ No newline at end of file +} + +/* Abstract */ +.abstract { + margin-bottom: 2.7em; +} diff --git a/article/resource_view.js b/article/resource_view.js index eafa5c2..fb8b5b7 100644 --- a/article/resource_view.js +++ b/article/resource_view.js @@ -51,7 +51,7 @@ ResourceView.Prototype = function() { } togglesEl.appendChild($$('a.toggle-res.toggle.action-toggle-resource', { "href": "#", - "html": " "+locales.Focus + "html": " Focus" })); headerEl.appendChild(togglesEl); diff --git a/converter/lens_converter.js b/converter/lens_converter.js index 87d673e..3ddc92b 100644 --- a/converter/lens_converter.js +++ b/converter/lens_converter.js @@ -1,13 +1,17 @@ "use strict"; + var _ = require("underscore"); var util = require("../substance/util"); var errors = util.errors; var ImporterError = errors.define("ImporterError"); var Article = require("../article"); -var NlmToLensConverter = function (options) { + +var NlmToLensConverter = function(options) { this.options = options || NlmToLensConverter.DefaultOptions; }; -NlmToLensConverter.Prototype = function () { + +NlmToLensConverter.Prototype = function() { + this._annotationTypes = { "bold": "strong", "italic": "emphasis", @@ -24,6 +28,7 @@ NlmToLensConverter.Prototype = function () { "inline-formula": "inline-formula", "uri": "link" }; + // mapping from xref.refType to node type this._refTypeMapping = { "bibr": "citation_reference", @@ -34,6 +39,7 @@ NlmToLensConverter.Prototype = function () { "other": "figure_reference", "list": "definition_reference", }; + // mapping of contrib type to human readable names // Can be overriden in specialized converter this._contribTypeMapping = { @@ -66,45 +72,56 @@ NlmToLensConverter.Prototype = function () { "section-editor": "Section Editor", "section-author": "Section Author" }; - this.isAnnotation = function (type) { + + this.isAnnotation = function(type) { return this._annotationTypes[type] !== undefined; }; - this.isParagraphish = function (node) { + + this.isParagraphish = function(node) { for (var i = 0; i < node.childNodes.length; i++) { var el = node.childNodes[i]; if (el.nodeType !== Node.TEXT_NODE && !this.isAnnotation(el.tagName.toLowerCase())) return false; } return true; }; - this.test = function (xml, documentUrl) { + + this.test = function(xml, documentUrl) { /* jshint unused:false */ return true; }; + // Helpers // -------- - this.getName = function (nameEl) { + + this.getName = function(nameEl) { if (!nameEl) return "N/A"; var names = []; + var surnameEl = nameEl.querySelector("surname"); var givenNamesEl = nameEl.querySelector("given-names"); var suffix = nameEl.querySelector("suffix"); + if (givenNamesEl) names.push(givenNamesEl.textContent); if (surnameEl) names.push(surnameEl.textContent); if (suffix) return [names.join(" "), suffix.textContent].join(", "); + return names.join(" "); }; - this.toHtml = function (el) { + + this.toHtml = function(el) { if (!el) return ""; var tmp = document.createElement("DIV"); tmp.appendChild(el.cloneNode(true)); return tmp.innerHTML; }; - this.mmlToHtmlString = function (el) { + + this.mmlToHtmlString = function(el) { var html = this.toHtml(el); html = html.replace(/<(\/)?mml:([^>]+)>/g, "<$1$2>"); return html; }; - this.selectDirectChildren = function (scopeEl, selector) { + + this.selectDirectChildren = function(scopeEl, selector) { // Note: if the ':scope' pseudo class was supported by more browsers // it would be the correct selector based solution. // However, for now we do simple filtering. @@ -116,57 +133,74 @@ NlmToLensConverter.Prototype = function () { } return result; }; + // ### The main entry point for starting an import - this.import = function (input) { + + this.import = function(input) { var xmlDoc; + // Note: when we are using jqueries get(".xml") we // magically get a parsed XML document already if (_.isString(input)) { var parser = new DOMParser(); - xmlDoc = parser.parseFromString(input, "text/xml"); + xmlDoc = parser.parseFromString(input,"text/xml"); } else { xmlDoc = input; } + this.sanitizeXML(xmlDoc); + // Creating the output Document via factore, so that it is possible to // create specialized NLMImporter later which would want to instantiate // a specialized Document type var doc = this.createDocument(); + // For debug purposes window.doc = doc; + // A deliverable state which makes this importer stateless var state = this.createState(xmlDoc, doc); + // Note: all other methods are called corresponding return this.document(state, xmlDoc); }; + // Sometimes we need to deal with unconsistent XML // When overwriting this function in your custom converter // you can solve those issues in a preprocessing step instead of adding // hacks in the main converter code - this.sanitizeXML = function (xmlDoc) { + + this.sanitizeXML = function(xmlDoc) { /* jshint unused:false */ }; - this.createState = function (xmlDoc, doc) { + + this.createState = function(xmlDoc, doc) { return new NlmToLensConverter.State(this, xmlDoc, doc); }; + // Overridden to create a Lens Article instance - this.createDocument = function () { + this.createDocument = function() { + var doc = new Article(); return doc; }; - this.show = function (state, nodes) { - _.each(nodes, function (n) { + + this.show = function(state, nodes) { + _.each(nodes, function(n) { this.showNode(state, n); }, this); }; - this.extractDate = function (dateEl) { + + this.extractDate = function(dateEl) { if (!dateEl) return null; + var year = dateEl.querySelector("year"); var month = dateEl.querySelector("month"); var day = dateEl.querySelector("day"); var res = (year !== null ? [year.textContent] : []); if (month) res.push(month.textContent); if (day) res.push(day.textContent); + return res.join("-"); }; this.extractURLSuffix = function (url) { @@ -175,24 +209,31 @@ NlmToLensConverter.Prototype = function () { } this.extractPublicationInfo = function (state, article) { var doc = state.doc; + var articleMeta = article.querySelector("article-meta"); var pubDate = articleMeta.querySelector("pub-date"); var history = articleMeta.querySelectorAll("history date"); + // Journal title // var journalTitle = article.querySelector("journal-title"); + // DOI // // 10.7554/eLife.00003 var articleDOI = article.querySelector("article-id[pub-id-type=doi]"); + // Related article if exists // // TODO: can't there be more than one? var relatedArticle = article.querySelector("related-article"); + // Article information var articleInfo = this.extractArticleInfo(state, article); + // Create PublicationInfo node // --------------- + var pubInfoNode = { "id": "publication_info", "type": "publication_info", @@ -217,6 +258,7 @@ NlmToLensConverter.Prototype = function () { // TODO: this is in the schema, but seems to be unused "provider": "", }; + for (var i = 0; i < history.length; i++) { var dateEl = history[i]; var historyEntry = { @@ -225,18 +267,23 @@ NlmToLensConverter.Prototype = function () { }; pubInfoNode.history.push(historyEntry); } + doc.create(pubInfoNode); doc.show("info", pubInfoNode.id, 0); + this.enhancePublicationInfo(state, pubInfoNode); }; - this.extractArticleInfo = function (state, article) { + + this.extractArticleInfo = function(state, article) { // Initialize the Article Info object var articleInfo = { "id": "articleinfo", "type": "paragraph", }; var doc = state.doc; + var nodes = []; + // Reviewing editor nodes = nodes.concat(this.extractEditor(state, article)); // Datasets @@ -249,66 +296,78 @@ NlmToLensConverter.Prototype = function () { nodes = nodes.concat(this.extractCopyrightAndLicense(state, article)); // Notes (Footnotes + Author notes) nodes = nodes.concat(this.extractNotes(state, article)); + articleInfo.children = nodes; doc.create(articleInfo); + return articleInfo; }; + // Get reviewing editor // -------------- // TODO: it is possible to have multiple editors. This does only show the first one // However, this would be easy: just querySelectorAll and have 'Reviewing Editors' as heading when there are multiple nodes found - this.extractEditor = function (state, article) { + + this.extractEditor = function(state, article) { var nodes = []; var doc = state.doc; + var editor = article.querySelector("contrib[contrib-type=editor]"); if (editor) { var content = []; + var name = this.getName(editor.querySelector('name')); if (name) content.push(name); var inst = editor.querySelector("institution"); if (inst) content.push(inst.textContent); var country = editor.querySelector("country"); if (country) content.push(country.textContent); + var h1 = { "type": "heading", "id": state.nextId("heading"), "level": 3, "content": "Reviewing Editor" }; - //doc.create(h1); - //nodes.push(h1.id); + + doc.create(h1); + nodes.push(h1.id); + var t1 = { "type": "text", "id": state.nextId("text"), "content": content.join(", ") }; - //TODO reviewing editor - //doc.create(t1); - //nodes.push(t1.id); + + doc.create(t1); + nodes.push(t1.id); } return nodes; }; + // // Extracts major datasets // ----------------------- - this.extractDatasets = function (state, article) { + + this.extractDatasets = function(state, article) { var nodes = []; var doc = state.doc; + var datasets = article.querySelectorAll('sec'); - for (var i = 0; i < datasets.length; i++) { + for (var i = 0;i 0) { - _.each(acks, function (ack) { + _.each(acks, function(ack) { var title = ack.querySelector('title'); var header = { - "type": "heading", - "id": state.nextId("heading"), - "level": 3, - "content": title ? this.capitalized(title.textContent.toLowerCase(), "all") : "Acknowledgements" + "type" : "heading", + "id" : state.nextId("heading"), + "level" : 3, + "content" : title ? this.capitalized(title.textContent.toLowerCase(), "all") : "Acknowledgements" }; doc.create(header); nodes.push(header.id); + // There may be multiple paragraphs per ack element var pars = this.bodyNodes(state, util.dom.getChildren(ack), { ignore: ["title"] }); - _.each(pars, function (par) { + _.each(pars, function(par) { nodes.push(par.id); }); }, this); } + return nodes; }; + // // Extracts footnotes that should be shown in article info // ------------------------------------------ // // Needs to be overwritten in configuration - this.extractNotes = function (/*state, article*/) { + + this.extractNotes = function(/*state, article*/) { var nodes = []; return nodes; }; + // Can be overridden by custom converter to ignore values. // TODO: Maybe switch to a whitelisting approach, so we don't show // nonsense. See HighWire implementation diff --git a/reader/panels/content/content_panel.js b/reader/panels/content/content_panel.js index 163b18e..b038a63 100644 --- a/reader/panels/content/content_panel.js +++ b/reader/panels/content/content_panel.js @@ -9,7 +9,7 @@ var ContentPanel = function() { type: "document", container: "content", label: 'Contents', - title: locales.Contents, + title: 'Contents', icon: 'fa-align-left', }); }; diff --git a/reader/panels/content/toc_view.js b/reader/panels/content/toc_view.js index 0a08d8d..a594483 100644 --- a/reader/panels/content/toc_view.js +++ b/reader/panels/content/toc_view.js @@ -32,7 +32,7 @@ TOCView.Prototype = function() { var backLink = document.createElement('a'); var linkUrl = ''; backLink.setAttribute('href',linkUrl); - backLink.textContent =locales.Back; + backLink.textContent ="Back"; backLinkContainer.appendChild(backLink); // this.el.appendChild(backLinkContainer); diff --git a/reader/panels/surface_scrollbar.js b/reader/panels/surface_scrollbar.js index 2fea14f..c5e9726 100644 --- a/reader/panels/surface_scrollbar.js +++ b/reader/panels/surface_scrollbar.js @@ -138,7 +138,8 @@ Scrollbar.Prototype = function() { $(this.el).addClass('hidden'); } - this.factor = (contentHeight / panelHeight); + // console.log("Scrollbar.update()", contentHeight, panelHeight); + this.factor = (contentHeight / panelHeight); this.surfaceTop = this.$nodes.offset().top; this.scrollTop = this.surface.$el.scrollTop(); this.updateVisibleArea();