diff --git a/Gemfile b/Gemfile index 13b410d9d..0aa77ae99 100644 --- a/Gemfile +++ b/Gemfile @@ -1,96 +1,90 @@ -source 'http://ruby.taobao.org' -#source 'http://ruby.sdutlinux.org/' - -unless RUBY_PLATFORM =~ /w32/ - # unix-like only - gem 'iconv' -end - -gem "mysql2", "= 0.3.18" -gem 'redis-rails' -gem 'rubyzip' -gem 'delayed_job_active_record'#, :group => :production -gem 'daemons' -gem 'grape', '~> 0.9.0' -gem 'grape-entity' -gem 'seems_rateable', '~> 1.0.13' -gem "rails", "3.2.13" -gem "jquery-rails", "~> 2.0.2" -gem "i18n", "~> 0.6.0" -gem 'coderay', '~> 1.1.0' -gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] -gem "builder", "3.0.0" -gem 'acts-as-taggable-on', '2.4.1' -gem 'spreadsheet' -gem 'ruby-ole' -gem 'rails_kindeditor',path:'lib/rails_kindeditor' -group :development do - gem 'grape-swagger' - #gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git' - gem 'puma' if RbConfig::CONFIG['host_os'] =~ /linux/ - gem 'pry-rails' - if RUBY_VERSION >= '2.0.0' - gem 'pry-byebug' - else - # gem 'pry-debugger' - end - gem 'pry-stack_explorer' - gem 'better_errors', '~> 1.1.0' - gem 'rack-mini-profiler', '~> 0.9.3' -end - -group :test do - gem "shoulda", "~> 3.5.0" - gem "mocha", "~> 1.1.0" - gem 'capybara', '~> 2.4.1' - gem 'nokogiri', '~> 1.6.3' - gem 'factory_girl', '~> 4.4.0' - gem 'selenium-webdriver', '~> 2.42.0' - - gem "faker" - # platforms :mri, :mingw do - # group :rmagick do - # # RMagick 2 supports ruby 1.9 - # # RMagick 1 would be fine for ruby 1.8 but Bundler does not support - # # different requirements for the same gem on different platforms - # gem "rmagick", ">= 2.0.0" - # end - #end -end - -# Gems used only for assets and not required -# in production environments by default. -group :assets do - gem 'sass-rails', '~> 3.2.3' - gem 'coffee-rails', '~> 3.2.1' - - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - gem 'therubyracer', :platforms => :ruby - - gem 'uglifier', '>= 1.0.3' -end - -# Optional gem for LDAP authentication -group :ldap do - gem "net-ldap", "~> 0.3.1" -end - - -# Optional gem for OpenID authentication -group :openid do - gem "ruby-openid", "~> 2.1.4", :require => "openid" - gem "rack-openid" -end - - -database_file = File.join(File.dirname(__FILE__), "config/database.yml") -if File.exist?(database_file) -else - warn("Please configure your config/database.yml first") -end - -# Load plugins' Gemfiles -Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file| - puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` - instance_eval File.read(file) -end +source 'http://ruby.taobao.org' +#source 'http://ruby.sdutlinux.org/' + +unless RUBY_PLATFORM =~ /w32/ + # unix-like only + gem 'iconv' +end + +gem "mysql2", "= 0.3.18" +gem 'redis-rails' +gem 'rubyzip' +gem 'delayed_job_active_record'#, :group => :production +gem 'daemons' +gem 'grape', '~> 0.9.0' +gem 'grape-entity' +gem 'seems_rateable', '~> 1.0.13' +gem "rails", "3.2.13" +gem "jquery-rails", "~> 2.0.2" +gem "i18n", "~> 0.6.0" +gem 'coderay', '~> 1.1.0' +gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] +gem "builder", "3.0.0" +gem 'acts-as-taggable-on', '2.4.1' +gem 'spreadsheet' +gem 'ruby-ole' +gem 'rails_kindeditor',path:'lib/rails_kindeditor' +gem "rmagick", ">= 2.0.0" + +group :development do + gem 'grape-swagger' + #gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git' + gem 'puma' if RbConfig::CONFIG['host_os'] =~ /linux/ + gem 'pry-rails' + if RUBY_VERSION >= '2.0.0' + gem 'pry-byebug' + else + # gem 'pry-debugger' + end + gem 'pry-stack_explorer' + gem 'better_errors', '~> 1.1.0' + gem 'rack-mini-profiler', '~> 0.9.3' +end + +group :test do + gem "shoulda", "~> 3.5.0" + gem "mocha", "~> 1.1.0" + gem 'capybara', '~> 2.4.1' + gem 'nokogiri', '~> 1.6.3' + gem 'factory_girl', '~> 4.4.0' + gem 'selenium-webdriver', '~> 2.42.0' + + gem "faker" +end + +# Gems used only for assets and not required +# in production environments by default. +group :assets do + gem 'sass-rails', '~> 3.2.3' + gem 'coffee-rails', '~> 3.2.1' + + # See https://github.com/sstephenson/execjs#readme for more supported runtimes + gem 'therubyracer', :platforms => :ruby + + gem 'uglifier', '>= 1.0.3' +end + +# Optional gem for LDAP authentication +group :ldap do + gem "net-ldap", "~> 0.3.1" +end + + +# Optional gem for OpenID authentication +group :openid do + gem "ruby-openid", "~> 2.1.4", :require => "openid" + gem "rack-openid" +end + + +database_file = File.join(File.dirname(__FILE__), "config/database.yml") +if File.exist?(database_file) +else + warn("Please configure your config/database.yml first") +end + +# Load plugins' Gemfiles +Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file| + puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` + instance_eval File.read(file) +end diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb index eeffe8b7b..caa199a72 100644 --- a/app/controllers/account_controller.rb +++ b/app/controllers/account_controller.rb @@ -31,9 +31,6 @@ class AccountController < ApplicationController else authenticate_user end - rescue AuthSourceException => e - logger.error "An error occured when authenticating #{params[:username]}: #{e.message}" - render_error :message => e.message end # Log out current user and redirect to welcome page @@ -47,6 +44,10 @@ class AccountController < ApplicationController # display the logout form end + def heartbeat + render :json => session[:user_id] + end + # Lets user choose a new password def lost_password (redirect_to(home_url); return) unless Setting.lost_password? @@ -329,7 +330,7 @@ class AccountController < ApplicationController end def set_autologin_cookie(user) - token = Token.create(:user => user, :action => 'autologin') + token = Token.get_or_create_permanent_login_token(user) cookie_options = { :value => token.value, :expires => 7.days.from_now, diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 741af2aee..0dc86fb01 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -156,16 +156,16 @@ class ApplicationController < ActionController::Base user end end - def try_to_autologin1 - - # auto-login feature starts a new session - user = User.try_to_autologin(params[:token]) - if user - start_user_session(user) - end - user + def try_to_autologin1 + user = User.try_to_autologin(params[:token]) + if user + logout_user if User.current.id != user.id + start_user_session(user) + end + user end + # Sets the logged in user def logged_user=(user) reset_session @@ -200,7 +200,7 @@ class ApplicationController < ActionController::Base def logout_user if User.current.logged? cookies.delete(autologin_cookie_name) - Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) + # Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) self.logged_user = nil end end diff --git a/app/controllers/avatar_controller.rb b/app/controllers/avatar_controller.rb index 771a14fe8..84b8a92e4 100644 --- a/app/controllers/avatar_controller.rb +++ b/app/controllers/avatar_controller.rb @@ -56,25 +56,9 @@ class AvatarController < ApplicationController # self.digest = md5.hexdigest end @temp_file = nil - # @avatar = Avatar.new(:receive_file => request.raw_post) - # @avatar.source_id = User.current.id - # @avatar.image_file = params[:filename].presence || Redmine::Utils.random_hex(16) - # saved = @avatar.save - begin - f = Magick::ImageList.new(diskfile) - # gif格式不再做大小处理 - if f.format != 'GIF' - width = 300.0 - proportion = (width/f[0].columns) - height = (f[0].rows*proportion) - f.resize_to_fill!(width,height) - f.write(diskfile) - end - - rescue Exception => e - logger.error "[Error] avatar : avatar_controller#upload ===> #{e}" - end + image = Trustie::Utils::Image.new(diskfile,true) + image.compress(300) respond_to do |format| format.js diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index fd1266095..431577f9a 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -93,15 +93,7 @@ class MessagesController < ApplicationController end call_hook(:controller_messages_new_after_save, { :params => params, :message => @message}) render_attachment_warning_if_needed(@message) - if params[:is_board] - if @project - redirect_to project_boards_path(@project) - elsif @course - redirect_to course_boards_path(@course) - end - else - redirect_to board_message_url(@board, @message) - end + redirect_to board_message_url(@board, @message) else layout_file = @project ? 'base_projects' : 'base_courses' render :action => 'new', :layout => layout_file @@ -131,24 +123,17 @@ class MessagesController < ApplicationController #@topic.update_attribute(:updated_on, Time.now) if !@reply.new_record? if params[:asset_id] - ids = params[:asset_id].split(',') - update_kindeditor_assets_owner ids,@reply.id,OwnerTypeHelper::MESSAGE + ids = params[:asset_id].split(',') + update_kindeditor_assets_owner ids,@reply.id,OwnerTypeHelper::MESSAGE end call_hook(:controller_messages_reply_after_save, { :params => params, :message => @reply}) attachments = Attachment.attach_files(@reply, params[:attachments]) render_attachment_warning_if_needed(@reply) - else - #render file: 'messages#show', layout: 'base_courses' - end - if params[:is_board] - if @project - redirect_to project_boards_path(@project) - elsif @course - redirect_to course_boards_path(@course) - end else - redirect_to board_message_url(@board, @topic, :r => @reply) + #render file: 'messages#show', layout: 'base_courses' end + redirect_to board_message_url(@board, @topic, :r => @reply) + end # Edit a message @@ -165,15 +150,7 @@ class MessagesController < ApplicationController render_attachment_warning_if_needed(@message) flash[:notice] = l(:notice_successful_update) @message.reload - if params[:is_board] - if @project - redirect_to project_boards_path(@project) - elsif @course - redirect_to course_boards_path(@course) - end - else - redirect_to board_message_url(@message.board, @message.root, :r => (@message.parent_id && @message.id)) - end + redirect_to board_message_url(@message.board, @message.root, :r => (@message.parent_id && @message.id)) elsif request.get? respond_to do |format| format.html { @@ -195,20 +172,16 @@ class MessagesController < ApplicationController @message.destroy # modify by nwb if @project - if params[:is_board] - redirect_to project_boards_url(@project) + if @message.parent + redirect_to board_message_url(@board, @message.parent, :r => r) else - redirect_to board_message_url(@board, @topic, :r => @reply) + redirect_to project_boards_url(@project) end elsif @course - if params[:is_board] - redirect_to course_boards_url(@course) + if @message.parent + redirect_to board_message_url(@board, @message.parent, :r => r) else - if @message.parent - redirect_to board_message_url(@board, @message.parent, :r => r) - else - redirect_to course_board_url(@course, @board) - end + redirect_to course_board_url(@course, @board) end end end @@ -229,7 +202,7 @@ class MessagesController < ApplicationController render :partial => 'common/preview' end -private + private def find_message return unless find_board @message = @board.messages.find(params[:id], :include => :parent) diff --git a/app/controllers/my_controller.rb b/app/controllers/my_controller.rb index d42a750a1..69d8bc3a6 100644 --- a/app/controllers/my_controller.rb +++ b/app/controllers/my_controller.rb @@ -95,76 +95,46 @@ class MyController < ApplicationController @pref = @user.pref diskfile = disk_filename('User', @user.id) diskfile1 = diskfile + 'temp' - if request.post? - @user.safe_attributes = params[:user] - @user.pref.attributes = params[:pref] - @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') - @user.login = params[:login] - unless @user.user_extensions.nil? - if @user.user_extensions.identity == 2 - @user.firstname = params[:enterprise_name] - end - end - - @se = @user.extensions - if params[:occupation].to_i.to_s == params[:occupation] - @se.school_id = params[:occupation] - else - @se.occupation = params[:occupation] - end - @se.gender = params[:gender] - @se.location = params[:province] if params[:province] - @se.location_city = params[:city] if params[:city] - @se.identity = params[:identity].to_i if params[:identity] - @se.technical_title = params[:technical_title] if params[:technical_title] - @se.student_id = params[:no] if params[:no] - - if @user.save && @se.save - # 头像保存 - if File.exist?(diskfile1) - if File.exist?(diskfile) - File.delete(diskfile) - end - File.open(diskfile1, "rb") do |f| - buffer = f.read(10) - if buffer != "DELETE" - File.open(diskfile1, "rb") do |f1| - File.open(diskfile, "wb") do |f| - buffer = "" - while (buffer = f1.read(8192)) - f.write(buffer) - end - end - end - - # File.rename(diskfile + 'temp',diskfile); - end + begin + if request.post? + @user.safe_attributes = params[:user] + @user.pref.attributes = params[:pref] + @user.pref[:no_self_notified] = (params[:no_self_notified] == '1') + @user.login = params[:login] + unless @user.user_extensions.nil? + if @user.user_extensions.identity == 2 + @user.firstname = params[:enterprise_name] end end - # 确保文件被删除 - if File.exist?(diskfile1) - File.delete(diskfile1) + @se = @user.extensions + if params[:occupation].to_i.to_s == params[:occupation] + @se.school_id = params[:occupation] + else + @se.occupation = params[:occupation] end + @se.gender = params[:gender] + @se.location = params[:province] if params[:province] + @se.location_city = params[:city] if params[:city] + @se.identity = params[:identity].to_i if params[:identity] + @se.technical_title = params[:technical_title] if params[:technical_title] + @se.student_id = params[:no] if params[:no] - @user.pref.save - @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) - set_language_if_valid @user.language - flash[:notice] = l(:notice_account_updated) - redirect_to user_url(@user) - return - else - # 确保文件被删除 - if File.exist?(diskfile1) - File.delete(diskfile1) + if @user.save && @se.save + # 头像保存 + FileUtils.mv diskfile1, diskfile, force: true if File.exist? diskfile1 + @user.pref.save + @user.notified_project_ids = (@user.mail_notification == 'selected' ? params[:notified_project_ids] : []) + set_language_if_valid @user.language + flash[:notice] = l(:notice_account_updated) + redirect_to user_url(@user) + return + else + @user.login = lg end - @user.login = lg - end - else - # 确保文件被删除 - if File.exist?(diskfile1) - File.delete(diskfile1) end + ensure + File.delete(diskfile1) if File.exist?(diskfile1) end end @@ -200,31 +170,20 @@ class MyController < ApplicationController @user = us.change_password params.merge(:current_user_id => @user.id) if @user.errors.full_messages.count <= 0 flash.now[:notice] = l(:notice_account_password_updated) - redirect_to my_account_url + # 修改完密码,让其重新登录,并更新Token + Token.delete_user_all_tokens(@user) + logout_user + redirect_to signin_url(back_url: my_account_path) + else + flash.now[:error] = l(:notice_account_wrong_password) end end rescue Exception => e if e.message == 'wrong password' flash.now[:error] = l(:notice_account_wrong_password) + else + flash.now[:error] = e.message end - # @user = User.current - # unless @user.change_password_allowed? - # flash.now[:error] = l(:notice_can_t_change_password) - # redirect_to my_account_url - # return - # end - # if request.post? - # if @user.check_password?(params[:password]) - # @user.password, @user.password_confirmation = params[:new_password], params[:new_password_confirmation] - # - # if @user.save - # flash.now[:notice] = l(:notice_account_password_updated) - # redirect_to my_account_url - # end - # else - # flash.now[:error] = l(:notice_account_wrong_password) - # end - # end end # Create a new feeds key diff --git a/app/models/token.rb b/app/models/token.rb index c89ff30bc..d9fc75d76 100644 --- a/app/models/token.rb +++ b/app/models/token.rb @@ -1,3 +1,4 @@ +#coding=utf-8 # Redmine - project management software # Copyright (C) 2006-2013 Jean-Philippe Lang # @@ -14,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# class Token < ActiveRecord::Base belongs_to :user validates_uniqueness_of :value @@ -27,6 +28,14 @@ class Token < ActiveRecord::Base self.value = Token.generate_token_value end + def self.get_or_create_permanent_login_token(user) + token = Token.get_token_from_user(user, 'autologin') + unless token + token = Token.create(:user => user, :action => 'autologin') + end + token + end + def self.get_token_from_user(user, action) token = Token.where(:action => action, :user_id => user).first unless token @@ -42,7 +51,7 @@ class Token < ActiveRecord::Base # Delete all expired tokens def self.destroy_expired - Token.delete_all ["action NOT IN (?) AND created_on < ?", ['feeds', 'api'], Time.now - @@validity_time] + Token.delete_all ["action NOT IN (?) AND created_on < ?", ['feeds', 'api', 'autologin'], Time.now - @@validity_time] end # Returns the active user who owns the key for the given action @@ -80,6 +89,10 @@ class Token < ActiveRecord::Base Redmine::Utils.random_hex(20) end + def self.delete_user_all_tokens(user) + Token.delete_all(user_id: user.id) + end + private # Removes obsolete tokens (same user and action) diff --git a/app/views/avatar/_avatar_form.html.erb b/app/views/avatar/_avatar_form.html.erb index 56f1f130e..43aaf9132 100644 --- a/app/views/avatar/_avatar_form.html.erb +++ b/app/views/avatar/_avatar_form.html.erb @@ -73,4 +73,7 @@ <% content_for :header_tags do %> <%= javascript_include_tag 'avatars' %> <% end %> - \ No newline at end of file + + + + diff --git a/app/views/avatar/upload.js.erb b/app/views/avatar/upload.js.erb index a7a341f10..b39e308ec 100644 --- a/app/views/avatar/upload.js.erb +++ b/app/views/avatar/upload.js.erb @@ -1,4 +1,4 @@ var imgSpan = $('#avatar_image'); -imgSpan.attr({"src":'<%= @urlfile.to_s << "?" << Time.now.to_s%>'}); +imgSpan.attr({"src":'<%= "#{@urlfile.to_s}?#{Time.now.to_i}" %>'}); diff --git a/app/views/files/_project_file_list.html.erb b/app/views/files/_project_file_list.html.erb index 3dd5134d7..e11e4416b 100644 --- a/app/views/files/_project_file_list.html.erb +++ b/app/views/files/_project_file_list.html.erb @@ -20,20 +20,16 @@
<%= link_to_attachment file, :download => true,:text => truncate(file.filename,length: 35, omission: '...'), :title => file.filename+"\n"+file.description.to_s, :style => "overflow: hidden; white-space: nowrap;text-overflow: ellipsis;",:class => "c_dblue f_14 f_b f_l" %> <% if User.current.logged? %> - <% if (manage_allowed || file.author_id == User.current.id) && project_contains_attachment?(project,file) %> + + + <% if project.is_public? %> <%= link_to(l(:label_slected_to_other_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %> - - <% if manage_allowed && file.container_id == project.id && file.container_type == "Project" %> + <% if (Member.where(:user_id => User.current.id, :project_id => @project.id).first.roles.to_s.include?("Manager") || file.author_id == User.current.id) && project_contains_attachment?(project,file) && file.container_id == project.id && file.container_type == "Project" %> <%= link_to (file.is_public? ? "公开":"私有"), update_file_dense_attachments_path(:attachmentid=>file.id,:newtype=>(file.is_public? ? 0:1)),:remote=>true,:class=>"f_l re_open",:method => :post %> - <% else %> - <% end %> - <% else %> - <%= link_to(l(:label_slected_to_project),quote_resource_show_project_project_file_path(project,file),:class => "f_l re_select",:remote => true) if has_project?(User.current,file) %> <% end %> - <% else %> <% end %>
diff --git a/app/views/homework_attach/edit.html.erb b/app/views/homework_attach/edit.html.erb index 63c3051aa..e31c5008f 100644 --- a/app/views/homework_attach/edit.html.erb +++ b/app/views/homework_attach/edit.html.erb @@ -42,7 +42,7 @@
<% end%> diff --git a/app/views/layouts/_base_friend_group.html.erb b/app/views/layouts/_base_friend_group.html.erb index 71d375501..16ccc09e5 100644 --- a/app/views/layouts/_base_friend_group.html.erb +++ b/app/views/layouts/_base_friend_group.html.erb @@ -12,7 +12,7 @@ (<%= @project.boards.first.topics.count %>) <% end %> <% if User.current.member_of?(@project) %> - <%= link_to "+"+l(:project_module_boards_post), project_boards_path(@project, :flag => true), :layout => 'base_projects', :class => "subnav_green ml105" %> + <%= link_to "+"+l(:project_module_boards_post), new_board_message_path(@project.boards.first), :layout => 'base_projects', :class => "subnav_green ml105" %> <% end %> <% end%> diff --git a/app/views/layouts/_base_research_team.html.erb b/app/views/layouts/_base_research_team.html.erb index 3f942bc40..a214e8c20 100644 --- a/app/views/layouts/_base_research_team.html.erb +++ b/app/views/layouts/_base_research_team.html.erb @@ -23,7 +23,7 @@ (<%= @project.boards.first.topics.count %>) <% end %> <% if User.current.member_of?(@project) %> - <%= link_to "+"+l(:project_module_boards_post), project_boards_path(@project, :flag => true), :layout => 'base_projects', :class => "subnav_green ml105" %> + <%= link_to "+"+l(:project_module_boards_post), new_board_message_path(@project.boards.first), :layout => 'base_projects', :class => "subnav_green ml105" %> <% end %> <% end%> diff --git a/app/views/layouts/base_courses.html.erb b/app/views/layouts/base_courses.html.erb index 8361c3874..2a26ff59f 100644 --- a/app/views/layouts/base_courses.html.erb +++ b/app/views/layouts/base_courses.html.erb @@ -133,7 +133,7 @@ - <%= link_to( - l(:button_edit), - {:action => 'edit', :id => @topic}, - :class => 'talk_edit fr' - ) if @message.course_editable_by?(User.current) %> <%= link_to( l(:button_delete), {:action => 'destroy', :id => @topic}, @@ -40,6 +35,11 @@ :data => {:confirm => l(:text_are_you_sure)}, :class => 'talk_edit fr' ) if @message.course_destroyable_by?(User.current) %> + <%= link_to( + l(:button_edit), + {:action => 'edit', :id => @topic}, + :class => 'talk_edit fr' + ) if @message.course_editable_by?(User.current) %>
<%= @topic.content.html_safe %>
<%= link_to_attachments_course @topic, :author => false %>
@@ -105,6 +105,7 @@ <%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message_form'} do |f| %> <%= render :partial => 'form_course', :locals => {:f => f, :replying => true} %> <%= link_to l(:button_submit),"javascript:void(0)",:onclick => 'course_board_submit_message_replay();' ,:class => "blue_btn fl c_white" ,:style=>"margin-left: 50px;"%> + <%= link_to l(:button_cancel), "javascript:void(0)", :onclick => 'course_board_canel_message_replay();', :class => "blue_btn grey_btn fl c_white" %> <% end %> <% end %> diff --git a/app/views/messages/_form_course.html.erb b/app/views/messages/_form_course.html.erb index 9324ea59e..1161e9f8a 100644 --- a/app/views/messages/_form_course.html.erb +++ b/app/views/messages/_form_course.html.erb @@ -1,16 +1,17 @@ <%= javascript_include_tag "/assets/kindeditor/kindeditor" %> <%= error_messages_for 'message' %> <% replying ||= false %> -<% extra_option = replying ? { readonly: true} : { maxlength: 200 } %> +<% extra_option = replying ? { hidden: "hidden"} : { maxlength: 200 } %>
  • - +
    <% if replying %> - <%= f.text_field :subject, { size: 60, id: "message_subject",:class=>"talk_input w585" }.merge(extra_option) %> +
    <%= f.text_field :subject, { size: 60, id: "message_subject",:class=>"talk_input w585 fl" }.merge(extra_option) %>
    <% else %> <%= f.text_field :subject, { size: 60, id: "message_subject", onkeyup: "regexSubject();",:class=>"talk_input w585" }.merge(extra_option) %> +

    <% end %> -

    +
  • <% unless replying %> @@ -26,7 +27,7 @@
  • -
    +
  • -
  • +
  • <% unless replying %> <% if @message.safe_attribute? 'sticky' %> <%= f.check_box :sticky %> diff --git a/app/views/messages/edit.html.erb b/app/views/messages/edit.html.erb index 1545fa610..d30aee45d 100644 --- a/app/views/messages/edit.html.erb +++ b/app/views/messages/edit.html.erb @@ -5,7 +5,7 @@ <% if @message.project %> <%#= board_breadcrumb(@message) %> -
    +
      <%= form_for @message, { :as => :message, :url => {:action => 'edit'}, @@ -23,7 +23,7 @@ <% elsif @message.course %> <%#= course_board_breadcrumb(@message) %>
      -
        +
          0 <%= form_for @message, { :as => :message, :url => {:action => 'edit'}, diff --git a/app/views/messages/quote.js.erb b/app/views/messages/quote.js.erb index 157e20764..e7ee0bca0 100644 --- a/app/views/messages/quote.js.erb +++ b/app/views/messages/quote.js.erb @@ -5,3 +5,4 @@ $('#quote_quote').html("<%= raw escape_javascript(@temp.content.html_safe) %>"); showAndScrollTo("reply", "message_content"); $('#message_content').scrollTop = $('#message_content').scrollHeight - $('#message_content').clientHeight; +$("img").removeAttr("align"); diff --git a/app/views/news/_course_form.html.erb b/app/views/news/_course_form.html.erb index b757ab274..a76d84701 100644 --- a/app/views/news/_course_form.html.erb +++ b/app/views/news/_course_form.html.erb @@ -25,11 +25,11 @@
        • <% if is_new %> - <%= link_to l(:button_create), "#", :onclick => 'submitNews();', :onmouseover => 'submitFocus(this);', :class => 'blue_btn fl c_white' %> + <%= link_to l(:button_create), "javascript:void(0)", :onclick => 'submitNews();', :onmouseover => 'submitFocus(this);', :class => 'blue_btn fl c_white' %> <%= link_to l(:button_cancel), course_news_index_path(@course), :onclick => '$("#add-news").hide()', :class => 'blue_btn grey_btn fl c_white' %> <% else %> - <%= link_to l(:button_save), "#", :onclick => "submitNews();",:onmouseover => 'this.focus()',:class => 'blue_btn fl c_white' %> - <%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;',:class => 'blue_btn grey_btn fl c_white' %> + <%= link_to l(:button_save), "javascript:void(0)", :onclick => "submitNews();",:onmouseover => 'this.focus()',:class => 'blue_btn fl c_white' %> + <%= link_to l(:button_cancel), "javascript:void(0)", :onclick => '$("#edit-news").hide(); return false;',:class => 'blue_btn grey_btn fl c_white' %> <% end %>
        • diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 3d06070a2..1d3a65f8b 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1 +1 @@ -Rails.application.config.session_store ActionDispatch::Session::CacheStore, :expire_after => 20.minutes, :key => '_trustie_session', :domain => :all +Rails.application.config.session_store ActionDispatch::Session::CacheStore, :expire_after => 90.minutes, :key => '_trustie_session', :domain => :all diff --git a/config/routes.rb b/config/routes.rb index d3b8a1b37..ae87c6a65 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -227,6 +227,8 @@ RedmineApp::Application.routes.draw do match '/projects/search', :via => [:get, :post] match '/users/search', :via => [:get, :post] #end + + match 'account/heartbeat', to: 'account#heartbeat', :via => :get match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post] match 'logout', :to => 'account#logout', :as => 'signout', :via => [:get, :post] match 'account/register', :via => [:get, :post], :as => 'register' diff --git a/db/schema.rb b/db/schema.rb index cd5cb1599..e798dba1c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -438,6 +438,13 @@ ActiveRecord::Schema.define(:version => 20150505025537) do add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" + create_table "discuss_demos", :force => true do |t| + t.string "title" + t.text "body" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "documents", :force => true do |t| t.integer "project_id", :default => 0, :null => false t.integer "category_id", :default => 0, :null => false diff --git a/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb b/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb index 33d44a2ec..56b4c7adf 100644 --- a/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb +++ b/lib/rails_kindeditor/lib/rails_kindeditor/helper.rb @@ -55,7 +55,7 @@ module RailsKindeditor }" else "KindEditor.ready(function(K){ - #{editor_id}K.create('##{dom_id}', #{get_options(options).to_json}); + #{editor_id}K.create('##{dom_id}', #{get_options(options).to_json}).loadPlugin('paste'); });" end end @@ -101,4 +101,4 @@ module RailsKindeditor @template.send("kindeditor", @object_name, method, objectify_options(options)) end end -end \ No newline at end of file +end diff --git a/lib/tasks/avatar.rake b/lib/tasks/avatar.rake new file mode 100644 index 000000000..9fe4f34bb --- /dev/null +++ b/lib/tasks/avatar.rake @@ -0,0 +1,11 @@ +desc "compress and backup avatar" +task :compress_avatar => :environment do + path = File.join(Rails.root, "public/images/avatars/User") + Dir.foreach(path) do |f| + if f.to_s =~ /^\d+$/ + puts f + image = Trustie::Utils::Image.new(File.join(path,f), true) + image.compress(300) + end + end +end diff --git a/lib/trustie.rb b/lib/trustie.rb index ff70d118c..b6cec3c86 100644 --- a/lib/trustie.rb +++ b/lib/trustie.rb @@ -1 +1,2 @@ -require 'trustie/utils' \ No newline at end of file +require 'trustie/utils' +require 'trustie/utils/image' diff --git a/lib/trustie/utils.rb b/lib/trustie/utils.rb index 7d0b2a272..45e5f0028 100644 --- a/lib/trustie/utils.rb +++ b/lib/trustie/utils.rb @@ -17,4 +17,4 @@ end if __FILE__ == $0 puts Trustie::Utils.digest('/Users/guange/Downloads/QQ_V4.0.2.dmg') -end \ No newline at end of file +end diff --git a/lib/trustie/utils/image.rb b/lib/trustie/utils/image.rb new file mode 100644 index 000000000..849c155ee --- /dev/null +++ b/lib/trustie/utils/image.rb @@ -0,0 +1,35 @@ +#coding=utf-8 + +module Trustie + module Utils + class Image + def initialize(file, bak) + @file = file + @bak = bak + end + + def compress(size=300) + backup if @bak + begin + f = Magick::ImageList.new(@file) + if f.format != 'GIF' + width = size + if f[0].columns > width + proportion = (width/f[0].columns.to_f) + height = (f[0].rows*proportion) + f.resize_to_fill!(width,height.to_i) + f.write(@file) + end + end + rescue Exception => e + logger.error "[Error] compress : ===> #{e}" + end + end + + def backup + FileUtils.cp @file, "#{@file}.bak" + end + + end + end +end diff --git a/public/assets/kindeditor/plugins/paste/paste.js b/public/assets/kindeditor/plugins/paste/paste.js new file mode 100644 index 000000000..0f63ce18c --- /dev/null +++ b/public/assets/kindeditor/plugins/paste/paste.js @@ -0,0 +1,37 @@ +KindEditor.plugin('paste', function(K) { + var editor = this, + name = 'paste'; + var contentWindow = document.getElementsByTagName('iframe')[0].contentWindow; + contentWindow.document.getElementsByTagName('body')[0].onpaste = function(event) { + // use event.originalEvent.clipboard for newer chrome versions + var items = (event.clipboardData || event.originalEvent.clipboardData).items; + console.log(JSON.stringify(items)); // will give you the mime types + // find pasted image among pasted items + var blob = null; + for (var i = 0; i < items.length; i++) { + if (items[i].type.indexOf("image") === 0) { + blob = items[i].getAsFile(); + } + } + // load image if there is a pasted image + if (blob !== null) { + var reader = new FileReader(); + reader.onload = function(event) { + console.log(event.target.result); // data url! + var data = new FormData(); + data.append("imgFile", blob, "imageFilename.png"); + $.ajax({ + url: '/kindeditor/upload?dir=image', + contentType: false, + type: 'POST', + data: data, + processData: false, + success: function(data) { + editor.exec('insertimage', JSON.parse(data).url); + } + }); + }; + reader.readAsDataURL(blob); + } + } +}); diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 4e5b5591e..b2bd70d8d 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -1,914 +1,921 @@ -//= require_directory ./rateable -//= require jquery.min -//= require jquery.infinitescroll - -/* Redmine - project management software - Copyright (C) 2006-2013 Jean-Philippe Lang */ - -function cleanArray (actual){ - var newArray = new Array(); - for (var i = 0; i< actual.length; i++){ - if (actual[i]){ - newArray.push(actual[i]); - } - } - return newArray; -} - -function checkAll(id, checked) { - if (checked) { - $('#'+id).find('input[type=checkbox]').attr('checked', true); - } else { - $('#'+id).find('input[type=checkbox]').removeAttr('checked'); - } -} - -function toggleCheckboxesBySelector(selector) { - var all_checked = true; - $(selector).each(function(index) { - if (!$(this).is(':checked')) { all_checked = false; } - }); - $(selector).attr('checked', !all_checked); -} - -function showAndScrollTo(id, focus) { - $('#'+id).show(); - if (focus !== null) { - $('#'+focus).focus(); - } - $('html, body').animate({scrollTop: $('#'+id).offset().top}, 400); -} - -function toggleRowGroup(el) { - var tr = $(el).parents('tr').first(); - var n = tr.next(); - tr.toggleClass('open'); - while (n.length && !n.hasClass('group')) { - n.toggle(); - n = n.next('tr'); - } -} - -function collapseAllRowGroups(el) { - var tbody = $(el).parents('tbody').first(); - tbody.children('tr').each(function(index) { - if ($(this).hasClass('group')) { - $(this).removeClass('open'); - } else { - $(this).hide(); - } - }); -} - -function expandAllRowGroups(el) { - var tbody = $(el).parents('tbody').first(); - tbody.children('tr').each(function(index) { - if ($(this).hasClass('group')) { - $(this).addClass('open'); - } else { - $(this).show(); - } - }); -} - -function toggleAllRowGroups(el) { - var tr = $(el).parents('tr').first(); - if (tr.hasClass('open')) { - collapseAllRowGroups(el); - } else { - expandAllRowGroups(el); - } -} - -function toggleFieldset(el) { - var fieldset = $(el).parents('fieldset').first(); - fieldset.toggleClass('collapsed'); - fieldset.children('div').toggle(); -} - -function hideFieldset(el) { - var fieldset = $(el).parents('fieldset').first(); - fieldset.toggleClass('collapsed'); - fieldset.children('div').hide(); -} - -function initFilters(){ - $('#add_filter_select').change(function(){ - addFilter($(this).val(), '', []); - }); - $('#filters-table td.field input[type=checkbox]').each(function(){ - toggleFilter($(this).val()); - }); - $('#filters-table td.field input[type=checkbox]').live('click',function(){ - toggleFilter($(this).val()); - }); - $('#filters-table .toggle-multiselect').live('click',function(){ - toggleMultiSelect($(this).siblings('select')); - }); - $('#filters-table input[type=text]').live('keypress', function(e){ - if (e.keyCode == 13) submit_query_form("query_form"); - }); -} - -function addFilter(field, operator, values) { - var fieldId = field.replace('.', '_'); - var tr = $('#tr_'+fieldId); - if (tr.length > 0) { - tr.show(); - } else { - buildFilterRow(field, operator, values); - } - $('#cb_'+fieldId).attr('checked', true); - toggleFilter(field); - $('#add_filter_select').val('').children('option').each(function(){ - if ($(this).attr('value') == field) { - $(this).attr('disabled', true); - } - }); -} - -function buildFilterRow(field, operator, values) { - var fieldId = field.replace('.', '_'); - var filterTable = $("#filters-table"); - var filterOptions = availableFilters[field]; - var operators = operatorByType[filterOptions['type']]; - var filterValues = filterOptions['values']; - var i, select; - - var tr = $('').attr('id', 'tr_'+fieldId).html( - '' + - '' + - ' 复选/multi-select' - ); - select = tr.find('td.values select'); - if (values.length > 1) { select.attr('multiple', true); } - for (i=0;i'); - if ($.isArray(filterValue)) { - option.val(filterValue[1]).text(filterValue[0]); - if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);} - } else { - option.val(filterValue).text(filterValue); - if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);} - } - select.append(option); - } - break; - case "date": - case "date_past": - tr.find('td.values').append( - '' + - ' ' + - ' '+labelDayPlural+'' - ); - $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions); - $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions); - $('#values_'+fieldId).val(values[0]); - break; - case "string": - case "text": - tr.find('td.values').append( - '' - ); - $('#values_'+fieldId).val(values[0]); - break; - case "relation": - tr.find('td.values').append( - '' + - '' - ); - $('#values_'+fieldId).val(values[0]); - select = tr.find('td.values select'); - for (i=0;i'); - option.val(filterValue[1]).text(filterValue[0]); - if (values[0] == filterValue[1]) { option.attr('selected', true); } - select.append(option); - } - case "integer": - case "float": - tr.find('td.values').append( - '' + - ' ' - ); - $('#values_'+fieldId+'_1').val(values[0]); - $('#values_'+fieldId+'_2').val(values[1]); - break; - } -} - -function toggleFilter(field) { - var fieldId = field.replace('.', '_'); - if ($('#cb_' + fieldId).is(':checked')) { - $("#operators_" + fieldId).show().removeAttr('disabled'); - toggleOperator(field); - } else { - $("#operators_" + fieldId).hide().attr('disabled', true); - enableValues(field, []); - } -} - -function enableValues(field, indexes) { - var fieldId = field.replace('.', '_'); - $('#tr_'+fieldId+' td.values .value').each(function(index) { - if ($.inArray(index, indexes) >= 0) { - $(this).removeAttr('disabled'); - $(this).parents('span').first().show(); - } else { - $(this).val(''); - $(this).attr('disabled', true); - $(this).parents('span').first().hide(); - } - - if ($(this).hasClass('group')) { - $(this).addClass('open'); - } else { - $(this).show(); - } - }); -} - -function toggleOperator(field) { - var fieldId = field.replace('.', '_'); - var operator = $("#operators_" + fieldId); - switch (operator.val()) { - case "!*": - case "*": - case "t": - case "ld": - case "w": - case "lw": - case "l2w": - case "m": - case "lm": - case "y": - case "o": - case "c": - enableValues(field, []); - break; - case "><": - enableValues(field, [0,1]); - break; - case "t+": - case ">t-": - case "0) { - lis.eq(i-1).show(); - } -} - -function displayTabsButtons() { - var lis; - var tabsWidth = 0; - var el; - $('div.tabs').each(function() { - el = $(this); - lis = el.find('ul').children(); - lis.each(function(){ - if ($(this).is(':visible')) { - tabsWidth += $(this).width() + 6; - } - }); - if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) { - el.find('div.tabs-buttons').hide(); - } else { - el.find('div.tabs-buttons').show(); - } - }); -} - -function setPredecessorFieldsVisibility() { - var relationType = $('#relation_relation_type'); - if (relationType.val() == "precedes" || relationType.val() == "follows") { - $('#predecessor_fields').show(); - } else { - $('#predecessor_fields').hide(); - } -} - -function showModal(id, width) { - var el = $('#'+id).first(); - if (el.length === 0 || el.is(':visible')) {return;} - var title = el.find('h3.title').text(); - el.dialog({ - width: width, - modal: true, - resizable: false, - dialogClass: 'modal', - title: title - }); - el.find("input[type=text], input[type=submit]").first().focus(); -} - -function hideModal(el) { - var modal; - if (el) { - modal = $(el).parents('.ui-dialog-content'); - } else { - modal = $('#ajax-modal'); - } - modal.dialog("close"); -} - -function submitPreview(url, form, target) { - $.ajax({ - url: url, - type: 'post', - data: $('#'+form).serialize(), - success: function(data){ - $('#'+target).html(data); - } - }); -} - -function collapseScmEntry(id) { - $('.'+id).each(function() { - if ($(this).hasClass('open')) { - collapseScmEntry($(this).attr('id')); - } - $(this).hide(); - }); - $('#'+id).removeClass('open'); -} - -function expandScmEntry(id) { - $('.'+id).each(function() { - $(this).show(); - if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) { - expandScmEntry($(this).attr('id')); - } - }); - $('#'+id).addClass('open'); -} - -function scmEntryClick(id, url) { - el = $('#'+id); - if (el.hasClass('open')) { - collapseScmEntry(id); - el.addClass('collapsed'); - return false; - } else if (el.hasClass('loaded')) { - expandScmEntry(id); - el.removeClass('collapsed'); - return false; - } - if (el.hasClass('loading')) { - return false; - } - el.addClass('loading'); - $.ajax({ - url: url, - success: function(data){ - el.after(data); - el.addClass('open').addClass('loaded').removeClass('loading'); - } - }); - return true; -} - -function randomKey(size) { - var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'); - var key = ''; - for (i = 0; i < size; i++) { - key += chars[Math.floor(Math.random() * chars.length)]; - } - return key; -} - -// Can't use Rails' remote select because we need the form data -function updateIssueFrom(url) { - $.ajax({ - url: url, - type: 'post', - data: $('#issue-form').serialize() - }); -} - -function updateBulkEditFrom(url) { - $.ajax({ - url: url, - type: 'post', - data: $('#bulk_edit_form').serialize() - }); -} - -function clearMessage(id) { - $('#'+id).val(""); -} - - -function observeAutocompleteField(fieldId, url, options) { - $(document).ready(function() { - $('#'+fieldId).autocomplete($.extend({ - source: url, - select: function(e,ui){self.location="/issues/"+ui.item.value;}, - minLength: 1, - search: function(){$('#'+fieldId).addClass('ajax-loading');}, - response: function(){$('#'+fieldId).removeClass('ajax-loading'); - } - }, options)); - $('#'+fieldId).addClass('autocomplete'); - - }); - -} - -function observeSearchfield(fieldId, targetId, url) { - $('#'+fieldId).each(function() { - var $this = $(this); - $this.addClass('autocomplete'); - $this.attr('data-value-was', $this.val()); - var check = function() { - var val = $this.val(); - if ($this.attr('data-value-was') != val){ - $this.attr('data-value-was', val); - $.ajax({ - url: url, - type: 'get', - data: {q: $this.val()}, - success: function(data){ if(targetId) $('#'+targetId).html(data); }, - beforeSend: function(){ $this.addClass('ajax-loading'); }, - complete: function(){ $this.removeClass('ajax-loading'); } - }); - } - }; - var reset = function() { - if (timer) { - clearInterval(timer); - timer = setInterval(check, 300); - } - }; - var timer = setInterval(check, 300); - $this.bind('keyup click mousemove', reset); - }); -} - -function observeProjectModules() { - var f = function() { - /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */ - if ($('#project_enabled_module_names_issue_tracking').attr('checked')) { - $('#project_trackers').show(); - }else{ - $('#project_trackers').hide(); - } - }; - - $(window).load(f); - $('#project_enabled_module_names_issue_tracking').change(f); -} - -function initMyPageSortable(list, url) { - $('#list-'+list).sortable({ - connectWith: '.block-receiver', - tolerance: 'pointer', - update: function(){ - $.ajax({ - url: url, - type: 'post', - data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})} - }); - } - }); - $("#list-top, #list-left, #list-right").disableSelection(); -} - -var warnLeavingUnsavedMessage; -function warnLeavingUnsaved(message) { - warnLeavingUnsavedMessage = message; - - $('form').submit(function(){ - $('textarea').removeData('changed'); - }); - $('textarea').change(function(){ - $(this).data('changed', 'changed'); - }); - window.onbeforeunload = function(){ - var warn = false; - $('textarea').blur().each(function(){ - if ($(this).data('changed')) { - warn = true; - } - }); - if (warn) {return warnLeavingUnsavedMessage;} - }; -} - -function setupAjaxIndicator() { - - $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) { - - if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') { - $('#ajax-indicator').show(); - } - }); - - $('#ajax-indicator').bind('ajaxStop', function() { - $('#ajax-indicator').hide(); - }); -} - -function hideOnLoad() { - $('.hol').hide(); -} - -function addFormObserversForDoubleSubmit() { - $('form[method=post]').each(function() { - if (!$(this).hasClass('multiple-submit')) { - $(this).submit(function(form_submission) { - if ($(form_submission.target).attr('data-submitted')) { - form_submission.preventDefault(); - } else { - $(form_submission.target).attr('data-submitted', true); - } - }); - } - }); -} - -function blockEventPropagation(event) { - event.stopPropagation(); - event.preventDefault(); -} - -function toggleAndSettingWordsVal(parent_widget, text_widget, value){ - text_widget.val(value) - parent_widget.slideToggle(400) -} -function transpotUrl (scope) { - $(scope).each(function(){ - var tmpContent = $(this).html(); - tmpContent = tmpContent.replace(/(^|[^\"\'])(http|ftp|mms|rstp|news|https)(\:\/\/[^<\s\+,,]+)/gi,"$1$2$3<\/a>"); - // tmpContent = tmpContent.replace(/(^|[^\/])(www\.[^<\s\+,,]+)/gi,"$1$2"); - $(this).html(tmpContent); - }); -} - -$(document).ready(setupAjaxIndicator); -$(document).ready(hideOnLoad); -$(document).ready(addFormObserversForDoubleSubmit); - -function img_thumbnails() { - $('.thumbnails a').colorbox({rel:'nofollow'}); - $('.attachments').find('a').each(function(index, element) { - var href_value = $(element).attr('href'); - if (/\.(jpg|png|gif|bmp|jpeg|PNG|BMP|GIF|JPG|JPEG)$/.test(href_value)) { - $(element).colorbox({rel:'nofollow'}); - } - }); - $('.for_img_thumbnails').find('a').each(function(index, element) { - var href_value = $(element).attr('href'); - if (/\.(jpg|png|gif|bmp|jpeg|PNG|BMP|GIF|JPG|JPEG)$/.test(href_value)) { - $(element).colorbox({rel:'nofollow'}); - } - }); -} -$(document).ready(img_thumbnails); - -function TimeClose(dateText, inst) { - if(inst.id=="issue_start_date"){ - time=dateText; - } -} -var time=new Date(); -function TimeBeforeShow(input){ - if(input.id=="issue_due_date"){ - //var minDate = $(input).datepicker('option', 'minDate'); - var tempdata=$("#issue_start_date").attr("value"); - - $(input).datepicker('option', 'minDate',new Date(tempdata.replace(/-/g, "/"))); - //$('.selector').datepicker('option', 'minDate', '12/25/2012'); - } -} - -function SetMinValue(){ - /// var tempdata=$("#issue_start_date").attr("value"); - //$('.selector').datepicker('option', 'minDate', '12/25/2012'); - //alert(tempdata); - //$("#issue_due_date").datepicker({ - // minDate: new Date(2014,08,23) - //var datepickerOptions= - //{dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true}; - //alert( $('.issue_due_date').length); - //$('.selector')[1].datepicker('option', 'minDate', new Date(2014, 0 - 8, 23)); - //$("#issue_due_date").datepicker(datepickerOptions); - //$("##{issue_due_date}").datepicker(datepickerOptions); - //$("#issue_due_date").datepicker( - // {dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true} - //) - //}); -} -function PrecentChange(obj){ - var _v= obj; - if(_v==100) - { - //var select=$("select[id='issue_status_id']"); - $("select[id='issue_status_id']").find("option[value='3']").attr("selected","selected"); - } - else if(_v==0) - { - //alert(1); - $("select[id='issue_status_id']").find("option[value='1']").attr("selected","selected"); - } - else if(_v!=100&&_v!=0) - { - // alert(2); - $("select[id='issue_status_id']").find("option[value='2']").attr("selected","selected"); - } -} - -//added by lizanle 日期選擇js -function HS_DateAdd(interval,number,date){ - number = parseInt(number); - if (typeof(date)=="string"){var date = new Date(date.split("-")[0],date.split("-")[1],date.split("-")[2])} - if (typeof(date)=="object"){var date = date} - switch(interval){ - case "y":return new Date(date.getFullYear()+number,date.getMonth(),date.getDate()); break; - case "m":return new Date(date.getFullYear(),date.getMonth()+number,checkDate(date.getFullYear(),date.getMonth()+number,date.getDate())); break; - case "d":return new Date(date.getFullYear(),date.getMonth(),date.getDate()+number); break; - case "w":return new Date(date.getFullYear(),date.getMonth(),7*number+date.getDate()); break; - } -} -function checkDate(year,month,date){ - var enddate = ["31","28","31","30","31","30","31","31","30","31","30","31"]; - var returnDate = ""; - if (year%4==0){enddate[1]="29"} - if (date>enddate[month]){returnDate = enddate[month]}else{returnDate = date} - return returnDate; -} - -function WeekDay(date){ - var theDate; - if (typeof(date)=="string"){theDate = new Date(date.split("-")[0],date.split("-")[1],date.split("-")[2]);} - if (typeof(date)=="object"){theDate = date} - return theDate.getDay(); -} -function HS_calender(){ - var lis = ""; - var style = ""; - /*可以把下面的css剪切出去独立一个css文件*/ - style +=""; - - var now; - if (typeof(arguments[0])=="string"){ - selectDate = arguments[0].split("-"); - var year = selectDate[0]; - var month = parseInt(selectDate[1])-1+""; - var date = selectDate[2]; - now = new Date(year,month,date); - }else if (typeof(arguments[0])=="object"){ - now = arguments[0]; - } - var lastMonthEndDate = HS_DateAdd("d","-1",now.getFullYear()+"-"+now.getMonth()+"-01").getDate(); - var lastMonthDate = WeekDay(now.getFullYear()+"-"+now.getMonth()+"-01"); - var thisMonthLastDate = HS_DateAdd("d","-1",now.getFullYear()+"-"+(parseInt(now.getMonth())+1).toString()+"-01"); - var thisMonthEndDate = thisMonthLastDate.getDate(); - var thisMonthEndDay = thisMonthLastDate.getDay(); - var todayObj = new Date(); - today = todayObj.getFullYear()+"-"+todayObj.getMonth()+"-"+todayObj.getDate(); - - for (i=0; i" + lis; - lastMonthEndDate--; - } - for (i=1; i<=thisMonthEndDate; i++){ // Current Month's Date - - if(today == now.getFullYear()+"-"+now.getMonth()+"-"+i){ - var todayString = now.getFullYear()+"-"+(parseInt(now.getMonth())+1).toString()+"-"+i; - lis += "
        • "+i+"
        • "; - }else{ - lis += "
        • "+i+"
        • "; - } - - } - var j=1; - for (i=thisMonthEndDay; i<6; i++){ // Next Month's Date - lis += "
        • "+j+"
        • "; - j++; - } - lis += style; - - var CalenderTitle = "»"; - CalenderTitle += "«"; - CalenderTitle += ""+now.getFullYear()+""+(parseInt(now.getMonth())+1).toString()+"月"; - - if (arguments.length>1){ - arguments[1].parentNode.parentNode.getElementsByTagName("ul")[1].innerHTML = lis; - arguments[1].parentNode.innerHTML = CalenderTitle; - - }else{ - var CalenderBox = style+"
          "+CalenderTitle+"
            "+lis+"
          "; - return CalenderBox; - } -} -function _selectThisDay(d){ - var boxObj = d.parentNode.parentNode.parentNode.parentNode.parentNode; - boxObj.targetObj.value = d.title; - boxObj.parentNode.removeChild(boxObj); -} -function closeCalender(d){ - var boxObj = d.parentNode.parentNode.parentNode; - boxObj.parentNode.removeChild(boxObj); -} - -function CalenderselectYear(obj){ - var opt = ""; - var thisYear = obj.innerHTML; - for (i=1970; i<=2020; i++){ - if (i==thisYear){ - opt += ""; - }else{ - opt += ""; - } - } - opt = ""; - obj.parentNode.innerHTML = opt; -} - -function selectThisYear(obj){ - HS_calender(obj.value+"-"+obj.parentNode.parentNode.getElementsByTagName("span")[1].getElementsByTagName("a")[0].innerHTML+"-1",obj.parentNode); -} - -function CalenderselectMonth(obj){ - var opt = ""; - var thisMonth = obj.innerHTML; - for (i=1; i<=12; i++){ - if (i==thisMonth){ - opt += ""; - }else{ - opt += ""; - } - } - opt = ""; - obj.parentNode.innerHTML = opt; -} -function selectThisMonth(obj){ - HS_calender(obj.parentNode.parentNode.getElementsByTagName("span")[0].getElementsByTagName("a")[0].innerHTML+"-"+obj.value+"-1",obj.parentNode); -} -function HS_setDate(inputObj){ - var calenderObj = document.createElement("span"); - calenderObj.innerHTML = HS_calender(new Date()); - calenderObj.style.position = "absolute"; - calenderObj.targetObj = inputObj; - inputObj.parentNode.insertBefore(calenderObj,inputObj.nextSibling); -} -//lizanle 刷新函数 -function redo() { - window.location.reload() -} - - -//// 作业附件删除 -$(function(){ - $('.attachments a.delete-homework-icon').bind('ajax:complete', //this will work - function(event, data, status, xhr) { //note parametes - $(this).parent('p').remove(); - console.log("delete complete."); - }); - - $('a.tb_all').bind('ajax:complete', function (event, data, status, xhr) { - if(status == 'success'){ - var res = JSON.parse(data.responseText); - if(res.length<1){ - return; - } - - if(res.length==1){ - location.href = '/zipdown/download?file='+res[0].file;return; - } - - document.getElementById('light').style.display='block'; - $container = $('#light .upload_box_ul'); - $container.empty(); - for(var i = 0; i 1){ - des = '第'+res[i].index+'-'+(res[i].count+res[i].index-1)+'个学生的作品下载'; - } else { - des = '第'+res[i].index+'个学生的作品下载'; - } - $('
        • '+(i+1)+'. '+des+'  (共'+res[i].size+'M)
        • ').appendTo($container); - - } - } - - }) -}); - - -//firefox的pre标签换行 -$(document).ready(function () { - var userAgent = navigator.userAgent.toLowerCase(); - var browser = { - version: (userAgent.match(/.+(?:rv|it|ra|ie)[/: ]([d.]+)/) || [])[1], - safari: /webkit/.test(userAgent), - opera: /opera/.test(userAgent), - msie: /msie/.test(userAgent) && !/opera/.test(userAgent), - mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) - }; - if (browser.mozilla || browser.opera){ - $("pre").addClass("break_word_firefox"); - } - else{ - $("pre").addClass("break_word"); - } -}); +//= require_directory ./rateable +//= require jquery.min +//= require jquery.infinitescroll + +/* Redmine - project management software + Copyright (C) 2006-2013 Jean-Philippe Lang */ + +function cleanArray (actual){ + var newArray = new Array(); + for (var i = 0; i< actual.length; i++){ + if (actual[i]){ + newArray.push(actual[i]); + } + } + return newArray; +} + +function checkAll(id, checked) { + if (checked) { + $('#'+id).find('input[type=checkbox]').attr('checked', true); + } else { + $('#'+id).find('input[type=checkbox]').removeAttr('checked'); + } +} + +function toggleCheckboxesBySelector(selector) { + var all_checked = true; + $(selector).each(function(index) { + if (!$(this).is(':checked')) { all_checked = false; } + }); + $(selector).attr('checked', !all_checked); +} + +function showAndScrollTo(id, focus) { + $('#'+id).show(); + if (focus !== null) { + $('#'+focus).focus(); + } + $('html, body').animate({scrollTop: $('#'+id).offset().top}, 400); +} + +function toggleRowGroup(el) { + var tr = $(el).parents('tr').first(); + var n = tr.next(); + tr.toggleClass('open'); + while (n.length && !n.hasClass('group')) { + n.toggle(); + n = n.next('tr'); + } +} + +function collapseAllRowGroups(el) { + var tbody = $(el).parents('tbody').first(); + tbody.children('tr').each(function(index) { + if ($(this).hasClass('group')) { + $(this).removeClass('open'); + } else { + $(this).hide(); + } + }); +} + +function expandAllRowGroups(el) { + var tbody = $(el).parents('tbody').first(); + tbody.children('tr').each(function(index) { + if ($(this).hasClass('group')) { + $(this).addClass('open'); + } else { + $(this).show(); + } + }); +} + +function toggleAllRowGroups(el) { + var tr = $(el).parents('tr').first(); + if (tr.hasClass('open')) { + collapseAllRowGroups(el); + } else { + expandAllRowGroups(el); + } +} + +function toggleFieldset(el) { + var fieldset = $(el).parents('fieldset').first(); + fieldset.toggleClass('collapsed'); + fieldset.children('div').toggle(); +} + +function hideFieldset(el) { + var fieldset = $(el).parents('fieldset').first(); + fieldset.toggleClass('collapsed'); + fieldset.children('div').hide(); +} + +function initFilters(){ + $('#add_filter_select').change(function(){ + addFilter($(this).val(), '', []); + }); + $('#filters-table td.field input[type=checkbox]').each(function(){ + toggleFilter($(this).val()); + }); + $('#filters-table td.field input[type=checkbox]').live('click',function(){ + toggleFilter($(this).val()); + }); + $('#filters-table .toggle-multiselect').live('click',function(){ + toggleMultiSelect($(this).siblings('select')); + }); + $('#filters-table input[type=text]').live('keypress', function(e){ + if (e.keyCode == 13) submit_query_form("query_form"); + }); +} + +function addFilter(field, operator, values) { + var fieldId = field.replace('.', '_'); + var tr = $('#tr_'+fieldId); + if (tr.length > 0) { + tr.show(); + } else { + buildFilterRow(field, operator, values); + } + $('#cb_'+fieldId).attr('checked', true); + toggleFilter(field); + $('#add_filter_select').val('').children('option').each(function(){ + if ($(this).attr('value') == field) { + $(this).attr('disabled', true); + } + }); +} + +function buildFilterRow(field, operator, values) { + var fieldId = field.replace('.', '_'); + var filterTable = $("#filters-table"); + var filterOptions = availableFilters[field]; + var operators = operatorByType[filterOptions['type']]; + var filterValues = filterOptions['values']; + var i, select; + + var tr = $('').attr('id', 'tr_'+fieldId).html( + '' + + '' + + ' 复选/multi-select' + ); + select = tr.find('td.values select'); + if (values.length > 1) { select.attr('multiple', true); } + for (i=0;i'); + if ($.isArray(filterValue)) { + option.val(filterValue[1]).text(filterValue[0]); + if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);} + } else { + option.val(filterValue).text(filterValue); + if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);} + } + select.append(option); + } + break; + case "date": + case "date_past": + tr.find('td.values').append( + '' + + ' ' + + ' '+labelDayPlural+'' + ); + $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions); + $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions); + $('#values_'+fieldId).val(values[0]); + break; + case "string": + case "text": + tr.find('td.values').append( + '' + ); + $('#values_'+fieldId).val(values[0]); + break; + case "relation": + tr.find('td.values').append( + '' + + '' + ); + $('#values_'+fieldId).val(values[0]); + select = tr.find('td.values select'); + for (i=0;i'); + option.val(filterValue[1]).text(filterValue[0]); + if (values[0] == filterValue[1]) { option.attr('selected', true); } + select.append(option); + } + case "integer": + case "float": + tr.find('td.values').append( + '' + + ' ' + ); + $('#values_'+fieldId+'_1').val(values[0]); + $('#values_'+fieldId+'_2').val(values[1]); + break; + } +} + +function toggleFilter(field) { + var fieldId = field.replace('.', '_'); + if ($('#cb_' + fieldId).is(':checked')) { + $("#operators_" + fieldId).show().removeAttr('disabled'); + toggleOperator(field); + } else { + $("#operators_" + fieldId).hide().attr('disabled', true); + enableValues(field, []); + } +} + +function enableValues(field, indexes) { + var fieldId = field.replace('.', '_'); + $('#tr_'+fieldId+' td.values .value').each(function(index) { + if ($.inArray(index, indexes) >= 0) { + $(this).removeAttr('disabled'); + $(this).parents('span').first().show(); + } else { + $(this).val(''); + $(this).attr('disabled', true); + $(this).parents('span').first().hide(); + } + + if ($(this).hasClass('group')) { + $(this).addClass('open'); + } else { + $(this).show(); + } + }); +} + +function toggleOperator(field) { + var fieldId = field.replace('.', '_'); + var operator = $("#operators_" + fieldId); + switch (operator.val()) { + case "!*": + case "*": + case "t": + case "ld": + case "w": + case "lw": + case "l2w": + case "m": + case "lm": + case "y": + case "o": + case "c": + enableValues(field, []); + break; + case "><": + enableValues(field, [0,1]); + break; + case "t+": + case ">t-": + case "0) { + lis.eq(i-1).show(); + } +} + +function displayTabsButtons() { + var lis; + var tabsWidth = 0; + var el; + $('div.tabs').each(function() { + el = $(this); + lis = el.find('ul').children(); + lis.each(function(){ + if ($(this).is(':visible')) { + tabsWidth += $(this).width() + 6; + } + }); + if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) { + el.find('div.tabs-buttons').hide(); + } else { + el.find('div.tabs-buttons').show(); + } + }); +} + +function setPredecessorFieldsVisibility() { + var relationType = $('#relation_relation_type'); + if (relationType.val() == "precedes" || relationType.val() == "follows") { + $('#predecessor_fields').show(); + } else { + $('#predecessor_fields').hide(); + } +} + +function showModal(id, width) { + var el = $('#'+id).first(); + if (el.length === 0 || el.is(':visible')) {return;} + var title = el.find('h3.title').text(); + el.dialog({ + width: width, + modal: true, + resizable: false, + dialogClass: 'modal', + title: title + }); + el.find("input[type=text], input[type=submit]").first().focus(); +} + +function hideModal(el) { + var modal; + if (el) { + modal = $(el).parents('.ui-dialog-content'); + } else { + modal = $('#ajax-modal'); + } + modal.dialog("close"); +} + +function submitPreview(url, form, target) { + $.ajax({ + url: url, + type: 'post', + data: $('#'+form).serialize(), + success: function(data){ + $('#'+target).html(data); + } + }); +} + +function collapseScmEntry(id) { + $('.'+id).each(function() { + if ($(this).hasClass('open')) { + collapseScmEntry($(this).attr('id')); + } + $(this).hide(); + }); + $('#'+id).removeClass('open'); +} + +function expandScmEntry(id) { + $('.'+id).each(function() { + $(this).show(); + if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) { + expandScmEntry($(this).attr('id')); + } + }); + $('#'+id).addClass('open'); +} + +function scmEntryClick(id, url) { + el = $('#'+id); + if (el.hasClass('open')) { + collapseScmEntry(id); + el.addClass('collapsed'); + return false; + } else if (el.hasClass('loaded')) { + expandScmEntry(id); + el.removeClass('collapsed'); + return false; + } + if (el.hasClass('loading')) { + return false; + } + el.addClass('loading'); + $.ajax({ + url: url, + success: function(data){ + el.after(data); + el.addClass('open').addClass('loaded').removeClass('loading'); + } + }); + return true; +} + +function randomKey(size) { + var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'); + var key = ''; + for (i = 0; i < size; i++) { + key += chars[Math.floor(Math.random() * chars.length)]; + } + return key; +} + +// Can't use Rails' remote select because we need the form data +function updateIssueFrom(url) { + $.ajax({ + url: url, + type: 'post', + data: $('#issue-form').serialize() + }); +} + +function updateBulkEditFrom(url) { + $.ajax({ + url: url, + type: 'post', + data: $('#bulk_edit_form').serialize() + }); +} + +function clearMessage(id) { + $('#'+id).val(""); +} + + +function observeAutocompleteField(fieldId, url, options) { + $(document).ready(function() { + $('#'+fieldId).autocomplete($.extend({ + source: url, + select: function(e,ui){self.location="/issues/"+ui.item.value;}, + minLength: 1, + search: function(){$('#'+fieldId).addClass('ajax-loading');}, + response: function(){$('#'+fieldId).removeClass('ajax-loading'); + } + }, options)); + $('#'+fieldId).addClass('autocomplete'); + + }); + +} + +function observeSearchfield(fieldId, targetId, url) { + $('#'+fieldId).each(function() { + var $this = $(this); + $this.addClass('autocomplete'); + $this.attr('data-value-was', $this.val()); + var check = function() { + var val = $this.val(); + if ($this.attr('data-value-was') != val){ + $this.attr('data-value-was', val); + $.ajax({ + url: url, + type: 'get', + data: {q: $this.val()}, + success: function(data){ if(targetId) $('#'+targetId).html(data); }, + beforeSend: function(){ $this.addClass('ajax-loading'); }, + complete: function(){ $this.removeClass('ajax-loading'); } + }); + } + }; + var reset = function() { + if (timer) { + clearInterval(timer); + timer = setInterval(check, 300); + } + }; + var timer = setInterval(check, 300); + $this.bind('keyup click mousemove', reset); + }); +} + +function observeProjectModules() { + var f = function() { + /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */ + if ($('#project_enabled_module_names_issue_tracking').attr('checked')) { + $('#project_trackers').show(); + }else{ + $('#project_trackers').hide(); + } + }; + + $(window).load(f); + $('#project_enabled_module_names_issue_tracking').change(f); +} + +function initMyPageSortable(list, url) { + $('#list-'+list).sortable({ + connectWith: '.block-receiver', + tolerance: 'pointer', + update: function(){ + $.ajax({ + url: url, + type: 'post', + data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})} + }); + } + }); + $("#list-top, #list-left, #list-right").disableSelection(); +} + +var warnLeavingUnsavedMessage; +function warnLeavingUnsaved(message) { + warnLeavingUnsavedMessage = message; + + $('form').submit(function(){ + $('textarea').removeData('changed'); + }); + $('textarea').change(function(){ + $(this).data('changed', 'changed'); + }); + window.onbeforeunload = function(){ + var warn = false; + $('textarea').blur().each(function(){ + if ($(this).data('changed')) { + warn = true; + } + }); + if (warn) {return warnLeavingUnsavedMessage;} + }; +} + +function setupHeartBeat(){ + var time = 60*1000*30; // 30 mins + setInterval(function(){$.getJSON('/account/heartbeat');},time); +} + +function setupAjaxIndicator() { + $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) { + if(settings && settings.url && settings.url.endsWith('account/heartbeat')){ + return; + } + if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') { + $('#ajax-indicator').show(); + } + }); + + $('#ajax-indicator').bind('ajaxStop', function() { + $('#ajax-indicator').hide(); + }); +} + +function hideOnLoad() { + $('.hol').hide(); +} + +function addFormObserversForDoubleSubmit() { + $('form[method=post]').each(function() { + if (!$(this).hasClass('multiple-submit')) { + $(this).submit(function(form_submission) { + if ($(form_submission.target).attr('data-submitted')) { + form_submission.preventDefault(); + } else { + $(form_submission.target).attr('data-submitted', true); + } + }); + } + }); +} + +function blockEventPropagation(event) { + event.stopPropagation(); + event.preventDefault(); +} + +function toggleAndSettingWordsVal(parent_widget, text_widget, value){ + text_widget.val(value) + parent_widget.slideToggle(400) +} +function transpotUrl (scope) { + $(scope).each(function(){ + var tmpContent = $(this).html(); + tmpContent = tmpContent.replace(/(^|[^\"\'])(http|ftp|mms|rstp|news|https)(\:\/\/[^<\s\+,,]+)/gi,"$1$2$3<\/a>"); + // tmpContent = tmpContent.replace(/(^|[^\/])(www\.[^<\s\+,,]+)/gi,"$1$2"); + $(this).html(tmpContent); + }); +} + +$(document).ready(setupAjaxIndicator); +$(document).ready(setupHeartBeat); +$(document).ready(hideOnLoad); +$(document).ready(addFormObserversForDoubleSubmit); + +function img_thumbnails() { + $('.thumbnails a').colorbox({rel:'nofollow'}); + $('.attachments').find('a').each(function(index, element) { + var href_value = $(element).attr('href'); + if (/\.(jpg|png|gif|bmp|jpeg|PNG|BMP|GIF|JPG|JPEG)$/.test(href_value)) { + $(element).colorbox({rel:'nofollow'}); + } + }); + $('.for_img_thumbnails').find('a').each(function(index, element) { + var href_value = $(element).attr('href'); + if (/\.(jpg|png|gif|bmp|jpeg|PNG|BMP|GIF|JPG|JPEG)$/.test(href_value)) { + $(element).colorbox({rel:'nofollow'}); + } + }); +} +$(document).ready(img_thumbnails); + +function TimeClose(dateText, inst) { + if(inst.id=="issue_start_date"){ + time=dateText; + } +} +var time=new Date(); +function TimeBeforeShow(input){ + if(input.id=="issue_due_date"){ + //var minDate = $(input).datepicker('option', 'minDate'); + var tempdata=$("#issue_start_date").attr("value"); + + $(input).datepicker('option', 'minDate',new Date(tempdata.replace(/-/g, "/"))); + //$('.selector').datepicker('option', 'minDate', '12/25/2012'); + } +} + +function SetMinValue(){ + /// var tempdata=$("#issue_start_date").attr("value"); + //$('.selector').datepicker('option', 'minDate', '12/25/2012'); + //alert(tempdata); + //$("#issue_due_date").datepicker({ + // minDate: new Date(2014,08,23) + //var datepickerOptions= + //{dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true}; + //alert( $('.issue_due_date').length); + //$('.selector')[1].datepicker('option', 'minDate', new Date(2014, 0 - 8, 23)); + //$("#issue_due_date").datepicker(datepickerOptions); + //$("##{issue_due_date}").datepicker(datepickerOptions); + //$("#issue_due_date").datepicker( + // {dateFormat: 'yy-mm-dd',minDate: new Date(2014,08,23), showOn: 'button', buttonImageOnly: true, buttonImage: "path_to_image('/images/calendar.png')", showButtonPanel: true, showWeek: true, showOtherMonths: true, selectOtherMonths: true} + //) + //}); +} +function PrecentChange(obj){ + var _v= obj; + if(_v==100) + { + //var select=$("select[id='issue_status_id']"); + $("select[id='issue_status_id']").find("option[value='3']").attr("selected","selected"); + } + else if(_v==0) + { + //alert(1); + $("select[id='issue_status_id']").find("option[value='1']").attr("selected","selected"); + } + else if(_v!=100&&_v!=0) + { + // alert(2); + $("select[id='issue_status_id']").find("option[value='2']").attr("selected","selected"); + } +} + +//added by lizanle 日期選擇js +function HS_DateAdd(interval,number,date){ + number = parseInt(number); + if (typeof(date)=="string"){var date = new Date(date.split("-")[0],date.split("-")[1],date.split("-")[2])} + if (typeof(date)=="object"){var date = date} + switch(interval){ + case "y":return new Date(date.getFullYear()+number,date.getMonth(),date.getDate()); break; + case "m":return new Date(date.getFullYear(),date.getMonth()+number,checkDate(date.getFullYear(),date.getMonth()+number,date.getDate())); break; + case "d":return new Date(date.getFullYear(),date.getMonth(),date.getDate()+number); break; + case "w":return new Date(date.getFullYear(),date.getMonth(),7*number+date.getDate()); break; + } +} +function checkDate(year,month,date){ + var enddate = ["31","28","31","30","31","30","31","31","30","31","30","31"]; + var returnDate = ""; + if (year%4==0){enddate[1]="29"} + if (date>enddate[month]){returnDate = enddate[month]}else{returnDate = date} + return returnDate; +} + +function WeekDay(date){ + var theDate; + if (typeof(date)=="string"){theDate = new Date(date.split("-")[0],date.split("-")[1],date.split("-")[2]);} + if (typeof(date)=="object"){theDate = date} + return theDate.getDay(); +} +function HS_calender(){ + var lis = ""; + var style = ""; + /*可以把下面的css剪切出去独立一个css文件*/ + style +=""; + + var now; + if (typeof(arguments[0])=="string"){ + selectDate = arguments[0].split("-"); + var year = selectDate[0]; + var month = parseInt(selectDate[1])-1+""; + var date = selectDate[2]; + now = new Date(year,month,date); + }else if (typeof(arguments[0])=="object"){ + now = arguments[0]; + } + var lastMonthEndDate = HS_DateAdd("d","-1",now.getFullYear()+"-"+now.getMonth()+"-01").getDate(); + var lastMonthDate = WeekDay(now.getFullYear()+"-"+now.getMonth()+"-01"); + var thisMonthLastDate = HS_DateAdd("d","-1",now.getFullYear()+"-"+(parseInt(now.getMonth())+1).toString()+"-01"); + var thisMonthEndDate = thisMonthLastDate.getDate(); + var thisMonthEndDay = thisMonthLastDate.getDay(); + var todayObj = new Date(); + today = todayObj.getFullYear()+"-"+todayObj.getMonth()+"-"+todayObj.getDate(); + + for (i=0; i" + lis; + lastMonthEndDate--; + } + for (i=1; i<=thisMonthEndDate; i++){ // Current Month's Date + + if(today == now.getFullYear()+"-"+now.getMonth()+"-"+i){ + var todayString = now.getFullYear()+"-"+(parseInt(now.getMonth())+1).toString()+"-"+i; + lis += "
        • "+i+"
        • "; + }else{ + lis += "
        • "+i+"
        • "; + } + + } + var j=1; + for (i=thisMonthEndDay; i<6; i++){ // Next Month's Date + lis += "
        • "+j+"
        • "; + j++; + } + lis += style; + + var CalenderTitle = "»"; + CalenderTitle += "«"; + CalenderTitle += ""+now.getFullYear()+""+(parseInt(now.getMonth())+1).toString()+"月"; + + if (arguments.length>1){ + arguments[1].parentNode.parentNode.getElementsByTagName("ul")[1].innerHTML = lis; + arguments[1].parentNode.innerHTML = CalenderTitle; + + }else{ + var CalenderBox = style+"
          "+CalenderTitle+"
            "+lis+"
          "; + return CalenderBox; + } +} +function _selectThisDay(d){ + var boxObj = d.parentNode.parentNode.parentNode.parentNode.parentNode; + boxObj.targetObj.value = d.title; + boxObj.parentNode.removeChild(boxObj); +} +function closeCalender(d){ + var boxObj = d.parentNode.parentNode.parentNode; + boxObj.parentNode.removeChild(boxObj); +} + +function CalenderselectYear(obj){ + var opt = ""; + var thisYear = obj.innerHTML; + for (i=1970; i<=2020; i++){ + if (i==thisYear){ + opt += ""; + }else{ + opt += ""; + } + } + opt = ""; + obj.parentNode.innerHTML = opt; +} + +function selectThisYear(obj){ + HS_calender(obj.value+"-"+obj.parentNode.parentNode.getElementsByTagName("span")[1].getElementsByTagName("a")[0].innerHTML+"-1",obj.parentNode); +} + +function CalenderselectMonth(obj){ + var opt = ""; + var thisMonth = obj.innerHTML; + for (i=1; i<=12; i++){ + if (i==thisMonth){ + opt += ""; + }else{ + opt += ""; + } + } + opt = ""; + obj.parentNode.innerHTML = opt; +} +function selectThisMonth(obj){ + HS_calender(obj.parentNode.parentNode.getElementsByTagName("span")[0].getElementsByTagName("a")[0].innerHTML+"-"+obj.value+"-1",obj.parentNode); +} +function HS_setDate(inputObj){ + var calenderObj = document.createElement("span"); + calenderObj.innerHTML = HS_calender(new Date()); + calenderObj.style.position = "absolute"; + calenderObj.targetObj = inputObj; + inputObj.parentNode.insertBefore(calenderObj,inputObj.nextSibling); +} +//lizanle 刷新函数 +function redo() { + window.location.reload() +} + + +//// 作业附件删除 +$(function(){ + $('.attachments a.delete-homework-icon').bind('ajax:complete', //this will work + function(event, data, status, xhr) { //note parametes + $(this).parent('p').remove(); + console.log("delete complete."); + }); + + $('a.tb_all').bind('ajax:complete', function (event, data, status, xhr) { + if(status == 'success'){ + var res = JSON.parse(data.responseText); + if(res.length<1){ + return; + } + + if(res.length==1){ + location.href = '/zipdown/download?file='+res[0].file;return; + } + + document.getElementById('light').style.display='block'; + $container = $('#light .upload_box_ul'); + $container.empty(); + for(var i = 0; i 1){ + des = '第'+res[i].index+'-'+(res[i].count+res[i].index-1)+'个学生的作品下载'; + } else { + des = '第'+res[i].index+'个学生的作品下载'; + } + $('
        • '+(i+1)+'. '+des+'  (共'+res[i].size+'M)
        • ').appendTo($container); + + } + } + + }) +}); + + +//firefox的pre标签换行 +$(document).ready(function () { + var userAgent = navigator.userAgent.toLowerCase(); + var browser = { + version: (userAgent.match(/.+(?:rv|it|ra|ie)[/: ]([d.]+)/) || [])[1], + safari: /webkit/.test(userAgent), + opera: /opera/.test(userAgent), + msie: /msie/.test(userAgent) && !/opera/.test(userAgent), + mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent) + }; + if (browser.mozilla || browser.opera){ + $("pre").addClass("break_word_firefox"); + } + else{ + $("pre").addClass("break_word"); + } +}); diff --git a/public/javascripts/avatars.js b/public/javascripts/avatars.js index 3d8420dc0..a8f10edf0 100644 --- a/public/javascripts/avatars.js +++ b/public/javascripts/avatars.js @@ -190,6 +190,9 @@ function dragOutHandler(e) { } function setupFileDrop() { + $('#avatar_image').on('click', function(){ + console.log("click"); + }); if (window.File && window.FileList && window.ProgressEvent && window.FormData) { $.event.fixHooks.drop = { props: [ 'dataTransfer' ] }; diff --git a/public/javascripts/course.js b/public/javascripts/course.js index cc57279f0..f0b1338da 100644 --- a/public/javascripts/course.js +++ b/public/javascripts/course.js @@ -8,6 +8,10 @@ function course_setting(id) $('#tbc_0'+(3-id)).removeClass().addClass("undis"); } +$(function(){ + $("img").removeAttr("align"); +}); + /////////////////////////////////////////////////////////////// //添加分班 function add_group(url,course_id) { @@ -266,6 +270,13 @@ function course_board_submit_message_replay() $("#message_form").submit(); } } + +function course_board_canel_message_replay() +{ + $("#reply").hide(200); + $("#message_quote").html(""); +} + function MessageReplayVevify() { var content = message_content_editor.html();//$.trim($("#message_content").val()); if (content.length == 0) { @@ -515,6 +526,7 @@ $(function(){ //查找TAG资源 function search_tag_attachment(url,tag_name,q,course_id,sort) { + //alert("111"); $.get( url, { diff --git a/public/javascripts/paste.js b/public/javascripts/paste.js new file mode 100644 index 000000000..961a29acb --- /dev/null +++ b/public/javascripts/paste.js @@ -0,0 +1,292 @@ +// Generated by CoffeeScript 1.9.0 + +/* +paste.js is an interface to read data ( text / image ) from clipboard in different browsers. It also contains several hacks. + +https://github.com/layerssss/paste.js + */ + +(function() { + var $, Paste, createHiddenEditable, dataURLtoBlob; + + $ = window.jQuery; + + $.paste = function(pasteContainer) { + var pm; + if (typeof console !== "undefined" && console !== null) { + console.log("DEPRECATED: This method is deprecated. Please use $.fn.pastableNonInputable() instead."); + } + pm = Paste.mountNonInputable(pasteContainer); + return pm._container; + }; + + $.fn.pastableNonInputable = function() { + var el, _i, _len; + for (_i = 0, _len = this.length; _i < _len; _i++) { + el = this[_i]; + Paste.mountNonInputable(el); + } + return this; + }; + + $.fn.pastableTextarea = function() { + var el, _i, _len; + for (_i = 0, _len = this.length; _i < _len; _i++) { + el = this[_i]; + Paste.mountTextarea(el); + } + return this; + }; + + $.fn.pastableContenteditable = function() { + var el, _i, _len; + for (_i = 0, _len = this.length; _i < _len; _i++) { + el = this[_i]; + Paste.mountContenteditable(el); + } + return this; + }; + + dataURLtoBlob = function(dataURL, sliceSize) { + var b64Data, byteArray, byteArrays, byteCharacters, byteNumbers, contentType, i, m, offset, slice, _ref; + if (sliceSize == null) { + sliceSize = 512; + } + if (!(m = dataURL.match(/^data\:([^\;]+)\;base64\,(.+)$/))) { + return null; + } + _ref = m, m = _ref[0], contentType = _ref[1], b64Data = _ref[2]; + byteCharacters = atob(b64Data); + byteArrays = []; + offset = 0; + while (offset < byteCharacters.length) { + slice = byteCharacters.slice(offset, offset + sliceSize); + byteNumbers = new Array(slice.length); + i = 0; + while (i < slice.length) { + byteNumbers[i] = slice.charCodeAt(i); + i++; + } + byteArray = new Uint8Array(byteNumbers); + byteArrays.push(byteArray); + offset += sliceSize; + } + return new Blob(byteArrays, { + type: contentType + }); + }; + + createHiddenEditable = function() { + return $(document.createElement('div')).attr('contenteditable', true).css({ + width: 1, + height: 1, + position: 'fixed', + left: -100, + overflow: 'hidden' + }); + }; + + Paste = (function() { + Paste.prototype._target = null; + + Paste.prototype._container = null; + + Paste.mountNonInputable = function(nonInputable) { + var paste; + paste = new Paste(createHiddenEditable().appendTo(nonInputable), nonInputable); + $(nonInputable).on('click', (function(_this) { + return function() { + return paste._container.focus(); + }; + })(this)); + paste._container.on('focus', (function(_this) { + return function() { + return $(nonInputable).addClass('pastable-focus'); + }; + })(this)); + return paste._container.on('blur', (function(_this) { + return function() { + return $(nonInputable).removeClass('pastable-focus'); + }; + })(this)); + }; + + Paste.mountTextarea = function(textarea) { + var ctlDown, paste; + if (-1 !== navigator.userAgent.toLowerCase().indexOf('chrome')) { + return this.mountContenteditable(textarea); + } + paste = new Paste(createHiddenEditable().insertBefore(textarea), textarea); + ctlDown = false; + $(textarea).on('keyup', function(ev) { + var _ref; + if ((_ref = ev.keyCode) === 17 || _ref === 224) { + return ctlDown = false; + } + }); + $(textarea).on('keydown', function(ev) { + var _ref; + if ((_ref = ev.keyCode) === 17 || _ref === 224) { + ctlDown = true; + } + if (ctlDown && ev.keyCode === 86) { + return paste._container.focus(); + } + }); + $(paste._target).on('pasteImage', (function(_this) { + return function() { + return $(textarea).focus(); + }; + })(this)); + $(paste._target).on('pasteText', (function(_this) { + return function() { + return $(textarea).focus(); + }; + })(this)); + $(textarea).on('focus', (function(_this) { + return function() { + return $(textarea).addClass('pastable-focus'); + }; + })(this)); + return $(textarea).on('blur', (function(_this) { + return function() { + return $(textarea).removeClass('pastable-focus'); + }; + })(this)); + }; + + Paste.mountContenteditable = function(contenteditable) { + var paste; + paste = new Paste(contenteditable, contenteditable); + $(contenteditable).on('focus', (function(_this) { + return function() { + return $(contenteditable).addClass('pastable-focus'); + }; + })(this)); + return $(contenteditable).on('blur', (function(_this) { + return function() { + return $(contenteditable).removeClass('pastable-focus'); + }; + })(this)); + }; + + function Paste(_at__container, _at__target) { + this._container = _at__container; + this._target = _at__target; + this._container = $(this._container); + this._target = $(this._target).addClass('pastable'); + this._container.on('paste', (function(_this) { + return function(ev) { + var clipboardData, file, item, reader, text, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _results; + if (((_ref = ev.originalEvent) != null ? _ref.clipboardData : void 0) != null) { + clipboardData = ev.originalEvent.clipboardData; + if (clipboardData.items) { + _ref1 = clipboardData.items; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + item = _ref1[_i]; + if (item.type.match(/^image\//)) { + reader = new FileReader(); + reader.onload = function(event) { + return _this._handleImage(event.target.result); + }; + reader.readAsDataURL(item.getAsFile()); + } + if (item.type === 'text/plain') { + item.getAsString(function(string) { + return _this._target.trigger('pasteText', { + text: string + }); + }); + } + } + } else { + if (-1 !== Array.prototype.indexOf.call(clipboardData.types, 'text/plain')) { + text = clipboardData.getData('Text'); + _this._target.trigger('pasteText', { + text: text + }); + } + _this._checkImagesInContainer(function(src) { + return _this._handleImage(src); + }); + } + } + if (clipboardData = window.clipboardData) { + if ((_ref2 = (text = clipboardData.getData('Text'))) != null ? _ref2.length : void 0) { + return _this._target.trigger('pasteText', { + text: text + }); + } else { + _ref3 = clipboardData.files; + _results = []; + for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { + file = _ref3[_j]; + _this._handleImage(URL.createObjectURL(file)); + _results.push(_this._checkImagesInContainer(function() {})); + } + return _results; + } + } + }; + })(this)); + } + + Paste.prototype._handleImage = function(src) { + var loader; + loader = new Image(); + loader.onload = (function(_this) { + return function() { + var blob, canvas, ctx, dataURL; + canvas = document.createElement('canvas'); + canvas.width = loader.width; + canvas.height = loader.height; + ctx = canvas.getContext('2d'); + ctx.drawImage(loader, 0, 0, canvas.width, canvas.height); + dataURL = null; + try { + dataURL = canvas.toDataURL('image/png'); + blob = dataURLtoBlob(dataURL); + } catch (_error) {} + if (dataURL) { + return _this._target.trigger('pasteImage', { + blob: blob, + dataURL: dataURL, + width: loader.width, + height: loader.height + }); + } + }; + })(this); + return loader.src = src; + }; + + Paste.prototype._checkImagesInContainer = function(cb) { + var img, timespan, _i, _len, _ref; + timespan = Math.floor(1000 * Math.random()); + _ref = this._container.find('img'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + img = _ref[_i]; + img["_paste_marked_" + timespan] = true; + } + return setTimeout((function(_this) { + return function() { + var _j, _len1, _ref1, _results; + _ref1 = _this._container.find('img'); + _results = []; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + img = _ref1[_j]; + if (!img["_paste_marked_" + timespan]) { + cb(img.src); + } + _results.push($(img).remove()); + } + return _results; + }; + })(this), 1); + }; + + return Paste; + + })(); + +}).call(this); diff --git a/public/stylesheets/courses.css b/public/stylesheets/courses.css index 4643be06b..f49ef22f1 100644 --- a/public/stylesheets/courses.css +++ b/public/stylesheets/courses.css @@ -437,6 +437,7 @@ a.link_file_board{ background:url(../images/pic_file.png) 0 3px no-repeat !impor /*上传图片处理*/ .upload_img img{max-width: 100%;} +blockquote img{max-width: 100%;} /* The following fixes a problem where IE7 and IE8 replace a PNG's alpha transparency with a black fill @@ -480,13 +481,13 @@ a:hover.link_file{ background:url(../images/pic_file.png) 0 -25px no-repeat; col /*日历选择图*/ img.ui-datepicker-trigger { display:block; - background:url(/images/public_icon.png) -31px 0 no-repeat; + background:url(../images/public_icon.png) -31px 0 no-repeat; cursor: pointer; vertical-align: middle; margin-left: 5px; margin-top: 5px; - width:16px; - height:15px; + width:16px; + height:15px; float:left; } @@ -561,7 +562,7 @@ a:hover.Reply_pic{border:1px solid #64bdd9;} .Replybox{ float:left; width:495px; margin-left:5px;} .talk_nextpage{ border:none; width:410px; margin:0 auto;} .newtalk { margin-top:8px; margin-right:8px;} -.talk_new{ border-bottom:1px dashed #d9d9d9; padding-bottom:10px;} +/*.talk_new{ border-bottom:1px dashed #d9d9d9; padding-bottom:10px;}*/ #about_newtalk{ display:none;}