Add carousel images feature.

This commit is contained in:
BoHung Chiu 2021-04-11 00:28:00 +08:00
parent 7ae01062b1
commit 92cd6b809e
8 changed files with 300 additions and 5 deletions

View File

@ -590,10 +590,16 @@ class AnnouncementsController < ApplicationController
img_src = (announcement.image.thumb.url || "/assets/announcement-default.jpg") if announcement.display_img? img_src = (announcement.image.thumb.url || "/assets/announcement-default.jpg") if announcement.display_img?
img_description = announcement.image_description if (announcement.image_description.present?) && (announcement.display_img?) img_description = announcement.image_description if (announcement.image_description.present?) && (announcement.display_img?)
show_comment_flag = announcement.open_comment_for_user(OrbitHelper.current_user) show_comment_flag = announcement.open_comment_for_user(OrbitHelper.current_user)
bulletin_carousel_images = announcement.bulletin_carousel_images.map{|image| {"src"=>image.file.url,"description"=>image.description.to_s,"description_text"=>image.description_text }}
resume_btn_title = (I18n.locale.to_s =="zh_tw") ? "繼續播放" : "resume"
pause_btn_title = (I18n.locale.to_s =="zh_tw") ? "暫停播放" : "pause"
prev_btn_title = (I18n.locale.to_s =="zh_tw") ? "上一張" : "prev"
next_btn_title = (I18n.locale.to_s =="zh_tw") ? "下一張" : "next"
{ {
"tags" => tags, "tags" => tags,
"bulletin_files" => files, "bulletin_files" => files,
"bulletin_links" => links, "bulletin_links" => links,
"bulletin_carousel_images" => bulletin_carousel_images,
"data" => { "data" => {
"title" => announcement.title, "title" => announcement.title,
"subtitle_ann" => subtitle_ann, "subtitle_ann" => subtitle_ann,
@ -604,7 +610,13 @@ class AnnouncementsController < ApplicationController
"img_src" => img_src, "img_src" => img_src,
"img_description" => img_description, "img_description" => img_description,
"hide_class" => announcement.display_img? ? '' : ' hide', "hide_class" => announcement.display_img? ? '' : ' hide',
"alt_title" => desc "alt_title" => desc,
"resume_btn_title" => resume_btn_title,
"pause_btn_title" => pause_btn_title,
"prev_btn_title" => prev_btn_title,
"next_btn_title" => next_btn_title,
"carousel_display_style" => (bulletin_carousel_images.count == 0 ? 'display: none' : ''),
"carousel_count" => bulletin_carousel_images.count
}, },
"comments" => announcement.comments, "comments" => announcement.comments,
"show_comment_flag" => show_comment_flag, "show_comment_flag" => show_comment_flag,
@ -665,6 +677,7 @@ class AnnouncementsController < ApplicationController
"tags" => tags, "tags" => tags,
"bulletin_files" => files, "bulletin_files" => files,
"bulletin_links" => links, "bulletin_links" => links,
"bulletin_carousel_images" => [],
"data" => { "data" => {
"title" => announcement["title_translations"][locale], "title" => announcement["title_translations"][locale],
"subtitle_ann" => subtitle_ann, "subtitle_ann" => subtitle_ann,
@ -675,7 +688,8 @@ class AnnouncementsController < ApplicationController
"img_src" => img_src, "img_src" => img_src,
"img_description" => img_description, "img_description" => img_description,
"hide_class" => announcement["display_img"] ? '' : ' hide', "hide_class" => announcement["display_img"] ? '' : ' hide',
"alt_title" => desc "alt_title" => desc,
"carousel_display_style" => 'display: none'
}, },
"comments" => [], "comments" => [],
"show_comment_flag" => false, "show_comment_flag" => false,

View File

@ -69,8 +69,10 @@ class Bulletin
has_many :bulletin_links, :autosave => true, :dependent => :destroy has_many :bulletin_links, :autosave => true, :dependent => :destroy
has_many :bulletin_files, :autosave => true, :dependent => :destroy has_many :bulletin_files, :autosave => true, :dependent => :destroy
has_many :bulletin_comments, :autosave => true, :dependent => :destroy has_many :bulletin_comments, :autosave => true, :dependent => :destroy
has_many :bulletin_carousel_images, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :bulletin_files, :allow_destroy => true accepts_nested_attributes_for :bulletin_files, :allow_destroy => true
accepts_nested_attributes_for :bulletin_links, :allow_destroy => true accepts_nested_attributes_for :bulletin_links, :allow_destroy => true
accepts_nested_attributes_for :bulletin_carousel_images, :allow_destroy => true
before_destroy :destroy_email before_destroy :destroy_email

View File

@ -0,0 +1,15 @@
# encoding: utf-8
class BulletinCarouselImage
include Mongoid::Document
include Mongoid::Timestamps
mount_uploader :file, AssetUploader
field :description, localize: true
belongs_to :bulletin
def description_text
Nokogiri::HTML(self.description.to_s).css("body").text() rescue ""
end
end

View File

@ -52,6 +52,7 @@
<% end %> <% end %>
<li><a href="#tag" data-toggle="tab"><%= t(:tags) %></a></li> <li><a href="#tag" data-toggle="tab"><%= t(:tags) %></a></li>
<li><a href="#imageupload" data-toggle="tab"><%= t('announcement.image') %></a></li> <li><a href="#imageupload" data-toggle="tab"><%= t('announcement.image') %></a></li>
<li><a href="#carousel_image_upload" data-toggle="tab" title="<%= t('announcement.carousel_image_title') %>"><%= t('announcement.carousel_image') %></a></li>
<li><a href="#mail-group" data-toggle="tab"><%= t('announcement.email_reminder')%></a></li> <li><a href="#mail-group" data-toggle="tab"><%= t('announcement.email_reminder')%></a></li>
</ul> </ul>
<!-- Module --> <!-- Module -->
@ -286,7 +287,27 @@
<% end %> <% end %>
</div> </div>
<!-- Images Module -->
<div class="tab-pane fade" id="carousel_image_upload">
<% if @bulletin && !@bulletin.bulletin_carousel_images.blank? %>
<div class="exist">
<% @bulletin.bulletin_carousel_images.each_with_index do |bulletin_carousel_image, i| %>
<%= f.fields_for :bulletin_carousel_images, bulletin_carousel_image do |f| %>
<%= render :partial => 'form_image', :object => bulletin_carousel_image, :locals => {:f => f, :i => i} %>
<% end %>
<% end %>
<hr>
</div>
<% end %>
<!-- Add -->
<div class="add-target">
</div>
<p class="add-btn controls">
<%= hidden_field_tag 'bulletin_carousel_image_count', @bulletin.bulletin_carousel_images.count %>
<a id="add_carousel_image" class="trigger btn btn-small btn-primary"><i class="icons-plus"></i> <%= t(:add) %></a>
</p>
</div>
</div>
<!-- Mail Group Module --> <!-- Mail Group Module -->
<div class="tab-pane fade" id="mail-group"> <div class="tab-pane fade" id="mail-group">
@ -560,6 +581,22 @@
formTip(); formTip();
add_click_for_privacy(); add_click_for_privacy();
}); });
$(document).on('click', '#add_carousel_image', function(){
var new_id = $(this).prev().attr('value');
var old_id = new RegExp("new_bulletin_carousel_images", "g");
var on = $('.language-nav li.active').index();
var le = $(this).parent('.add-btn').prev('.add-target').children('.start-line').length;
$(this).prev().attr('value', parseInt(new_id) + 1);
$(this).parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'form_image', f, :bulletin_carousel_images) %>").replace(old_id, new_id));
$(this).parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
$(this).children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
});
});
$(document).on('click', '.fileupload-remove', function(){
if($(this).find(".delete_image").length != 0){
$(this).parents('.image_group').remove();
}
});
$(document).on('click', '.delete_link', function(){ $(document).on('click', '.delete_link', function(){
$(this).parents('.input-prepend').remove(); $(this).parents('.input-prepend').remove();
}); });

