Skip to content

Commit

Permalink
For code & highlighting automatically use DIVs instead of SPANs for b…
Browse files Browse the repository at this point in the history
…locks.

Added endless scrolling.
  • Loading branch information
geoffyoungs committed Jul 27, 2011
1 parent a576373 commit 8db1aef
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 84 deletions.
14 changes: 13 additions & 1 deletion app/controllers/journal_controller.rb
Expand Up @@ -21,7 +21,19 @@ def view
end end


def load def load
dates = params[:dates].split(/,/) if entryDate = params['before-date']
@entry= JournalEntry.where(:date.lt => entryDate).order([[:date, Mongo::DESCENDING]]).first()
if @entry
render :content_type => 'application/javascript', :layout => false, :inline => <<-EOI
$("#spinner").remove();window.loadingNext = false;
$("#journal-data").append(<%= raw(render(:partial => 'entry', :locals => { :entry => @entry, :today => false }).to_json) %>);
EOI
else
render :content_type => 'application/javascript', :text => 'window.NoMoreData = true;$("#spinner").remove();', :layout => false
end
else
# Something else
end
end end


def search def search
Expand Down
83 changes: 4 additions & 79 deletions app/views/journal/view.html.erb
Expand Up @@ -5,7 +5,8 @@
<div id="tools"> <div id="tools">
<button id="bold" style="font-weight: bold">B</button> <button id="bold" style="font-weight: bold">B</button>
<button id="italic" style="font-style: italic">I</button> <button id="italic" style="font-style: italic">I</button>
<button id="hiliteColor" data-arg="#ffff00" style="background: #990">Highlight</button> <button id="code" data-arg="Droid Sans Mono, Courier, monospace" style="font-family: Droid Sans Mono, Courier, monospace;">Code</button>
<button id="highlight" data-arg="#ffff00" style="background: #990">Highlight</button>
<button id="removeformat">Clear formatting</button> <button id="removeformat">Clear formatting</button>
</div> </div>
</div> </div>
Expand Down Expand Up @@ -37,6 +38,7 @@
</div> </div>
</div> </div>
<script> <script>
var LoadData = <%=raw url_for(:load).to_json %>;
jQuery(function ($) { jQuery(function ($) {
$(".journal-entry").live('blur', function () { $(".journal-entry").live('blur', function () {
$.ajax(<%=raw url_for(:update).to_json %>, { 'type' : 'POST', 'data' : { 'date' : $(this).data('date'), 'entry' : $(this).html() } }) $.ajax(<%=raw url_for(:update).to_json %>, { 'type' : 'POST', 'data' : { 'date' : $(this).data('date'), 'entry' : $(this).html() } })
Expand All @@ -51,87 +53,10 @@ jQuery(function ($) {
$(".journal-entry[data-date=\""+date+"\"]").focus(); $(".journal-entry[data-date=\""+date+"\"]").focus();
} else { } else {
console.log("Can't find %s - %o ", date, journal); console.log("Can't find %s - %o ", date, journal);
// Load journal? // Load journal & display in popup?
} }
}); });



var resize = function () {
$('#journal-pane-container, #sidebar').css('height', ($(window).height()-32)+"px");
$('#journal-pane').css('min-height', '100%');
$('#today').css('width', ($('#journal-data').width())+"px");
var res = $("#search-results");
res.css('overflow-y','auto');
res.css('height', ($(window).height() - 32 - res[0].offsetTop)+"px");
};
resize();
$(window).resize(resize);

var cont = $('#journal-pane-container');
//cont.scrollTop(64);
var i = 0;
cont.scroll(function (e) {
if (cont.scrollTop() < 64 && false) {
console.log("Loading more content...");
i += 1;
var h = 83 + parseInt(Math.random() * 300);
var first_child = $("#journal-pane :first-child").first();
var offset = first_child.offset().top;
console.log(first_child);
$('#journal-pane').prepend('<div style="height: '+h+'px; border: 1px solid #ccc;">Blah '+i+'</div>');
console.log("Scroll top was %i is now %i", offset, first_child.offset().top);
console.log(first_child);
cont.scrollTop(first_child.offset().top);
// Load more content...
}
});


function clearStyleFromSelection() {
var sel = window.getSelection();
var blat = [], postscan = [];
for (var i = 0; i < sel.rangeCount; i++) {
var range = sel.getRangeAt(i);
for (var node = range.startContainer; node && node !== range.endContainer;
node = node.nextSibling) {
if (1 === node.nodeType) {
if ('SPAN' === node.nodeName.toUpperCase()) {
if ($(node).hasClass('Apple-style-span')) {
blat.push(node);
}
} else {
postscan.push(node);
}
}
}
}
var eliminate = function(index, node) {
$(node).replaceWith($(node).html());
}
$.each(postscan, function (index, node) {
$(node).find('.Apple-style-span').each(eliminate);
});
$.each(blat, eliminate);
}

document.execCommand('styleWithCSS', false, true);
$("#tools button").each(function () {
var id = $(this).attr('id');
var arg = null;
arg = $(this).data("arg");

$(this).click(function () {
console.log("execCommand %s", id);
if ("removeformat" === id) {
document.execCommand('unlink', false, null);
document.execCommand('removeformat', false, null);
clearStyleFromSelection();
} else {
document.execCommand(id, false, arg);
}
});
});

$(function() { $(function() {
$( "#datepicker" ).datepicker({ $( "#datepicker" ).datepicker({
dateFormat : "yy-mm-dd", dateFormat : "yy-mm-dd",
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Expand Up @@ -18,6 +18,8 @@


get "journal/view" get "journal/view"


get "journal/load", :as => :load

match "journal/search", :as => :search match "journal/search", :as => :search


post "journal/update", :as => :update post "journal/update", :as => :update
Expand Down
Binary file added public/images/ajax-loader.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
147 changes: 145 additions & 2 deletions public/javascripts/application.js
@@ -1,2 +1,145 @@
// Place your application-specific JavaScript functions and classes here jQuery(function ($) {
// This file is automatically included by javascript_include_tag :defaults var resize = function () {
$('#journal-pane-container, #sidebar').css('height', ($(window).height()-32)+"px");
$('#journal-pane').css('min-height', '100%');
$('#today').css('width', ($('#journal-data').width())+"px");
var res = $("#search-results");
res.css('overflow-y','auto');
res.css('height', ($(window).height() - 32 - res[0].offsetTop)+"px");
};
resize();
$(window).resize(resize);



// Auto-scroll
var cont = $('#journal-pane-container');
//cont.scrollTop(64);
var i = 0;
var spinner = new Image('/images/ajax-spinner.gif');
cont.scroll(function (e) {
var node = $("#journal-pane-container")[0];

if (!window.loadingNext) {
// Add 32px padding/warning?
if (node.scrollTop >= (node.scrollHeight - node.clientHeight - 32)) {
console.log("Loading more content...");
i += 1;
var h = 83 + parseInt(Math.random() * 300);
var last_child = $("#journal-data div[data-date]").last();
var date = $(last_child).data('date');

var load = function () {
$('#journal-data').append('<div id="spinner" style="text-align: center;"><img src="/images/ajax-loader.gif"></div>');
$.ajax(LoadData+"?before-date="+date);
window.loadingNext = true;
};
if (window.NoMoreData !== true) {
if (window.LoadData) {
load();
} else {
// Not loaded page yet?
jQuery(load);
}
}
}
}
});


function eachNodeInRange(range, callback) {
for (var node = range.startContainer;
node && node !== range.endContainer;
node = node.nextSibling) {
if (1 === node.nodeType) {
callback(node);
}
}
}

function eachSelectedRange(callback) {
var sel = window.getSelection();
for (var i = 0; i < sel.rangeCount; i++) {
var range = sel.getRangeAt(i);
callback(range);
}
}

function clearStyleFromSelection(klass) {
var blat = [], postscan = [];
eachSelectedRange(function (range) {
eachNodeInRange(range, function (node) {
if ('SPAN' === node.nodeName.toUpperCase()) {
if ($(node).hasClass(klass)) {
blat.push(node);
}
} else {
postscan.push(node);
}
});
});
var eliminate = function(index, node) {
$(node).replaceWith($(node).html());
}
$.each(postscan, function (index, node) {
$(node).find('SPAN.'+klass).each(eliminate);
});
$.each(blat, eliminate);
}

function rangeIsBlock(range) {
var looksLikeBlock = false;

eachNodeInRange(range, function(node) {
switch(node.nodeName) {
case 'BR': case 'DIV': case 'P': case 'LI': case 'H1': case 'H2': case 'H3': case 'H4': case 'H5': case 'H6':
case 'TABLE': case 'TR': case 'TD': case 'TH': case 'OL': case 'UL': case 'DT': case 'DD': case 'DL':
looksLikeBlock = true;
break;
default:
// do nothing
}
});

return looksLikeBlock;
}

function wrapSelectionIn(inline_snippet, block_snippet) {
var ranges = [];
var sel = window.getSelection();
for (var i = 0; i < sel.rangeCount; i++) {
ranges.push(sel.getRangeAt(i));
}
$.each(ranges, function (index, range) {
if (rangeIsBlock(range)) {
range.surroundContents($(block_snippet)[0]);
} else {
range.surroundContents($(inline_snippet)[0]);
}
});
}

document.execCommand('styleWithCSS', false, true);
$("#tools button").each(function () {
var id = $(this).attr('id');
var arg = null;
arg = $(this).data("arg");

$(this).click(function () {
console.log("execCommand %s", id);
if ("removeformat" === id) {
document.execCommand('unlink', false, null);
document.execCommand('removeformat', false, null);
clearStyleFromSelection('Apple-style-span');
} else if ("highlight" === id) {
// Should we distinguish between inline snippets & blocks?
wrapSelectionIn('<span class="journal-entry-highlight"></span>', '<div class="journal-entry-highlight"></div>');
} else if ("code" === id) {
// Should we distinguish between inline snippets & blocks?
wrapSelectionIn('<span class="journal-entry-code"></span>', '<div class="journal-entry-code"></div>');
} else {
document.execCommand(id, false, arg);
}
});
});
});
26 changes: 24 additions & 2 deletions public/stylesheets/application.css
Expand Up @@ -81,7 +81,8 @@ body {
top: 32px; top: 32px;
position: relative; position: relative;
} }
#journal-pane { #journal-data {
margin-bottom: 64px;
/* padding-top: 64px;*/ /* padding-top: 64px;*/
} }
/*#today { /*#today {
Expand Down Expand Up @@ -112,7 +113,7 @@ body {
#user, #tools { #user, #tools {
padding: 2px 12px; padding: 2px 12px;
display: inline-block; display: inline-block;
width: 20em; width: 40%;
} }
#tools { #tools {
-webkit-user-select: none; -webkit-user-select: none;
Expand All @@ -132,11 +133,13 @@ body {
padding: 0.5em; padding: 0.5em;
line-height: 1.2em; line-height: 1.2em;
} }

.journal-entry[contenteditable]:focus { .journal-entry[contenteditable]:focus {
outline: none; outline: none;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ffc)); background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ffc));
background-image: -moz-linear-gradient(top, #fff, #ffc); background-image: -moz-linear-gradient(top, #fff, #ffc);
} }

.weekend .journal-entry[contenteditable]:focus { .weekend .journal-entry[contenteditable]:focus {
outline: none; outline: none;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#f7f7f7), to(#ffc)); background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#f7f7f7), to(#ffc));
Expand Down Expand Up @@ -168,6 +171,7 @@ body {
#search-results h4 { #search-results h4 {
margin: 0.3em 0.7em; margin: 0.3em 0.7em;
} }

#search-results h5 { #search-results h5 {
font-family: Fontin, serif; font-family: Fontin, serif;
font-style: italic; font-style: italic;
Expand All @@ -192,6 +196,24 @@ body {
background: #ff9999; background: #ff9999;
} }


.journal-entry-highlight {
background: #ffff66;
border: 1px solid #ffcc00;
padding: 2px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}

.journal-entry-code {
font-family: "Droid Sans Mono", Courier New, Courier, monospace;
font-size: 0.9em;
background: #eeeeee;
padding: 2px;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}


#search-box input[type="search"] { #search-box input[type="search"] {
border: 1px solid #ccc; border: 1px solid #ccc;
Expand Down

0 comments on commit 8db1aef

Please sign in to comment.