Commit 0bf532c9 by tady (Masato TADA)

Merge pull request #144 from tadyjp/form-design

Form design
parents 5cf43780 4da1e1c4
...@@ -31,3 +31,5 @@ ...@@ -31,3 +31,5 @@
.env .env
!.env.sample !.env.sample
*.zip
GIT GIT
remote: git://github.com/amatsuda/kaminari.git remote: git://github.com/amatsuda/kaminari.git
revision: b1281e21452486b49911e8616fce885b0ea46730 revision: b206d89922378dcf6f1f7a6247ce1d5f6f1534ad
specs: specs:
kaminari (1.0.0.alpha) kaminari (1.0.0.alpha)
actionpack (>= 3.0.0) actionpack (>= 3.0.0)
...@@ -175,7 +175,7 @@ GEM ...@@ -175,7 +175,7 @@ GEM
github-markdown (0.6.7) github-markdown (0.6.7)
gmail_xoauth (0.4.1) gmail_xoauth (0.4.1)
oauth (>= 0.3.6) oauth (>= 0.3.6)
guard (2.7.1) guard (2.8.1)
formatador (>= 0.2.4) formatador (>= 0.2.4)
listen (~> 2.7) listen (~> 2.7)
lumberjack (~> 1.0) lumberjack (~> 1.0)
...@@ -184,7 +184,7 @@ GEM ...@@ -184,7 +184,7 @@ GEM
guard-rspec (4.3.1) guard-rspec (4.3.1)
guard (~> 2.1) guard (~> 2.1)
rspec (>= 2.14, < 4.0) rspec (>= 2.14, < 4.0)
guard-rubocop (1.1.0) guard-rubocop (1.2.0)
guard (~> 2.0) guard (~> 2.0)
rubocop (~> 0.20) rubocop (~> 0.20)
guard-teaspoon (0.8.0) guard-teaspoon (0.8.0)
...@@ -199,7 +199,7 @@ GEM ...@@ -199,7 +199,7 @@ GEM
htmlentities (4.3.2) htmlentities (4.3.2)
http-cookie (1.0.2) http-cookie (1.0.2)
domain_name (~> 0.5) domain_name (~> 0.5)
httparty (0.13.1) httparty (0.13.3)
json (~> 1.8) json (~> 1.8)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
i18n (0.6.11) i18n (0.6.11)
...@@ -213,7 +213,7 @@ GEM ...@@ -213,7 +213,7 @@ GEM
jwt (0.1.11) jwt (0.1.11)
multi_json (>= 1.5) multi_json (>= 1.5)
kgio (2.9.2) kgio (2.9.2)
launchy (2.4.2) launchy (2.4.3)
addressable (~> 2.3) addressable (~> 2.3)
libv8 (3.16.14.7) libv8 (3.16.14.7)
listen (2.7.11) listen (2.7.11)
...@@ -221,7 +221,7 @@ GEM ...@@ -221,7 +221,7 @@ GEM
rb-fsevent (>= 0.9.3) rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9) rb-inotify (>= 0.9)
lumberjack (1.0.9) lumberjack (1.0.9)
mail (2.6.1) mail (2.6.3)
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 3)
mechanize (2.7.3) mechanize (2.7.3)
domain_name (~> 0.5, >= 0.5.1) domain_name (~> 0.5, >= 0.5.1)
...@@ -234,7 +234,7 @@ GEM ...@@ -234,7 +234,7 @@ GEM
webrobots (>= 0.0.9, < 0.2) webrobots (>= 0.0.9, < 0.2)
method_source (0.8.2) method_source (0.8.2)
mime-types (2.4.3) mime-types (2.4.3)
mini_portile (0.6.0) mini_portile (0.6.1)
minitest (5.4.2) minitest (5.4.2)
multi_json (1.10.1) multi_json (1.10.1)
multi_xml (0.5.5) multi_xml (0.5.5)
...@@ -248,8 +248,8 @@ GEM ...@@ -248,8 +248,8 @@ GEM
net-ssh (2.9.1) net-ssh (2.9.1)
netrc (0.8.0) netrc (0.8.0)
newrelic_rpm (3.9.6.257) newrelic_rpm (3.9.6.257)
nokogiri (1.6.3.1) nokogiri (1.6.4)
mini_portile (= 0.6.0) mini_portile (~> 0.6.0)
ntlm-http (0.1.1) ntlm-http (0.1.1)
oauth (0.4.7) oauth (0.4.7)
oauth2 (0.9.3) oauth2 (0.9.3)
...@@ -273,7 +273,7 @@ GEM ...@@ -273,7 +273,7 @@ GEM
paper_trail (3.0.6) paper_trail (3.0.6)
activerecord (>= 3.0, < 5.0) activerecord (>= 3.0, < 5.0)
activesupport (>= 3.0, < 5.0) activesupport (>= 3.0, < 5.0)
parser (2.2.0.pre.6) parser (2.2.0.pre.7)
ast (>= 1.1, < 3.0) ast (>= 1.1, < 3.0)
slop (~> 3.4, >= 3.4.5) slop (~> 3.4, >= 3.4.5)
poltergeist (1.5.1) poltergeist (1.5.1)
...@@ -363,7 +363,7 @@ GEM ...@@ -363,7 +363,7 @@ GEM
powerpack (~> 0.0.6) powerpack (~> 0.0.6)
rainbow (>= 1.99.1, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4) ruby-progressbar (~> 1.4)
ruby-progressbar (1.6.1) ruby-progressbar (1.7.0)
sass (3.4.7) sass (3.4.7)
sdoc (0.4.1) sdoc (0.4.1)
json (~> 1.7, >= 1.7.7) json (~> 1.7, >= 1.7.7)
......
# Desc
# フォームサイズ,スクロール位置の調整を自動で行う
# Usage:
#
# Example:
#
$.extend
mod_form_resizer: (options) ->
settings =
$editor: null,
$preview: null,
height_offset: 0,
settings = $.extend settings, options
$window = $(window)
editor_height = 0
settings.$preview.css('overflow', 'scroll')
# Set editor & preview height
adjustHeight = ->
h = $window.height()
editor_height = h - settings.height_offset
settings.$editor.css('height', editor_height)
settings.$preview.css('height', editor_height)
adjustHeight()
$window.on 'resize', ->
adjustHeight()
# Set preview scrollTop by editor scrollTop
adjustPreviewScroll = ->
settings.$preview.prop('scrollHeight')
editor_scrollTop = settings.$editor.scrollTop()
preview_scrollHeight = settings.$preview.prop('scrollHeight')
editor_scrollHeight = settings.$editor.prop('scrollHeight')
preview_scrollTop = (preview_scrollHeight - editor_height) / (editor_scrollHeight - editor_height) * editor_scrollTop
settings.$preview.scrollTop(preview_scrollTop)
console.log([editor_scrollTop, preview_scrollHeight, editor_height, editor_scrollHeight, preview_scrollTop])
settings.$editor.on 'scroll', _.throttle(adjustPreviewScroll, 1000 / 30)
...@@ -29,7 +29,7 @@ $.fn.extend ...@@ -29,7 +29,7 @@ $.fn.extend
$textarea = $root.find('.mod-mdEditor-textarea') $textarea = $root.find('.mod-mdEditor-textarea')
# textareのサイズ調整 # textareのサイズ調整
$textarea.autosize(); # $textarea.autosize();
# textareaのtabキー制御,indent維持 # textareaのtabキー制御,indent維持
$textarea.on 'keydown', (e) -> $textarea.on 'keydown', (e) ->
...@@ -87,7 +87,7 @@ $.fn.extend ...@@ -87,7 +87,7 @@ $.fn.extend
# TODO # TODO
prettyPrint() prettyPrint()
$textarea.on('keyup mouseup change', generatePreview) $textarea.on('keyup mouseup change', _.debounce(generatePreview, 200))
generatePreview() generatePreview()
......
.body-padding {
body {
padding-top: 70px; padding-top: 70px;
} }
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
.mod-mdEditor-textarea { .mod-mdEditor-textarea {
width: 100%; width: 100%;
min-height: 400px; min-height: 100px;
font-size: 12pt; font-size: 12pt;
padding: 3px; padding: 3px;
tab-size: 2; tab-size: 2;
} }
.mod-mdEditor-preview { .mod-mdEditor-preview {
min-height: 400px; min-height: 100px;
} }
...@@ -62,6 +62,14 @@ ...@@ -62,6 +62,14 @@
#save_button { #save_button {
margin-bottom: 10px; margin-bottom: 10px;
} }
table {
width: 100%;
}
td {
width: 50%;
}
} }
input, input,
......
...@@ -19,12 +19,13 @@ class PostsController < ApplicationController ...@@ -19,12 +19,13 @@ class PostsController < ApplicationController
# GET /posts/new # GET /posts/new
def new def new
@post = Post.new(title: '新しい投稿') @post = Post.new(title: '新しい投稿')
render layout: 'edit'
end end
def fork def fork
@post = set_post.generate_fork(current_user) @post = set_post.generate_fork(current_user)
@post.tags.destroy Tag.find_by(name: 'template') @post.tags.destroy Tag.find_by(name: 'template')
render action: 'new' render layout: 'edit', action: 'new'
end end
def mail def mail
...@@ -43,6 +44,7 @@ class PostsController < ApplicationController ...@@ -43,6 +44,7 @@ class PostsController < ApplicationController
# GET /posts/1/edit # GET /posts/1/edit
def edit def edit
render layout: 'edit'
end end
# POST /posts # POST /posts
......
...@@ -3,28 +3,7 @@ class MarkdownRenderer ...@@ -3,28 +3,7 @@ class MarkdownRenderer
@text = text || '' @text = text || ''
end end
# pdf viewerの変換
# !slide!(file-url) -> %%slide:0%% -> <iframe>...</iframe>
def render def render
# slideのurlを一時保管 GitHub::Markdown.render_gfm(@text).html_safe
slide_urls = []
text = @text.gsub(/!slide!\(([^\)]+)\)/) do |_|
slide_urls << %(
<div class="embed-responsive embed-responsive-4by3">
<iframe style="text-align:center;" src="/ViewerJS/##{Regexp.last_match[1]}"
width="400" height="300" allowfullscreen="true" webkitallowfullscreen="true"></iframe>
</div>
)
"%%slide:#{slide_urls.size - 1}%%"
end
text = GitHub::Markdown.render_gfm(text)
# 保管したslide urlを取り出す
text = text.gsub(/%%slide:(\d+)%%/) do |_|
slide_urls[Regexp.last_match[1].to_i]
end
text.html_safe
end end
end end
...@@ -16,6 +16,8 @@ html lang="ja" ...@@ -16,6 +16,8 @@ html lang="ja"
= render_style = render_style
= csrf_meta_tags = csrf_meta_tags
body class="rails-#{params[:controller]}-#{params[:action]}" body class="rails-#{params[:controller]}-#{params[:action]}"
.body-padding
= render partial: 'partials/header_notifications' = render partial: 'partials/header_notifications'
- if params[:controller] != 'welcome' - if params[:controller] != 'welcome'
= render partial: 'partials/app_header' = render partial: 'partials/app_header'
......
doctype html
= render partial: 'partials/rendezvous'
html lang="ja"
head
title Rendezvous
meta content="width=device-width, initial-scale=1.0" name="viewport" /
link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" /
link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css" rel="stylesheet" /
link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/1.6.4/fullcalendar.css" rel="stylesheet" /
link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/1.6.4/fullcalendar.print.css" rel="stylesheet" /
link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"
= favicon_link_tag 'favicon.ico'
script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"
= render partial: 'partials/google_analytics'
= stylesheet_link_tag "application", media: "all"
= render_style
= csrf_meta_tags
body class="rails-#{params[:controller]}-#{params[:action]}"
.container-fluid.container-main#yield
= yield
script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"
script src="//cdnjs.cloudflare.com/ajax/libs/underscore.string/2.3.3/underscore.string.min.js"
script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"
script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"
script src="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/1.6.4/fullcalendar.min.js"
javascript:
window.RV = window.RV || {};
window.RV.AllTags = JSON.parse('#{raw Tag.all.pluck(:name).to_json}');
hr/
= javascript_include_tag "application"
= yield :footer_js
...@@ -22,19 +22,17 @@ ...@@ -22,19 +22,17 @@
= hidden_field :post, :tags, class: 'mod-mdEditor-tags', style: 'width:300px', value: @post.tags.map{ |_tag| _tag.name }.join(',') = hidden_field :post, :tags, class: 'mod-mdEditor-tags', style: 'width:300px', value: @post.tags.map{ |_tag| _tag.name }.join(',')
.col-xs-3 .col-xs-3
p.actions
br/ = f.submit class: 'btn btn-lg js-disable-confirm-unload', id: 'save_button'
p.actions
= f.check_box :is_draft
= f.label :is_draft, "&nbsp;下書き保存".html_safe
p.actions
= f.date_select :specified_date
.row .row
#progress-wrapper.alert.alert-warning.fade.in style="display:none;"
span.progress-title
| Uploading files...
#progress style="height:20px;"
.progress-bar.progress-bar-success.progress-bar-striped.active role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"
| 0%
.row .col-xs-6.editor-panel
.col-xs-6
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
.btn-toolbar role="toolbar" .btn-toolbar role="toolbar"
...@@ -57,31 +55,50 @@ ...@@ -57,31 +55,50 @@
.btn-group.btn-group-xs .btn-group.btn-group-xs
button#uploadButton.btn.btn-default type="button" title="Upload" button#uploadButton.btn.btn-default type="button" title="Upload"
| Upload | Upload
.btn-group.btn-group-xs.pull-right.mode-editor
button#uploadButton.btn.btn-default type="button"
i.fa.fa-angle-right
.btn-group.btn-group-xs.pull-right.mode-split style="display:none"
button#uploadButton.btn.btn-default type="button"
i.fa.fa-angle-left
.panel-body.panel-body-nopadding style="position:relative"
= f.text_area :body, class: 'mod-mdEditor-textarea mod-form-resizer-editor', placehoder: 'type your text....'
#progress-wrapper style="display:none;position:absolute;bottom:0;z-index:1000;width:100%"
.alert.alert-warning.fade.in style="margin-bottom:0"
span.progress-title
| Uploading files...
#progress style="height:20px;"
.progress-bar.progress-bar-success.progress-bar-striped.active role="progressbar" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"
| 0%
.panel-body.panel-body-nopadding .col-xs-6.preview-panel
= f.text_area :body, class: 'mod-mdEditor-textarea', placehoder: 'type your text....'
p.actions
= f.submit class: 'btn btn-lg js-disable-confirm-unload', id: 'save_button'
p.actions
= f.check_box :is_draft
= f.label :is_draft, "下書き保存"
p.actions
= f.date_select :specified_date
.col-xs-6
.panel.preview-wrapper .panel.preview-wrapper
.panel-heading .panel-heading
h5 Preview - 入力した内容がここに表示されます span Preview
.panel-body
.box-text .panel-body.text-box.body.viewer.github.mod-mdEditor-preview.mod-form-resizer-preview
.text-box.body.viewer.github.mod-mdEditor-preview
input#fileupload data-url="/apis/file_receiver" multiple="" name="files[]" style="display:none" type="file" / input#fileupload data-url="/apis/file_receiver" multiple="" name="files[]" style="display:none" type="file" /
- content_for :footer_js do - content_for :footer_js do
javascript: javascript:
// Bounce confirm.
$.setConfirmUnload(); $.setConfirmUnload();
// Mode change
$('.mode-editor button').on('click', function(){
$('.mode-editor').hide();
$('.mode-split').show();
$('.editor-panel').addClass('col-xs-12').removeClass('col-xs-6'); $('.preview-panel').hide();
})
$('.mode-split button').on('click', function(){
$('.mode-split').hide();
$('.mode-editor').show();
$('.editor-panel').addClass('col-xs-6').removeClass('col-xs-12'); $('.preview-panel').show();
})
$('#post-form').mod_mdEditor({end_point: '/apis/markdown_preview'}); $('#post-form').mod_mdEditor({end_point: '/apis/markdown_preview'});
$.mod_fileuploader({ $.mod_fileuploader({
...@@ -91,6 +108,13 @@ input#fileupload data-url="/apis/file_receiver" multiple="" name="files[]" style ...@@ -91,6 +108,13 @@ input#fileupload data-url="/apis/file_receiver" multiple="" name="files[]" style
$progressBar: $('#progress .progress-bar') $progressBar: $('#progress .progress-bar')
}); });
// フォームサイズ調整
$.mod_form_resizer({
$editor: $('.mod-form-resizer-editor'),
$preview: $('.mod-form-resizer-preview'),
height_offset: 250
})
// Display upload dialog. // Display upload dialog.
$('#uploadButton').on('click', function(){ $('#uploadButton').on('click', function(){
$('input#fileupload').trigger('click'); $('input#fileupload').trigger('click');
...@@ -147,3 +171,4 @@ input#fileupload data-url="/apis/file_receiver" multiple="" name="files[]" style ...@@ -147,3 +171,4 @@ input#fileupload data-url="/apis/file_receiver" multiple="" name="files[]" style
.textcomplete-wrapper { .textcomplete-wrapper {
width: 100%; width: 100%;
} }
/**
* Copyright (C) 2013-2014 KO GmbH <copyright@kogmbh.com>
*
* @licstart
* This file is part of WebODF.
*
* WebODF is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License (GNU AGPL)
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* WebODF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with WebODF. If not, see <http://www.gnu.org/licenses/>.
* @licend
*
* @source: http://www.webodf.org/
* @source: https://github.com/kogmbh/WebODF/
*/
@namespace cursor url(urn:webodf:names:cursor);
.caret {
opacity: 0 !important;
}
/**
* Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
*
* @licstart
* This file is part of WebODF.
*
* WebODF is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License (GNU AGPL)
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* WebODF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with WebODF. If not, see <http://www.gnu.org/licenses/>.
* @licend
*
* @source: http://www.webodf.org/
* @source: https://github.com/kogmbh/WebODF/
*/
/*global runtime, document, odf, gui, console, webodf*/
function ODFViewerPlugin() {
"use strict";
function init(callback) {
var lib = document.createElement('script'),
pluginCSS;
lib.async = false;
lib.src = './webodf.js';
lib.type = 'text/javascript';
lib.onload = function () {
runtime.loadClass('gui.HyperlinkClickHandler');
runtime.loadClass('odf.OdfCanvas');
runtime.loadClass('ops.Session');
runtime.loadClass('gui.CaretManager');
runtime.loadClass("gui.HyperlinkTooltipView");
runtime.loadClass('gui.SessionController');
runtime.loadClass('gui.SvgSelectionView');
runtime.loadClass('gui.SelectionViewManager');
runtime.loadClass('gui.ShadowCursor');
runtime.loadClass('gui.SessionView');
callback();
};
document.getElementsByTagName('head')[0].appendChild(lib);
pluginCSS = document.createElement('link');
pluginCSS.setAttribute("rel", "stylesheet");
pluginCSS.setAttribute("type", "text/css");
pluginCSS.setAttribute("href", "./ODFViewerPlugin.css");
document.head.appendChild(pluginCSS);
}
// that should probably be provided by webodf
function nsResolver(prefix) {
var ns = {
'draw' : "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
'presentation' : "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
'text' : "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
'office' : "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
};
return ns[prefix] || console.log('prefix [' + prefix + '] unknown.');
}
var self = this,
pluginName = "WebODF",
pluginURL = "http://webodf.org",
odfCanvas = null,
odfElement = null,
initialized = false,
root = null,
documentType = null,
pages = [],
currentPage = null;
this.initialize = function (viewerElement, documentUrl) {
// If the URL has a fragment (#...), try to load the file it represents
init(function () {
var session,
sessionController,
sessionView,
odtDocument,
shadowCursor,
selectionViewManager,
caretManager,
localMemberId = 'localuser',
hyperlinkTooltipView,
eventManager;
odfElement = document.getElementById('canvas');
odfCanvas = new odf.OdfCanvas(odfElement);
odfCanvas.load(documentUrl);
odfCanvas.addListener('statereadychange', function () {
root = odfCanvas.odfContainer().rootElement;
initialized = true;
documentType = odfCanvas.odfContainer().getDocumentType(root);
if (documentType === 'text') {
odfCanvas.enableAnnotations(true, false);
session = new ops.Session(odfCanvas);
odtDocument = session.getOdtDocument();
shadowCursor = new gui.ShadowCursor(odtDocument);
sessionController = new gui.SessionController(session, localMemberId, shadowCursor, {});
eventManager = sessionController.getEventManager();
caretManager = new gui.CaretManager(sessionController);
selectionViewManager = new gui.SelectionViewManager(gui.SvgSelectionView);
sessionView = new gui.SessionView({
caretAvatarsInitiallyVisible: false
}, localMemberId, session, sessionController.getSessionConstraints(), caretManager, selectionViewManager);
selectionViewManager.registerCursor(shadowCursor);
hyperlinkTooltipView = new gui.HyperlinkTooltipView(odfCanvas,
sessionController.getHyperlinkClickHandler().getModifier);
eventManager.subscribe("mousemove", hyperlinkTooltipView.showTooltip);
eventManager.subscribe("mouseout", hyperlinkTooltipView.hideTooltip);
var op = new ops.OpAddMember();
op.init({
memberid: localMemberId,
setProperties: {
fillName: runtime.tr("Unknown Author"),
color: "blue"
}
});
session.enqueue([op]);
sessionController.insertLocalCursor();
}
self.onLoad();
});
});
};
this.isSlideshow = function () {
return documentType === 'presentation';
};
this.onLoad = function () {};
this.getWidth = function () {
return odfElement.clientWidth;
};
this.getHeight = function () {
return odfElement.clientHeight;
};
this.fitToWidth = function (width) {
odfCanvas.fitToWidth(width);
};
this.fitToHeight = function (height) {
odfCanvas.fitToHeight(height);
};
this.fitToPage = function (width, height) {
odfCanvas.fitToContainingElement(width, height);
};
this.fitSmart = function (width) {
odfCanvas.fitSmart(width);
};
this.getZoomLevel = function () {
return odfCanvas.getZoomLevel();
};
this.setZoomLevel = function (value) {
odfCanvas.setZoomLevel(value);
};
// return a list of tuples (pagename, pagenode)
this.getPages = function () {
var pageNodes = Array.prototype.slice.call(root.getElementsByTagNameNS(nsResolver('draw'), 'page')),
pages = [],
i,
tuple;
for (i = 0; i < pageNodes.length; i += 1) {
tuple = [
pageNodes[i].getAttribute('draw:name'),
pageNodes[i]
];
pages.push(tuple);
}
return pages;
};
this.showPage = function (n) {
odfCanvas.showPage(n);
};
this.getPluginName = function () {
return pluginName;
};
this.getPluginVersion = function () {
var version;
if (String(typeof webodf) !== "undefined") {
version = webodf.Version;
} else {
version = "Unknown";
}
return version;
};
this.getPluginURL = function () {
return pluginURL;
};
}
.page {
margin: 7px auto 7px auto;
position: relative;
overflow: hidden;
background-clip: content-box;
background-color: white;
box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
-webkit-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
-moz-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
-ms-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
-o-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
}
.textLayer {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
color: #000;
font-family: sans-serif;
overflow: hidden;
}
.textLayer > div {
color: transparent;
position: absolute;
line-height: 1;
white-space: pre;
cursor: text;
}
::selection { background:rgba(0,0,255,0.3); }
::-moz-selection { background:rgba(0,0,255,0.3); }
/**
* @license
* Copyright (C) 2012 KO GmbH <copyright@kogmbh.com>
*
* @licstart
* The JavaScript code in this page is free software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* (GNU AGPL) as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. The code is distributed
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
* As additional permission under GNU AGPL version 3 section 7, you
* may distribute non-source (e.g., minimized or compacted) forms of
* that code without the copy of the GNU GPL normally required by
* section 4, provided you include this license notice and a URL
* through which recipients can access the Corresponding Source.
*
* As a special exception to the AGPL, any HTML file which merely makes function
* calls to this code, and for that purpose includes it by reference shall be
* deemed a separate work for copyright law purposes. In addition, the copyright
* holders of this code give you permission to combine this code with free
* software libraries that are released under the GNU LGPL. You may copy and
* distribute such a system following the terms of the GNU AGPL for this code
* and the LGPL for the libraries. If you modify this code, you may extend this
* exception to your version of the code, but you are not obligated to do so.
* If you do not wish to do so, delete this exception statement from your
* version.
*
* This license applies to this entire compilation.
* @licend
* @source: http://viewerjs.org/
* @source: http://github.com/kogmbh/ViewerJS
*/
/*global document, window, Viewer, ODFViewerPlugin, PDFViewerPlugin*/
var viewer;
function loadPlugin(pluginName, callback) {
"use strict";
var script, style;
// Load script
script = document.createElement('script');
script.async = false;
script.onload = callback;
script.src = pluginName + '.js';
script.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(script);
}
function loadDocument(documentUrl) {
"use strict";
if (documentUrl) {
var extension = documentUrl.split('.').pop(),
Plugin;
extension = extension.toLowerCase();
switch (extension) {
case 'odt':
case 'odp':
case 'ods':
case 'fodt':
loadPlugin('./ODFViewerPlugin', function () {
Plugin = ODFViewerPlugin;
});
break;
case 'pdf':
loadPlugin('./PDFViewerPlugin', function () {
Plugin = PDFViewerPlugin;
});
break;
}
window.onload = function () {
if (Plugin) {
viewer = new Viewer(new Plugin());
}
};
}
}
/* This is just a sample file with CSS rules. You should write your own @font-face declarations
* to add support for your desired fonts.
*/
@font-face {
font-family: 'Novecentowide Book';
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot");
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot?#iefix") format("embedded-opentype"),
url("/ViewerJS/fonts/Novecentowide-Bold-webfont.woff") format("woff"),
url("/fonts/Novecentowide-Bold-webfont.ttf") format("truetype"),
url("/fonts/Novecentowide-Bold-webfont.svg#NovecentowideBookBold") format("svg");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'exotica';
src: url('/ViewerJS/fonts/Exotica-webfont.eot');
src: url('/ViewerJS/fonts/Exotica-webfont.eot?#iefix') format('embedded-opentype'),
url('/ViewerJS/fonts/Exotica-webfont.woff') format('woff'),
url('/ViewerJS/fonts/Exotica-webfont.ttf') format('truetype'),
url('/ViewerJS/fonts/Exotica-webfont.svg#exoticamedium') format('svg');
font-weight: normal;
font-style: normal;
}
<!DOCTYPE html>
<!--
Copyright (C) 2012-2014 KO GmbH <copyright@kogmbh.com>
@licstart
This file is part of WebODF.
WebODF is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License (GNU AGPL)
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
WebODF is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with WebODF. If not, see <http://www.gnu.org/licenses/>.
@licend
@source: http://www.webodf.org/
@source: https://github.com/kogmbh/WebODF/
-->
<!--
This file is a derivative from a part of Mozilla's PDF.js project. The
original license header follows.
-->
<!--
Copyright 2012 Mozilla Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html dir="ltr" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>ViewerJS</title>
<!-- If you want to use custom CSS (@font-face rules, for example) you should uncomment
the following reference and use a local.css file for that. See the example.local.css
file for a sample.
<link rel="stylesheet" type="text/css" href="local.css" media="screen"/>
-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" type="text/css" href="viewer.css" media="screen"/>
<script src="viewer.js" type="text/javascript" charset="utf-8"></script>
<script src="PluginLoader.js" type="text/javascript" charset="utf-8"></script>
<script>
loadDocument(window.location.hash);
</script>
</head>
<body>
<div id = "viewer">
<div id = "titlebar">
<div id = "documentName"></div>
<div id = "toolbarRight">
<button id = "presentation" class = "toolbarButton presentation" title = "Presentation"></button>
<button id = "fullscreen" class = "toolbarButton fullscreen" title = "Fullscreen"></button>
<button id = "download" class = "toolbarButton download" title = "Download"></button>
</div>
</div>
<div id = "toolbarContainer">
<div id = "toolbar">
<div id = "toolbarLeft">
<div id = "navButtons" class = "splitToolbarButton">
<button id = "previous" class = "toolbarButton pageUp" title = "Previous Page"></button>
<div class="splitToolbarButtonSeparator"></div>
<button id = "next" class = "toolbarButton pageDown" title = "Next Page"></button>
</div>
<label id = "pageNumberLabel" class = "toolbarLabel" for = "pageNumber">Page:</label>
<input type = "number" id = "pageNumber" class = "toolbarField pageNumber"/>
<span id = "numPages" class = "toolbarLabel"></span>
</div>
<div id = "toolbarMiddleContainer" class = "outerCenter">
<div id = "toolbarMiddle" class = "innerCenter">
<div id = 'zoomButtons' class = "splitToolbarButton">
<button id = "zoomOut" class = "toolbarButton zoomOut" title = "Zoom Out"></button>
<div class="splitToolbarButtonSeparator"></div>
<button id = "zoomIn" class = "toolbarButton zoomIn" title = "Zoom In"></button>
</div>
<span id="scaleSelectContainer" class="dropdownToolbarButton">
<select id="scaleSelect" title="Zoom" oncontextmenu="return false;">
<option id="pageAutoOption" value="auto" selected>Automatic</option>
<option id="pageActualOption" value="page-actual">Actual Size</option>
<option id="pageWidthOption" value="page-width">Full Width</option>
<option id="customScaleOption" value="custom"> </option>
<option value="0.5">50%</option>
<option value="0.75">75%</option>
<option value="1">100%</option>
<option value="1.25">125%</option>
<option value="1.5">150%</option>
<option value="2">200%</option>
</select>
</span>
<div id = "sliderContainer">
<div id = "slider"></div>
</div>
</div>
</div>
</div>
</div>
<div id = "canvasContainer">
<div id = "canvas"></div>
</div>
<div id = "overlayNavigator">
<div id = "previousPage"></div>
<div id = "nextPage"></div>
</div>
<div id = "overlayCloseButton">
&#10006;
</div>
<div id = "dialogOverlay"></div>
</div>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
/* globals PDFFindController, FindStates, mozL10n */
/**
* Creates a "search bar" given set of DOM elements
* that act as controls for searching, or for setting
* search preferences in the UI. This object also sets
* up the appropriate events for the controls. Actual
* searching is done by PDFFindController
*/
var PDFFindBar = {
opened: false,
bar: null,
toggleButton: null,
findField: null,
highlightAll: null,
caseSensitive: null,
findMsg: null,
findStatusIcon: null,
findPreviousButton: null,
findNextButton: null,
initialize: function(options) {
if(typeof PDFFindController === 'undefined' || PDFFindController === null) {
throw 'PDFFindBar cannot be initialized ' +
'without a PDFFindController instance.';
}
this.bar = options.bar;
this.toggleButton = options.toggleButton;
this.findField = options.findField;
this.highlightAll = options.highlightAllCheckbox;
this.caseSensitive = options.caseSensitiveCheckbox;
this.findMsg = options.findMsg;
this.findStatusIcon = options.findStatusIcon;
this.findPreviousButton = options.findPreviousButton;
this.findNextButton = options.findNextButton;
var self = this;
this.toggleButton.addEventListener('click', function() {
self.toggle();
});
this.findField.addEventListener('input', function() {
self.dispatchEvent('');
});
this.bar.addEventListener('keydown', function(evt) {
switch (evt.keyCode) {
case 13: // Enter
if (evt.target === self.findField) {
self.dispatchEvent('again', evt.shiftKey);
}
break;
case 27: // Escape
self.close();
break;
}
});
this.findPreviousButton.addEventListener('click',
function() { self.dispatchEvent('again', true); }
);
this.findNextButton.addEventListener('click', function() {
self.dispatchEvent('again', false);
});
this.highlightAll.addEventListener('click', function() {
self.dispatchEvent('highlightallchange');
});
this.caseSensitive.addEventListener('click', function() {
self.dispatchEvent('casesensitivitychange');
});
},
dispatchEvent: function(aType, aFindPrevious) {
var event = document.createEvent('CustomEvent');
event.initCustomEvent('find' + aType, true, true, {
query: this.findField.value,
caseSensitive: this.caseSensitive.checked,
highlightAll: this.highlightAll.checked,
findPrevious: aFindPrevious
});
return window.dispatchEvent(event);
},
updateUIState: function(state, previous) {
var notFound = false;
var findMsg = '';
var status = '';
switch (state) {
case FindStates.FIND_FOUND:
break;
case FindStates.FIND_PENDING:
status = 'pending';
break;
case FindStates.FIND_NOTFOUND:
findMsg = mozL10n.get('find_not_found', null, 'Phrase not found');
notFound = true;
break;
case FindStates.FIND_WRAPPED:
if (previous) {
findMsg = mozL10n.get('find_reached_top', null,
'Reached top of document, continued from bottom');
} else {
findMsg = mozL10n.get('find_reached_bottom', null,
'Reached end of document, continued from top');
}
break;
}
if (notFound) {
this.findField.classList.add('notFound');
} else {
this.findField.classList.remove('notFound');
}
this.findField.setAttribute('data-status', status);
this.findMsg.textContent = findMsg;
},
open: function() {
if (!this.opened) {
this.opened = true;
this.toggleButton.classList.add('toggled');
this.bar.classList.remove('hidden');
}
this.findField.select();
this.findField.focus();
},
close: function() {
if (!this.opened) return;
this.opened = false;
this.toggleButton.classList.remove('toggled');
this.bar.classList.add('hidden');
PDFFindController.active = false;
},
toggle: function() {
if (this.opened) {
this.close();
} else {
this.open();
}
}
};
var /**@const{!string}*/pdfjs_version = "d45d7bc";
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
// optimised CSS custom property getter/setter
var CustomStyle = (function CustomStyleClosure() {
// As noted on: http://www.zachstronaut.com/posts/2009/02/17/
// animate-css-transforms-firefox-webkit.html
// in some versions of IE9 it is critical that ms appear in this list
// before Moz
var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
var _cache = { };
function CustomStyle() {
}
CustomStyle.getProp = function get(propName, element) {
// check cache only when no element is given
if (arguments.length == 1 && typeof _cache[propName] == 'string') {
return _cache[propName];
}
element = element || document.documentElement;
var style = element.style, prefixed, uPropName;
// test standard property first
if (typeof style[propName] == 'string') {
return (_cache[propName] = propName);
}
// capitalize
uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
// test vendor specific properties
for (var i = 0, l = prefixes.length; i < l; i++) {
prefixed = prefixes[i] + uPropName;
if (typeof style[prefixed] == 'string') {
return (_cache[propName] = prefixed);
}
}
//if all fails then set to undefined
return (_cache[propName] = 'undefined');
};
CustomStyle.setProp = function set(propName, element, str) {
var prop = this.getProp(propName);
if (prop != 'undefined')
element.style[prop] = str;
};
return CustomStyle;
})();
function getFileName(url) {
var anchor = url.indexOf('#');
var query = url.indexOf('?');
var end = Math.min(
anchor > 0 ? anchor : url.length,
query > 0 ? query : url.length);
return url.substring(url.lastIndexOf('/', end) + 1, end);
}
/**
* Returns scale factor for the canvas. It makes sense for the HiDPI displays.
* @return {Object} The object with horizontal (sx) and vertical (sy)
scales. The scaled property is set to false if scaling is
not required, true otherwise.
*/
function getOutputScale(ctx) {
var devicePixelRatio = window.devicePixelRatio || 1;
var backingStoreRatio = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
var pixelRatio = devicePixelRatio / backingStoreRatio;
return {
sx: pixelRatio,
sy: pixelRatio,
scaled: pixelRatio != 1
};
}
/**
* Scrolls specified element into view of its parent.
* element {Object} The element to be visible.
* spot {Object} An object with optional top and left properties,
* specifying the offset from the top left edge.
*/
function scrollIntoView(element, spot) {
// Assuming offsetParent is available (it's not available when viewer is in
// hidden iframe or object). We have to scroll: if the offsetParent is not set
// producing the error. See also animationStartedClosure.
var parent = element.offsetParent;
var offsetY = element.offsetTop + element.clientTop;
var offsetX = element.offsetLeft + element.clientLeft;
if (!parent) {
console.error('offsetParent is not set -- cannot scroll');
return;
}
while (parent.clientHeight === parent.scrollHeight) {
if (parent.dataset._scaleY) {
offsetY /= parent.dataset._scaleY;
offsetX /= parent.dataset._scaleX;
}
offsetY += parent.offsetTop;
offsetX += parent.offsetLeft;
parent = parent.offsetParent;
if (!parent) {
return; // no need to scroll
}
}
if (spot) {
if (spot.top !== undefined) {
offsetY += spot.top;
}
if (spot.left !== undefined) {
offsetX += spot.left;
parent.scrollLeft = offsetX;
}
}
parent.scrollTop = offsetY;
}
/**
* Event handler to suppress context menu.
*/
function noContextMenuHandler(e) {
e.preventDefault();
}
/**
* Returns the filename or guessed filename from the url (see issue 3455).
* url {String} The original PDF location.
* @return {String} Guessed PDF file name.
*/
function getPDFFileNameFromURL(url) {
var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
// SCHEME HOST 1.PATH 2.QUERY 3.REF
// Pattern to get last matching NAME.pdf
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
var splitURI = reURI.exec(url);
var suggestedFilename = reFilename.exec(splitURI[1]) ||
reFilename.exec(splitURI[2]) ||
reFilename.exec(splitURI[3]);
if (suggestedFilename) {
suggestedFilename = suggestedFilename[0];
if (suggestedFilename.indexOf('%') != -1) {
// URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
try {
suggestedFilename =
reFilename.exec(decodeURIComponent(suggestedFilename))[0];
} catch(e) { // Possible (extremely rare) errors:
// URIError "Malformed URI", e.g. for "%AA.pdf"
// TypeError "null has no properties", e.g. for "%2F.pdf"
}
}
}
return suggestedFilename || 'document.pdf';
}
var ProgressBar = (function ProgressBarClosure() {
function clamp(v, min, max) {
return Math.min(Math.max(v, min), max);
}
function ProgressBar(id, opts) {
// Fetch the sub-elements for later.
this.div = document.querySelector(id + ' .progress');
// Get the loading bar element, so it can be resized to fit the viewer.
this.bar = this.div.parentNode;
// Get options, with sensible defaults.
this.height = opts.height || 100;
this.width = opts.width || 100;
this.units = opts.units || '%';
// Initialize heights.
this.div.style.height = this.height + this.units;
this.percent = 0;
}
ProgressBar.prototype = {
updateBar: function ProgressBar_updateBar() {
if (this._indeterminate) {
this.div.classList.add('indeterminate');
this.div.style.width = this.width + this.units;
return;
}
this.div.classList.remove('indeterminate');
var progressSize = this.width * this._percent / 100;
this.div.style.width = progressSize + this.units;
},
get percent() {
return this._percent;
},
set percent(val) {
this._indeterminate = isNaN(val);
this._percent = clamp(val, 0, 100);
this.updateBar();
},
setWidth: function ProgressBar_setWidth(viewer) {
if (viewer) {
var container = viewer.parentNode;
var scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
if (scrollbarWidth > 0) {
this.bar.setAttribute('style', 'width: calc(100% - ' +
scrollbarWidth + 'px);');
}
}
},
hide: function ProgressBar_hide() {
this.bar.classList.add('hidden');
this.bar.removeAttribute('style');
}
};
return ProgressBar;
})();
var Cache = function cacheCache(size) {
var data = [];
this.push = function cachePush(view) {
var i = data.indexOf(view);
if (i >= 0)
data.splice(i);
data.push(view);
if (data.length > size)
data.shift().destroy();
};
};
//#if !(FIREFOX || MOZCENTRAL || B2G)
var isLocalStorageEnabled = (function isLocalStorageEnabledClosure() {
// Feature test as per http://diveintohtml5.info/storage.html
// The additional localStorage call is to get around a FF quirk, see
// bug #495747 in bugzilla
try {
return ('localStorage' in window && window['localStorage'] !== null &&
localStorage);
} catch (e) {
return false;
}
})();
//#endif
function Viewer(c){function M(){var a,b,A,d,f;c&&(A=c.getPluginName(),d=c.getPluginVersion(),f=c.getPluginURL());a=document.createElement("div");a.id="aboutDialogCentererTable";b=document.createElement("div");b.id="aboutDialogCentererCell";n=document.createElement("div");n.id="aboutDialog";n.innerHTML='<h1>ViewerJS</h1><p>Open Source document viewer for webpages, built with HTML and JavaScript.</p><p>Learn more and get your own copy on the <a href="http://viewerjs.org/" target="_blank">ViewerJS website</a>.</p>'+
(c?'<p>Using the <a href = "'+f+'" target="_blank">'+A+'</a> (<span id = "pluginVersion">'+d+"</span>) plugin to show you this document.</p>":"")+'<p>Supported by <a href="http://nlnet.nl" target="_blank"><br><img src="images/nlnet.png" width="160" height="60" alt="NLnet Foundation"></a></p><p>Made by <a href="http://kogmbh.com" target="_blank"><br><img src="images/kogmbh.png" width="172" height="40" alt="KO GmbH"></a></p><button id = "aboutDialogCloseButton" class = "toolbarButton textButton">Close</button>';
u.appendChild(a);a.appendChild(b);b.appendChild(n);a=document.createElement("button");a.id="about";a.className="toolbarButton textButton about";a.title="About";a.innerHTML="ViewerJS";N.appendChild(a);a.addEventListener("click",function(){u.style.display="block"});document.getElementById("aboutDialogCloseButton").addEventListener("click",function(){u.style.display="none"})}function B(a){var b=O.options,c,d=!1,f;for(f=0;f<b.length;f+=1)c=b[f],c.value!==a?c.selected=!1:d=c.selected=!0;return d}function C(a,
c,d){a!==b.getZoomLevel()&&(b.setZoomLevel(a),d=document.createEvent("UIEvents"),d.initUIEvent("scalechange",!1,!1,window,0),d.scale=a,d.resetAutoSettings=c,window.dispatchEvent(d))}function D(){var a;if(c.onScroll)c.onScroll();c.getPageInView&&(a=c.getPageInView())&&(k=a,document.getElementById("pageNumber").value=a)}function E(a){window.clearTimeout(F);F=window.setTimeout(function(){D()},a)}function e(a,b,g){var e,f;if(e="custom"===a?parseFloat(document.getElementById("customScaleOption").textContent)/
100:parseFloat(a))C(e,!0,g);else{e=d.clientWidth-p;f=d.clientHeight-p;switch(a){case "page-actual":C(1,b,g);break;case "page-width":c.fitToWidth(e);break;case "page-height":c.fitToHeight(f);break;case "page-fit":c.fitToPage(e,f);break;case "auto":c.isSlideshow()?c.fitToPage(e+p,f+p):c.fitSmart(e)}B(a)}E(300)}function q(){l=!l;r&&!l&&b.togglePresentationMode()}function v(){s&&(w.className="viewer-touched",window.clearTimeout(G),G=window.setTimeout(function(){w.className=""},5E3))}function x(){h.classList.add("viewer-touched");
m.classList.add("viewer-touched");window.clearTimeout(H);H=window.setTimeout(function(){I()},5E3)}function I(){h.classList.remove("viewer-touched");m.classList.remove("viewer-touched")}function P(){h.classList.contains("viewer-touched")?I():x()}var b=this,p=40,r=!1,l=!1,J=!1,s=!1,y,g=document.getElementById("viewer"),d=document.getElementById("canvasContainer"),w=document.getElementById("overlayNavigator"),h=document.getElementById("titlebar"),m=document.getElementById("toolbarContainer"),K=document.getElementById("toolbarLeft"),
Q=document.getElementById("toolbarMiddleContainer"),O=document.getElementById("scaleSelect"),u=document.getElementById("dialogOverlay"),N=document.getElementById("toolbarRight"),n,L,t=[],k,F,G,H;this.initialize=function(){var a=String(document.location),z=a.indexOf("#"),a=a.substr(z+1);-1===z||0===a.length?console.log("Could not parse file path argument."):(y=a,L=y.replace(/^.*[\\\/]/,""),document.title=L,document.getElementById("documentName").innerHTML=document.title,c.onLoad=function(){document.getElementById("pluginVersion").innerHTML=
c.getPluginVersion();(s=c.isSlideshow())?(d.classList.add("slideshow"),K.style.visibility="visible"):(Q.style.visibility="visible",c.getPageInView&&(K.style.visibility="visible"));J=!0;t=c.getPages();document.getElementById("numPages").innerHTML="of "+t.length;b.showPage(1);e("auto");d.onscroll=D;E()},c.initialize(d,a))};this.showPage=function(a){0>=a?a=1:a>t.length&&(a=t.length);c.showPage(a);k=a;document.getElementById("pageNumber").value=k};this.showNextPage=function(){b.showPage(k+1)};this.showPreviousPage=
function(){b.showPage(k-1)};this.download=function(){var a=y.split("#")[0];window.open(a+"#viewer.action=download","_parent")};this.toggleFullScreen=function(){l?document.cancelFullScreen?document.cancelFullScreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitCancelFullScreen?document.webkitCancelFullScreen():document.msExitFullscreen&&document.msExitFullscreen():g.requestFullScreen?g.requestFullScreen():g.mozRequestFullScreen?g.mozRequestFullScreen():g.webkitRequestFullScreen?
g.webkitRequestFullScreen():g.msRequestFullscreen&&g.msRequestFullscreen()};this.togglePresentationMode=function(){var a=document.getElementById("overlayCloseButton");r?(h.style.display=m.style.display="block",a.style.display="none",d.classList.remove("presentationMode"),d.onmouseup=function(){},d.oncontextmenu=function(){},d.onmousedown=function(){},e("auto"),s=c.isSlideshow()):(h.style.display=m.style.display="none",a.style.display="block",d.classList.add("presentationMode"),s=!0,d.onmousedown=
function(a){a.preventDefault()},d.oncontextmenu=function(a){a.preventDefault()},d.onmouseup=function(a){a.preventDefault();1===a.which?b.showNextPage():b.showPreviousPage()},e("page-fit"));r=!r};this.getZoomLevel=function(){return c.getZoomLevel()};this.setZoomLevel=function(a){c.setZoomLevel(a)};this.zoomOut=function(){var a=(b.getZoomLevel()/1.1).toFixed(2),a=Math.max(0.25,a);e(a,!0)};this.zoomIn=function(){var a=(1.1*b.getZoomLevel()).toFixed(2),a=Math.min(4,a);e(a,!0)};(function(){M();c&&(b.initialize(),
document.cancelFullScreen||document.mozCancelFullScreen||document.webkitCancelFullScreen||document.msExitFullscreen||(document.getElementById("fullscreen").style.visibility="hidden",document.getElementById("presentation").style.visibility="hidden"),document.getElementById("overlayCloseButton").addEventListener("click",b.toggleFullScreen),document.getElementById("fullscreen").addEventListener("click",b.toggleFullScreen),document.getElementById("presentation").addEventListener("click",function(){l||
b.toggleFullScreen();b.togglePresentationMode()}),document.addEventListener("fullscreenchange",q),document.addEventListener("webkitfullscreenchange",q),document.addEventListener("mozfullscreenchange",q),document.addEventListener("MSFullscreenChange",q),document.getElementById("download").addEventListener("click",function(){b.download()}),document.getElementById("zoomOut").addEventListener("click",function(){b.zoomOut()}),document.getElementById("zoomIn").addEventListener("click",function(){b.zoomIn()}),
document.getElementById("previous").addEventListener("click",function(){b.showPreviousPage()}),document.getElementById("next").addEventListener("click",function(){b.showNextPage()}),document.getElementById("previousPage").addEventListener("click",function(){b.showPreviousPage()}),document.getElementById("nextPage").addEventListener("click",function(){b.showNextPage()}),document.getElementById("pageNumber").addEventListener("change",function(){b.showPage(this.value)}),document.getElementById("scaleSelect").addEventListener("change",
function(){e(this.value)}),d.addEventListener("click",v),w.addEventListener("click",v),d.addEventListener("click",P),h.addEventListener("click",x),m.addEventListener("click",x),window.addEventListener("scalechange",function(a){var b=document.getElementById("customScaleOption"),c=B(String(a.scale));b.selected=!1;c||(b.textContent=Math.round(1E4*a.scale)/100+"%",b.selected=!0)},!0),window.addEventListener("resize",function(a){J&&(document.getElementById("pageWidthOption").selected||document.getElementById("pageAutoOption").selected)&&
e(document.getElementById("scaleSelect").value);v()}),window.addEventListener("keydown",function(a){var c=a.shiftKey;switch(a.keyCode){case 33:case 38:case 37:b.showPreviousPage();break;case 34:case 40:case 39:b.showNextPage();break;case 32:c?b.showPreviousPage():b.showNextPage()}}))})()};
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -25,18 +25,8 @@ EOS ...@@ -25,18 +25,8 @@ EOS
!slide!(http://test.com/slide-2.pdf) !slide!(http://test.com/slide-2.pdf)
EOS EOS
expect(renderer.render.to_s.gsub(/^ +/, '')).to eq(<<EOS) expect(renderer.render.to_s.gsub(/^ +/, '')).to eq(<<EOS)
<p> <p>!slide!(<a href="http://test.com/slide-1.pdf">http://test.com/slide-1.pdf</a>)<br>
<div class="embed-responsive embed-responsive-4by3"> !slide!(<a href="http://test.com/slide-2.pdf">http://test.com/slide-2.pdf</a>)</p>
<iframe style="text-align:center;" src="/ViewerJS/#http://test.com/slide-1.pdf"
width="400" height="300" allowfullscreen="true" webkitallowfullscreen="true"></iframe>
</div>
<br>
<div class="embed-responsive embed-responsive-4by3">
<iframe style="text-align:center;" src="/ViewerJS/#http://test.com/slide-2.pdf"
width="400" height="300" allowfullscreen="true" webkitallowfullscreen="true"></iframe>
</div>
</p>
EOS EOS
end end
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment