Merge branch 'master' into 'master'

add some feature as description said

1.change the default color of gallery frame
2.let user can rotate images
3.add playable feature for show page

See merge request !11
This commit is contained in:
wmcheng 2020-01-14 01:39:15 +08:00
commit 285c62d5ab
13 changed files with 329 additions and 82 deletions

View File

@ -1,3 +1,14 @@
function rotate(){
$("#crop_div").dialog("open");
}
function change_degree(degree_change){
var degree_org = parseInt($('#show_degree').text())
degree_org+=degree_change
if (degree_org==360 || degree_org==-360){
degree_org = 0
}
$('#show_degree').text(degree_org)
}
function init_upload(temp_length){ function init_upload(temp_length){
var value = $("input[name='all_upload_length']") var value = $("input[name='all_upload_length']")
if (value.val()==''){ if (value.val()==''){
@ -119,15 +130,22 @@ function batch_crop(){
function select_all() { function select_all() {
$('#imgholder').find("input[type='checkbox']:not(:checked)").trigger('click') $('#imgholder').find("input[type='checkbox']:not(:checked)").trigger('click')
} }
function translate(ele,pretext,text){ function translate(ele,pretext,text,return_flag){
var return_value
if (navigator.onLine) { if (navigator.onLine) {
$.ajax({ $.ajax({
url : "/admin/galleries/translate", url : "/admin/galleries/translate",
dataType : "json", dataType : "json",
type : "post", type : "post",
async: false,
data:{text:text}, data:{text:text},
success:function(data){ success:function(data){
ele.html(pretext + data.translate) if (return_flag){
return_value = data.translate
}
else{
ele.html(pretext + data.translate)
}
}, },
error:function(){ error:function(){
var back = text.split('.')[1].split('_') var back = text.split('.')[1].split('_')
@ -135,7 +153,12 @@ function translate(ele,pretext,text){
for (i=0;i<back.length;i++){ for (i=0;i<back.length;i++){
result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1)) result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1))
} }
ele.html(pretext + result.join(' ')) if (return_flag){
return_value = result.join(' ')
}
else{
ele.html(pretext + result.join(' '))
}
alert('Your server has some problem, please try again later!') alert('Your server has some problem, please try again later!')
} }
}) })
@ -146,9 +169,17 @@ function translate(ele,pretext,text){
for (i=0;i<back.length;i++){ for (i=0;i<back.length;i++){
result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1)) result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1))
} }
ele.html(pretext + result.join(' ')) if (return_flag){
return_value = result.join(' ')
}
else{
ele.html(pretext + result.join(' '))
}
alert('Please connect the network and try again later!') alert('Please connect the network and try again later!')
} }
if (return_flag){
return return_value
}
} }
$(function() { $(function() {
@ -342,7 +373,7 @@ $(function() {
$(".order-edit-notification").slideDown(); $(".order-edit-notification").slideDown();
images_order = $container.sortable( "toArray", { attribute: "data-image-id" }); images_order = $container.sortable( "toArray", { attribute: "data-image-id" });
$container.data("order-edit","1"); $container.data("order-edit","1");
translate(el,'','gallery.save_order') translate(el,'','gallery.save_order',false)
}else{ }else{
var temp = $container.sortable( "toArray", { attribute: "data-image-id" }), var temp = $container.sortable( "toArray", { attribute: "data-image-id" }),
type = $container.attr("id"); type = $container.attr("id");
@ -357,7 +388,7 @@ $(function() {
$(".order-edit-notification").slideUp(); $(".order-edit-notification").slideUp();
$container.sortable("disable"); $container.sortable("disable");
$container.data("order-edit","0"); $container.data("order-edit","0");
translate(el,'','gallery.edit_order') translate(el,'','gallery.edit_order',false)
} }
return false; return false;
}) })
@ -369,7 +400,7 @@ $(function() {
click: function() { click: function() {
$('#fileupload').slideToggle(300, function() { $('#fileupload').slideToggle(300, function() {
if(!$(this).is(':hidden')) { if(!$(this).is(':hidden')) {
translate($('.add-imgs'),'<i class="icons-cross-2"></i> ','gallery.close_panel') translate($('.add-imgs'),'<i class="icons-cross-2"></i> ','gallery.close_panel',false)
$('.rgbody').stop(true, false).animate({'padding-bottom': 280}, 300); $('.rgbody').stop(true, false).animate({'padding-bottom': 280}, 300);
$("#edit-order-btn").hide(); $("#edit-order-btn").hide();
$.ajax({ $.ajax({
@ -381,7 +412,7 @@ $(function() {
last_image_id = d.last_image_id; last_image_id = d.last_image_id;
}) })
} else { } else {
translate($('.add-imgs'),'<i class="icons-plus"></i> ','gallery.add_image') translate($('.add-imgs'),'<i class="icons-plus"></i> ','gallery.add_image',false)
$('.files').empty() $('.files').empty()
$('#file-list').checkListLength(); $('#file-list').checkListLength();
$('.rgbody').stop(true, false).animate({'padding-bottom': 0}, 300); $('.rgbody').stop(true, false).animate({'padding-bottom': 0}, 300);
@ -416,5 +447,43 @@ $(function() {
}) })
} }
var buttons_option={}
var op_fn1 = function() {
var check_img = $('#imgholder').find("input[type='checkbox']:checked").parents('li').find('img');
check_img.each(function(){
check_img.css('transform','rotate('+$('#show_degree').text()+'deg)');
});
}
var op_fn2 = function() {
var confirm_msg = translate('','','gallery.confirm_msg',true)
if ( confirm (confirm_msg) ){
var check_li = $('#imgholder').find("input[type='checkbox']:checked").parents('li');
var image_ids =[];
check_li.each(function(){
image_ids.push($(this).data('image-id'));
});
if (navigator.onLine) {
window.location.href = '/admin/galleries/rotate_images?image_ids=' + image_ids.join(',') +'&rotate_angle=' + $('#show_degree').text()
} else {
alert('Please connect the network and try again later!')
}
console.log(image_ids)
$(this).dialog("close");
}
}
var op_fn3 = function() { $(this).dialog("close"); }
var op1 = translate('','','gallery.review',true)
var op2 = translate('','','gallery.rotate',true)
var op3 = translate('','','gallery.close_panel',true)
buttons_option[op1] = op_fn1
buttons_option[op2] = op_fn2
buttons_option[op3] = op_fn3
$("#crop_div").dialog({
autoOpen: false,
show: "blind",
hide: "explode",
buttons: buttons_option
});
}); });

View File

@ -25,7 +25,12 @@ var GalleryTheater = function(){
gt.thumbStrip = null; gt.thumbStrip = null;
gt.descriptionArea = null; gt.descriptionArea = null;
gt.isTheaterInitialized = false; gt.isTheaterInitialized = false;
var play_flag = false;
var button_left_string = '<button id ="theaterPreviousButton" class="theaterButton">< </button>',
button_right_string = '<button id ="theaterNextButton" class="theaterButton">> </button>',
button_play_string = '<button id ="theaterPlayButton" class="theaterButton">▶ </button>',
button_stop_string = '<button id ="theaterStopButton" class="theaterButton">|| </button>',
playtimeoutID;
var initialize = function(){ var initialize = function(){
gt.stage = $("#gallery-theater-stage"); gt.stage = $("#gallery-theater-stage");
gt.closeBtn = gt.stage.find(".gallery-close"); gt.closeBtn = gt.stage.find(".gallery-close");
@ -49,7 +54,12 @@ var GalleryTheater = function(){
} }
var addButton = function () { var addButton = function () {
$('.theaterButton').remove(); $('.theaterButton').remove();
$('<button id ="theaterPreviousButton" class="theaterButton">' + '<' + ' </button> <button id ="theaterNextButton" class="theaterButton">' + '>' + ' </button>').insertAfter($('img.gal-active')); if (!play_flag){
$(button_left_string+button_play_string+button_right_string).insertAfter($('img.gal-active'));
}
else{
$(button_left_string+button_stop_string+button_right_string).insertAfter($('img.gal-active'));
}
if (!$(".gal-prev").length) { $('#theaterPreviousButton').remove(); } if (!$(".gal-prev").length) { $('#theaterPreviousButton').remove(); }
if (!$(".gal-next").length) { $('#theaterNextButton').remove(); } if (!$(".gal-next").length) { $('#theaterNextButton').remove(); }
@ -59,6 +69,18 @@ var GalleryTheater = function(){
$('#theaterNextButton').click(function () { $('#theaterNextButton').click(function () {
gt.nextPic(); gt.nextPic();
}); });
$('#theaterPlayButton').click(function () {
play_flag = true;
playtimeoutID = window.setInterval(function(){
gt.playallPic();
},3000)
window.onhashchange()
});
$('#theaterStopButton').click(function () {
play_flag = false;
window.onhashchange()
window.clearInterval(playtimeoutID)
});
} }
addButton(); addButton();
@ -198,7 +220,33 @@ var GalleryTheater = function(){
} }
} }
} }
gt.playallPic = function(){
if(loadingProcess == 0){
mainPicLoading = 1;
nextPicLoading = 1;
prevPicLoading = 1;
if(gt.hasNextImage()){
currentPic.image = gt.albumData.images[currentPic.index + 1];
currentPic.index = currentPic.index + 1;
setMainPic("next");
}
else{
currentPic.image = gt.albumData.images[0];
currentPic.index = 0;
setMainPic();
gt.isTheaterInitialized = false;
setTimeout(function(){
loadingProcess = 0;
nextPicLoading = 0;
$('.theaterButton').remove()
$("img.gallery-image.gal-prev.gal-inactive").remove();
img = $("img.gallery-image.gal-active");
img.eq(0).remove();
window.onhashchange()
},100)
}
}
}
gt.previousPic = function(){ gt.previousPic = function(){
@ -310,6 +358,9 @@ var GalleryTheater = function(){
setThumbNavs(); setThumbNavs();
} }
setMainPic(); setMainPic();
if (!$('.theaterButton').length){
window.onhashchange()
}
} }

View File

@ -465,15 +465,18 @@ body {
} }
/* 相本裡的左右控制鍵 */ /* 相本裡的左右控制鍵 */
#theaterPlayButton,#theaterStopButton{
left:30%;
}
.theaterButton{ .theaterButton{
position: absolute; position: absolute;
text-align: center; text-align: center;
width: 45%; width: 35%;
bottom: 50px; bottom: 1.8em;
background-color: transparent; background-color: transparent;
border: none; border: none;
color: white; color: white;
padding: 15px 32px; padding: 0.4em 1em;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
display: inline-block; display: inline-block;

View File

@ -38,62 +38,135 @@ class Admin::GalleriesController < OrbitAdminController
end end
end end
end end
def rotate_images
begin
image_ids = params['image_ids'].split(',')
images = AlbumImage.find(image_ids)
count = images.length
rot_ang = params[:rotate_angle].to_i
images.each_with_index do |image,index|
if !(image.album_crops.first.nil?)
w_and_h = image.file.get_w_and_h
cords = image.album_crops.map{|v| [[v.crop_x.to_f,v.crop_y.to_f],
[v.crop_x.to_f,v.crop_y.to_f+v.crop_h.to_f],
[v.crop_w.to_f+v.crop_x.to_f,v.crop_y.to_f],
[v.crop_w.to_f+v.crop_x.to_f,v.crop_y.to_f+v.crop_h.to_f]]}[0]
rot_diff = rot_ang/90
if (rot_diff) % 2 == 1
new_w = (w_and_h[1]).to_f
new_h = (w_and_h[0]).to_f
else
new_w = (w_and_h[0]).to_f
new_h = (w_and_h[1]).to_f
end
rot_times = rot_diff % 4
deg = (90.0*rot_times/180*Math::PI)
cords = cords.collect do |cord|
x = cord[0]-w_and_h[0].to_f/2
y = cord[1]-w_and_h[1].to_f/2
[x*Math.cos(deg)-y*Math.sin(deg)+new_w/2,x*Math.sin(deg)+y*Math.cos(deg)+new_h/2]
end
all_x = cords.collect do |cord|
cord[0]
end
all_y = cords.collect do |cord|
cord[1]
end
image.album_crops.first.update_attributes(crop_x: all_x.min,crop_y: all_y.min,crop_w: all_x.max - all_x.min,crop_h: all_y.max - all_y.min)
end
end
variable = AlbumVariable.first
if variable.nil?
variable = AlbumVariable.new
end
variable.finish = false
variable.save!
Thread.new do
variable = AlbumVariable.first
images.each_with_index do |image,index|
variable.progress_percent = (index*100.0/count).floor.to_s+'%'
image.file.rotate_ang(rot_ang)
all_version = image.file.versions.map{|k,v| k}
begin
variable.progress_filename = image[:file].to_s
all_version.each do |version|
if !(version.to_s == 'resized' && crop_but_no_backup(image))
image.file.recreate_versions! version
image.save!
end
end
rescue => e
variable.progress_filename = e.inspect.to_s
puts e.inspect
end
variable.save!
end
variable.finish = true
variable.save!
end
rescue => e
puts e.inspect
end
redirect_to :controller=> 'images' ,:action => 'crop_process'
end
def save_crop def save_crop
begin begin
images = AlbumImage.all.select{|value| params[:id].include? value.id.to_s} images = AlbumImage.all.select{|value| params[:id].include? value.id.to_s}
id = images.first.album_id.to_s id = images.first.album_id.to_s
x = params['x'] x = params['x']
y = params['y'] y = params['y']
w = params['w'] w = params['w']
h = params['h'] h = params['h']
cords = x.zip(y,w,h) cords = x.zip(y,w,h)
count = cords.length count = cords.length
images.each_with_index do |image,index| images.each_with_index do |image,index|
cord = cords[index] cord = cords[index]
if image.album_crops.first.nil? if image.album_crops.first.nil?
image.album_crops.create(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3]) image.album_crops.create(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3])
else else
image.album_crops.first.update_attributes(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3]) image.album_crops.first.update_attributes(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3])
end end
end
variable = AlbumVariable.first
if variable.nil?
variable = AlbumVariable.new
end
variable.finish = false
variable.save!
Thread.new do
variable = AlbumVariable.first
images.each_with_index do |image,index|
variable.progress_percent = (index*100.0/count).floor.to_s+'%'
all_version = image.file.versions.map{|k,v| k}
begin
#org_fname = image.file.path
#org_extname = File.extname(org_fname)
#org_fname.slice! org_extname
#FileUtils.cp(org_fname + org_extname, org_fname + '_resized' + org_extname)
variable.progress_filename = image[:file].to_s
all_version.each do |version|
if !(version.to_s == 'resized' && crop_but_no_backup(image))
image.file.recreate_versions! version
image.save!
end
end
rescue => e
variable.progress_filename = e.inspect.to_s
puts e.inspect
end
variable.save!
end end
variable.finish = true variable = AlbumVariable.first
if variable.nil?
variable = AlbumVariable.new
end
variable.finish = false
variable.save! variable.save!
end Thread.new do
rescue => e variable = AlbumVariable.first
puts e.inspect images.each_with_index do |image,index|
end variable.progress_percent = (index*100.0/count).floor.to_s+'%'
redirect_url = "/admin/galleries/crop_process" all_version = image.file.versions.map{|k,v| k}
render :json => {'href' => redirect_url}.to_json begin
#org_fname = image.file.path
#org_extname = File.extname(org_fname)
#org_fname.slice! org_extname
#FileUtils.cp(org_fname + org_extname, org_fname + '_resized' + org_extname)
variable.progress_filename = image[:file].to_s
all_version.each do |version|
if !(version.to_s == 'resized' && crop_but_no_backup(image))
image.file.recreate_versions! version
image.save!
end
end
rescue => e
variable.progress_filename = e.inspect.to_s
puts e.inspect
end
variable.save!
end
variable.finish = true
variable.save!
end
rescue => e
puts e.inspect
end
redirect_url = "/admin/galleries/crop_process"
render :json => {'href' => redirect_url}.to_json
end end
def call_translate def call_translate
text = params['text'] text = params['text']
@ -180,7 +253,7 @@ class Admin::GalleriesController < OrbitAdminController
def index def index
Album.each do |album| Album.each do |album|
if album.album_colors.first.nil? if album.album_colors.first.nil?
album.album_colors.create('color' => '#000000') album.album_colors.create('color' => 'transparent')
end end
end end
@tags = @module_app.tags @tags = @module_app.tags
@ -199,7 +272,7 @@ class Admin::GalleriesController < OrbitAdminController
@color_save = AlbumColor.desc('updated_at').first[:color] @color_save = AlbumColor.desc('updated_at').first[:color]
end end
else else
@color_save = '#000000' @color_save = 'transparent'
end end
if request.xhr? if request.xhr?
render :partial => "album", :collection => @albums render :partial => "album", :collection => @albums

