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 - + 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/my_controller.rb b/app/controllers/my_controller.rb index d42a750a1..ebb7c2fc8 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 + @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/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/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/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);