diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 02ff58b..2bcb576 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -40,7 +40,7 @@ register_event_for_close_dialog =-> $('.ui-dialog-content').dialog('close') ) -notify = -> +window.notify = -> return if $('#notice').length <= 0 height = $('#notice').css('height') $('#notice') diff --git a/app/assets/javascripts/clips_form.js.coffee.erb b/app/assets/javascripts/clips_form.js.coffee.erb index e5ac4ee..cad2f92 100644 --- a/app/assets/javascripts/clips_form.js.coffee.erb +++ b/app/assets/javascripts/clips_form.js.coffee.erb @@ -1,33 +1,27 @@ $( -> - $clip_field = $('#clip_dialog') $container = $('#container') - $clip_field.dialog({ - autoOpen: false, - title: '投稿ダイアログ', - closeOnEscape: true, - modal: true, - resizable: false, - minWidth: 480, - buttons: { - 'キャンセル': -> $(@).dialog('close') - } - }) - - $container.on('click', '.box img', -> - $('img#selected').removeAttr('id') - $(@).attr('id', 'selected') - - url = $(@).attr('src') - $('#clip_url').attr('value', url) - ) + initialize_new_clip_dialog() + + $container.on('click', '.clip a', (event) -> + # デフォルトの挙動をキャンセル + event.stopPropagation() + event.preventDefault() + + $box = $(@).closest('.box') + $image = $box.find('img') - $container.on('click', '#selected', -> $preview_image = $('') - $preview_image.attr('src', $(@).attr('src')) - $preview_image.attr('style', $(@).attr('style')) + $preview_image.attr('src', $image.attr('src')) + $preview_image.attr('style', $image.attr('style')) $('#preview').html($preview_image) - $clip_field.dialog('open') + $('#clip_url').attr('value', $image.attr('src')) + + # TODO: 追加済み項目は追加できないようにする + # $box.css({ opacity: 0.5 }) + # $box.find('.clip').addClass('hidden') + + show_new_clip_dialog() ) $('#load').click( -> @@ -36,3 +30,11 @@ $( -> $container.html('<%= image_tag 'loader.gif' %>') ) ) + +initialize_new_clip_dialog = -> + $new_clip_dialog = $('#new_clip_dialog') + $new_clip_dialog.appendTo('body') + +show_new_clip_dialog = -> + $new_clip_dialog = $('#new_clip_dialog') + $new_clip_dialog.modal('show') diff --git a/app/assets/javascripts/wall.js.coffee.erb b/app/assets/javascripts/wall.js.coffee.erb index 19ee84e..f5f3eeb 100644 --- a/app/assets/javascripts/wall.js.coffee.erb +++ b/app/assets/javascripts/wall.js.coffee.erb @@ -49,7 +49,7 @@ window.resize_images = ($container) -> $(@).width(width) $(@).height(height) else - $(@).parent().remove() + $(@).closest('.box').remove() ) is_available_image_size = (width, height) -> diff --git a/app/assets/stylesheets/application.css.scss.erb b/app/assets/stylesheets/application.css.scss.erb index 5ff090a..85dac5c 100644 --- a/app/assets/stylesheets/application.css.scss.erb +++ b/app/assets/stylesheets/application.css.scss.erb @@ -135,6 +135,26 @@ $logo_height: $header_height; } } +#header .left { + .new > a, + .like > a { + // hover時の背景グラデーションがずれるのを防ぐ + background-position: 0% 0%; + font-weight: normal; + &:before { + font-weight: bold; + } + } + + .new > a { + @include icon(plus); + } + + .like > a { + @include icon(heart); + } +} + #header .profile a, #header .signin a { font-weight: normal; @@ -177,15 +197,18 @@ $logo_height: $header_height; } } +#header .signin form { + text-align: center; +} + #header form { $width: 250px; $padding: 12px; width: $width; padding: $padding; - text-align: center; + text-align: left; background-color: #fff3da; - @include border-bottom-radius(4px); input { margin-bottom: 10px; @@ -279,6 +302,12 @@ $logo_height: $header_height; } } +#alert { + margin: 1.5em 0 2em; + color: red; + text-align: center; +} + #notice { position: absolute; top: $header_height; @@ -329,3 +358,18 @@ $main_width: 1000px; #dialog { @extend .fade; } + +/* chosen */ +form .chosen-container { + margin: 10px 5px 0; + + .chosen-choices { + @extend input[type="text"]; + @include box-sizing(content-box); + margin: 0; + } + + input { + padding-left: 0; + } +} diff --git a/app/assets/stylesheets/clips.css.scss b/app/assets/stylesheets/clips.css.scss index 4e37f45..be73688 100644 --- a/app/assets/stylesheets/clips.css.scss +++ b/app/assets/stylesheets/clips.css.scss @@ -2,20 +2,23 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@import "compass/utilities"; -@import "compass/css3"; - @import "bootstrap/variables"; @import "bootstrap/mixins"; @import "bootstrap/buttons"; @import "bootstrap/forms"; +@import "compass/utilities"; +@import "compass/css3"; + $margin: 20px; $clip_width: 860px; $image_box_width: 580px; $info_box_width: $clip_width - $image_box_width - $margin; #image_selecter { + margin: 20px auto; + text-align: center; + h2 { font-size: x-large; margin-bottom: 0.5em; @@ -25,39 +28,67 @@ $info_box_width: $clip_width - $image_box_width - $margin; font-size: large; margin-bottom: 0.5em; } +} - form { - margin: 20px auto; - text-align: center; - @extend .form-inline; - - input[type="submit"] { - @extend .btn; - } - } +#image_selecter #container { + text-align: center; .box { - margin: 0; - width: auto; - border: 0; + margin: 5px; + + img { + @include border-radius(4px); + } } +} - .box img { - border: 5px solid transparent; - &#selected { - border-color: #666666; +// 親ダイアログが.hideを指定していると +// chosen初期化時にwidth: 0が指定されてしまうので +// 対策のために一定幅を強制 +#new_clip_dialog { + $feild_width: 215px; + $padding: 5px; + + .chosen-choices { + width: $feild_width - ($padding * 2) !important; + input { + width: 5em !important; } } - #container { - text-align: center; + .chosen-drop, + .chosen-drop ul { + width: $feild_width !important; } } -#preview { - float: left; - margin-right: 10px; - min-height: 150px; +#new_clip_dialog form { + @extend .form-inline; + + label { + display: block; + } + + .title input, + .chosen-container { + margin-top: 0; + margin-bottom: 10px; + } + + input[type="submit"] { + @extend .btn; + @extend .btn-primary; + } + + #preview { + @include inline-block; + vertical-align: top; + margin-right: 10px; + } + + #field { + @include inline-block; + } } /* dialog */ diff --git a/app/assets/stylesheets/matomes.css.scss b/app/assets/stylesheets/matomes.css.scss index 1418065..4c82503 100644 --- a/app/assets/stylesheets/matomes.css.scss +++ b/app/assets/stylesheets/matomes.css.scss @@ -255,19 +255,8 @@ $cover_size: 100px; @extend .btn-primary; } - .chosen-container { - margin: 10px 5px 0; - - .chosen-choices { - @extend input[type="text"]; - @include box-sizing(content-box); - width: 640px; - margin: 0; - } - - input { - padding-left: 0; - } + .chosen-choices { + width: 640px; } } diff --git a/app/assets/stylesheets/wall.css.scss.erb b/app/assets/stylesheets/wall.css.scss.erb index 529ba88..ac5725b 100644 --- a/app/assets/stylesheets/wall.css.scss.erb +++ b/app/assets/stylesheets/wall.css.scss.erb @@ -59,6 +59,10 @@ } } + .image_box img { + vertical-align: middle !important; + } + .image_box a img { @include border-top-radius(5px); cursor: url("<%= image_path 'cursor_zoom_in.cur' %>"), pointer; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8a6c686..e95339a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,4 +7,22 @@ class ApplicationController < ActionController::Base def first_page? params[:page].blank? || params[:page].to_i <= 1 end + + def tag_names_by_params(target=nil) + tag_names = target ? params[target].delete(:tags) : params.delete(:tags) + tag_names ||= [] + tag_names.map! {|tag_name| tag_name.strip } + tag_names.reject!(&:blank?) + end + + def update_tags_for(obj, tag_names) + return if tag_names.blank? + obj_tag_names = Tag.for(obj).pluck(:name) + add_tag_names = tag_names - obj_tag_names + remove_tag_names = obj_tag_names - tag_names + Tag.where(name: remove_tag_names).for(obj).destroy_all if remove_tag_names.any? + add_tag_names.each do |add_tag_name| + obj.tags.create!(name: add_tag_name, user: current_user) + end + end end diff --git a/app/controllers/clips_controller.rb b/app/controllers/clips_controller.rb index b7c0bb8..49efdf5 100644 --- a/app/controllers/clips_controller.rb +++ b/app/controllers/clips_controller.rb @@ -22,20 +22,13 @@ def get_image_tags @clip = Clip.new(params[:clip]) return unless @clip - doc = Hpricot(load_html_cahce_file) - @image_tags = (doc/:img).paginate(page: params[:page], per_page: Clip.per_page) - @html = @image_tags.join + @image_tags = image_tags_from_html + @image_tags = image_tag(@clip.url) if @image_tags.blank? rescue + logger.error $!.message + $!.backtrace.join("\n") render nothing: true unless @clip end - def get_image_tags_for_next_page - doc = Hpricot(load_html_cahce_file) - image_tags = (doc/:img).paginate(page: params[:page], per_page: Clip.per_page) - html = "
#{image_tags.map(&insert_div_tag_for_image_tag).join}
" - render text: html - end - def like @clip = Clip.where(id: params[:id]).first current_user.like(@clip) unless @clip.nil? @@ -128,6 +121,7 @@ def edit # POST /clips # POST /clips.json def create + tag_names = tag_names_by_params(:clip) clip_attr = { user_id: current_user.id } @clip = Clip.new(clip_attr.merge(params[:clip])) @@ -135,12 +129,16 @@ def create respond_to do |format| if !exist_image_flag && @clip.save - format.html { redirect_to @clip, notice: 'Clip was successfully created.' } + update_tags_for(@clip, tag_names) + + format.html { redirect_to @clip, notice: 'クリップを投稿しました' } format.json { render json: @clip, status: :created, location: @clip } + format.js { render } else - flash.now[:alert] = 'This image was existed.' if exist_image_flag + flash.now[:alert] = 'すでに存在している画像です' if exist_image_flag format.html { render action: :new } format.json { render json: @clip.errors, status: :unprocessable_entity } + format.js { render } end end end @@ -152,7 +150,7 @@ def update respond_to do |format| if @clip.update_attributes(params[:clip]) - format.html { redirect_to @clip, notice: 'Clip was successfully updated.' } + format.html { redirect_to @clip, notice: 'クリップを更新しました' } format.json { head :no_content } else format.html { render action: "edit" } @@ -175,15 +173,13 @@ def destroy private - def insert_div_tag_for_image_tag - -> image_tag { "
#{image_tag}
" } + def get_image_tags_for_next_page + render partial: 'wall', locals: { image_tags: image_tags_from_html } end - def create_html_cahce_file(html) - FileUtils.mkdir Settings.html_cache_dir unless File.exist? Settings.html_cache_dir - File.open(html_cache_file_path, 'w') do |file| - file.write(html) - end + def image_tags_from_html + doc = Hpricot(load_html_cahce_file) + image_tags = (doc/:img).paginate(page: params[:page], per_page: Clip.per_page) end def load_html_cahce_file diff --git a/app/controllers/matomes_controller.rb b/app/controllers/matomes_controller.rb index 8d43a8c..054be0e 100644 --- a/app/controllers/matomes_controller.rb +++ b/app/controllers/matomes_controller.rb @@ -51,6 +51,7 @@ def clips # POST /clips def create + tag_names = tag_names_by_params(:matome) clip_ids = params[:matome].delete(:clip_ids) @matome = Matome.new(params[:matome]) @@ -58,6 +59,7 @@ def create @matome.clips = Clip.where(user_id: current_user.id, id: clip_ids) if @matome.save + update_tags_for(@matome, tag_names) redirect_to @matome, notice: "「#{@matome.title}」まとめを作成しました" else @clips = @matome.clips @@ -74,23 +76,14 @@ def edit # PUT /clips/:id def update + tag_names = tag_names_by_params(:matome) clip_ids = params[:matome].delete(:clip_ids) - tag_names = params[:matome].delete(:tags) || [] - tag_names.map! {|tag_name| tag_name.strip } - tag_names.reject!(&:blank?) @matome = Matome.find(params[:id]) @matome.clip_ids = Clip.where(user_id: current_user.id, id: clip_ids).pluck(:id) - matome_tag_names = Tag.for(@matome).pluck(:name) - add_tag_names = tag_names - matome_tag_names - remove_tag_names = matome_tag_names - tag_names - Tag.where(name: remove_tag_names).for(@matome).destroy_all if remove_tag_names.any? - add_tag_names.each do |add_tag_name| - @matome.tags.create!(name: add_tag_name, user: current_user) - end - if @matome.update_attributes(params[:matome]) + update_tags_for(@matome, tag_names) redirect_to @matome, notice: "「#{@matome.title}」まとめを更新しました" else @clips = @matome.clips diff --git a/app/views/base/_header.html.slim b/app/views/base/_header.html.slim index 24af0bb..7d7eeca 100644 --- a/app/views/base/_header.html.slim +++ b/app/views/base/_header.html.slim @@ -2,16 +2,19 @@ .wrap .left ul + li.dropdown.new + = link_to '投稿', new_clip_path, class: 'dropdown-toggle', role: 'button', data: { toggle: 'dropdown' } + .dropdown-menu role='menu' + ul + li + = form_tag new_clip_path, method: :get do + = label_tag :url, 'イラストを投稿:' + = text_field_tag :url, nil, placeholder: 'http://画像URL、ページURL' + li = link_to 'ブックマークレットから投稿', bookmarklet_path + li.divider + li = link_to 'まとめを作成', new_matome_path - if user_signed_in? - li.dropdown - = link_to(new_clip_path, class: 'dropdown-toggle', role: 'button', data: { toggle: 'dropdown' }) { icon_tag('plus') } - .dropdown-menu role='menu' - ul - li = link_to 'URLから投稿', new_clip_path - li = link_to 'ブックマークレットから投稿', bookmarklet_path - li.divider - li = link_to 'まとめを作成', new_matome_path - li = link_to(user_likes_path(current_user), title: 'お気に入り') { icon_tag('heart') } + li.like = link_to 'イイネ!', user_likes_path(current_user) .center.logo h1 = link_to Settings.site_name, root_path diff --git a/app/views/clips/_form.html.slim b/app/views/clips/_form.html.slim index 75b8b66..8f038d7 100644 --- a/app/views/clips/_form.html.slim +++ b/app/views/clips/_form.html.slim @@ -10,29 +10,15 @@ = form_for @clip, url: { action: :clipping }, remote: true, html: { id: 'load_form' } do |f| h2 あたらしくクリップ h3 1. 画像をセレクト - p 画像のあるページのURLを入力してください。 - = f.text_field :origin_url, id: 'loading_url', value: @url + = f.text_field :origin_url, id: 'loading_url', value: @url, placeholder: 'http://画像URL、ページURL' = f.submit 'ロード', id: 'load' #container + - if @url + = image_tag('loader.gif') #page-nav = link_to 'next', controller: :clips, action: :get_image_tags, page: 2 -#clip_dialog - = form_for @clip do |f| - = f.error_messages - - #preview - - h3 2. タイトルを入力(任意) - #field - = f.label :title - br - = f.text_field :title - = f.hidden_field :url - = f.hidden_field :origin_url - - h3 3. 投稿! - .actions - = f.submit +- body = render partial: 'form_dialog', locals: { clip: @clip } +== render partial: 'base/dialog', locals: { id: :new_clip_dialog, title: '2. クリップの情報を入力', body: body } diff --git a/app/views/clips/_form_dialog.html.slim b/app/views/clips/_form_dialog.html.slim new file mode 100644 index 0000000..2269a0f --- /dev/null +++ b/app/views/clips/_form_dialog.html.slim @@ -0,0 +1,16 @@ += form_for clip, remote: true do |f| + = f.error_messages + = f.hidden_field :url + = f.hidden_field :origin_url + + #preview + + #field + .title + = f.label :title, class: 'control-label' + = f.text_field :title, placeholder: 'タイトル' + .tags + = f.label :tags, class: 'control-label' + = f.select :tags, Tag.uniques.by(current_user).pluck(:name), { include_blank: true, selected: Tag.uniques.by(current_user).for(clip).pluck(:name) }, { class: 'chosen-select', multiple: true, data: { placeholder: 'タグ' } } + .controls + = f.submit 'あたらしくクリップ' diff --git a/app/views/clips/_wall.html.slim b/app/views/clips/_wall.html.slim new file mode 100644 index 0000000..8c6d13e --- /dev/null +++ b/app/views/clips/_wall.html.slim @@ -0,0 +1,8 @@ +ul + - image_tags.each do |image_tag| + li.box + .image_box + == image_tag + .status + p.clip + = link_to 'クリップ', '#add' diff --git a/app/views/clips/create.js.coffee b/app/views/clips/create.js.coffee new file mode 100644 index 0000000..040469a --- /dev/null +++ b/app/views/clips/create.js.coffee @@ -0,0 +1,28 @@ +hide_new_clip_dialog = -> + $new_clip_dialog = $('#new_clip_dialog') + $new_clip_dialog.modal('hide') + +has_alert_flag = -> + <%= !!flash.now[:alert] %> + +initialize_notice = (text) -> + $('#alert').remove() + $('#notice').remove() + $('
') + .attr('id', 'notice') + .addClass('hidden') + .appendTo('#header .wrap') + .text(text) + notify() + +reset_form = -> + $('.chosen-select').trigger("chosen:updated") + $('#new_clip').get(0).reset(); + +hide_new_clip_dialog() +if has_alert_flag() + initialize_notice('エラー: <%= flash.now[:alert] %>') + <% flash.now[:alert] = nil %> +else + initialize_notice('クリップが投稿されました') +reset_form() diff --git a/app/views/clips/get_image_tags.js.coffee b/app/views/clips/get_image_tags.js.coffee index 8d3c89f..4a8332e 100644 --- a/app/views/clips/get_image_tags.js.coffee +++ b/app/views/clips/get_image_tags.js.coffee @@ -13,21 +13,12 @@ page_nav.html('<%= link_to 'next', page: @image_tags.next_page %>') page_nav.insertAfter('#container') <% end %> -#
で囲まないと、body 直下の img が取得できない -html = '
<%= raw @html.gsub("'", '"').presence || (@clip.url && image_tag(@clip.url)) || '' %>
' - -$(html).find('img').each( -> - box = $('
') - box.appendTo('#container') - $(@).appendTo('#active_box') - box.removeAttr('id') -) +$container.html("<%= escape_javascript(render template: 'clips/_wall', formats: :html, locals: { image_tags: @image_tags }) %>") $container.css({ opacity: 0 }).imagesLoaded( -> resize_images() @.removeClass('hidden') @.masonry('reload') - @.find('img:first').attr('id', 'selected') @.animate({ opacity: 1 }) # 無限スクロール機能の初期化 diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index e5ae8f4..c3db82f 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -16,5 +16,6 @@ html #main .wrap - p#alert = alert + - if alert + p#alert = alert == yield diff --git a/app/views/matomes/clips.js.coffee b/app/views/matomes/clips.js.coffee index 20fadb7..b36efbb 100644 --- a/app/views/matomes/clips.js.coffee +++ b/app/views/matomes/clips.js.coffee @@ -13,7 +13,6 @@ page_nav.attr('id', 'page-nav') page_nav.html('<%= link_to 'next', page: @clips.next_page %>') page_nav.insertAfter('#container') -#
で囲まないと、body 直下の img が取得できない $container.html("<%= escape_javascript(render template: 'matomes/_wall', formats: :html) %>") $container.css({ opacity: 0 }).imagesLoaded( ->