View File

@ -1,5 +1,7 @@
class Admin::ImagesController < OrbitAdminController class Admin::ImagesController < OrbitAdminController
before_filter :setup_vars before_filter :setup_vars
def crop_process
end
def batch_crop def batch_crop
images = params['image_ids'].split(',') images = params['image_ids'].split(',')
@img = [] @img = []
@ -47,7 +49,11 @@ class Admin::ImagesController < OrbitAdminController
images = params['images'] images = params['images']
images.each do |image| images.each do |image|
img = AlbumImage.find(image) img = AlbumImage.find(image)
FileUtils.rm_rf(File.dirname(img.file.path)) begin
FileUtils.rm_rf(File.dirname(img.file.path))
rescue => e
puts ["can't delete",e]
end
img.delete img.delete
end end
if params['delete_cover'] == "true" if params['delete_cover'] == "true"

View File

@ -100,19 +100,39 @@ class GalleryUploader < CarrierWave::Uploader::Base
# rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e # rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
# raise CarrierWave::ProcessingError.new("Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: #{e}") # raise CarrierWave::ProcessingError.new("Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: #{e}")
# end # end
def optimize (*arg) def get_w_and_h
manipulate! do |img| if have_crop?
return img unless img.mime_type.match /image\/jpeg/ img = MiniMagick::Image.open(model.file.resized.path)
img.strip else
img.combine_options do |c| img = MiniMagick::Image.open(model.file.path)
c.quality "90" end
c.depth "24" [img[:width], img[:height]]
c.interlace "plane" end
end def rotate_ang(angle)
img if have_crop?
end img_path = model.file.resized.path
else
img_path = model.file.path
end
puts img_path
img = MiniMagick::Image.open(img_path)
img.rotate(angle)
puts img
img.write(img_path)
end
def optimize (*arg)
manipulate! do |img|
return img unless img.mime_type.match /image\/jpeg/
img.strip
img.combine_options do |c|
c.quality "90"
c.depth "24"
c.interlace "plane"
end end
private img
end
end
private
def resizer def resizer
size_of_file = size.to_f / (2**20) size_of_file = size.to_f / (2**20)
if size_of_file > 5 if size_of_file > 5

