ふとした時にブログサイトを作成していたのですが、実際に記事を書いている段階でいまいちデザインのイメージやレイアウトがつかめない…
通常Railsにデフォルトで用意されている入力エリアだとtextしか入力できないので一度投稿しないと勝手がわからず効率が悪いんですよね…
そこでQiita記事のようなプレビュー機能があったらいいなと思ったのでこちらでまとめてみました。
完成形は☝のようにmarkdown形式でtextエリアに入力し、プレビューボタンを押すとその結果が表示されるようになります。
前提
- model: Article(title: string, content: text)
- controller: articles_controller
gem 'redcarpet'
$ bundle install
module MarkdownHelper
def markdown(text)
unless @markdown
options = {
filter_html: true,
hard_wrap: true,
space_after_headers: true,
}
extensions = {
autolink: true,
no_intra_emphasis: true,
fenced_code_blocks: true,
}
renderer = Redcarpet::Render::HTML.new(options)
@markdown = Redcarpet::Markdown.new(renderer, extensions)
end
@markdown.render(text).html_safe
end
end
controllerの設定
今回は通常のコントローラーとは別にapiというapiというnamspaceを作成し、こちらにviewからリクエストをjson形式で送り、結果をプレビューエリアに表示します。
apiディレクトリを作成
↓
その配下にarticles_controller.rbを作成(通常のarticle_controllerとは別途)
class Api::ArticlesController < ApplicationController
def preview
@html = view_context.markdown(params[:body])
end
end
routes
リクエストを受け取れるようにルーティングも変更します。
resources :articles
## json形式でのルーティングを作成
namespace :api, format: 'json' do
get 'articles/preview'
end
js
肝心なjsです。
window.addEventListener('DOMContentLoaded', function(){
//画面がロードされてからイベントを発生
$('#preview').on('click', function() {
var content = $('#mark-down-area').val();
$.ajax({
url: '/api/articles/preview',
dataType: 'json',
type: 'GET',
data: { body: content }
})
.done(function(html) {
$('#preview-area').toggleClass("open");
$('#preview-area').append(html.body);
$('#markdown').fadeToggle();
$('#preview').fadeToggle();
})
.fail(function() {
alert('プレビューを表示できませんでした。');
})
})
$('#markdown').on('click', function() {
$('#preview-area').empty();
$('#preview-area').toggleClass("open");
$('#preview').fadeToggle();
$('#markdown').fadeToggle();
})
});
json builder
json.body @html
view
<%= form_for @article, :html => {multipart: true} do |f| %>
<div class = "pd col-6 right preview-area" id = "preview-area">
</div>
<div class="form-group">
<div class = "col-md-10">
<%= f.label "タイトル" %>
<span style = "color:red">*</span>
<%= f.text_field :title, required: true, class: "form-control",maxlength: 32 %>
</div>
<div class = "col-md-10"><%= f.label "本文"%>
<%= f.text_area :content, required: true, class: "form-control", id: "mark-down-area"%>
</div>
</div>
<div class = "col-md-10">
<label >カテゴリー</label>
<div class="ui field ">
<%= f.collection_check_boxes :category_ids, Category.all, :id, :name do |cd| %>
<%= cd.label(){cd.check_box(class: "ui radio checkbox") + cd.text} %>
<% end %>
</div>
</div>
<div class="row center margin-vertical">
<div class="col-3">
<div class="btn btn-success" id = "markdown" style = "display:none">
戻す
</div>
</div>
<div class="col-3">
<div class="btn btn-success" id = "preview">
プレビュー
</div>
</div>
</div>
<div class = "form-group center">
<%= f.submit "保存", class: "col-4 btn btn-primary" %>
</div>
<% end %>
最後にcssでデザインを整えてプレビューボタンのクリック時にプレビューエリアがスライドインされるようにします。
また今回はより使いやすいように表示エリア(.article-display)とプレビューエリア(.preview-area)のデザインを統一してます。
css
# プレビューエリアと実際の表示エリアを同じデザインに統一
.preview-area,.article-display{
color: rgb(80,80,80);
font:{
size:16px;
weight: normal;
}
h2{
border-left: solid 5px orange;
padding:20px;
margin: 50px 0;
background-color:rgb(250,250,250);
font-weight: bold;
font-size: 28px;
}
h3{
border-left: solid 5px skyblue;
padding-left: 20px;
margin: 30px 0;
font-weight: bold;
font-size: 24px;
}
ul{
padding:10px;
border: dashed 2px royalblue;
background-color: rgb(250,250,270);
}
p{
img{
width: 100%;
}
}
}
----------------------------
.preview-area{
transform: translate(1000px);
position: fixed;
top: 0;
bottom:0;
right: 0;
z-index: 10;
border-left:dashed 1px rgb(200,200,200);
background-color:white;
overflow-y: auto;
transition: all .5s;
}
.open{
transform:translate(0);
}
# openクラスを付与することでプレビューエリアを横からスライドイン
これで投稿画面でプレビューボタンをクリックするとプレビュー画面がスライドインされるようになりました。
参考にさせていただいた記事
RailsにMarkdown導入してプレビュー表示させるまで
大いに参考させていただきました、ありがとうございます。