Skip to content

Commit

Permalink
Merge pull request #128 from lepo-project/easier-ui-for-highlight
Browse files Browse the repository at this point in the history
Release v0.2.2
  • Loading branch information
kyoshizaki authored Feb 10, 2018
2 parents 8926164 + 2b06264 commit 1ed4d28
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 68 deletions.
14 changes: 7 additions & 7 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ GEM
io-like (~> 0.3.0)
arel (7.1.4)
ast (2.4.0)
autoprefixer-rails (7.2.5)
autoprefixer-rails (7.2.6)
execjs
autosize (2.4.0.0)
bindex (0.5.0)
Expand Down Expand Up @@ -88,7 +88,7 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
combine_pdf (1.0.8)
combine_pdf (1.0.9)
ruby-rc4 (>= 0.1.5)
concurrent-ruby (1.0.5)
crass (1.0.3)
Expand All @@ -102,15 +102,15 @@ GEM
factory_bot_rails (4.8.2)
factory_bot (~> 4.8.2)
railties (>= 3.0.0)
ffi (1.9.18)
ffi (1.9.21)
font-awesome-rails (4.7.0.3)
railties (>= 3.2, < 5.2)
globalid (0.4.1)
activesupport (>= 4.2.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
http_accept_language (2.1.1)
i18n (0.9.3)
i18n (0.9.4)
concurrent-ruby (~> 1.0)
i18n_generators (2.1.1)
rails (>= 3.0.0)
Expand Down Expand Up @@ -229,9 +229,9 @@ GEM
scss_lint (0.56.0)
rake (>= 0.9, < 13)
sass (~> 3.5.3)
selenium-webdriver (3.8.0)
selenium-webdriver (3.9.0)
childprocess (~> 0.5)
rubyzip (~> 1.0)
rubyzip (~> 1.2)
spring (2.0.2)
activesupport (>= 4.2)
spring-watcher-listen (2.0.1)
Expand All @@ -254,7 +254,7 @@ GEM
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.4)
unf_ext (0.0.7.5)
unicode-display_width (1.3.0)
unicorn (5.4.0)
kgio (~> 2.6)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,84 @@
function addHighlight(mouseupTarget, selectionTarget, relativeUrl) {
function showCreateHighlightBtns(mouseupTarget, selectionTarget) {
// mouseupTarget: jQuery element to detect mouseup event
mouseupTarget.mouseup(function(evt) {
// selectionTarget: document element for text selection
var selectedText = selectionTarget.getSelection().getRangeAt(0).toString();
if (selectedText.length > 0) {
jQuery.ajax({type: "post", url: relativeUrl + "/courses/ajax_create_snippet/", data:{'description': selectedText}});
if (showHighlightBtns(evt, true)) {
document.getElementById('highlight-create-btn').onclick = function() {
jQuery.ajax({type: 'post', url: '<%= Rails.application.config.relative_url_root %>/courses/ajax_create_snippet/', data:{'description': selectedText}});
hideHighlightBtns(selectionTarget);
};
document.getElementById('highlight-cancel-btn').onclick = function() {
hideHighlightBtns(selectionTarget);
};
return
};
};
hideHighlightBtns (selectionTarget);
});
};

function showDeleteHighlightBtns(evt, element) {
if (showHighlightBtns(evt, false)) {
var highlightId = element.getAttribute('data-lepo').slice('highlight-'.length);
document.getElementById('highlight-delete-btn').onclick = function() {
jQuery.ajax({type: 'post', url: '<%= Rails.application.config.relative_url_root %>/courses/ajax_destroy_snippet/', data:{'snippet_id': highlightId}});
removeElement(document.getElementById('page-frame').contentWindow.document, highlightId)
hideHighlightBtns();
};
document.getElementById('highlight-cancel-btn').onclick = function() {
hideHighlightBtns();
};
setTimeout(function() {hideHighlightBtns();}, 2000)
};

function removeElement(targetDocument, highlightId) {
elements = targetDocument.querySelectorAll('lepo-highlight[data-lepo="highlight-' + highlightId + '"]');
for (var i = 0; i < elements.length; i++) {
if (elements[i].firstChild == null) {
$(elements[i]).remove();
} else {
$(elements[i].firstChild).unwrap();
}
}
}
}

function showHighlight(targetDocument, targetClass, highlightText) {
var documentText = ""; // Full text of target document
function showHighlightBtns(evt, createBtnDisplay) {
var btns = document.getElementById('highlight-btns');
if (btns.style.display == 'inline-flex') {
return false
} else {
document.getElementById('highlight-create-btn').style.display = createBtnDisplay ? 'block' : 'none';
document.getElementById('highlight-delete-btn').style.display = createBtnDisplay ? 'none' : 'block';
btns.style.top = (evt.pageY - 16) + 'px';
btns.style.left = (evt.pageX - 12) + 'px';
btns.style.display = 'inline-flex';
return true
};
}

function hideHighlightBtns (selectionTarget) {
document.getElementById('highlight-btns').style.display = 'none';
if (selectionTarget != null) {
selectionTarget.getSelection().removeAllRanges();
}
}

function showHighlight(targetDocument, targetClass, highlightId, highlightText) {
var documentText = ''; // Full text of target document
var textNodes = []; // Array to store text nodes
var textAccumLengths = []; // Array to store accumulate character lengths for text node

setDocumentText();
searchHighlightText(documentText, 0);

function setDocumentText(){
documentText = "";
documentText = '';
textNodes = [];
textAccumLengths = [];
if (targetClass === "") {
if (targetClass === '') {
// For HTML
var walker = targetDocument.createTreeWalker(targetDocument.body, NodeFilter.SHOW_ALL, null, false);
} else {
Expand Down Expand Up @@ -98,7 +154,6 @@ function showHighlight(targetDocument, targetClass, highlightText) {
searchHighlightText(checkText.slice(index + highlightText.length), textIndex + highlightText.length);
}


function setHighlight(){
// Create range object for highlight
var range = targetDocument.createRange();
Expand Down Expand Up @@ -161,12 +216,12 @@ function showHighlight(targetDocument, targetClass, highlightText) {
var range = targetDocument.createRange();
range.selectNode(node);
// Change target node to lepo-highlight element
node = targetDocument.createElement("lepo-highlight");
node = targetDocument.createElement('lepo-highlight');
range.surroundContents(node);
setStyle(node);
} else if(node.nodeType != Node.COMMENT_NODE){
var clone = node.cloneNode(true);
var newChild = targetDocument.createElement("lepo-highlight");
var newChild = targetDocument.createElement('lepo-highlight');
for(var i=0;i<clone.childNodes.length;i++){
newChild.appendChild(clone.childNodes[i]);
}
Expand All @@ -180,6 +235,8 @@ function showHighlight(targetDocument, targetClass, highlightText) {
function setStyle(target){
target.style.setProperty('background-color', '#fe0', 'important');
target.style.setProperty('display', 'inline-block', 'important');
target.setAttribute('data-lepo', 'highlight-' + highlightId);
target.setAttribute('onmouseover', 'window.parent.showDeleteHighlightBtns(event, this)');
}

function nextSibling(){
Expand Down
15 changes: 15 additions & 0 deletions app/assets/stylesheets/components/_highlight.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// variables & mixins for highlight
//

@mixin highlight-btns {
#highlight-btns {
box-shadow: 1px 1px 2px #666;
display: none;
position: absolute;
z-index: 100;
button {
padding: 0 0.3rem 0 0.6rem;
}
}
}
15 changes: 2 additions & 13 deletions app/assets/stylesheets/main_pane.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@import 'components/card';
@import 'components/color';
@import 'components/file_submit_btn';
@import 'components/highlight';
@import 'components/image';
@import 'components/toolbar';
@import 'components/versatile_cards';
Expand Down Expand Up @@ -159,19 +160,6 @@
}

#message-card {
.message-info {
background-color: #666;
color: #fff;
display: none;
font-size: 20pt;
opacity: 0.9;
padding: 20px 0;
position: absolute;
text-align: center;
top: 32px;
width: 100%;
z-index: 1000;
}
.card-info {
background-color: #ffb;
box-shadow: 1px 1px 2px #222;
Expand Down Expand Up @@ -201,6 +189,7 @@

#resource {
@include file-submit-btn;
@include highlight-btns;
@include image-80px;
@include report-card;
@include resources-card;
Expand Down
6 changes: 6 additions & 0 deletions app/controllers/courses_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,12 @@ def ajax_destroy_lesson
render 'layouts/renders/resource', locals: { resource: 'courses/edit_lessons' }
end

def ajax_destroy_snippet
snippet = Snippet.find_by(id: params[:snippet_id])
snippet.destroy if snippet.deletable?(session[:id])
head :no_content
end

def ajax_duplicate
original_course = Course.find params[:original_id]
return unless original_course
Expand Down
2 changes: 1 addition & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def full_name_all

def highlight_texts(lesson_note_id, page_file_id)
ids = NoteIndex.where(note_id: lesson_note_id, item_type: 'Snippet').pluck(:item_id)
Snippet.where(id: ids, manager_id: id, category: 'text', source_type: 'page_file', source_id: page_file_id).pluck(:description)
Snippet.where(id: ids, manager_id: id, category: 'text', source_type: 'page_file', source_id: page_file_id).pluck(:id, :description)
end

def open_notes
Expand Down
2 changes: 1 addition & 1 deletion app/views/contents/_index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<h2 class="card-header"><%= t('.system_version') %></h2>
<div class="card-body">
<p class="card-text">
0.2.1 (<%= t '.released_at' %> <%= l(Date.new(2018, 1, 18), format: :default) %>)
0.2.2 (<%= t '.released_at' %> <%= l(Date.new(2018, 2, 10), format: :default) %>)
</p>
</div>
</div>
Expand Down
19 changes: 15 additions & 4 deletions app/views/courses/_toolbar_show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,28 @@
<div id="toolbar-btns">
<div class="btn-group">
<% if @note %>
<%= link_to(raw("<i class='fa fa-book'></i> ") + t('activerecord.models.content'), {controller: 'courses', action: 'ajax_toggle_lesson_note', from: 'note' }, {class: 'toolbar-btn', remote: true}) %>
<div class="toolbar-btn">
<i class='fa fa-plus'></i> <%= t('activerecord.models.sticky') %> (<%= pg['stickies'].size %>)
<!-- For lesson note view -->
<%= link_to(raw("<i class='fa fa-book'></i> "), {controller: 'courses', action: 'ajax_toggle_lesson_note', from: 'note' }, {class: 'toolbar-btn', 'data-toggle': 'tooltip', 'data-placement': 'bottom', title: t('.show_content'), remote: true}) %>
<div class="toolbar-btn" data-toggle='tooltip' data-placement='bottom' title="<%= t('.create_sticky') %>">
<i class='fa fa-sticky-note-o'></i> (<%= pg['stickies'].size %>)
</div>
<div class="toolbar-btn dropdown-toggle"><i class="fa fa-cog fa-2x"></i></div>
<% else %>
<%= link_to(raw("<i class='fa fa-file-text'></i> ") + t('activerecord.models.note'), { controller: 'courses', action: 'ajax_toggle_lesson_note', from: 'content' }, class: 'toolbar-btn', remote: true) %>
<!-- For content page view -->
<%= link_to(raw("<i class='fa fa-file-text'></i> "), { controller: 'courses', action: 'ajax_toggle_lesson_note', from: 'content' }, {class: 'toolbar-btn', 'data-toggle': 'tooltip', 'data-placement': 'bottom', title: t('.show_note'), remote: true}) %>
<div id="sticky-toolbar">
<% url_hash = {action: 'ajax_arrange_sticky_panel', content_id: @content.id, target_type: 'PageFile', target_id: pg['file_id'], sticky_panel: 'show'} %>
<%= render partial: 'stickies/toolbar', locals: {stickies: pg['stickies'], url_hash: url_hash} %>
</div>
<% end %>
</div>
</div>

<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="tooltip"]').on('click', function () {
$(this).tooltip('hide')
})
})
</script>
16 changes: 4 additions & 12 deletions app/views/courses/renders/snippet_saved.js.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
$("#page-file-snippet-saved").slideToggle(100);
setTimeout(function() {
$("#page-file-snippet-saved").slideToggle(100);
}, 2000);

// Reload highlight texts in page
<% current_user.highlight_texts(@course.lesson_note(session[:id]).id, pg['file_id']).each do |text| %>
var iframe_document = document.getElementById('page-frame').contentDocument;
<% current_user.highlight_texts(@course.lesson_note(session[:id]).id, pg['file_id']).each do |highlight| %>
var iframeDoc = document.getElementById('page-frame').contentDocument;
<% case pg['file_type'] when 'pdf' %>
showHighlight(iframe_document, 'textLayer', "<%= text %>");
showHighlight(iframeDoc, 'textLayer', <%= highlight[0] %>, "<%= highlight[1] %>");
<% when 'html' %>
showHighlight(iframe_document, '', "<%= text %>");
showHighlight(iframeDoc, '', <%= highlight[0] %>, "<%= highlight[1] %>");
<% end %>
<% end %>

// Release text selection
iframe_document.getSelection().removeAllRanges();
5 changes: 0 additions & 5 deletions app/views/layouts/_message_card.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,3 @@
<script>
$("#message-card-closer").click(function(){toggleShortcutKey();})
</script>


<div id="page-file-snippet-saved" class="message-info">
<%= t('.snippet_saved') %>
</div>
21 changes: 12 additions & 9 deletions app/views/layouts/_page_viewer.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
<%= render(partial: 'stickies/sticky_panel', locals: { stickies: pg['stickies'] }) %>
</div>

<div id="highlight-btns" class="btn-group" role="group" aria-label="highlight-btns">
<button id="highlight-create-btn" type="button" class="btn btn-light"><i class='fa fa-paint-brush fa-lg'></i></button>
<button id="highlight-delete-btn" type="button" class="btn btn-light"><i class='fa fa-trash-o fa-lg'></i></button>
<button id="highlight-cancel-btn" type="button" class="btn btn-light"><i class='fa fa-times-circle fa-lg'></i></button>
</div>

<script>
document.getElementById('page-frame').onload = function(e){
Expand All @@ -15,20 +20,18 @@ document.getElementById('page-frame').onload = function(e){
keyBinder($(iframeWin));

<% if @course %>
addHighlight($(iframeDoc), iframeDoc, "<%= Rails.application.config.relative_url_root %>");
showCreateHighlightBtns($(iframeDoc), iframeDoc);
<% case pg['file_type'] when 'pdf' %>
// Show highlight color even while text is selecting
$(this.contentDocument).find("head").append($('<style>#pdfjs_viewer-minimal *::selection {background-color: #fe0;} #pdfjs_viewer-minimal *::-moz-selection {background-color: #fe0;}</style>'))
// Set color for text selection
$(this.contentDocument).find("head").append($('<style>#pdfjs_viewer-minimal .textLayer ::selection {background-color: #acf;} #pdfjs_viewer-minimal *::-moz-selection {background-color: #acf;}</style>'))
this.contentDocument.addEventListener('textlayerrendered', function (e) {
<% current_user.highlight_texts(@course.lesson_note(session[:id]).id, pg['file_id']).each do |text| %>
showHighlight(this, 'textLayer', "<%= text %>");
<% current_user.highlight_texts(@course.lesson_note(session[:id]).id, pg['file_id']).each do |highlight| %>
showHighlight(this, 'textLayer', <%= highlight[0] %>, "<%= highlight[1] %>");
<% end %>
}, true);
<% when 'html' %>
// Show highlight color even while text is selecting
$(this.contentDocument).find("head").append($('<style>*::selection {background-color: #fe0;} *::-moz-selection {background-color: #fe0;}</style>'))
<% current_user.highlight_texts(@course.lesson_note(session[:id]).id, pg['file_id']).each do |text| %>
showHighlight(this.contentDocument, '', "<%= text %>");
<% current_user.highlight_texts(@course.lesson_note(session[:id]).id, pg['file_id']).each do |highlight| %>
showHighlight(this.contentDocument, '', <%= highlight[0] %>, "<%= highlight[1] %>");
<% end %>
<% end %>
<% end %>
Expand Down
3 changes: 0 additions & 3 deletions app/views/layouts/renders/all_with_pg.js.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
$('#main-nav').html("<%= j render(partial: 'layouts/main_nav') %>");
$('#variable-toolbar').html("<%= j render(partial: 'toolbar_show', locals: {pg: pg}) %>");
$('#resource').html("<%= j render(partial: resource, locals: {pg: pg}) %>");

// FIXME: Currently, text highlights can only be abled on pages other than the cover nor assignment
// addHighlight($(document.getElementById("simple-html-content")), document, "<%#= Rails.application.config.relative_url_root %>");
Loading

0 comments on commit 1ed4d28

Please sign in to comment.