View File

@ -103,7 +103,7 @@ input.minicolors-input{
</div> </div>
<!-- Frame Color Module --> <!-- Frame Color Module -->
<% if @album.album_colors.first.nil? %> <% if @album.album_colors.first.nil? %>
<% @album.album_colors.new('color' => '#000000') %> <% @album.album_colors.new('color' => 'transparent') %>
<% end %> <% end %>
<%= f.fields_for :album_colors do |album_color_form| %> <%= f.fields_for :album_colors do |album_color_form| %>
<div class="tab-pane fade" id="frame_color"> <div class="tab-pane fade" id="frame_color">

View File

@ -16,6 +16,15 @@
<a href="javascript:select_all()" class='btn btn-small'> <%= t('gallery.checked') %></a> <a href="javascript:select_all()" class='btn btn-small'> <%= t('gallery.checked') %></a>
</div> </div>
<div class="action pull-right"> <div class="action pull-right">
<div id="crop_div" style="text-align: center;">
<%= t('gallery.crop_div').html_safe %>
<br>
<span id="show_degree">0</span>°
<br>
<button onclick="change_degree(90)"><%= t('gallery.add_degree') %></button>
<button onclick="change_degree(-90)"><%= t('gallery.reduce_degree') %></button>
</div>
<a href="javascript:rotate()" class="btn btn-small hide crop"><%= t('gallery.rotate_images') %></a>
<a href="javascript:batch_crop()" class="btn btn-small hide crop"><%= t('gallery.batch_crop') %></a> <a href="javascript:batch_crop()" class="btn btn-small hide crop"><%= t('gallery.batch_crop') %></a>
<a href="#" class="btn btn-inverse btn-small deselect hide"><%= t('gallery.deselect') %></a> <a href="#" class="btn btn-inverse btn-small deselect hide"><%= t('gallery.deselect') %></a>
<% if can_edit_or_delete?(@album) %> <% if can_edit_or_delete?(@album) %>

View File

@ -31,6 +31,7 @@
y[0] = e.detail.y y[0] = e.detail.y
w[0] = e.detail.width w[0] = e.detail.width
h[0] = e.detail.height h[0] = e.detail.height
console.log('x:'+x+'y:'+y)
}, },
viewMode: 2, viewMode: 2,
zoomOnWheel: false, zoomOnWheel: false,