View File

@ -0,0 +1,49 @@
<!-- Images Upload -->
<div class="image_group">
<div class="control-group">
<label class="control-label muted"><%= t(:image) %></label>
<div class="controls">
<div class="fileupload fileupload-new clearfix <%= 'fileupload-edit' if @bulletin.image.file %>" data-provides="fileupload">
<div class="fileupload-new thumbnail pull-left">
<% if form_image.file.file %>
<%= image_tag form_image.file %>
<% else %>
<img src="http://www.placehold.it/50x50/EFEFEF/AAAAAA" />
<% end %>
</div>
<div class="fileupload-preview fileupload-exists thumbnail pull-left"></div>
<span class="btn btn-file">
<span class="fileupload-new"><%= t(:select_image) %></span>
<span class="fileupload-exists"><%= t(:change) %></span>
<%= f.file_field :file %>
</span>
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload"><%= t(:cancel) %></a>
<div class="controls" data-toggle="buttons-checkbox">
<label class="checkbox inline btn btn-danger fileupload-remove">
<% if form_image.new_record? %>
<span class="delete_file delete_image add-on" title="<%= t(:delete_) %>">
<%= t(:delete_) %>
</span>
<% else %>
<span class="remove_existing_record add-on" title="<%= t(:remove) %>">
<%= f.hidden_field :id %>
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
<%= t(:remove) %>
</span>
<% end %>
</label>
</div>
</div>
</div>
</div>
<% @site_in_use_locales.each do |locale| %>
<%= f.fields_for :description_translations do |f| %>
<div class="control-group">
<label class="control-label muted" for="image_description_<%= locale.to_s %>"><%= t(:description) + " (#{t(locale.to_s)})" %></label>
<div class="controls">
<%= f.text_field locale, value: (form_image.description_translations[locale.to_s] rescue nil) %>
</div>
</div>
<% end %>
<% end %>
</div>

