Add preview functionality to rich text controls

This commit is contained in:
Tom Hughes 2012-03-03 18:40:44 +00:00
parent b6163f0fc2
commit 561f2f694a
15 changed files with 191 additions and 8 deletions

View file

@ -205,3 +205,51 @@ function makeShortCode(lat, lon, zoom) {
} }
return str; return str;
} }
/*
* Click handler to switch a rich text control to preview mode
*/
function previewRichtext(event) {
var editor = $(this).parents(".richtext_container").find("textarea");
var preview = $(this).parents(".richtext_container").find(".richtext_preview");
var width = editor.outerWidth() - preview.outerWidth() + preview.innerWidth();
var minHeight = editor.outerHeight() - preview.outerHeight() + preview.innerHeight();
editor.hide();
preview.load(editor.attr("data-preview-url"), { text: editor.val() });
preview.width(width);
preview.css("min-height", minHeight + "px");
preview.show();
$(this).siblings(".richtext_doedit").prop("disabled", false);
$(this).prop("disabled", true);
event.preventDefault();
}
/*
* Click handler to switch a rich text control to edit mode
*/
function editRichtext(event) {
var editor = $(this).parents(".richtext_container").find("textarea");
var preview = $(this).parents(".richtext_container").find(".richtext_preview");
preview.hide();
editor.show();
$(this).siblings(".richtext_dopreview").prop("disabled", false);
$(this).prop("disabled", true);
event.preventDefault();
}
/*
* Setup any rich text controls
*/
$(document).ready(function () {
$(".richtext_preview").hide();
$(".richtext_doedit").prop("disabled", true);
$(".richtext_dopreview").prop("disabled", false);
$(".richtext_doedit").click(editRichtext);
$(".richtext_dopreview").click(previewRichtext);
});

View file

@ -1040,3 +1040,61 @@ abbr.geo {
vertical-align: text-bottom; vertical-align: text-bottom;
border: 0; border: 0;
} }
/* Rules for rich text editors */
.richtext_container {
white-space: nowrap;
.richtext_content {
display: inline-block;
vertical-align: top;
.richtext_preview {
display: inline-block;
margin-top: 1px;
margin-bottom: 1px;
border: 4px solid #eee;
background-color: #eee;
white-space: normal;
> :first-child {
margin-top: 0px;
}
}
}
.richtext_help {
display: inline-block;
vertical-align: top;
background-color: #ddd;
margin-left: 15px;
padding: 5px 10px 10px 10px;
font-size: 12px;
p {
margin: 0px;
}
th {
vertical-align: top;
padding: 0px 15px 0px 0px !important;
}
td {
font-family: fixed;
line-height: 16px;
padding: 0px !important;
}
input.richtext_doedit {
margin-top: 5px !important;
margin-right: 10px !important;
}
input.richtext_dopreview {
margin-top: 5px !important;
margin-left: 10px !important;
}
}
}

View file

@ -85,4 +85,8 @@ class SiteController < ApplicationController
def copyright def copyright
@locale = params[:copyright_locale] || I18n.locale @locale = params[:copyright_locale] || I18n.locale
end end
def preview
render :text => RichText.new(params[:format], params[:text]).to_html
end
end end

View file

@ -121,6 +121,24 @@ module ApplicationHelper
Math.log(360.0 / (scale.to_f * 512.0)) / Math.log(2.0) Math.log(360.0 / (scale.to_f * 512.0)) / Math.log(2.0)
end end
def richtext_area(object_name, method, options = {})
id = "#{object_name.to_s}_#{method.to_s}"
format = options.delete(:format) || "markdown"
content_tag(:div, :id => "#{id}_container", :class => "richtext_container") do
output_buffer << content_tag(:div, :id => "#{id}_content", :class => "richtext_content") do
output_buffer << text_area(object_name, method, options.merge("data-preview-url" => preview_url(:format => format)))
output_buffer << content_tag(:div, "", :id => "#{id}_preview", :class => "richtext_preview")
end
output_buffer << content_tag(:div, :id => "#{id}_help", :class => "richtext_help") do
output_buffer << render("site/#{format}_help")
output_buffer << submit_tag(I18n.t("site.richtext_area.edit"), :id => "#{id}_doedit", :class => "richtext_doedit", :disabled => true)
output_buffer << submit_tag(I18n.t("site.richtext_area.preview"), :id => "#{id}_dopreview", :class => "richtext_dopreview")
end
end
end
private private
def javascript_strings_for_key(key) def javascript_strings_for_key(key)