View File

@ -4,7 +4,7 @@
<%= javascript_include_tag "theater" %> <%= javascript_include_tag "theater" %>
<% OrbitHelper.render_meta_tags([{"name" => "mobile-web-app-capable","content" => "yes"},{"name" => "apple-mobile-web-app-status-bar-style","content" => "black-translucent"}]) %> <% OrbitHelper.render_meta_tags([{"name" => "mobile-web-app-capable","content" => "yes"},{"name" => "apple-mobile-web-app-status-bar-style","content" => "black-translucent"}]) %>
<div id="gallery-theater-stage"> <div id="gallery-theater-stage">
<div class="gallery"> <div class="gallery" style="margin-top: 2.4em;">
<div class="gallery-loader"> <div class="gallery-loader">
<div class="spinner"> <div class="spinner">
<div class="rect1"></div> <div class="rect1"></div>

View File

@ -6,6 +6,13 @@ en:
show_original_image: Show the original picture show_original_image: Show the original picture
width: Width width: Width
height: Height height: Height
review: Review
rotate: Rotate
confirm_msg: Are you sure to rotate images
add_degree: Add 90 degree
reduce_degree: Reduce 90 degree
crop_div: "Please input the degree you want to rotate.<br>(positive for clockwise)"
rotate_images: Rotate images
batch_crop: Batch crop images batch_crop: Batch crop images
use_set: Use the previously configured color use_set: Use the previously configured color
add_files: Add files add_files: Add files