View File

@ -37,6 +37,8 @@ en:
'yes': 'Yes' 'yes': 'Yes'
'no': 'No' 'no': 'No'
image: Cover Image image: Cover Image
carousel_image: Carousel Image
carousel_image_title: Carousel Image(display at the bottom of show page)
picture_showing_size: Picture Showing Size picture_showing_size: Picture Showing Size
orignal_size: Original Size orignal_size: Original Size
small_size: Small Size small_size: Small Size

View File

@ -37,6 +37,8 @@ zh_tw:
'yes': 'yes':
'no': 'no':
image: 封面圖片 image: 封面圖片
carousel_image: 輪播圖片
carousel_image_title: 輪播圖片(在show頁面底部顯示)
picture_showing_size: 圖片顯示大小 picture_showing_size: 圖片顯示大小
orignal_size: 原圖大小 orignal_size: 原圖大小
small_size: 小張縮圖 small_size: 小張縮圖

View File

@ -44,9 +44,100 @@
</ul> </ul>
</article> </article>
<div class="carousel_images" style="{{carousel_display_style}}">
<div class="w-ba-banner ba-banner-widget-1">
<div class="w-ba-banner__wrap cycle-slideshow"
data-list="bulletin_carousel_images"
data-level="0"
data-cycle-slides=".bulletin_carousel_slide"
data-cycle-log="false"
data-cycle-auto-height="0"
data-cycle-speed="300"
data-cycle-timeout="5000"
data-cycle-fx="fade"
data-pager-active-class="active-slide"
data-cycle-swipe=true
data-cycle-swipe-fx="scrollHorz"
>
<div class="w-ba-banner__slide bulletin_carousel_slide"
data-cycle-title="{{description_text}}"
>
<img class="w-ba-banner__image banner-responsive" src="{{src}}" alt="{{description_text}}">
<div class="ad-overlay w-ad-banner__overlay bulletin_carousel__overlay">
<p><strong class="carousel__description">{{description}}</strong></p>
</div>
<div class="transitionfade"></div>
</div>
</div>
<ul class="controlplay"><a class="resume-slide" title = "{{resume_btn_title}}"><i></i></a><a class="pause-slide" title = "{{pause_btn_title}}"><i></i></a></ul>
<ul class="button-mid">
<i class="fa fa-angle-left prev-button" aria-hidden="true" title = "{{prev_btn_title}}"></i>
<i class="fa fa-angle-right next-button" aria-hidden="true" title = "{{next_btn_title}}"></i>
</ul>
</div>
<div style="position: relative;">
<h4><span class="active_slide">1</span>/{{carousel_count}}</h4>
<ul class="carousel_images_slide w-annc__list row list-unstyled" data-level="0" data-list="bulletin_carousel_images">
<li class="carousel_img_item col-sm-3">
<div class="carousel_img-wrap">
<img class="carousel_img" src="{{src}}" alt="{{description_text}}">
</div>
</li>
</ul>
<ul class="button-mid">
<i class="fa fa-angle-left prev-button prev_img" aria-hidden="true" title = "{{prev_btn_title}}"></i>
<i class="fa fa-angle-right next-button next_img" aria-hidden="true" title = "{{next_btn_title}}"></i>
</ul>
</div>
</div>
{{link_to_edit}} {{link_to_edit}}
<style type="text/css">
.carousel_img_item{
display: none;
float: left;
}
.carousel_images_slide{
padding: 3em;
}
.carousel_img_item img{
cursor: pointer;
}
@media (max-width: 479px){
.carousel_img_item:nth-child(-n+1){
display: block;
float: left;
}
.carousel_img_item{
width: 100%;
}
}
@media (min-width: 480px){
.carousel_img_item:nth-child(-n+2){
display: block;
float: left;
}
.carousel_img_item{
width: 50%;
}
}
@media (min-width: 768px){
.carousel_img_item:nth-child(-n+3){
display: block;
width: 33%;
float: left;
}
.carousel_img_item{
width: 33%;
}
}
@media (min-width: 1280px){
.carousel_img_item:nth-child(-n+4){
display: block;
float: left;
}
}
</style>
<script> <script>
(function($) { (function($) {
@ -67,6 +158,89 @@
hideEmptyEl($('.s-annc__link-title'), $('.s-annc__related-link')); hideEmptyEl($('.s-annc__link-title'), $('.s-annc__related-link'));
$("img[src='']").remove(); $("img[src='']").remove();
$('.pause-slide').click(function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle('pause');
});
$('.resume-slide').click(function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle('resume');
});
$('.next-button').off('click').on('click',function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("next");
})
$('.prev-button').off('click').on('click',function(){
$(this).parent("ul").parent('.w-ba-banner').find(".cycle-slideshow").cycle("prev");
})
window.active_slide = 0;
$('.prev_img').off('click').on('click',function(){
var carousel_images_slide = $('.carousel_images_slide');
var carousel_images_slide_first_child = carousel_images_slide.find(">li").eq(active_slide);
if(carousel_images_slide_first_child.length > 0){
var content_size = Math.floor(carousel_images_slide.width() / carousel_images_slide_first_child.width());
if(carousel_images_slide.find(">li").length > content_size && active_slide > 0){
active_slide -= content_size;
carousel_images_slide.find(">li").css("display","none");
for(var i = active_slide; i < active_slide + content_size;i++){
carousel_images_slide.find(">li").eq(i).css("display","block");
}
}
}
})
$('.next_img').off('click').on('click',function(){
var carousel_images_slide = $('.carousel_images_slide');
var carousel_images_slide_first_child = carousel_images_slide.find(">li").eq(active_slide);
if(carousel_images_slide_first_child.length > 0){
var content_size = Math.floor(carousel_images_slide.width() / carousel_images_slide_first_child.width());
if(carousel_images_slide.find(">li").length > content_size && (active_slide < carousel_images_slide.find(">li").length - 1)){
active_slide += content_size;
carousel_images_slide.find(">li").css("display","none");
for(var i = active_slide; i < active_slide + content_size;i++){
carousel_images_slide.find(">li").eq(i).css("display","block");
}
}
}
})
$(".carousel_img_item img").off("click").on("click",function(){
$(".carousel_images .cycle-slideshow").cycle($(this).index(".carousel_img_item img"));
})
$(document).ready(function(){
$(".carousel_images .cycle-slideshow").cycle('pause');
var carousel_image_block_width = $('.carousel_images').width();
var heights = $(".bulletin_carousel_slide").map(function(i,v){
return $(v).height() * carousel_image_block_width / $(v).width();
})
var max_height = Math.max.apply(null,heights);
$(".bulletin_carousel_slide").each(function(i,v){
$(v).height(max_height);
})
$(".carousel_images .cycle-slideshow").cycle('resume');
$('.cycle-slideshow').on('cycle-after',function(){
$(".active_slide").text($('.bulletin_carousel_slide.cycle-slide-active').index());
})
})
$(window).resize(function(){
var carousel_images_slide = $('.carousel_images_slide');
var carousel_images_slide_first_child = carousel_images_slide.find(">li").eq(active_slide);
if(carousel_images_slide_first_child.length > 0){
var content_size = Math.floor(carousel_images_slide.width() / carousel_images_slide_first_child.width());
carousel_images_slide.find(">li").css("display","none");
var active_count = carousel_images_slide.find(">li").length - active_slide;
if(active_count < content_size){
active_slide -= (content_size - active_count);
}
for(var i = active_slide; i < active_slide + content_size;i++){
carousel_images_slide.find(">li").eq(i).css("display","block");
}
}
var carousel_image_block_width = $('.carousel_images').width();
$(".bulletin_carousel_slide").css("height",'');
var heights = $(".bulletin_carousel_slide").map(function(i,v){
return $(v).height() * carousel_image_block_width / $(v).width();
})
var max_height = Math.max.apply(null,heights);
$(".bulletin_carousel_slide").each(function(i,v){
$(v).height(max_height);
})
})
}(jQuery)); }(jQuery));
</script> </script>