View file

@ -10,7 +10,7 @@
</tr> </tr>
<tr valign="top"> <tr valign="top">
<td class="fieldName"><%= t 'diary_entry.edit.body' -%></td> <td class="fieldName"><%= t 'diary_entry.edit.body' -%></td>
<td><%= f.text_area :body, :cols => 80 %></td> <td><%= richtext_area :diary_entry, :body, :cols => 80 %></td>
</tr> </tr>
<tr valign="top"> <tr valign="top">
<td class="fieldName"><%= t 'diary_entry.edit.language' -%></td> <td class="fieldName"><%= t 'diary_entry.edit.language' -%></td>

View file

@ -13,8 +13,8 @@
<%= error_messages_for 'diary_comment' %> <%= error_messages_for 'diary_comment' %>
<%= form_for DiaryComment.new, :url => { :action => 'comment' } do |f| %> <%= form_for :diary_comment, :url => { :action => 'comment' } do |f| %>
<%= f.text_area :body, :cols => 80, :rows => 5 %> <%= richtext_area :diary_comment, :body, :cols => 80, :rows => 15 %>
<br /> <br />
<br /> <br />
<%= submit_tag t('diary_entry.view.save_button') %> <%= submit_tag t('diary_entry.view.save_button') %>

View file

@ -10,7 +10,7 @@
</tr> </tr>
<tr valign="top"> <tr valign="top">
<td class="fieldName"><%= t'message.new.body' %></td> <td class="fieldName"><%= t'message.new.body' %></td>
<td><%= f.text_area :body, :cols => 80, :value => @body %></td> <td><%= richtext_area :message, :body, :cols => 80, :value => @body %></td>
</tr> </tr>
<tr> <tr>
<td></td> <td></td>

View file

@ -0,0 +1,29 @@
<table>
<thead>
<tr>
<th colspan="2"><%= t "site.markdown_help.title" %></th>
</tr>
</thead>
<tbody>
<tr>
<th><%= t "site.markdown_help.headings" %></th>
<td># <%= t "site.markdown_help.heading" %><br />## <%= t "site.markdown_help.subheading" %></td>
</tr>
<tr>
<th><%= t "site.markdown_help.unordered" %></th>
<td>* <%= t "site.markdown_help.first" %><br />* <%= t "site.markdown_help.second" %></td>
</tr>
<tr>
<th><%= t "site.markdown_help.ordered" %></th>
<td>1. <%= t "site.markdown_help.first" %><br />2. <%= t "site.markdown_help.second" %></td>
</tr>
<tr>
<th><%= t "site.markdown_help.link" %></th>
<td>[<%= t "site.markdown_help.text" %>](<%= t "site.markdown_help.url" %>)</td>
</tr>
<tr>
<th><%= t "site.markdown_help.image" %></th>
<td>![<%= t "site.markdown_help.alt" %>](<%= t "site.markdown_help.url" %>)</td>
</tr>
</tbody>
</table>

View file

@ -63,7 +63,7 @@
<tr> <tr>
<td class="fieldName"><%= t 'user.account.profile description' %></td> <td class="fieldName"><%= t 'user.account.profile description' %></td>
<td><%= f.text_area :description, :rows => '5', :cols => '60' %></td> <td><%= richtext_area :user, :description, :rows => '15', :cols => '80' %></td>
</tr> </tr>
<tr> <tr>

View file