View File

@ -6,6 +6,13 @@ zh_tw:
show_original_image: 顯示原始圖片 show_original_image: 顯示原始圖片
width: width:
height: height:
review: 預覽
rotate: 旋轉
confirm_msg: 確定要旋轉圖片嗎?
add_degree: 增加90度
reduce_degree: 減少90度
crop_div: "請輸入需要旋轉的角度.<br>(順時針為正)"
rotate_images: 旋轉圖片
batch_crop: 批量裁減圖片 batch_crop: 批量裁減圖片
use_set: 使用先前已設定的顏色 use_set: 使用先前已設定的顏色
add_files: 新增檔案 add_files: 新增檔案

View File

@ -20,6 +20,7 @@ Rails.application.routes.draw do
post "galleries/order" => "images#changeorder" post "galleries/order" => "images#changeorder"
post "galleries/translate" => "galleries#call_translate" post "galleries/translate" => "galleries#call_translate"
post "galleries/save_crop" => "galleries#save_crop" post "galleries/save_crop" => "galleries#save_crop"
get "galleries/rotate_images" => "galleries#rotate_images"
get "galleries/upload_process" => "galleries#upload_process" get "galleries/upload_process" => "galleries#upload_process"
post "galleries/start_upload_process" => "galleries#start_upload_process" post "galleries/start_upload_process" => "galleries#start_upload_process"
post "galleries/init_upload" => "galleries#init_upload" post "galleries/init_upload" => "galleries#init_upload"