@ -9,7 +9,7 @@
<p> <p>
<%= f.label :reason, t('user_block.new.reason', :name => @this_user.display_name) %><br /> <%= f.label :reason, t('user_block.new.reason', :name => @this_user.display_name) %><br />
<%= f.text_area :reason, :cols => 80, :rows => 5 %> <%= richtext_area :user_block, :reason, :cols => 80, :rows => 20 %>
</p> </p>
<p> <p>
<%= label_tag 'user_block_period', t('user_block.new.period') %><br /> <%= label_tag 'user_block_period', t('user_block.new.period') %><br />

View file

@ -1404,6 +1404,23 @@ en:
permissive: "Permissive access" permissive: "Permissive access"
destination: "Destination access" destination: "Destination access"
construction: "Roads under construction" construction: "Roads under construction"
richtext_area:
edit: Edit
preview: Preview
markdown_help:
title: Parsed with Markdown
headings: Headings
heading: Heading
subheading: Subheading
unordered: Unordered list
ordered: Ordered list
first: First item
second: Second item
link: Link
text: Text
image: Image
alt: Alt text
url: url
trace: trace:
visibility: visibility:
private: "Private (only shared as anonymous, unordered points)" private: "Private (only shared as anonymous, unordered points)"

View file

@ -122,6 +122,9 @@ OpenStreetMap::Application.routes.draw do
# permalink # permalink
match '/go/:code' => 'site#permalink', :via => :get, :code => /[a-zA-Z0-9_@~]+[=-]*/ match '/go/:code' => 'site#permalink', :via => :get, :code => /[a-zA-Z0-9_@~]+[=-]*/
# rich text preview
match '/preview/:format' => 'site#preview', :as => :preview
# traces # traces
match '/user/:display_name/traces/tag/:tag/page/:page' => 'trace#list', :via => :get match '/user/:display_name/traces/tag/:tag/page/:page' => 'trace#list', :via => :get
match '/user/:display_name/traces/tag/:tag' => 'trace#list', :via => :get match '/user/:display_name/traces/tag/:tag' => 'trace#list', :via => :get

View file

@ -159,7 +159,9 @@ class DiaryEntryControllerTest < ActionController::TestCase
assert_select "input#latitude[name='diary_entry[latitude]']", :count => 1 assert_select "input#latitude[name='diary_entry[latitude]']", :count => 1
assert_select "input#longitude[name='diary_entry[longitude]']", :count => 1 assert_select "input#longitude[name='diary_entry[longitude]']", :count => 1
assert_select "input[name=commit][type=submit][value=Save]", :count => 1 assert_select "input[name=commit][type=submit][value=Save]", :count => 1
assert_select "input", :count => 5 assert_select "input[name=commit][type=submit][value=Edit]", :count => 1
assert_select "input[name=commit][type=submit][value=Preview]", :count => 1
assert_select "input", :count => 7
end end
end end
end end

View file

@ -54,6 +54,10 @@ class SiteControllerTest < ActionController::TestCase
{ :path => "/go/shortcode", :method => :get }, { :path => "/go/shortcode", :method => :get },
{ :controller => "site", :action => "permalink", :code => "shortcode" } { :controller => "site", :action => "permalink", :code => "shortcode" }
) )
assert_routing(
{ :path => "/preview/formatname", :method => :get },
{ :controller => "site", :action => "preview", :format => "formatname" }
)
end end
## Lets check that we can get all the pages without any errors ## Lets check that we can get all the pages without any errors

View file

@ -367,7 +367,7 @@ class UserControllerTest < ActionController::TestCase
assert_template :account assert_template :account
assert_select "div#errorExplanation", false assert_select "div#errorExplanation", false
assert_select "div#notice", /^User information updated successfully/ assert_select "div#notice", /^User information updated successfully/
assert_select "table#accountForm > tr > td > textarea#user_description", user.description assert_select "table#accountForm > tr > td > div#user_description_container > div#user_description_content > textarea#user_description", user.description
# Changing name to one that exists should fail # Changing name to one that exists should fail
user.display_name = users(:public_user).display_name user.display_name = users(:public_user).display_name