diff --git a/.gitignore b/.gitignore index 93c7eb248..bc936c34c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ .DS_Store public/api_doc/ /.metadata +vendor/cache diff --git a/.metadata/.plugins/com.aptana.index.core/2874248206.index b/.metadata/.plugins/com.aptana.index.core/2874248206.index deleted file mode 100644 index 2200403a8..000000000 Binary files a/.metadata/.plugins/com.aptana.index.core/2874248206.index and /dev/null differ diff --git a/.metadata/.plugins/com.aptana.index.core/2924452064.index b/.metadata/.plugins/com.aptana.index.core/2924452064.index deleted file mode 100644 index 982acfcbc..000000000 Binary files a/.metadata/.plugins/com.aptana.index.core/2924452064.index and /dev/null differ diff --git a/.metadata/.plugins/com.aptana.index.core/4010369919.index b/.metadata/.plugins/com.aptana.index.core/4010369919.index deleted file mode 100644 index e2902378c..000000000 Binary files a/.metadata/.plugins/com.aptana.index.core/4010369919.index and /dev/null differ diff --git a/Gemfile b/Gemfile index 34e81cef6..29b2716a9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ -source 'http://rubygems.org' +source 'http://ruby.taobao.org' #source 'http://ruby.sdutlinux.org/' unless RUBY_PLATFORM =~ /w32/ @@ -10,11 +10,11 @@ end gem 'grape', '~> 0.9.0' gem 'grape-entity' -gem 'seems_rateable', path: 'lib/seems_rateable' +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.0.6" +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' @@ -23,14 +23,20 @@ gem 'ruby-ole' #gem 'email_verifier', path: 'lib/email_verifier' gem 'rufus-scheduler' #gem 'dalli', path: 'lib/dalli-2.7.2' +gem 'rails_kindeditor' group :development do gem 'grape-swagger' #gem 'grape-swagger-ui', git: 'https://github.com/guange2015/grape-swagger-ui.git' - #gem 'puma' + gem 'puma' if RbConfig::CONFIG['host_os'] =~ /linux/ gem 'pry-rails' - gem 'pry-byebug' - gem 'better_errors', path: 'lib/better_errors' - gem 'rack-mini-profiler', path: 'lib/rack-mini-profiler' + 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 diff --git a/app/api/mobile/apis/comments.rb b/app/api/mobile/apis/comments.rb index 75932d60f..2e84fe5a9 100644 --- a/app/api/mobile/apis/comments.rb +++ b/app/api/mobile/apis/comments.rb @@ -2,6 +2,7 @@ module Mobile module Apis class Comments < Grape::API + include ApplicationHelper resource :comments do desc '课程通知评论' params do @@ -82,8 +83,8 @@ module Mobile memo: {:subject => params[:subject],:content => '该贴来自手机App意见反馈'}, } cs = CommentService.new - memo = cs.create_feedback cs_params, current_user - raise "commit failed #{memo.errors.full_messages}" if memo.new_record? + memo,message = cs.create_feedback cs_params, current_user + raise message if memo.new_record? present :status, 0 end diff --git a/app/api/mobile/apis/users.rb b/app/api/mobile/apis/users.rb index 9a5307be6..b6d1db25c 100644 --- a/app/api/mobile/apis/users.rb +++ b/app/api/mobile/apis/users.rb @@ -82,7 +82,7 @@ module Mobile desc "用户搜索" params do requires :name, type: String, desc: '用户名关键字' - requires :search_by, type: String,desc: '搜索依据:0 昵称,1 用户名,2 邮箱' + requires :search_by, type: String,desc: '搜索依据:0 昵称,1 用户名,2 邮箱,3 昵称和姓名' end get 'search/search_user' do us = UsersService.new diff --git a/app/api/mobile/entities/course_dynamic.rb b/app/api/mobile/entities/course_dynamic.rb index aa8aadbb6..b6e4630e4 100644 --- a/app/api/mobile/entities/course_dynamic.rb +++ b/app/api/mobile/entities/course_dynamic.rb @@ -15,6 +15,8 @@ module Mobile course_dynamic_expose :type course_dynamic_expose :count course_dynamic_expose :course_name + course_dynamic_expose :course_term + course_dynamic_expose :course_time course_dynamic_expose :course_id course_dynamic_expose :course_img_url course_dynamic_expose :message diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb index 9b66c047f..c055d38ae 100644 --- a/app/controllers/courses_controller.rb +++ b/app/controllers/courses_controller.rb @@ -873,13 +873,15 @@ class CoursesController < ApplicationController "show_course_news" => true, "show_course_messages" => true, "show_bids" => true, - "show_course_journals_for_messages" => true + "show_course_journals_for_messages" => true, + "show_homeworks" => true } @date_to ||= Date.today + 1 # @date_from = (@date_to - @days) > @course.created_at.to_date ? (@date_to - @days) : @course.created_at.to_date #@date_from = @date_to - @days-1.years @author = (params[:user_id].blank? ? nil : User.active.find(params[:user_id])) + @author ||= @course.teacher # 决定显示所用用户或单个用户活动 @activity = Redmine::Activity::Fetcher.new(User.current, :course => @course, :with_subprojects => false, diff --git a/app/controllers/discuss_demos_controller.rb b/app/controllers/discuss_demos_controller.rb new file mode 100644 index 000000000..a0955efe2 --- /dev/null +++ b/app/controllers/discuss_demos_controller.rb @@ -0,0 +1,40 @@ +class DiscussDemosController < ApplicationController + def index + + @discuss_demo_list = DiscussDemo.where("body is not null").order("created_at desc").page(params[:page] || 1).per(10) + end + + def new + @discuss_demo = DiscussDemo.create + @discuss_demo.save! + @discuss_demo + end + + def create + + end + + def update + @discuss_demo = DiscussDemo.find(params[:id]) + @discuss_demo.update_attributes(:title => params[:discuss_demo][:title],:body => params[:discuss_demo][:body]) + redirect_to :controller=> 'discuss_demos',:action => 'show',:id => params[:id] + end + + def delete + + end + + def destroy + asset = Kindeditor::Asset.find_by_owner_id(params[:id]) + filepath = File.join(Rails.root,"public","files","uploads", + asset[:created_at].to_s.gsub("+0800","").to_datetime.strftime("%Y%m").to_s, + asset[:asset].to_s) + File.delete(filepath) if File.exist?filepath + DiscussDemo.destroy(params[:id]) + redirect_to :controller=> 'discuss_demos',:action => 'index' + end + + def show + @discuss_demo = DiscussDemo.find(params[:id]) + end +end diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb index 545d61155..9bf2ee846 100644 --- a/app/controllers/documents_controller.rb +++ b/app/controllers/documents_controller.rb @@ -91,6 +91,7 @@ class DocumentsController < ApplicationController def update @document.safe_attributes = params[:document] + @document.save_attachments(params[:attachments]) if request.put? and @document.save flash[:notice] = l(:notice_successful_update) redirect_to document_url(@document) diff --git a/app/controllers/forums_controller.rb b/app/controllers/forums_controller.rb index 2f7092d9a..64157ea42 100644 --- a/app/controllers/forums_controller.rb +++ b/app/controllers/forums_controller.rb @@ -20,7 +20,7 @@ class ForumsController < ApplicationController #@memo.author_id = User.current.id #@forum = @memo.forum cs = CommentService.new - @memo = cs.create_feedback params,User.current + @memo,message = cs.create_feedback params,User.current respond_to do |format| if !@memo.new_record? format.html { redirect_to forum_path(@memo.forum) } diff --git a/app/controllers/git_callback_controller.rb b/app/controllers/git_callback_controller.rb new file mode 100644 index 000000000..717a22961 --- /dev/null +++ b/app/controllers/git_callback_controller.rb @@ -0,0 +1,9 @@ +class GitCallbackController < ApplicationController + + def post_update + @repository = Repository.find_by_root_url(params[:root_url]) + @repository.fetch_changesets + render :text => 'success' + end + +end \ No newline at end of file diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 6a251a80c..de9477b8a 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -58,7 +58,7 @@ class IssuesController < ApplicationController def index retrieve_query - sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria) + sort_init(@query.sort_criteria.empty? ? [['updated_on', 'desc']] : @query.sort_criteria) sort_update(@query.sortable_columns) @query.sort_criteria = sort_criteria.to_a @@ -162,7 +162,7 @@ class IssuesController < ApplicationController respond_to do |format| format.html { render_attachment_warning_if_needed(@issue) - flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("#{@issue.source_from}", issue_path(@issue), :title => @issue.subject)) + flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("#{@issue.subject}", issue_path(@issue), :title => @issue.subject)) #flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("##{@issue.id}", issue_path(@issue), :title => @issue.subject)) if params[:continue] attrs = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?} @@ -381,7 +381,7 @@ class IssuesController < ApplicationController def retrieve_previous_and_next_issue_ids retrieve_query_from_session if @query - sort_init(@query.sort_criteria.empty? ? [['id', 'desc']] : @query.sort_criteria) + sort_init(@query.sort_criteria.empty? ? [['updated_on', 'desc']] : @query.sort_criteria) sort_update(@query.sortable_columns, 'issues_index_sort') limit = 500 issue_ids = @query.issue_ids(:order => sort_clause, :limit => (limit + 1), :include => [:assigned_to, :tracker, :priority, :category, :fixed_version]) diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index ba312c74a..aaaa4484d 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -109,7 +109,7 @@ class MembersController < ApplicationController end if params[:flag] unless members.present? && members.all? {|m| m.valid? } - flash[:error] = members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ') + flash[:error] = members.empty? ? l(:label_user_role_null) :members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ') else flash[:notice] = l(:label_invite_success) end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 44e5fd8a3..e9a27cf44 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -340,6 +340,7 @@ class ProjectsController < ApplicationController @is_zhuce =false flash[:notice] = l(:notice_email_sent, :value => email) else + flash[:error] = l(:notice_registed_success, :value => email) @is_zhuce = true end respond_to do |format| diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 0c1f65317..6c115fc11 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -92,6 +92,22 @@ class RepositoriesController < ApplicationController render :action => 'show', :layout => 'base_projects' end + + HOOK_TEMPLATE = %Q{#!/bin/sh +exec sh -c ' +function update() +{ + CMD_PATH=`dirname $0`; + cd $CMD_PATH; + PY_PATH=$PWD/../../git_refresh_changes.py; + [[ -s "$PY_PATH" ]] && $(which python) $PY_PATH $PWD; + cd -; +} +git update-server-info +update +' + } + def create if params[:repository_scm].to_s == 'Gitlab' # add by nwb @@ -127,7 +143,6 @@ class RepositoriesController < ApplicationController if attrs[:attrs_extra].keys.any? @repository.merge_extra_info(attrs[:attrs_extra]) end - #by xianbo @repository.project = @project if request.post? && @repository.save @@ -145,12 +160,11 @@ class RepositoriesController < ApplicationController " \n ' >> "+ @root_path+"htdocs/"+ @repository_name+"/.htaccess" system "cd "+@project_path+" ;git update-server-info" - # if(create_repo_file&&create_passwd&&create_group&&init_repository&&add_privilege&&init_server_info) - # else - # logger.info "An error occured when authenticating "+"create passwd"+@creat_passwd+"create_group"+ - # crate_group+"create repository file "+create_repo_file+"init repository"+init_repostory+ - # "aad privilege to rpository"+add_privilege+"init server infos"+init_server_info - # end + + File.open(@project_path+"/hooks/post-update", "w+") do |f| + f.write(HOOK_TEMPLATE) + end + @repository.update_attributes(:login => User.current.login.to_s) end redirect_to settings_project_url(@project, :tab => 'repositories') @@ -160,6 +174,8 @@ class RepositoriesController < ApplicationController render :action => 'new', :layout =>'base_projects' end end + + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d770a4633..4db471ab4 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -445,15 +445,15 @@ class UsersController < ApplicationController else activity = Activity.where(where_condition).where('user_id = ?', @user.id).order('id desc') end - activity = activity.reject { |e| - e.act.nil? || - (!User.current.admin? && !e.act.nil? - (((e.act_type == "Issue") && !e.act.project.visible?(User.current)) || - (e.act_type == "Bid" && !e.act.courses.first.nil? && e.act.courses.first.is_public == 0 && !User.current.member_of_course?(e.act.courses.first)) || - (e.act_type == "Journal" && e.act.respond_to?("Project") && !e.act.project.visible?(User.current)) || - (e.act_type == "News" && ((!e.act.project.nil? && !e.act.project.visible?(User.current)) || (!e.act.course.nil? && e.act.course.is_public == 0 && !User.current.member_of_course?(e.act.course)))) || - (e.act_type == "Message" && !e.act.board.nil? && ((!e.act.board.project.nil? && !e.act.board.project.visible?(User.current)) || (!e.act.board.course.nil? && e.act.board.course.is_public == 0 && !User.current.member_of_course?(e.act.board.course)))))) - } + # activity = activity.reject { |e| + # e.act.nil? || + # (!User.current.admin? && !e.act.nil? + # (((e.act_type == "Issue") && !e.act.project.visible?(User.current)) || + # (e.act_type == "Bid" && !e.act.courses.first.nil? && e.act.courses.first.is_public == 0 && !User.current.member_of_course?(e.act.courses.first)) || + # (e.act_type == "Journal" && e.act.respond_to?("Project") && !e.act.project.visible?(User.current)) || + # (e.act_type == "News" && ((!e.act.project.nil? && !e.act.project.visible?(User.current)) || (!e.act.course.nil? && e.act.course.is_public == 0 && !User.current.member_of_course?(e.act.course)))) || + # (e.act_type == "Message" && !e.act.board.nil? && ((!e.act.board.project.nil? && !e.act.board.project.visible?(User.current)) || (!e.act.board.course.nil? && e.act.board.course.is_public == 0 && !User.current.member_of_course?(e.act.board.course)))))) + # } @activity_count = activity.count @activity_pages = Paginator.new @activity_count, pre_count, params['page'] @activity = activity.slice(@activity_pages.offset,@activity_pages.per_page) diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 949ddd643..f35210f01 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -20,7 +20,7 @@ class WelcomeController < ApplicationController include WelcomeHelper helper :project_score caches_action :robots - before_filter :find_first_page, :only => [:index] + #before_filter :find_first_page, :only => [:index] # before_filter :fake, :only => [:index, :course] before_filter :entry_select, :only => [:index] diff --git a/app/helpers/api_helper.rb b/app/helpers/api_helper.rb index c865a500b..afdc306a4 100644 --- a/app/helpers/api_helper.rb +++ b/app/helpers/api_helper.rb @@ -60,4 +60,8 @@ module ApiHelper end [count,is_teacher] end + + def get_user_language user + (user.language.nil? || user.language == "") ? 'zh':user.language + end end \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9629ed437..b4f54f075 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1994,4 +1994,10 @@ module ApplicationHelper end technical_title end + + + def ie8? + request.env["HTTP_USER_AGENT"] =~ /MSIE 8.0/ + end + end diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb index db547061f..bd017757a 100644 --- a/app/helpers/courses_helper.rb +++ b/app/helpers/courses_helper.rb @@ -355,7 +355,7 @@ module CoursesHelper # 课程time+term简写(2014.春/2014.秋)国际化输出 def get_course_term course strterm = course.try(:term).to_s - if !(User.current.language == 'zh') + if !(User.current.language == 'zh'||User.current.language == '') strterm == '春季学期' ? strterm = 'spring term' : strterm = 'autumn term' str = ( course.try(:time).to_s << '.' << strterm ) str[0..-6] @@ -369,7 +369,7 @@ module CoursesHelper # 课程term(春季学期/秋季学期)国际化输出 def get_course_term_locales course str = course.try(:term).to_s - if !(User.current.language == 'zh') + if !(User.current.language == 'zh'||User.current.language == '') str == '春季学期' ? str = ' ' + 'spring term' : str = ' ' + 'autumn term' end return str diff --git a/app/helpers/discuss_demos_helper.rb b/app/helpers/discuss_demos_helper.rb new file mode 100644 index 000000000..71bf8fb62 --- /dev/null +++ b/app/helpers/discuss_demos_helper.rb @@ -0,0 +1,2 @@ +module DiscussDemosHelper +end diff --git a/app/helpers/watchers_helper.rb b/app/helpers/watchers_helper.rb index b9e658bb5..02bc3d8b3 100644 --- a/app/helpers/watchers_helper.rb +++ b/app/helpers/watchers_helper.rb @@ -43,7 +43,7 @@ module WatchersHelper ) method = watched ? 'delete' : 'post' - link_to text, url, :remote => true, :method => method, :class => css + link_to text, url, :remote => true, :method => method, :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 22px; line-height: 21px;padding-top:1px; background: none repeat scroll 0% 0% #64BDD9; TES" end ############## added by linchun @@ -278,11 +278,11 @@ module WatchersHelper ) method = applied ? 'delete' : 'post' - link_to text, url, :remote => true, :method => method ,:class=>css + link_to text, url, :remote => true, :method => method ,:style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 21px; line-height: 22px;padding-top:1px; background: none repeat scroll 0% 0% #64BDD9; TES" end def exit_project_link(project) link_to(l(:label_exit_project),exit_cur_project_path(project.id), - :remote => true, :confirm => l(:lable_sure_exit_project), :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 22px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES" ) + :remote => true, :confirm => l(:lable_sure_exit_project), :style => "color: #fff; display:block; padding: 0px 5px; margin-right: 10px; height: 21px; line-height: 22px; background: none repeat scroll 0% 0% #64BDD9; TES;padding-top:1px;" ) end end diff --git a/app/models/bid.rb b/app/models/bid.rb index e5de47b24..10476b4d3 100644 --- a/app/models/bid.rb +++ b/app/models/bid.rb @@ -61,14 +61,21 @@ class Bid < ActiveRecord::Base end } + scope :course_visible, lambda {|*args| + includes(:courses).where(Course.allowed_to_condition(args.shift || User.current, :view_homeworks, *args)) + } + acts_as_watchable acts_as_taggable - acts_as_event :title => Proc.new {|o| "#{l(:label_requirement)} ##{o.id}: #{o.name}" }, + acts_as_event :title => Proc.new {|o| "#{l(:label_course_homework)} ##{o.id}: #{o.name}" }, :description => :description, :author => :author, :url => Proc.new {|o| {:controller => 'bids', :action => 'show', :id => o.id}} + acts_as_activity_provider :type => 'homeworks', + :author_key => :author_id + acts_as_activity_provider :find_options => {:include => [:projects, :author]}, :author_key => :author_id diff --git a/app/models/discuss_demo.rb b/app/models/discuss_demo.rb new file mode 100644 index 000000000..6ed8d15b6 --- /dev/null +++ b/app/models/discuss_demo.rb @@ -0,0 +1,4 @@ +class DiscussDemo < ActiveRecord::Base + attr_accessible :title, :body + has_many_kindeditor_assets :assets, :dependent => :destroy +end diff --git a/app/models/kindeditor/asset.rb b/app/models/kindeditor/asset.rb new file mode 100644 index 000000000..bae948c99 --- /dev/null +++ b/app/models/kindeditor/asset.rb @@ -0,0 +1,15 @@ +class Kindeditor::Asset < ActiveRecord::Base + self.table_name = 'kindeditor_assets' + mount_uploader :asset, Kindeditor::AssetUploader + validates_presence_of :asset + before_save :update_asset_attributes + attr_accessible :asset + + private + def update_asset_attributes + if asset.present? && asset_changed? + self.file_size = asset.file.size + self.file_type = asset.file.content_type + end + end +end \ No newline at end of file diff --git a/app/models/kindeditor/file.rb b/app/models/kindeditor/file.rb new file mode 100644 index 000000000..4b5f11441 --- /dev/null +++ b/app/models/kindeditor/file.rb @@ -0,0 +1,3 @@ +class Kindeditor::File < Kindeditor::Asset + mount_uploader :asset, Kindeditor::FileUploader +end \ No newline at end of file diff --git a/app/models/kindeditor/flash.rb b/app/models/kindeditor/flash.rb new file mode 100644 index 000000000..efaf5de9b --- /dev/null +++ b/app/models/kindeditor/flash.rb @@ -0,0 +1,3 @@ +class Kindeditor::Flash < Kindeditor::Asset + mount_uploader :asset, Kindeditor::FlashUploader +end \ No newline at end of file diff --git a/app/models/kindeditor/image.rb b/app/models/kindeditor/image.rb new file mode 100644 index 000000000..a400c816d --- /dev/null +++ b/app/models/kindeditor/image.rb @@ -0,0 +1,3 @@ +class Kindeditor::Image < Kindeditor::Asset + mount_uploader :asset, Kindeditor::ImageUploader +end \ No newline at end of file diff --git a/app/models/kindeditor/media.rb b/app/models/kindeditor/media.rb new file mode 100644 index 000000000..071763319 --- /dev/null +++ b/app/models/kindeditor/media.rb @@ -0,0 +1,3 @@ +class Kindeditor::Media < Kindeditor::Asset + mount_uploader :asset, Kindeditor::MediaUploader +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index 83e08254c..9abe80779 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -214,6 +214,8 @@ class User < Principal where(" LOWER(login) LIKE '#{pattern}' ") elsif type == "1" where(" LOWER(concat(lastname, firstname)) LIKE '#{pattern}' ") + elsif type == "3" + where(" LOWER(concat(lastname, firstname,login)) LIKE '#{pattern}' ") else where(" LOWER(mail) LIKE '#{pattern}' ") end @@ -776,7 +778,7 @@ class User < Principal (block_given? ? yield(role, self) : true) } #添加课程相关的权限判断 - elsif context && context.is_a?(Course) + elsif context && context.is_a?(Course) return false unless context.allows_to?(action) # Admin users are authorized for anything else return true if admin? diff --git a/app/models/user_extensions.rb b/app/models/user_extensions.rb index 92690d1db..09c88e6df 100644 --- a/app/models/user_extensions.rb +++ b/app/models/user_extensions.rb @@ -32,40 +32,42 @@ class UserExtensions < ActiveRecord::Base def get_brief_introduction return self.brief_introduction end - + + # added by meng def show_identity - if self.identity == 0 - if User.current.language == 'zh' - user_identity = '教师' - else - user_identity = 'Teacher' - end - elsif self.identity == 1 - if User.current.language == 'zh' - user_identity = '学生' - else - user_identity = 'Student' - end - elsif self.identity == 2 - if User.current.language == 'zh' - user_identity = '企业' - else - user_identity = 'Enterprise' - end - elsif self.identity == 3 - if User.current.language == 'zh' - user_identity = '开发者' - else - user_identity = 'Developer' + if User.current.language == 'zh'||User.current.language == '' + case self.identity + when 0 + user_identity = l(:label_account_identity_teacher) + when 1 + user_identity = l(:label_account_identity_student) + when 2 + user_identity = l(:label_account_identity_enterprise) + when 3 + user_identity = l(:label_account_identity_developer) + else + user_identity = '' end else - user_identity = '' + case self.identity + when 0 + user_identity = l(:label_account_identity_teacher) + when 1 + user_identity = l(:label_account_identity_student) + when 2 + user_identity = l(:label_account_identity_enterprise) + when 3 + user_identity = l(:label_account_identity_developer) + else + user_identity = '' + end end return user_identity end -# end - +# end + + def self.introduction(user, message) unless user.user_extensions.nil? info = user.user_extensions diff --git a/app/services/comment_service.rb b/app/services/comment_service.rb index e74cc902b..f75e14b85 100644 --- a/app/services/comment_service.rb +++ b/app/services/comment_service.rb @@ -1,4 +1,6 @@ class CommentService + include ApiHelper + include Redmine::I18n #评论 def news_comments params,current_user @news = News.find(params[:id]) @@ -84,7 +86,8 @@ class CommentService @memo.forum_id = "1" @memo.author_id = current_user.id @memo.save - @memo + message = "#{l(:label_commit_failed,:locale => get_user_language(current_user))}: #{@memo.errors.full_messages}" if @memo.new_record? + [@memo,message] end #课程留言列表 diff --git a/app/services/courses_service.rb b/app/services/courses_service.rb index 1ec8a0ef0..c689d699d 100644 --- a/app/services/courses_service.rb +++ b/app/services/courses_service.rb @@ -38,7 +38,7 @@ class CoursesService if name.blank? raise 'sumbit empty' end - @courses = courses_all.visible + @courses = courses_all.visible(current_user) if params[:name].present? @courses_all = @courses.like(params[:name]) else @@ -346,7 +346,7 @@ class CoursesService membership = @user.coursememberships.all(:conditions => Course.visible_condition(current_user)) end if membership.nil? || membership.count == 0 - raise l(:label_no_courses,:locale => current_user.language.nil? ? 'zh':current_user.language) + raise l(:label_no_courses,:locale => get_user_language(current_user)) end membership.sort! {|older, newer| newer.created_on <=> older.created_on } result = [] @@ -355,19 +355,19 @@ class CoursesService latest_course_dynamics = [] latest_news = course.news.order("created_on desc").first unless latest_news.nil? - latest_course_dynamics << {:type => 1,:time => latest_news.created_on,:message => l(:label_recently_updated_notification,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 1,:time => latest_news.created_on,:message => l(:label_recently_updated_notification,:locale => get_user_language(current_user))} end latest_message = course.journals_for_messages.order("created_on desc").first unless latest_message.nil? - latest_course_dynamics << {:type => 2,:time => latest_message.created_on,:message => l(:label_recently_updated_message,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 2,:time => latest_message.created_on,:message => l(:label_recently_updated_message,:locale => get_user_language(current_user))} end latest_attachment = course.attachments.order("created_on desc").first unless latest_attachment.nil? - latest_course_dynamics << {:type => 3,:time => latest_attachment.created_on,:message => l(:label_recently_updated_courseware,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 3,:time => latest_attachment.created_on,:message => l(:label_recently_updated_courseware,:locale => get_user_language(current_user))} end latest_bid = course.homeworks.order('updated_on DESC').first unless latest_bid.nil? - latest_course_dynamics << {:type => 4,:time => latest_bid.updated_on,:message => l(:label_recently_updated_homework,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 4,:time => latest_bid.updated_on,:message => l(:label_recently_updated_homework,:locale => get_user_language(current_user))} end #每个作业中的最新留言 messages = [] @@ -382,7 +382,7 @@ class CoursesService end latest_bid_message = messages.first unless latest_bid_message.nil? - latest_course_dynamics << {:type => 4,:time => latest_bid_message.created_on,:message => l(:label_recently_updated_message,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 4,:time => latest_bid_message.created_on,:message => l(:label_recently_updated_message,:locale => get_user_language(current_user))} end #每个作业中学生最后提交的作业 homeworks = [] @@ -397,12 +397,12 @@ class CoursesService end latest_homework_attach = homeworks.first unless latest_homework_attach.nil? - latest_course_dynamics << {:type => 4,:time => latest_homework_attach.updated_at,:message => l(:label_recently_updated_homework,:locale => current_user.language.nil? ? 'zh':current_user.language)} + latest_course_dynamics << {:type => 4,:time => latest_homework_attach.updated_at,:message => l(:label_recently_updated_homework,:locale => get_user_language(current_user))} end latest_course_dynamics.sort!{|order,newer| newer[:time] <=> order[:time]} latest_course_dynamic = latest_course_dynamics.first unless latest_course_dynamic.nil? - result << {:course_name => course.name,:course_id => course.id,:course_img_url => url_to_avatar(course),:type => latest_course_dynamic[:type],:update_time => latest_course_dynamic[:time],:message => latest_course_dynamic[:message],:count => nil} + result << {:course_name => course.name,:course_id => course.id,:course_img_url => url_to_avatar(course),:course_time => course.time,:course_term => course.term,:type => latest_course_dynamic[:type],:update_time => latest_course_dynamic[:time],:message => latest_course_dynamic[:message],:count => nil} end end result.sort!{|order,newer| newer[:update_time] <=> order[:update_time]} diff --git a/app/services/users_service.rb b/app/services/users_service.rb index f75a84c5b..39ca37d26 100644 --- a/app/services/users_service.rb +++ b/app/services/users_service.rb @@ -193,7 +193,6 @@ class UsersService @current_user.save #raise @current_user.errors.full_message #return @current_user - else raise 'wrong password' end diff --git a/app/views/attachments/_form.html.erb b/app/views/attachments/_form.html.erb index 0949899dd..0772529f9 100644 --- a/app/views/attachments/_form.html.erb +++ b/app/views/attachments/_form.html.erb @@ -1,5 +1,22 @@ <% if defined?(container) && container && container.saved_attachments %> + <% container.attachments.each_with_index do |attachment, i| %> + + <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%> + <%= text_field_tag("attachments[p#{i}][description]", attachment.description, :maxlength => 254, :placeholder => l(:label_optional_description), :class => 'description', :style=>"display: inline-block;") %> + <%= l(:field_is_public)%>: + <%= check_box_tag("attachments[p#{i}][is_public_checkbox]", attachment.is_public,attachment.is_public == 1 ? true : false,:class => 'is_public')%> + <%= if attachment.id.nil? + #待补充代码 + else + link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') + end + %> + <%#= render :partial => 'tags/tag', :locals => {:obj => attachment, :object_flag => "6"} %> + + <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %> + + <% end %> <% container.saved_attachments.each_with_index do |attachment, i| %> <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'filename readonly', :readonly=>'readonly')%> @@ -31,13 +48,13 @@ <%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %> - <%= button_tag "浏览", :type=>"button", :onclick=>"_file.click()",:onmouseover => 'this.focus()' %> + <%= button_tag l(:button_browse), :type=>"button", :onclick=>"_file.click()",:onmouseover => 'this.focus()', :style => ie8? ? 'display:none' : '' %> <%= file_field_tag 'attachments[dummy][file]', :id => '_file', :class => 'file_selector', :multiple => true, :onchange => 'addInputFiles(this);', - :style => 'display:none', + :style => ie8? ? '' : 'display:none', :data => { :max_file_size => Setting.attachment_max_size.to_i.kilobytes, :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)), diff --git a/app/views/attachments/_form_course.html.erb b/app/views/attachments/_form_course.html.erb index b2089d629..43f99056b 100644 --- a/app/views/attachments/_form_course.html.erb +++ b/app/views/attachments/_form_course.html.erb @@ -38,7 +38,7 @@ <%#= button_tag "浏览", :type=>"button", :onclick=>"CompatibleSend();" %> -<%= button_tag "浏览", :type=>"button", :onclick=>"_file.click()" %> +<%= button_tag l(:button_browse), :type=>"button", :onclick=>"_file.click()" %> <%= file_field_tag 'attachments[dummy][file]', :id => '_file', :class => 'file_selector', diff --git a/app/views/attachments/destroy.js.erb b/app/views/attachments/destroy.js.erb index 04cd4e02d..4893d22fe 100644 --- a/app/views/attachments/destroy.js.erb +++ b/app/views/attachments/destroy.js.erb @@ -1,7 +1,7 @@ $('#attachments_<%= j params[:attachment_id] %>').remove(); var count=$('#attachments_fields>span').length; if(count<=0){ - $("#upload_file_count").text("未上传文件"); + $("#upload_file_count").text(<%= l(:label_no_file_uploaded)%>); $(".remove_all").remove(); }else{ $("#upload_file_count").html("已上传"+""+count+""+"个文件"); diff --git a/app/views/boards/_project_show.html.erb b/app/views/boards/_project_show.html.erb index 1d9408e86..7ddd37ad6 100644 --- a/app/views/boards/_project_show.html.erb +++ b/app/views/boards/_project_show.html.erb @@ -24,10 +24,6 @@ -
-

<%= h @board.name %>

-
- <% if !User.current.logged? %>
<% if @project.project_type == 1 %> @@ -39,62 +35,52 @@
<% end %> -
- - 共有 - <%= link_to @topic_count,:controller => 'boards',:action => 'index' %> - 个贴子 - - <% if @project.enabled_modules.where("name = 'boards'").count > 0 && User.current.member_of?(@project) %> - - <%= link_to l(:label_message_new), - new_board_message_path(@board), - :class => 'icon icon-add', - :onclick => 'showAndScrollTo("add-message", "message_subject"); return false;' if User.current.logged? %> - - <% end %> -
-
- <% if @topics.any? %> - <% @topics.each do |topic| %> - - - - - -
- <%= link_to image_tag(url_to_avatar(topic.author), :class => "avatar"), user_path(topic.author) %> - - - - - - - - - -
- <%= link_to h(topic.subject.truncate(40,ommision:'...')), board_message_path(@board, topic),title:topic.subject.to_s %> - - - - - - - - -
<%= link_to (topic.replies_count), board_message_path(@board, topic) %>
回答
-
- <%= authoring topic.created_on, topic.author %>
-
- <% end %> - + + +
+
+

<%= h @board.name %>

+
+
+
项目讨论区共有<%= @topic_count %>个帖子
+ <% if @project.enabled_modules.where("name = 'boards'").count > 0 && User.current.member_of?(@project) %> + <%= link_to l(:label_message_new), new_board_message_path(@board), + :class => 'problem_new_btn fl', + :onclick => 'showAndScrollTo("add-message", "message_subject"); return false;' if User.current.logged? %> + <% end %> +
+
+ + <% if @topics.any? %> + <% @topics.each do |topic| %> +
+ + <%= link_to image_tag(url_to_avatar(topic.author), :class => "problem_pic talk_pic fl"), user_path(topic.author) %> + +
+
+ <%= link_to h(topic.subject), board_message_path(@board, topic), title:topic.subject.to_s, :class =>"problem_tit fl" %> + <% if topic.sticky? %> + 置顶 + <% end %> +
+
+ 由<%= link_to topic.author, user_path(topic.author), :class =>"problem_name" %> + 添加于<%= format_time topic.created_on %> +
+
+ 回复<%= link_to (topic.replies_count), board_message_path(@board, topic), :style =>"color:#fff;" %> +
+
+ <% end %> +
    + <%= pagination_links_full @topic_pages, @topic_count, :per_page_links => false, :remote => false, :flag => true %> +
<% else %>

<%= l(:label_no_data) %>

<% end %> + +
<% other_formats_links do |f| %> diff --git a/app/views/discuss_demos/index.html.erb b/app/views/discuss_demos/index.html.erb new file mode 100644 index 000000000..b24937357 --- /dev/null +++ b/app/views/discuss_demos/index.html.erb @@ -0,0 +1,25 @@ +

文章列表

+
+ + <% @discuss_demo_list.each do |e| %> + + + + + + + + + + <% end %> +
<%= truncate(e.title,:length => 50) %> + <%= truncate(e.body,:length => 50) %>   + + <%= link_to '查看文章',{:controller => 'discuss_demos',:action => 'show',:id=>e.id} %> + +    + <%= link_to '删除文章',discuss_demo_path(e.id), :method => :delete,:confirm => l(:text_are_you_sure) %> +
+ <% paginate @discuss_demo_list %> + <%= link_to '新建文章',new_discuss_demo_path %> +
\ No newline at end of file diff --git a/app/views/discuss_demos/new.html.erb b/app/views/discuss_demos/new.html.erb new file mode 100644 index 000000000..8cf1630e2 --- /dev/null +++ b/app/views/discuss_demos/new.html.erb @@ -0,0 +1,7 @@ +<%= javascript_include_tag src='/assets/kindeditor/kindeditor' %> +

新建文章

+<%= form_for @discuss_demo,:url => {:controller => 'discuss_demos',:action => "show",:id =>@discuss_demo.id, :method => :put} do |f| %> + <%= f.text_field :title %> + <%= f.kindeditor :body ,:owner_id => @discuss_demo.id%> + <%= f.submit :value=> '提交' %> +<% end %> \ No newline at end of file diff --git a/app/views/discuss_demos/show.html.erb b/app/views/discuss_demos/show.html.erb new file mode 100644 index 000000000..4b6bd3cee --- /dev/null +++ b/app/views/discuss_demos/show.html.erb @@ -0,0 +1,3 @@ +

<%= @discuss_demo.title %>

+<%= textAreailizable @discuss_demo.body %> +<%=link_to "返回首页",discuss_demos_path %> \ No newline at end of file diff --git a/app/views/documents/_form.html.erb b/app/views/documents/_form.html.erb index 72361b9ab..50f47e5f7 100644 --- a/app/views/documents/_form.html.erb +++ b/app/views/documents/_form.html.erb @@ -11,8 +11,8 @@ <%= wikitoolbar_for 'document_description' %> -<% if @document.new_record? %> +

<%= render :partial => 'attachments/form', :locals => {:container => @document} %>

-<% end %> + diff --git a/app/views/documents/edit.html.erb b/app/views/documents/edit.html.erb index 8a6122f8c..5c6ed2383 100644 --- a/app/views/documents/edit.html.erb +++ b/app/views/documents/edit.html.erb @@ -1,4 +1,6 @@ -

<%=l(:label_document)%>

+
+

<%=l(:label_document_plural)%>

+
<%= labelled_form_for @document do |f| %> <%= render :partial => 'form', :locals => {:f => f} %> diff --git a/app/views/files/_attachement_list.html.erb b/app/views/files/_attachement_list.html.erb index 001519a28..41025e619 100644 --- a/app/views/files/_attachement_list.html.erb +++ b/app/views/files/_attachement_list.html.erb @@ -22,13 +22,13 @@
- + <%= file_field_tag 'attachments[dummy][file]', :id => '_file', :class => 'file_selector', :multiple => true, :onchange => 'addInputFiles(this);', - :style => 'display:none', + :style => ie8? ? '': 'display:none', :data => { :max_file_size => Setting.attachment_max_size.to_i.kilobytes, :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)), diff --git a/app/views/files/_new.html.erb b/app/views/files/_new.html.erb index 6e8e806cf..76aab9a73 100644 --- a/app/views/files/_new.html.erb +++ b/app/views/files/_new.html.erb @@ -8,10 +8,10 @@ <% if versions.any? %> - + <% if attachmenttypes.any? %> @@ -31,14 +31,10 @@ <% end %>

<% end %> -

<%= l(:field_version) %>

<%= l(:field_version) %>

<%= select_tag "version_id", content_tag('option', '') + - options_from_collection_for_select(versions, "id", "name"), {style: 'width:100px'} %> + options_from_collection_for_select(versions, "id", "name"), {style: 'width:230px'} %> <%= l(:attachment_type) %>
- - +

<%=l(:label_attachment_plural)%><%= render :partial => 'attachments/form', locals: {project: project} %>

- -

<%=l(:label_attachment_plural)%><%= render :partial => 'attachments/form', locals: {project: project} %>

<%= submit_tag l(:button_add) %> <% end %> diff --git a/app/views/files/_project_file.html.erb b/app/views/files/_project_file.html.erb index aa597f3f2..b4d849cd6 100644 --- a/app/views/files/_project_file.html.erb +++ b/app/views/files/_project_file.html.erb @@ -1,7 +1,7 @@ <% attachmenttypes = @project.attachmenttypes %> <% sufixtypes = @project.contenttypes %>
-

资源共享区

+

<%= l(:lable_file_sharingarea) %>

@@ -16,12 +16,12 @@
diff --git a/app/views/files/_sort_by_attachtypel.html.erb b/app/views/files/_sort_by_attachtypel.html.erb index 5faa73b0f..27aaf2f3d 100644 --- a/app/views/files/_sort_by_attachtypel.html.erb +++ b/app/views/files/_sort_by_attachtypel.html.erb @@ -15,8 +15,8 @@ <%= sort_header_tag('filename', :caption => l(:field_filename), :scope => "col", :id => "vzebra-adventure" ,:class => "tableth") %> <%= sort_header_tag('size', :caption => l(:field_filesize), :default_order => 'desc', :scope => "col", :id => "vzebra-children",:class => "tableth") %> - <%= sort_header_tag('attach_type', :caption => l(:attachment_browse), :default_order => 'desc', :scope => "col", :id => "vzebra-attachmenttype",:class => "tableth") %> - <%= content_tag('th', l(:attachment_sufix_browse), id: 'vzebra-contenttype', class: 'tableth', style: 'color: black')%> + <%= sort_header_tag('attach_type', :caption => l(:field_filecontenttype), :default_order => 'desc', :scope => "col", :id => "vzebra-attachmenttype",:class => "tableth") %> + <%= content_tag('th', l(:field_filetype), id: 'vzebra-contenttype', class: 'tableth', style: 'color: black')%> <%= sort_header_tag('field_file_dense', :caption => l(:field_file_dense), :default_order => 'desc', :scope => "col", :id => "vzebra-field_file_dense",:class => "tableth") %> <%= sort_header_tag('downloads', :caption => l(:field_downloads), :default_order => 'desc', :scope => "col", :id => "vzebra-action",:class => "tableth") %> <%= sort_header_tag('operation', :caption => "", :scope => "col", :id => "vzebra-children",:class => "tableth") %> @@ -76,7 +76,7 @@
diff --git a/app/views/files/_upload_show.html.erb b/app/views/files/_upload_show.html.erb index 91d050d93..70465c21e 100644 --- a/app/views/files/_upload_show.html.erb +++ b/app/views/files/_upload_show.html.erb @@ -4,7 +4,8 @@
<%= error_messages_for 'attachment' %> - <%= form_tag(course_files_path(course), :multipart => true,:remote => true,:method => :post,:name=>"upload_form") do %> + + <%= form_tag(course_files_path(course), :multipart => true,:remote => !ie8?,:name=>"upload_form") do %> <%= render :partial => 'attachement_list',:locals => {:course => course} %>
diff --git a/app/views/issues/_action_menu.html.erb b/app/views/issues/_action_menu.html.erb index 61cea920c..bcd7b30c5 100644 --- a/app/views/issues/_action_menu.html.erb +++ b/app/views/issues/_action_menu.html.erb @@ -12,7 +12,7 @@ <% end %> -<%= watcher_link(@issue, User.current) %> + <%= link_to l(:button_copy), project_copy_issue_path(@project, @issue), :class => 'icon icon-copy' if User.current.allowed_to?(:add_issues, @project) %> <%= link_to l(:button_delete), issue_path(@issue.id), :data => {:confirm => issues_destroy_confirmation_message(@issue)}, :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_issues, @project) %>
diff --git a/app/views/issues/_newissue_index.html.erb b/app/views/issues/_newissue_index.html.erb deleted file mode 100644 index 4b282aa8f..000000000 --- a/app/views/issues/_newissue_index.html.erb +++ /dev/null @@ -1,139 +0,0 @@ -
-

问题跟踪

-
-
- <% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %> - - <% if User.current.member_of?(@project) %> - <%= link_to l(:label_issue_new), {:controller => 'issues', :action => 'new', :copy_from => nil}, :param => :project_id, :caption => :label_issue_new, - :html => {:accesskey => Redmine::AccessKeys.key_for(:new_issue)}, :class => 'icon icon-add' %> - <% end %> - <%= link_to l(:label_query), '#', :class => 'icon icon-help', - :onclick => '$("#custom_query").slideToggle(400); ' if true || User.current.logged? %> - - <% end %> - 问题总数:<%= @project.issues.count %> 未解决:<%= @project.issues.where('status_id in (1,2,4,6)').count %> -
-
- <% if !@query.new_record? && @query.editable_by?(User.current) %> - <%= link_to l(:button_edit), edit_query_path(@query), :class => 'icon icon-edit' %> - <%= delete_link query_path(@query) %> - <% end %> -
- -<% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %> -
- <%= form_tag({:controller => 'issues', :action => 'index', :project_id => @project}, :method => :get, :id => 'query_form', :class => 'query_form') do %> - <%= hidden_field_tag 'set_filter', '1' %> - -
- ---<%= l :label_query_new %>--- - -
-
"> - - <%= l(:label_issue_query_condition) %> - -
"> - <%= render :partial => 'queries/filters', :locals => {:query => @query} %> -
-
- -
- <%= link_to_function l(:label_issue_query), 'submit_query_form("query_form")', :class => 'icon icon-checked' %> - <%= link_to l(:label_issue_cancel_query), {:set_filter => 1, :project_id => @project}, :class => 'icon icon-reload' %> -
-
-
- <% end %> -
- -<%= error_messages_for 'query' %> - -<% if @query.valid? %> - <% if @issues.empty? %> -

- <%= l(:label_no_data) %> -

- <% else %> - <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> - - <% end %> -
- <% other_formats_links do |f| %> - <%= f.link_to 'Atom', :url => params.merge(:key => User.current.rss_key) %> - <%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '330px'); return false;" %> - <%= f.link_to 'PDF', :url => params %> - <% end %> -
- - - - -<% end %> - -<%= call_hook(:view_issues_index_bottom, {:issues => @issues, :project => @project, :query => @query}) %> - -<% content_for :sidebar do %> - <%= render :partial => 'issues/sidebar' %> -<% end %> - -<% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, - {:query_id => @query, :format => 'atom', - :page => nil, :key => User.current.rss_key}, - :title => l(:label_issue_plural)) %> - <%= auto_discovery_link_tag(:atom, - {:controller => 'journals', :action => 'index', - :query_id => @query, :format => 'atom', - :page => nil, :key => User.current.rss_key}, - :title => l(:label_changes_details)) %> -<% end %> - -<%= context_menu issues_context_menu_path %> diff --git a/app/views/issues/index.html.erb b/app/views/issues/index.html.erb index b3750a770..4b282aa8f 100644 --- a/app/views/issues/index.html.erb +++ b/app/views/issues/index.html.erb @@ -1 +1,139 @@ -<%= render :partial => 'issues/newissue_index' %> \ No newline at end of file +
+

问题跟踪

+
+
+ <% unless @project.enabled_modules.where("name = 'issue_tracking'").empty? %> + + <% if User.current.member_of?(@project) %> + <%= link_to l(:label_issue_new), {:controller => 'issues', :action => 'new', :copy_from => nil}, :param => :project_id, :caption => :label_issue_new, + :html => {:accesskey => Redmine::AccessKeys.key_for(:new_issue)}, :class => 'icon icon-add' %> + <% end %> + <%= link_to l(:label_query), '#', :class => 'icon icon-help', + :onclick => '$("#custom_query").slideToggle(400); ' if true || User.current.logged? %> + + <% end %> + 问题总数:<%= @project.issues.count %> 未解决:<%= @project.issues.where('status_id in (1,2,4,6)').count %> +
+
+ <% if !@query.new_record? && @query.editable_by?(User.current) %> + <%= link_to l(:button_edit), edit_query_path(@query), :class => 'icon icon-edit' %> + <%= delete_link query_path(@query) %> + <% end %> +
+ +<% html_title(@query.new_record? ? l(:label_issue_plural) : @query.name) %> +
+ <%= form_tag({:controller => 'issues', :action => 'index', :project_id => @project}, :method => :get, :id => 'query_form', :class => 'query_form') do %> + <%= hidden_field_tag 'set_filter', '1' %> + +
+ ---<%= l :label_query_new %>--- + +
+
"> + + <%= l(:label_issue_query_condition) %> + +
"> + <%= render :partial => 'queries/filters', :locals => {:query => @query} %> +
+
+ +
+ <%= link_to_function l(:label_issue_query), 'submit_query_form("query_form")', :class => 'icon icon-checked' %> + <%= link_to l(:label_issue_cancel_query), {:set_filter => 1, :project_id => @project}, :class => 'icon icon-reload' %> +
+
+
+ <% end %> +
+ +<%= error_messages_for 'query' %> + +<% if @query.valid? %> + <% if @issues.empty? %> +

+ <%= l(:label_no_data) %> +

+ <% else %> + <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> + + <% end %> +
+ <% other_formats_links do |f| %> + <%= f.link_to 'Atom', :url => params.merge(:key => User.current.rss_key) %> + <%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '330px'); return false;" %> + <%= f.link_to 'PDF', :url => params %> + <% end %> +
+ + + + +<% end %> + +<%= call_hook(:view_issues_index_bottom, {:issues => @issues, :project => @project, :query => @query}) %> + +<% content_for :sidebar do %> + <%= render :partial => 'issues/sidebar' %> +<% end %> + +<% content_for :header_tags do %> + <%= auto_discovery_link_tag(:atom, + {:query_id => @query, :format => 'atom', + :page => nil, :key => User.current.rss_key}, + :title => l(:label_issue_plural)) %> + <%= auto_discovery_link_tag(:atom, + {:controller => 'journals', :action => 'index', + :query_id => @query, :format => 'atom', + :page => nil, :key => User.current.rss_key}, + :title => l(:label_changes_details)) %> +<% end %> + +<%= context_menu issues_context_menu_path %> diff --git a/app/views/issues/index.js.erb b/app/views/issues/index.js.erb deleted file mode 100644 index 866882053..000000000 --- a/app/views/issues/index.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#content').html('<%= escape_javascript(render :partial => 'issues/newissue_index') %>'); diff --git a/app/views/issues/show.html.erb b/app/views/issues/show.html.erb index 69abf79a6..38afc672d 100644 --- a/app/views/issues/show.html.erb +++ b/app/views/issues/show.html.erb @@ -1,181 +1,181 @@ -
-

<%= l(:label_issue_plural) %>

-
-<%# html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %> -<% html_title "#{@issue.tracker.name} #{@issue.source_from}'#'#{@issue.project_index}: #{@issue.subject}" %> - -<%= render :partial => 'action_menu' %> - -

- <%= issue_heading(@issue) %> -

- - - -
- <% if @prev_issue_id || @next_issue_id %> - - <% end %> - - - -
-<%= render_issue_subject_with_tree(@issue) %> -
- - - - <%= render :partial => "/praise_tread/praise_tread",:locals => {:obj => @issue,:show_flag => true,:user_id =>User.current.id,:horizontal => false}%> - - -

- <%= authoring @issue.created_on, @issue.author %>. - <% if @issue.created_on != @issue.updated_on %> - <%= l(:label_updated_time, time_tag(@issue.updated_on)).html_safe %>. - <% end %> -

- -
- <%= render :partial => 'tags/tag', :locals => {:obj => @issue,:object_flag => "3" }%> -
- -<%= issue_fields_rows do |rows| - rows.left l(:field_status), h(@issue.status.name), :class => 'status' - rows.left l(:field_priority), h(@issue.priority.name), :class => 'priority' - - unless @issue.disabled_core_fields.include?('assigned_to_id') - #modified by nie - #modified by huang - rows.left l(:field_assigned_to), (image_tag url_to_avatar(@issue.assigned_to(@user)), :class => 'avatar').to_s.html_safe + (@issue.assigned_to ? link_to_user(@issue.assigned_to) : "-"), :class => 'assigned-to' - end - # end huang - unless @issue.disabled_core_fields.include?('category_id') - rows.left l(:field_category), h(@issue.category ? @issue.category.name : "-"), :class => 'category' - end - unless @issue.disabled_core_fields.include?('fixed_version_id') - rows.left l(:field_fixed_version), (@issue.fixed_version ? link_to_version(@issue.fixed_version) : "-"), :class => 'fixed-version' - end - - unless @issue.disabled_core_fields.include?('start_date') - rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date' - end - unless @issue.disabled_core_fields.include?('due_date') - rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date' - end - unless @issue.disabled_core_fields.include?('done_ratio') - rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress' - end - unless @issue.disabled_core_fields.include?('estimated_hours') - unless @issue.estimated_hours.nil? - rows.right l(:field_estimated_hours), l_hours(@issue.estimated_hours), :class => 'estimated-hours' - end - end - if User.current.allowed_to?(:view_time_entries, @project) - rows.right l(:label_spent_time), (@issue.total_spent_hours > 0 ? link_to(l_hours(@issue.total_spent_hours), project_issue_time_entries_path(@project, @issue)) : "-"), :class => 'spent-time' - end -end %> -<%= render_custom_fields_rows(@issue) %> -<%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %> -
-woca -<% if @issue.description? || @issue.attachments.any? -%> -
-<% if @issue.description? %> -
-
- <%= link_to l(:button_quote), quoted_issue_path(@issue.id), :remote => true, :method => 'post', :class => 'icon icon-comment' if authorize_for('issues', 'edit') %> -
- -

<%=l(:field_description)%>

-
- <%= textilizable @issue, :description, :attachments => @issue.attachments %> -
-
-<% end %> -<%= link_to_attachments @issue, :thumbnails => true %> -<% end -%> - -<%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %> - -<% if false # !@issue.leaf? || User.current.allowed_to?(:manage_subtasks, @project) %> -
- -
-
- <%= link_to_new_subtask(@issue) if User.current.allowed_to?(:manage_subtasks, @project) %> -
- -

<%=l(:label_subtask_plural)%>

-<%= render_descendants_tree(@issue) unless @issue.leaf? %> -
-<% end %> - -<% if @relations.present? || User.current.allowed_to?(:manage_issue_relations, @project) %> -
-
-<%= render :partial => 'relations' %> -
-<% end %> - -
- -<% if @changesets.present? %> -
-

<%=l(:label_associated_revisions)%>

-<%= render :partial => 'changesets', :locals => { :changesets => @changesets} %> -
-<% end %> - -<% if @journals.present? %> -
-

<%=l(:label_history)%>

-<%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> -
-<% end %> - - -
-<%= render :partial => 'action_menu' %> - -
-<% if @issue.editable? %> -
-

<%= l(:button_update) %>

- <%= render :partial => 'edit' %> -
-<% end %> - -<% other_formats_links do |f| %> - <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> - <%= f.link_to 'PDF' %> -<% end %> - - -<% content_for :sidebar do %> - <%= render :partial => 'issues/sidebar' %> - - <% if User.current.allowed_to?(:add_issue_watchers, @project) || - (@issue.watchers.present? && User.current.allowed_to?(:view_issue_watchers, @project)) %> -
- <%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %> -
- <% end %> -<% end %> - -<% content_for :header_tags do %> - <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@issue.project} - #{@issue.tracker} ##{@issue.id}: #{@issue.subject}") %> -<% end %> - -<%= context_menu issues_context_menu_path %> +
+

<%= l(:label_issue_plural) %>

+
+<%# html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %> +<% html_title "#{@issue.tracker.name} #{@issue.source_from}'#'#{@issue.project_index}: #{@issue.subject}" %> + +<%= render :partial => 'action_menu' %> + +

+ <%= issue_heading(@issue) %> +

+ + + +
+ <% if @prev_issue_id || @next_issue_id %> + + <% end %> + + + +
+<%= render_issue_subject_with_tree(@issue) %> +
+ + + + <%= render :partial => "/praise_tread/praise_tread",:locals => {:obj => @issue,:show_flag => true,:user_id =>User.current.id,:horizontal => false}%> + + +

+ <%= authoring @issue.created_on, @issue.author %>. + <% if @issue.created_on != @issue.updated_on %> + <%= l(:label_updated_time, time_tag(@issue.updated_on)).html_safe %>. + <% end %> +

+ +
+ <%= render :partial => 'tags/tag', :locals => {:obj => @issue,:object_flag => "3" }%> +
+ +<%= issue_fields_rows do |rows| + rows.left l(:field_status), h(@issue.status.name), :class => 'status' + rows.left l(:field_priority), h(@issue.priority.name), :class => 'priority' + + unless @issue.disabled_core_fields.include?('assigned_to_id') + #modified by nie + #modified by huang + rows.left l(:field_assigned_to), (image_tag url_to_avatar(@issue.assigned_to(@user)), :class => 'avatar').to_s.html_safe + (@issue.assigned_to ? link_to_user(@issue.assigned_to) : "-"), :class => 'assigned-to' + end + # end huang + unless @issue.disabled_core_fields.include?('category_id') + rows.left l(:field_category), h(@issue.category ? @issue.category.name : "-"), :class => 'category' + end + unless @issue.disabled_core_fields.include?('fixed_version_id') + rows.left l(:field_fixed_version), (@issue.fixed_version ? link_to_version(@issue.fixed_version) : "-"), :class => 'fixed-version' + end + + unless @issue.disabled_core_fields.include?('start_date') + rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date' + end + unless @issue.disabled_core_fields.include?('due_date') + rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date' + end + unless @issue.disabled_core_fields.include?('done_ratio') + rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress' + end + unless @issue.disabled_core_fields.include?('estimated_hours') + unless @issue.estimated_hours.nil? + rows.right l(:field_estimated_hours), l_hours(@issue.estimated_hours), :class => 'estimated-hours' + end + end + if User.current.allowed_to?(:view_time_entries, @project) + rows.right l(:label_spent_time), (@issue.total_spent_hours > 0 ? link_to(l_hours(@issue.total_spent_hours), project_issue_time_entries_path(@project, @issue)) : "-"), :class => 'spent-time' + end +end %> +<%= render_custom_fields_rows(@issue) %> +<%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %> +
+ +<% if @issue.description? || @issue.attachments.any? -%> +
+<% if @issue.description? %> +
+
+ <%= link_to l(:button_quote), quoted_issue_path(@issue.id), :remote => true, :method => 'post', :class => 'icon icon-comment' if authorize_for('issues', 'edit') %> +
+ +

<%=l(:field_description)%>

+
+ <%= textilizable @issue, :description, :attachments => @issue.attachments %> +
+
+<% end %> +<%= link_to_attachments @issue, :thumbnails => true %> +<% end -%> + +<%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %> + +<% if false # !@issue.leaf? || User.current.allowed_to?(:manage_subtasks, @project) %> +
+ +
+
+ <%= link_to_new_subtask(@issue) if User.current.allowed_to?(:manage_subtasks, @project) %> +
+ +

<%=l(:label_subtask_plural)%>

+<%= render_descendants_tree(@issue) unless @issue.leaf? %> +
+<% end %> + +<% if @relations.present? || User.current.allowed_to?(:manage_issue_relations, @project) %> +
+
+<%= render :partial => 'relations' %> +
+<% end %> + +
+ +<% if @changesets.present? %> +
+

<%=l(:label_associated_revisions)%>

+<%= render :partial => 'changesets', :locals => { :changesets => @changesets} %> +
+<% end %> + +<% if @journals.present? %> +
+

<%=l(:label_history)%>

+<%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> +
+<% end %> + + +
+<%= render :partial => 'action_menu' %> + +
+<% if @issue.editable? %> +
+

<%= l(:button_update) %>

+ <%= render :partial => 'edit' %> +
+<% end %> + +<% other_formats_links do |f| %> + <%= f.link_to 'Atom', :url => {:key => User.current.rss_key} %> + <%= f.link_to 'PDF' %> +<% end %> + + +<% content_for :sidebar do %> + <%= render :partial => 'issues/sidebar' %> + + <% if User.current.allowed_to?(:add_issue_watchers, @project) || + (@issue.watchers.present? && User.current.allowed_to?(:view_issue_watchers, @project)) %> +
+ <%= render :partial => 'watchers/watchers', :locals => {:watched => @issue} %> +
+ <% end %> +<% end %> + +<% content_for :header_tags do %> + <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@issue.project} - #{@issue.tracker} ##{@issue.id}: #{@issue.subject}") %> +<% end %> + +<%= context_menu issues_context_menu_path %> diff --git a/app/views/layouts/base_contest.html.erb b/app/views/layouts/base_contest.html.erb index a11defebf..42a7eccd1 100644 --- a/app/views/layouts/base_contest.html.erb +++ b/app/views/layouts/base_contest.html.erb @@ -194,7 +194,7 @@ <% if show_more_fans?(@bid) %> - <%= link_to l(:label_more), :controller => 'bids', :action => 'show_bid_user'%> + <%= link_to l(:button_more), :controller => 'bids', :action => 'show_bid_user'%> <% end %> @@ -217,7 +217,7 @@ <% if show_more_bid_project?(@bid) %> - <%= link_to l(:label_more), :controller => 'bids', :action => 'show_project'%> + <%= link_to l(:button_more), :controller => 'bids', :action => 'show_project'%> <% end %> @@ -244,7 +244,7 @@ <% if show_more_participate?(@bid) %> - <%= link_to l(:label_more), :controller => "bids", :action => "show_participator"%> + <%= link_to l(:button_more), :controller => "bids", :action => "show_participator"%> <% end %> diff --git a/app/views/layouts/base_newcontest.html.erb b/app/views/layouts/base_newcontest.html.erb index f3c598598..26015d536 100644 --- a/app/views/layouts/base_newcontest.html.erb +++ b/app/views/layouts/base_newcontest.html.erb @@ -215,7 +215,7 @@ <%= l(:label_x_followers, :count => @contest.watcher_users.count) %> <% if show_more_fans?(@contest) %> - <%= link_to l(:label_more), show_contest_user_contest_path(@contest) %> + <%= link_to l(:button_more), show_contest_user_contest_path(@contest) %> <% end %>
diff --git a/app/views/layouts/base_projects.html.erb b/app/views/layouts/base_projects.html.erb index 3098a5cda..9c999aa05 100644 --- a/app/views/layouts/base_projects.html.erb +++ b/app/views/layouts/base_projects.html.erb @@ -93,7 +93,7 @@ <%= image_tag(url_to_avatar(@project), :style => 'width:61px; height:61px;') %>
- ID:<%= @project.id %> + <%= l(:label_project_id)%><%= @project.id %>
@@ -126,7 +126,9 @@ <%= link_to "#{@project.watcher_users.count}", {:controller=>"projects", :action=>"watcherlist", :id => @project.id}, :style => "color:#3CA5C6;font-weight:bold" %>) | <%= l(:project_module_attachments) %>( - <%= link_to "#{@project.attachments.count}", project_files_path(@project), :style => "color:#3CA5C6;font-weight:bold" %>)
+ <% attaments_num = @project.attachments.count+Attachment.where(["`container_type` = 'Version' and `container_id` in (?)",@project.versions.map{ |v| v.id}]).all.count %> + <%= link_to "#{attaments_num}", project_files_path(@project), :style => "color:#3CA5C6;font-weight:bold" %>
) +
@@ -168,9 +170,9 @@ <% end%> <% unless @project.enabled_modules.where("name = 'files'").empty? %> <% end %> - + diff --git a/app/views/layouts/base_users.html.erb b/app/views/layouts/base_users.html.erb index d68e6abe5..213c9ed07 100644 --- a/app/views/layouts/base_users.html.erb +++ b/app/views/layouts/base_users.html.erb @@ -258,10 +258,10 @@ <% else %> - <%= l(:label_identity)%>: + <%= l(:label_identity)%>: - <%= l(:label_account_student) %> + <%= l(:label_account_identity_student) %> @@ -269,10 +269,10 @@ <% elsif @user.user_extensions.identity == 3 %> - <%= l(:label_identity)%>: + <%= l(:label_identity)%>: - <%= l(:label_account_developer) %> + <%= l(:label_account_identity_developer) %> <% end %> @@ -295,7 +295,7 @@ <% if show_more_watchers?(@user) %>
- <%= link_to l(:label_more), :controller => "users", :action => "user_watchlist"%> + <%= link_to l(:button_more), :controller => "users", :action => "user_watchlist"%>
<% end %> @@ -319,7 +319,7 @@ <% if show_more_fans?(@user) %>
- <%= link_to l(:label_more), :controller => "users", :action => "user_fanslist"%> + <%= link_to l(:button_more), :controller => "users", :action => "user_fanslist"%>
<% end %> diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb index c5be3f4fd..c24ab84e7 100644 --- a/app/views/layouts/mailer.html.erb +++ b/app/views/layouts/mailer.html.erb @@ -41,7 +41,8 @@ a:hover.mail_reply{ background:#06a9bc; text-decoration:none;}
-

<%= l(:mail_issue_greetings)%>

+ +
<%= yield %>
diff --git a/app/views/messages/_project_show.html.erb b/app/views/messages/_project_show.html.erb index b0a593180..01465188c 100644 --- a/app/views/messages/_project_show.html.erb +++ b/app/views/messages/_project_show.html.erb @@ -57,6 +57,9 @@
+
+

<%= h @board.name %>

+
<%= render :partial => "/praise_tread/praise_tread",:locals => {:obj => @topic,:show_flag => true,:user_id =>User.current.id,:horizontal => true}%> diff --git a/app/views/news/_form.html.erb b/app/views/news/_form.html.erb index 5e5cdf532..024360597 100644 --- a/app/views/news/_form.html.erb +++ b/app/views/news/_form.html.erb @@ -1,4 +1,4 @@ -<%= error_messages_for @news %> +.<%= error_messages_for @news %>
<%= @project ? l(:label_news_new) : l(:bale_news_notice) %>
diff --git a/app/views/news/_project_show.html.erb b/app/views/news/_project_show.html.erb index 874e89e1f..bde061f31 100644 --- a/app/views/news/_project_show.html.erb +++ b/app/views/news/_project_show.html.erb @@ -72,9 +72,9 @@ :html => { :id => 'news-form', :multipart => true, :method => :put } do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> <%#= submit_tag l(:button_save) %> - <%= link_to l(:button_save), "#", :onclick => 'submitNews();',:onmouseover => 'this.focus()',:class => 'whiteButton m3p10' %> + <%= link_to l(:button_save), "#", :onclick => 'submitNews();',:onmouseover => 'this.focus()',:class => 'ButtonColor m3p10' %> <%#= preview_link preview_news_path(:project_id => @project, :id => @news), 'news-form',target='preview',{:class => 'whiteButton m3p10'} %> - <%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;',:class => 'whiteButton m3p10' %> + <%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;',:class => 'ButtonColor m3p10'%> <% end %>
diff --git a/app/views/projects/_member_list.html.erb b/app/views/projects/_member_list.html.erb index 09173b835..ca42e1c86 100644 --- a/app/views/projects/_member_list.html.erb +++ b/app/views/projects/_member_list.html.erb @@ -3,7 +3,7 @@
<% next if member.new_record? %> <% unless member.created_on.nil? %> - <%= content_tag "p", "#{format_date(member.created_on)}#{l(:label_member_since)}", :class => "float_right member_since" %> + <%= content_tag "p", (User.current.language == ""|| User.current.language == "zh")?("#{format_date(member.created_on)}"+" "+"#{l(:label_member_since)}"):("#{l(:label_member_since)}"+" "+"#{format_date(member.created_on)}"), :class => "float_right member_since" %> <% end %> <%= member.user.nil? ? '' : (image_tag(url_to_avatar(member.user), :class => 'avatar')) %> <%= content_tag "div", link_to(member.user.name, user_path(member.user)), :class => "nomargin avatar_name" %> diff --git a/app/views/projects/_tools_expand.html.erb b/app/views/projects/_tools_expand.html.erb index b6e5f8c0d..f62b0822a 100644 --- a/app/views/projects/_tools_expand.html.erb +++ b/app/views/projects/_tools_expand.html.erb @@ -42,7 +42,7 @@
  • <% unless @project.enabled_modules.where("name = 'dts'").empty? %> - <%= link_to l(:label_module_share) ,share_show_path(@project) %> + <%= link_to l(:project_module_dts) ,share_show_path(@project) %> <% end %>
  • diff --git a/app/views/projects/invite_members_by_mail.html.erb b/app/views/projects/invite_members_by_mail.html.erb index 63f69e120..c222bece1 100644 --- a/app/views/projects/invite_members_by_mail.html.erb +++ b/app/views/projects/invite_members_by_mail.html.erb @@ -45,6 +45,7 @@
    +

    <%= l(:label_invite_new_user)%>

    <%= l(:label_invite_email_tips)%> @@ -62,5 +63,6 @@ <%#= submit_tag '免费发送', :style => "display:block; width:80px; text-align:center; color:#fff; height:26px; padding-top:3px; margin-bottom:10px;" %> <% end %> +

    \ No newline at end of file diff --git a/app/views/projects/watcherlist.html.erb b/app/views/projects/watcherlist.html.erb index 1acefe092..0a7a222d4 100644 --- a/app/views/projects/watcherlist.html.erb +++ b/app/views/projects/watcherlist.html.erb @@ -17,7 +17,7 @@

    <% unless user.memberships.empty? %> - <%= l(:label_contribute_to, :project_count => "#{user.memberships.count}") %> + <%= l(:label_contribute_to, :count => user.memberships.count) %> <% for member in user.memberships %> <%= link_to_project(member.project) %><%= (user.memberships.last == member) ? '' : ',' %> <% end %> @@ -25,7 +25,7 @@

    - <%= l(:label_user_joinin) %><%= format_date(user.created_on) %> + <%= l(:label_user_joinin) %> <%= format_date(user.created_on) %> diff --git a/app/views/tags/_project_tag.html.erb b/app/views/tags/_project_tag.html.erb index 8694d69ca..d10506d0d 100644 --- a/app/views/tags/_project_tag.html.erb +++ b/app/views/tags/_project_tag.html.erb @@ -1,32 +1,30 @@ -
    +
    <%= render :partial => "tags/tag_name",:locals => {:obj => obj,:non_list_all => false ,:object_flag => object_flag} %>
    +
    <% if User.current.logged? %> <%= toggle_link (l(:label_add_tag)), 'put-tag-form', {:focus => 'tags_name'} %> <% end %> + - +
    diff --git a/app/views/tags/_show_attachments.html.erb b/app/views/tags/_show_attachments.html.erb index a76211fc6..ca6a2dd7a 100644 --- a/app/views/tags/_show_attachments.html.erb +++ b/app/views/tags/_show_attachments.html.erb @@ -24,19 +24,19 @@    <%= file.description %>
    - <%= l('label_attachment_category')%> + <%= l('attachment.category')%> <%=result_come_from file%>
    - <%= l('label_attachment_download_num')%> + <%= l('attachment.download_num')%> <%= file.downloads%>| - <%= l('label_attachment_size')%> + <%= l('attachment.size')%> <%= number_to_human_size(file.filesize) %>| - <%= l('label_attachment_sharer')%> + <%= l('attachment.sharer')%> <%= link_to file.author, user_path(file.author), target: "_blank" unless file.author.blank? %> | - <%= l('label_attachment_upload_time')%> + <%= l('attachment.upload_time')%> <%= format_time(file.created_on) %>
    diff --git a/app/views/tags/_tag_name.html.erb b/app/views/tags/_tag_name.html.erb index 225a09aec..b97012723 100644 --- a/app/views/tags/_tag_name.html.erb +++ b/app/views/tags/_tag_name.html.erb @@ -31,7 +31,12 @@ <% if @tags.size > 0 %> <% @tags.each do |tag| %> -
    + + <% if object_flag == '2' %> + + <%= link_to tag, :controller => "tags", :action => "index", :q => tag, :object_flag => object_flag, :obj_id => obj.id %> + <% else %> +
    <%= link_to tag, :controller => "tags", :action => "index", :q => tag, :object_flag => object_flag, :obj_id => obj.id %> @@ -43,13 +48,6 @@ :taggable_id => obj.id, :taggable_type => object_flag %> <% end %> - <% when '2' %> - <% if (ProjectInfo.find_by_project_id(obj.id)).try(:user_id) == User.current.id %> - - <%= link_to 'x', :controller => "tags", :action => "remove_tag", :remote => true, :tag_name => tag, - :taggable_id => obj.id, :taggable_type => object_flag %> - - <% end %> <% when '3' %> <% if (ProjectInfo.find_by_project_id(obj.project_id)).try(:user_id) == User.current.id %> @@ -101,6 +99,7 @@ <% end %>
    - <% end %> + <% end %> + <% end %> <% end %> <% end %> \ No newline at end of file diff --git a/app/views/users/_my_joinedcourse.html.erb b/app/views/users/_my_joinedcourse.html.erb index e616004e6..373ed9234 100644 --- a/app/views/users/_my_joinedcourse.html.erb +++ b/app/views/users/_my_joinedcourse.html.erb @@ -16,8 +16,8 @@ diff --git a/app/views/welcome/_hot_projects_list.html.erb b/app/views/welcome/_hot_projects_list.html.erb index d14a6901b..ff41fa532 100644 --- a/app/views/welcome/_hot_projects_list.html.erb +++ b/app/views/welcome/_hot_projects_list.html.erb @@ -10,7 +10,7 @@ <% end %> <%= link_to( project.name, project_path(project.id), :class => "d-g-blue d-p-project-name",:title => "#{project.name}" )%> - (<%= link_to l(:label_project_member_amount, :count=>projectCount(project)), project_member_path(project) ,:course =>'0' %>) + (<%= link_to l(:label_project_member_amount, :count => projectCount(project)), project_member_path(project) ,:course =>'0' %>)
    <%=project.description.truncate(90, omission: '...')%> diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb index 51139ac89..ba0002eff 100644 --- a/app/views/welcome/index.html.erb +++ b/app/views/welcome/index.html.erb @@ -115,7 +115,7 @@

    <%= l(:lable_bar_active)%> <%= link_to l(:label_my_question) , newbie_send_path, {:class => 'orangeButton idea_btn', :style => "color: #EEEEEE" }%> <%= link_to l(:label_my_feedback) , suggestion_send_path, {:class => 'orangeButton idea_btn', :style => "color: #EEEEEE" }%>

    - <%= link_to l(:label_more), forums_path %> + <%= link_to l(:button_more), forums_path %>
    <% topics = find_new_forum_topics(12) %> diff --git a/config/initializers/rails_kindeditor.rb b/config/initializers/rails_kindeditor.rb new file mode 100644 index 000000000..e928a6c7d --- /dev/null +++ b/config/initializers/rails_kindeditor.rb @@ -0,0 +1,19 @@ +RailsKindeditor.setup do |config| + + # Specify the subfolders in public directory. + # You can customize it , eg: config.upload_dir = 'this/is/my/folder' + config.upload_dir = 'files/uploads' + + # Allowed file types for upload. + config.upload_image_ext = %w[gif jpg jpeg png bmp] + config.upload_flash_ext = %w[swf flv] + config.upload_media_ext = %w[swf flv mp3 wav wma wmv mid avi mpg asf rm rmvb] + config.upload_file_ext = %w[doc docx xls xlsx ppt htm html txt zip rar gz bz2] + + # Porcess upload image size + # eg: 1600x1600 => 800x800 + # 1600x800 => 800x400 + # 400x400 => 400x400 # No Change + # config.image_resize_to_limit = [800, 800] + +end diff --git a/config/locales/commons/en.yml b/config/locales/commons/en.yml index 5998ee875..296e8bc30 100644 --- a/config/locales/commons/en.yml +++ b/config/locales/commons/en.yml @@ -138,10 +138,7 @@ en: circular_dependency: "This relation would create a circular dependency" cant_link_an_issue_with_a_descendant: "An issue cannot be linked to one of its subtasks" - attachment_all: "All" - attachment_browse: "Attachment Content Browse" - attachment_sufix_browse: "Attachment Type Browse" - attachment_type: "Attachment Type" + general_text_No: 'No' general_text_Yes: 'Yes' general_text_no: 'no' @@ -166,7 +163,6 @@ en: label_requirement: Calls label_forum: Forum label_contest: Contest - @@ -189,7 +185,7 @@ en: text_are_you_sure: Are you sure? #js 提示 - + label_no_data: No data to display # 项目、课程、用户公用 label_settings: Settings label_information_plural: Information @@ -206,11 +202,12 @@ en: button_cancel: Cancel label_submit: Submit button_project_tags_add: Add - label_more: "More>>" button_download: Download + button_more: "More»" button_delete: Delete - - + button_unfollow: Unfollow + button_follow: Follow + button_browse: Browse # diff --git a/config/locales/commons/zh.yml b/config/locales/commons/zh.yml index a0eb6e74a..efb08ec6e 100644 --- a/config/locales/commons/zh.yml +++ b/config/locales/commons/zh.yml @@ -147,10 +147,7 @@ zh: cant_link_an_issue_with_a_descendant: "问题不能关联到它的子任务" groupname_repeat: "该班名已存在" - attachment_all: "全部" - attachment_sufix_browse: "文件类型" - attachment_browse: "内容类型" - attachment_type: '分类' + general_text_No: '否' general_text_Yes: '是' general_text_no: '否' @@ -190,7 +187,10 @@ zh: text_are_you_sure: 您确定要删除吗? #js 提示 - + + + + label_no_data: 没有任何数据可供显示 # 项目、课程、用户公用 label_settings: 配置 label_information_plural: 信息 @@ -207,10 +207,14 @@ zh: button_cancel: 取消 label_submit: 提交 button_project_tags_add: 增加 - label_more: "更多>>" button_download: 下载 - button_more: 更多 + button_more: "更多»" button_delete: 删除 + button_unfollow: 取消关注 + button_follow: 关注 + button_watch: 跟踪 + button_unwatch: 取消跟踪 + button_browse: 浏览 # diff --git a/config/locales/contests/en.yml b/config/locales/contests/en.yml index e124e3f1a..1c2784050 100644 --- a/config/locales/contests/en.yml +++ b/config/locales/contests/en.yml @@ -2,3 +2,13 @@ en: # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl) direction: ltr + # + # 竞赛托管平台 + # + # 主页 + # + label_current_hot_contest: Latest Hot Competition + label_current_attendingcontest_work: Latest Competition Work + label_issue_feedback_activities: Question&Feedback + label_more_information: More... + label_release_time: Release-time \ No newline at end of file diff --git a/config/locales/contests/zh.yml b/config/locales/contests/zh.yml index 08115110b..1c4c4d126 100644 --- a/config/locales/contests/zh.yml +++ b/config/locales/contests/zh.yml @@ -3,4 +3,15 @@ # by tsechingho (http://github.com/tsechingho) zh: # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl) - direction: ltr \ No newline at end of file + direction: ltr + + # + # 竞赛托管平台 + # + # 主页 + # + label_current_hot_contest: 最新热门竞赛 + label_current_attendingcontest_work: 最新参赛作品 + label_issue_feedback_activities: 问题和反馈动态 + label_more_information: 更多>> + label_release_time: 发布时间 diff --git a/config/locales/en.yml b/config/locales/en.yml index cf37867b5..910eb0f98 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -71,10 +71,9 @@ en: field_summary: Summary field_job_category: Job category # added by bai - field_filename: File - field_file_dense: File Dense - field_filesize: Size - field_downloads: Downloads + + + field_author: Author field_created_on: Created field_closed_on: Closed @@ -108,7 +107,6 @@ en: field_last_login_on: Last connection field_effective_date: Date - field_version: Version field_type: Type field_host: Host field_port: Port @@ -329,10 +327,7 @@ en: permission_notificationcomment_contestnotifications: Add the notice of contest comments permission_upload_attachments: Uploading resource - project_module_issue_tracking: Issue tracking - project_module_time_tracking: Time tracking - project_module_files: Files - project_module_boards: Forums + # edit by meng lable_hot_course: Hot Courses label_course_join_student: Join a course @@ -343,8 +338,7 @@ en: label_create_new_projects: Create a project label_work_scores_people: The total number of users given scores label_project_grade: Score - label_user_for_project_grade: Score - label_relation_files: Select an existing resource + # Personal signature tips @@ -481,13 +475,11 @@ en: label_text: Long text label_attribute: Attribute label_attribute_plural: Attributes - label_no_data: No data to display label_change_status: Change status label_history: History label_attachment: Files - label_attachment_new: New file label_attachment_delete: Delete file - label_attachment_plural: Files + label_file_added: File added label_report: Report label_report_plural: Reports @@ -617,12 +609,10 @@ en: label_latest_revision_plural: Latest revisions label_view_revisions: View revisions label_view_all_revisions: View all revisions - label_max_size: Maximum size label_sort_highest: Move to top label_sort_higher: Move up label_sort_lower: Move down label_sort_lowest: Move to bottom - label_roadmap: Roadmap label_roadmap_due_in: "Due in %{value}" label_roadmap_overdue: "%{value} late" label_roadmap_no_issues: No issues for this version @@ -727,7 +717,6 @@ en: label_plugins: Plugins label_ldap_authentication: LDAP authentication label_downloads_abbr: D/L - label_optional_description: Optional description label_add_another_file: Add another file label_preferences: Preferences label_chronological_order: In chronological order @@ -797,7 +786,7 @@ en: label_cross_project_hierarchy: With project hierarchy label_cross_project_system: With all projects label_gantt_progress_line: Progress line - label_files_filter: Files Filter: + button_check_all: Check all button_uncheck_all: Uncheck all @@ -896,7 +885,7 @@ en: text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?' text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)." text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?' - text_select_project_modules: 'Select modules to enable for this project:' + text_default_administrator_account_changed: Default administrator account changed text_file_repository_writable: Attachments directory writable text_plugin_assets_writable: Plugin assets directory writable @@ -936,9 +925,7 @@ en: text_turning_multiple_off: "If you disable multiple values, multiple values will be removed in order to preserve only one value per item." text_applied_project: "User %{id} Apply Join Project %{project}" - default_role_manager: Manager - default_role_developer: Developer - default_role_reporter: Reporter + default_tracker_bug: Bug default_tracker_feature: Feature default_tracker_support: Support @@ -1022,8 +1009,7 @@ en: #end by huang #added by liuping - button_unfollow: Unfollow - button_follow: Follow + label_delete_confirm: Confirm delete? label_exit_project: Exit Project @@ -1037,7 +1023,7 @@ en: label_leave_message: Message content label_message: message board field_add: Add before %{time} - button_more: More + label_bidding_project: projects button_bidding: I will participate in it @@ -1070,11 +1056,6 @@ en: zero: Follower one: Follower other: Followers - #end - label_member_since: joined - label_contribute_to: Participates %{project_count} projects: - #modify by men - #end label_total_commit: Totally %{total_commit} commits # modified by bai #modify by men @@ -1087,7 +1068,7 @@ en: label_type_as: Type as label_status_as: Status as label_priority_as: Priority as - label_member_list: Member list + label_author_name: Posted by %{author_name} label_comments_count: (%{count} comments) label_post_on: posts on @@ -1443,13 +1424,7 @@ en: label_your_course: your course label_have_message: have a new message lable_not_receive_mail: Click here don't receive email form site! -#added by linchun as competition# - label_current_hot_contest: Latest Hot Competition - label_current_attendingcontest_work: Latest Competition Work - label_issue_feedback_activities: Question&Feedback - label_more_information: More... - label_release_time: Release-time label_weixin: WeiXin @@ -1584,7 +1559,6 @@ en: label_trustie_team: The Trustie development team label_memos_max_length: The content of the post up to 65535 characters in length label_forums_max_length: Post Bar describing the maximum length of 65535 characters - label_unknow_type: Unknow type review_assignments: Review assignments label_my_school: My school @@ -1609,3 +1583,5 @@ en: label_recently_updated_message: Recently updated the message label_recently_updated_courseware: Recently updated the courseware label_no_courses: You do not participate in any course, please search the curriculum, course, or create a course! + label_commit_failed: commit failed + #api end diff --git a/config/locales/projects/en.yml b/config/locales/projects/en.yml index 56177bea3..5aca81426 100644 --- a/config/locales/projects/en.yml +++ b/config/locales/projects/en.yml @@ -19,7 +19,9 @@ en: # lable_hot_projects: Hot Projects label_private: private - label_project_member_amount: "%{count} members" + label_project_member_amount: + one: "%{count} member" + other: "%{count} members" label_project_score_tips: "Considering all activities of the project, project's score reflects the activity level of project" label_project_score: Score @@ -29,7 +31,7 @@ en: # # 左边栏 # - label_id: "ID:" + label_project_id: "Projcet ID:" label_apply_project: Apply to Join label_exit_project: Exit @@ -48,24 +50,116 @@ en: project_module_boards: Forums project_module_boards_post: New Post - # 与课程公用资源库 + project_module_files: Resources + label_upload_files: New File project_module_repository: Repository project_module_create_repository: New Repository - + label_project_more: More project_module_news: News project_module_wiki: Wiki project_module_code_review: Code Review project_module_calendar: Calendar project_module_gantt: Gantt project_module_documents: Documents - label_project_tool_response: Response - label_module_share: DTS Test Tool + label_roadmap: Roadmap + label_project_tool_response: Feedback + project_module_dts: DTS Test Tool label_project_overview: "Profile:" label_expend_information: More Information + # + # 项目托管平台 + # + # 项目成员 + # + label_member_list: Members + + label_member_since: "joined at" + label_user_for_project_grade: Score + + default_role_manager: Manager + default_role_developer: Developer + default_role_reporter: Reporter + + + # + # 项目托管平台 + # + # 关注者列表 + # + label_followers: Followers + label_contribute_to: + one: "Participates %{count} project—" + other: "Participates %{count} projects—" + + + # + # 项目托管平台 + # + # 资源库 + # + lable_file_sharingarea: Resources + + # 资源库(附件)公用 + label_relation_files: Select an existing resource + label_search_by_keyword: "Search by keywords" + label_files_filter: "Files Filter:" + + attachment_all: "All" + attachment_browse: "Attachment Content Browse" + attachment_sufix_browse: "Attachment Type Browse" + label_unknow_type: Unknow type + + field_filename: File + field_filesize: Size + field_filecontenttype: Content + field_filetype: File Typ + field_downloads: Downloads + field_file_dense: Dense + + # 资源库(附件)公用 > 上传文件 + label_attachment_new: New file + field_version: Version + attachment_type: "Attachment Type" + + label_attachment_plural: Files + label_no_file_uploaded: No file uploaded + label_max_size: Maximum size + + label_optional_description: Description + label_file_count: "%{count} files were uploaded successfully" + + # + # 项目托管平台 + # + # 问题跟踪 + # + + + # + # 项目托管平台 + # + # 项目讨论区 + # + + + # + # 项目托管平台 + # + # 资源库 + # + + + # + # 项目托管平台 + # + # 版本库 + # + + # # 项目托管平台 # @@ -77,6 +171,12 @@ en: label_repository_plural: Repositories enumeration_activities: Activities + text_select_project_modules: "Select modules to enable for this project:" + project_module_issue_tracking: Issue tracking + project_module_time_tracking: Time tracking + project_module_course: 课程 + project_module_boards: Forums + # # 项目托管平台 # @@ -100,7 +200,7 @@ en: # # 项目托管平台 # - # 新建项目 + # 新建项目/项目配置 >信息 # label_project_new_description: "A project can be used to do anything that requires distributed collaboration." field_name: Name @@ -155,6 +255,10 @@ en: - + # + # 项目托管平台 + # + # 项目得分 + # label_approve: Approve label_refusal: Refusal \ No newline at end of file diff --git a/config/locales/projects/zh.yml b/config/locales/projects/zh.yml index c70392171..bd547c37e 100644 --- a/config/locales/projects/zh.yml +++ b/config/locales/projects/zh.yml @@ -22,7 +22,9 @@ zh: # lable_hot_projects: 热门项目 label_private: 私有 - label_project_member_amount: "%{count}人" + label_project_member_amount: + one: "%{count}人" + other: "%{count}人" label_project_score_tips: 项目得分,综合考虑了项目的各项活动,反映了该项目的活跃程度 label_project_score: 项目评分 @@ -32,13 +34,14 @@ zh: # # 左边栏 # - label_id: "ID:" + label_project_id: "项目ID:" label_apply_project: 申请加入 label_exit_project: 退出项目 label_apply_project_waiting: 已处理申请,请等待管理员审核 label_unapply_project: 取消申请 - + lable_sure_exit_project: 是否确认退出该项目 + label_member: 成员 project_module_attachments: 资源 @@ -49,22 +52,119 @@ zh: project_module_boards: 讨论区 project_module_boards_post: 发帖 - # 与课程公用资源库 + project_module_files: 资源库 project_module_repository: 版本库 project_module_create_repository: 创建版本库 + label_project_more: 更多 project_module_news: 新闻 project_module_wiki: Wiki project_module_code_review: 代码审查 project_module_calendar: 日历 project_module_gantt: 甘特图 project_module_documents: 文档 + label_roadmap: 里程碑 #版本路线图 + project_module_dts: DTS测试工具 label_project_tool_response: 用户反馈 - label_module_share: DTS测试工具 label_project_overview: "项目简介:" label_expend_information: 展开更多信息 + + # + # 项目托管平台 + # + # 项目成员 + # + label_member_list: 成员列表 + + label_member_since: "加入" + label_user_for_project_grade: 个人得分 + + default_role_manager: 管理人员 + default_role_developer: 开发人员 + default_role_reporter: 报告人员 + + + # + # 项目托管平台 + # + # 关注者列表 + # + label_followers: 关注 + label_contribute_to: + one: "参与了 %{count}个项目:" + other: "参与了 %{count}个项目:" + + + # + # 项目托管平台 + # + # 资源库 + # + lable_file_sharingarea: 资源共享区 + + label_upload_files: 上传文件 + + + # 资源库(附件)公用 > 关联资源 + label_relation_files: 关联已有资源 + label_search_by_keyword: "按关键字搜索:" + label_files_filter: "资源过滤:" + + field_filename: 文件 + field_filesize: 大小 + field_filecontenttype: 内容分类 + field_filetype: 文件格式 + field_file_dense: 是否公开 + field_downloads: 下载次数 + + attachment_sufix_browse: "文件类型" + attachment_browse: "内容类型" + attachment_all: "全部" + label_unknow_type: 未知类型 + + # 资源库(附件)公用 > 上传文件 + label_attachment_new: 新建文件 + field_version: 版本 + attachment_type: "分类" + + label_attachment_plural: 文件 + label_no_file_uploaded: 未上传文件 + label_max_size: 最大文件大小 + + label_optional_description: 可选的描述 + + + # + # 项目托管平台 + # + # 问题跟踪 + # + + + + + + # + # 项目托管平台 + # + # 项目讨论区 + # + + + # + # 项目托管平台 + # + # 资源库 + # + + + # + # 项目托管平台 + # + # 版本库 + # # # 项目托管平台 @@ -79,8 +179,12 @@ zh: text_select_project_modules: '请选择此项目可以使用的模块:' - - + project_module_issue_tracking: 问题跟踪 + project_moule_boards_show: 项目论坛 + project_module_time_tracking: 时间跟踪 + project_module_course: 课程 + + # # 项目托管平台 # @@ -91,6 +195,7 @@ zh: label_invite_email_tips: 输入好友邮箱地址,Trustie会自动为该邮箱注册用户! notice_registed_success: 您输入的邮箱为空或者该邮箱已被注册! label_email_format_error: 您所填写的电子邮件格式不正确 + label_user_role_null: 用户和角色不能留空! label_send_email: 免费发送 label_input_email: 请输入邮箱地址 diff --git a/config/locales/users/en.yml b/config/locales/users/en.yml index fbfe1444e..ed10c69ee 100644 --- a/config/locales/users/en.yml +++ b/config/locales/users/en.yml @@ -77,8 +77,6 @@ en: label_technical_title: Title label_bidding_user_studentcode: Student ID - label_account_developer: Developer - label_account_student: Student # @@ -112,7 +110,7 @@ en: label_layouts_feedback: "a message " label_of_feedback: from - label_goto: Go to>> + label_goto: "Go to»" label_activity_project: "Project:" label_active_call: call @@ -180,12 +178,12 @@ en: # label_responses: Messages label_user_response: Feedback - label_leave_a_message: Leave him/her a message + label_leave_a_message: "Leave him/her a message" button_leave_meassge: Submit button_clear_meassge: Reset label_user_login_new: Login - label_user_login_tips: You haven't logged in, please login first to leave a message! + label_user_login_tips: "You haven't logged in, please login first to leave a message!" label_bid_respond_delete: Delete label_bid_respond_quote: Respond diff --git a/config/locales/users/zh.yml b/config/locales/users/zh.yml index 1362380a0..c6f7e4142 100644 --- a/config/locales/users/zh.yml +++ b/config/locales/users/zh.yml @@ -36,6 +36,7 @@ zh: label_user_edit: "修改资料" label_user_score: 个人综合得分 + # 用户身份在/my的修改资料下 label_user_score_of_collaboration: 协同得分 label_user_score_of_influence: 影响力得分 label_user_score_of_skill: 技术得分 @@ -87,10 +88,9 @@ zh: label_technicl_title_associate_professor: 副教授 label_technicl_title_lecturer: 讲师 label_technicl_title_teaching_assistant: 助教 - + + # 用户身份(学生、开发者)标签在/my的修改资料下 label_bidding_user_studentcode: 学号 - label_account_developer: 开发者 - label_account_student: 学生 label_no_current_fans: 该用户暂无粉丝 label_no_current_watchers: 该用户暂未关注其他用户 @@ -115,7 +115,7 @@ zh: label_of_feedback: 的 label_layouts_feedback: 留言 - label_goto: 前往>> + label_goto: "前往»" label_activity_project: "项目:" label_active_call: 需求 diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 45d6a9d20..f3879421a 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -99,10 +99,9 @@ zh: lastname_empty: 姓氏不能为空 enterprise_empty: 企业名不能为空 field_lastname_eg: '(例:张三丰,请填写[张])' - field_filename: 文件 - field_file_dense: 是否公开 - field_filesize: 大小 - field_downloads: 下载次数 + + + field_author: 作者 field_created_on: 创建于 field_updated_on: 更新于 @@ -130,13 +129,12 @@ zh: field_priority: 优先级 field_fixed_version: 目标版本 field_user: 用户 - field_principal: 用户/用户组 + field_principal: 用户 field_role: 角色 field_homepage: 主页 field_time: 课时 field_class_period: 学时 field_code: 学分 - field_is_public: 公开 field_open_student: 学生列表公开 field_parent: 上级项目 field_is_in_roadmap: 在路线图中显示 @@ -145,7 +143,6 @@ zh: field_last_login_on: 最后登录 field_language: 语言 field_effective_date: 日期 - field_version: 版本 field_type: 类型 field_host: 主机 field_port: 端口 @@ -350,17 +347,9 @@ zh: permission_contest_attachments_download: 竞赛附件下载 permission_upload_attachments: 资源上传 - project_module_issue_tracking: 问题跟踪 - project_moule_boards_show: 项目论坛 - project_module_time_tracking: 时间跟踪 - - - project_module_course: 课程 - - label_user: 用户 label_user_plural: 用户列表 @@ -474,8 +463,6 @@ zh: label_new_contest: 竞赛 label_requirement_focus: 关注需求 label_developer: 用户 - label_account_developer: 开发者 - label_account_student: 学生 label_enterprise_into: 进入企业 label_college_into: 进入高校 label_investor: 投资人: @@ -517,7 +504,7 @@ zh: label_summer: 夏季学期 label_autumn: 秋季学期 label_winter: 冬季学期 - label_followers: 关注 + label_teacher_list: 教师列表 label_student_list: 学生列表 @@ -566,15 +553,15 @@ zh: label_text: 文本 label_attribute: 属性 label_attribute_plural: 属性 - label_no_data: 没有任何数据可供显示 + label_change_status: 变更状态 label_history: 历史记录 label_attachment: 文件 - label_attachment_new: 新建文件 + label_file_upload: 上传资料 label_course_file_upload: 上传了课件 label_attachment_delete: 删除文件 - label_attachment_plural: 文件 + label_file_added: 文件已添加 label_report: 报表 label_report_plural: 报表 @@ -700,13 +687,11 @@ zh: label_latest_revision_plural: 最近的修订版本 label_view_revisions: 查看修订 label_view_all_revisions: 查看所有修订 - label_no_file_uploaded: 未上传文件 - label_max_size: 最大文件大小 + label_sort_highest: 置顶 label_sort_higher: 上移 label_sort_lower: 下移 label_sort_lowest: 置底 - label_roadmap: 里程碑 #版本路线图 label_roadmap_due_in: "截止日期到 %{value}" label_roadmap_overdue: "%{value} 延期" label_roadmap_no_issues: 该版本没有问题 @@ -855,7 +840,7 @@ zh: label_plugins: 插件 label_ldap_authentication: LDAP 认证 label_downloads_abbr: D/L - label_optional_description: 可选的描述 + label_add_another_file: 添加其它文件 label_preferences: 首选项 label_chronological_order: 按时间顺序 @@ -923,8 +908,6 @@ zh: button_sort: 排序 button_log_time: 登记工时 button_rollback: 恢复到这个版本 - button_watch: 跟踪 - button_unwatch: 取消跟踪 button_reply: 回复 button_archive: 存档 button_unarchive: 取消存档 @@ -1011,9 +994,6 @@ zh: text_applied_project: "用户 %{id} 申请加入项目 %{project}" text_issue_expire: "分配给您的任务%{issue}即将到期" - default_role_manager: 管理人员 - default_role_developer: 开发人员 - default_role_reporter: 报告人员 default_tracker_bug: 错误 default_tracker_feature: 功能 default_tracker_support: 支持 @@ -1107,7 +1087,7 @@ zh: description_all_columns: 所有列 button_export: 导出 label_export_options: "%{export_format} 导出选项" - error_attachment_too_big: 该文件无法上传。超过文件大小限制 (%{max_size}) + error_pic_type: "仅支持如下图片格式:" notice_failed_to_save_time_entries: "无法保存下列所选取的 %{total} 个项目中的 %{count} 工时: %{ids}。" label_x_issues: @@ -1236,11 +1216,6 @@ zh: zero: 个关注者 one: 个关注者 other: 个关注者 - #end - label_member_since: 加入 - label_contribute_to: 参与了 %{project_count} 个项目: - #modify by men - #end label_total_commit: 共%{total_commit}次提交 label_question_number: 第%{question_number}题: @@ -1257,7 +1232,7 @@ zh: label_type_as: 类型为 label_status_as: 状态为 label_priority_as: 优先级为 - label_member_list: 成员列表 + label_author_name: 由%{author_name}发表了 label_post_on: 发表了 @@ -1271,12 +1246,8 @@ zh: #added by liuping - button_unfollow: 取消关注 - button_follow: 关注 - label_followers: 关注 label_delete_confirm: 确认删除? - label_more_tags: 更多 label_tags_bid: 需求名称 label_tags_course_name: 课程名称 label_tags_bid_description: 需求描述 @@ -1613,8 +1584,6 @@ zh: label_code_submit_number: 代码提交次数 label_topic_number: 讨论区发言数量 - label_files_filter: 资源过滤: - label_join_contest: 加入竞赛 @@ -1741,7 +1710,6 @@ zh: label_project_grade: 项目得分 label_user_grade: 个人得分 - label_user_for_project_grade: 个人得分 label_system_grade: 系统评分 label_ta: 助教 @@ -1807,7 +1775,6 @@ zh: you_are_master: 您是该项目的版主 #add by linchun (竞赛相关) - label_upload_files: 上传文件 label_upload_softwarepackage: 上传软件包 label_upload_cuttingphoto: 上传截图 label_contests_reward_method: 奖励方式 @@ -1888,7 +1855,6 @@ zh: one: 个动态 other: 个动态 - label_relation_files: 关联已有资源 label_contest_settings: 配置竞赛 label_contest_delete: 删除竞赛 label_noawards_current: 暂未评奖 @@ -1945,12 +1911,6 @@ zh: lable_not_receive_mail: 点此设置接收本站邮件偏好! label_contest_notification: 竞赛通知 - #english site translation - label_current_hot_contest: 最新热门竞赛 - label_current_attendingcontest_work: 最新参赛作品 - label_issue_feedback_activities: 问题和反馈动态 - label_more_information: 更多>> - label_release_time: 发布时间 label_weixin: 微信扫码 @@ -1985,7 +1945,6 @@ zh: lable_hot_course: 活跃课程 lable_student_list_visable: 学生列表是否公开 - lable_sure_exit_project: 是否确认退出该项目 lable_input_class_vilidate: 学时只能为整数 lable_school_list: 学校列表 @@ -1993,7 +1952,6 @@ zh: lable_teacher_evaluation: 作业综评 lable_course_teacher: 主讲老师 lable_course_end: 课程学期已结束 - lable_file_sharingarea: 资源共享区 label_no_contest_news_description: 竞赛描述不能为空 label_contest_news_condition: 竞赛描述超过5000个汉字 label_no_contest_news_title: 竞赛标题不能为空 @@ -2061,13 +2019,6 @@ zh: label_enterprise_nil: 该模块为最新上线模块,目前还没有创建企业项目! label_enterprises: 组织 - label_tags_opensource: 开源项目 - label_attachment_category: 所属分类 - label_attachment_download_num: 下载 - label_attachment_size: 大小 - label_attachment_sharer: 共享者 - label_attachment_upload_time: 上传时间 - #api label_recently_updated_notification: 最近更新了通知 @@ -2075,9 +2026,12 @@ zh: label_recently_updated_message: 最近更新了留言 label_recently_updated_courseware: 最近更新了课件 label_no_courses: 您没有参与任何课程,请搜索课程、加入课程,或者创建课程吧! + label_commit_failed: 提交失败 + #api end + label_end_time: 截止时间 label_send_email: 确定发送 label_input_email: 请输入邮箱地址 - project_module_files: 资源库 + diff --git a/config/routes.rb b/config/routes.rb index 365c5a78e..3ec814839 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,6 +27,9 @@ RedmineApp::Application.routes.draw do + resources :discuss_demos + #match '/discuss_demos/new',:to => 'discuss_demo#create',:via =>[:post] + #match '/discuss_demo/show',:to => 'discuss_demo#show' mount Mobile::API => '/api' resources :homework_users @@ -860,6 +863,11 @@ RedmineApp::Application.routes.draw do match 'system_log/clear' ##ended by lizanle + resources :git_callback do + collection do + post 'post_update' + end + end Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir| file = File.join(plugin_dir, "config/routes.rb") diff --git a/db/migrate/20150316032155_create_discuss_demos.rb b/db/migrate/20150316032155_create_discuss_demos.rb new file mode 100644 index 000000000..af7a2a6ed --- /dev/null +++ b/db/migrate/20150316032155_create_discuss_demos.rb @@ -0,0 +1,9 @@ +class CreateDiscussDemos < ActiveRecord::Migration + def change + create_table :discuss_demos do |t| + t.string :title + t.text :body + t.timestamps + end + end +end diff --git a/db/migrate/20150316083717_create_kindeditor_assets.rb b/db/migrate/20150316083717_create_kindeditor_assets.rb new file mode 100644 index 000000000..19a108b2e --- /dev/null +++ b/db/migrate/20150316083717_create_kindeditor_assets.rb @@ -0,0 +1,17 @@ +class CreateKindeditorAssets < ActiveRecord::Migration + def self.up + create_table :kindeditor_assets do |t| + t.string :asset + t.integer :file_size + t.string :file_type + t.integer :owner_id + t.string :asset_type # list by kindeditor: image, file, media, flash + t.timestamps + end + end + + def self.down + drop_table :kindeditor_assets + end +end + diff --git a/db/schema.rb b/db/schema.rb index 4cce0b5c8..bad1cf2ae 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20150311013036) do +ActiveRecord::Schema.define(:version => 20150305081132) do create_table "activities", :force => true do |t| t.integer "act_id", :null => false diff --git a/doc/Git仓库优化-上线补充.docx b/doc/Git仓库优化-上线补充.docx new file mode 100644 index 000000000..89627f155 Binary files /dev/null and b/doc/Git仓库优化-上线补充.docx differ diff --git a/doc/tools/ImageMagick-6.6.0-0-Q16-windows-dll.exe b/doc/tools/ImageMagick-6.6.0-0-Q16-windows-dll.exe deleted file mode 100644 index 7fde8e34d..000000000 Binary files a/doc/tools/ImageMagick-6.6.0-0-Q16-windows-dll.exe and /dev/null differ diff --git a/files/2013/09/130913110338_YodaoDict.exe b/files/2013/09/130913110338_YodaoDict.exe deleted file mode 100644 index cb0fb4658..000000000 Binary files a/files/2013/09/130913110338_YodaoDict.exe and /dev/null differ diff --git a/files/2013/09/130913112844_YodaoDict.exe b/files/2013/09/130913112844_YodaoDict.exe deleted file mode 100644 index cb0fb4658..000000000 Binary files a/files/2013/09/130913112844_YodaoDict.exe and /dev/null differ diff --git a/files/2013/09/130913150242_YodaoDict.exe b/files/2013/09/130913150242_YodaoDict.exe deleted file mode 100644 index cb0fb4658..000000000 Binary files a/files/2013/09/130913150242_YodaoDict.exe and /dev/null differ diff --git a/files/2013/09/130913150350_89d0a4acf8770fc08309561559c49b62.exe b/files/2013/09/130913150350_89d0a4acf8770fc08309561559c49b62.exe deleted file mode 100644 index 6b17f167a..000000000 Binary files a/files/2013/09/130913150350_89d0a4acf8770fc08309561559c49b62.exe and /dev/null differ diff --git a/files/2013/09/130913211313_navicat.exe b/files/2013/09/130913211313_navicat.exe deleted file mode 100644 index cde21f595..000000000 Binary files a/files/2013/09/130913211313_navicat.exe and /dev/null differ diff --git a/files/2013/09/130913214441_89d0a4acf8770fc08309561559c49b62.exe b/files/2013/09/130913214441_89d0a4acf8770fc08309561559c49b62.exe deleted file mode 100644 index 6b17f167a..000000000 Binary files a/files/2013/09/130913214441_89d0a4acf8770fc08309561559c49b62.exe and /dev/null differ diff --git a/files/2013/09/130913214715_navicat.exe b/files/2013/09/130913214715_navicat.exe deleted file mode 100644 index cde21f595..000000000 Binary files a/files/2013/09/130913214715_navicat.exe and /dev/null differ diff --git a/files/2013/09/130913214952_YodaoDict.exe b/files/2013/09/130913214952_YodaoDict.exe deleted file mode 100644 index cb0fb4658..000000000 Binary files a/files/2013/09/130913214952_YodaoDict.exe and /dev/null differ diff --git a/lib/better_errors/.travis.yml b/lib/better_errors/.travis.yml deleted file mode 100644 index ce51187cf..000000000 --- a/lib/better_errors/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: ruby -rvm: - - 2.1.0 - - 2.0.0 diff --git a/lib/better_errors/.yardopts b/lib/better_errors/.yardopts deleted file mode 100644 index 73034ccf8..000000000 --- a/lib/better_errors/.yardopts +++ /dev/null @@ -1 +0,0 @@ ---markup markdown --no-private diff --git a/lib/better_errors/CHANGELOG.md b/lib/better_errors/CHANGELOG.md deleted file mode 100644 index 00fc2466b..000000000 --- a/lib/better_errors/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -# Changelog - -See https://github.com/charliesome/better_errors/releases diff --git a/lib/better_errors/Gemfile b/lib/better_errors/Gemfile deleted file mode 100644 index 287f7749b..000000000 --- a/lib/better_errors/Gemfile +++ /dev/null @@ -1,10 +0,0 @@ -source 'https://rubygems.org' - -gemspec - -gem "rake" -gem "rspec", "2.14.1" -gem "binding_of_caller", platforms: :ruby -gem "pry", "0.9.12" -gem "yard" -gem "kramdown" diff --git a/lib/better_errors/LICENSE.txt b/lib/better_errors/LICENSE.txt deleted file mode 100644 index 755ce77a8..000000000 --- a/lib/better_errors/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2014 Charlie Somerville - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/better_errors/README.md b/lib/better_errors/README.md deleted file mode 100644 index 91488695a..000000000 --- a/lib/better_errors/README.md +++ /dev/null @@ -1,103 +0,0 @@ -# Better Errors [![Gem Version](http://img.shields.io/gem/v/better_errors.svg)](https://rubygems.org/gems/better_errors) [![Build Status](https://travis-ci.org/charliesome/better_errors.svg)](https://travis-ci.org/charliesome/better_errors) [![Code Climate](http://img.shields.io/codeclimate/github/charliesome/better_errors.svg)](https://codeclimate.com/github/charliesome/better_errors) - -Better Errors replaces the standard Rails error page with a much better and more useful error page. It is also usable outside of Rails in any Rack app as Rack middleware. - -![image](http://i.imgur.com/6zBGAAb.png) - -## Features - -* Full stack trace -* Source code inspection for all stack frames (with highlighting) -* Local and instance variable inspection -* Live REPL on every stack frame - -## Installation - -Add this to your Gemfile: - -```ruby -group :development do - gem "better_errors" -end -``` - -If you would like to use Better Errors' **advanced features** (REPL, local/instance variable inspection, pretty stack frame names), you need to add the [`binding_of_caller`](https://github.com/banister/binding_of_caller) gem by [@banisterfiend](http://twitter.com/banisterfiend) to your Gemfile: - -```ruby -gem "binding_of_caller" -``` - -This is an optional dependency however, and Better Errors will work without it. - -_Note: If you discover that Better Errors isn't working - particularly after upgrading from version 0.5.0 or less - be sure to set `config.consider_all_requests_local = true` in `config/environments/development.rb`._ - -## Security - -**NOTE:** It is *critical* you put better\_errors in the **development** section. **Do NOT run better_errors in production, or on Internet facing hosts.** - -You will notice that the only machine that gets the Better Errors page is localhost, which means you get the default error page if you are developing on a remote host (or a virtually remote host, such as a Vagrant box). Obviously, the REPL is not something you want to expose to the public, but there may also be other pieces of sensitive information available in the backtrace. - -To poke selective holes in this security mechanism, you can add a line like this to your startup (for example, on Rails it would be `config/environments/development.rb`) - -```ruby -BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP'] -``` - -Then run Rails like this: - -```shell -TRUSTED_IP=66.68.96.220 rails s -``` - -Note that the `allow_ip!` is actually backed by a `Set`, so you can add more than one IP address or subnet. - -**Tip:** You can find your apparent IP by hitting the old error page's "Show env dump" and looking at "REMOTE_ADDR". - -**VirtualBox:** If you are using VirtualBox and are accessing the guest from your host's browser, you will need to use `allow_ip!` to see the error page. - -## Usage - -If you're using Rails, there's nothing else you need to do. - -If you're not using Rails, you need to insert `BetterErrors::Middleware` into your middleware stack, and optionally set `BetterErrors.application_root` if you'd like Better Errors to abbreviate filenames within your application. - -Here's an example using Sinatra: - -```ruby -require "sinatra" -require "better_errors" - -configure :development do - use BetterErrors::Middleware - BetterErrors.application_root = __dir__ -end - -get "/" do - raise "oops" -end -``` - -### Unicorn, Puma, and other multi-worker servers - -Better Errors works by leaving a lot of context in server process memory. If -you're using a web server that runs multiple "workers" it's likely that a second -request (as happens when you click on a stack frame) will hit a different -worker. That worker won't have the necessary context in memory, and you'll see -a `Session Expired` message. - -If this is the case for you, consider turning the number of workers to one (1) -in `development`. Another option would be to use Webrick, Mongrel, Thin, -or another single-process server as your `rails server`, when you are trying -to troubleshoot an issue in development. - -## Get in touch! - -If you're using better_errors, I'd love to hear from you. Drop me a line and tell me what you think! - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request diff --git a/lib/better_errors/Rakefile b/lib/better_errors/Rakefile deleted file mode 100644 index b6329726d..000000000 --- a/lib/better_errors/Rakefile +++ /dev/null @@ -1,13 +0,0 @@ -require "bundler/gem_tasks" -require "rspec/core/rake_task" - -namespace :test do - RSpec::Core::RakeTask.new(:with_binding_of_caller) - - without_task = RSpec::Core::RakeTask.new(:without_binding_of_caller) - without_task.ruby_opts = "-I spec -r without_binding_of_caller" - - task :all => [:with_binding_of_caller, :without_binding_of_caller] -end - -task :default => "test:all" diff --git a/lib/better_errors/better_errors.gemspec b/lib/better_errors/better_errors.gemspec deleted file mode 100644 index 315c110c5..000000000 --- a/lib/better_errors/better_errors.gemspec +++ /dev/null @@ -1,27 +0,0 @@ -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'better_errors/version' - -Gem::Specification.new do |s| - s.name = "better_errors" - s.version = BetterErrors::VERSION - s.authors = ["Charlie Somerville"] - s.email = ["charlie@charliesomerville.com"] - s.description = %q{Provides a better error page for Rails and other Rack apps. Includes source code inspection, a live REPL and local/instance variable inspection for all stack frames.} - s.summary = %q{Better error page for Rails and other Rack apps} - s.homepage = "https://github.com/charliesome/better_errors" - s.license = "MIT" - - s.files = `git ls-files`.split($/) - s.test_files = s.files.grep(%r{^(test|spec|features)/}) - s.require_paths = ["lib"] - - s.required_ruby_version = ">= 2.0.0" - - s.add_dependency "erubis", ">= 2.6.6" - s.add_dependency "coderay", ">= 1.0.0" - - # optional dependencies: - # s.add_dependency "binding_of_caller" - # s.add_dependency "pry" -end diff --git a/lib/better_errors/lib/better_errors.rb b/lib/better_errors/lib/better_errors.rb deleted file mode 100644 index 394060ecf..000000000 --- a/lib/better_errors/lib/better_errors.rb +++ /dev/null @@ -1,146 +0,0 @@ -require "pp" -require "erubis" -require "coderay" -require "uri" - -require "better_errors/code_formatter" -require "better_errors/error_page" -require "better_errors/middleware" -require "better_errors/raised_exception" -require "better_errors/repl" -require "better_errors/stack_frame" -require "better_errors/version" - -module BetterErrors - POSSIBLE_EDITOR_PRESETS = [ - { symbols: [:emacs, :emacsclient], sniff: /emacs/i, url: "emacs://open?url=file://%{file}&line=%{line}" }, - { symbols: [:macvim, :mvim], sniff: /vim/i, url: proc { |file, line| "mvim://open?url=file://#{file}&line=#{line}" } }, - { symbols: [:sublime, :subl, :st], sniff: /subl/i, url: "subl://open?url=file://%{file}&line=%{line}" }, - { symbols: [:textmate, :txmt, :tm], sniff: /mate/i, url: "txmt://open?url=file://%{file}&line=%{line}" }, - ] - - class << self - # The path to the root of the application. Better Errors uses this property - # to determine if a file in a backtrace should be considered an application - # frame. If you are using Better Errors with Rails, you do not need to set - # this attribute manually. - # - # @return [String] - attr_accessor :application_root - - # The logger to use when logging exception details and backtraces. If you - # are using Better Errors with Rails, you do not need to set this attribute - # manually. If this attribute is `nil`, nothing will be logged. - # - # @return [Logger, nil] - attr_accessor :logger - - # @private - attr_accessor :binding_of_caller_available - - # @private - alias_method :binding_of_caller_available?, :binding_of_caller_available - - # The ignored instance variables. - # @return [Array] - attr_accessor :ignored_instance_variables - end - @ignored_instance_variables = [] - - # Returns a proc, which when called with a filename and line number argument, - # returns a URL to open the filename and line in the selected editor. - # - # Generates TextMate URLs by default. - # - # BetterErrors.editor["/some/file", 123] - # # => txmt://open?url=file:///some/file&line=123 - # - # @return [Proc] - def self.editor - @editor - end - - # Configures how Better Errors generates open-in-editor URLs. - # - # @overload BetterErrors.editor=(sym) - # Uses one of the preset editor configurations. Valid symbols are: - # - # * `:textmate`, `:txmt`, `:tm` - # * `:sublime`, `:subl`, `:st` - # * `:macvim` - # - # @param [Symbol] sym - # - # @overload BetterErrors.editor=(str) - # Uses `str` as the format string for generating open-in-editor URLs. - # - # Use `%{file}` and `%{line}` as placeholders for the actual values. - # - # @example - # BetterErrors.editor = "my-editor://open?url=%{file}&line=%{line}" - # - # @param [String] str - # - # @overload BetterErrors.editor=(proc) - # Uses `proc` to generate open-in-editor URLs. The proc will be called - # with `file` and `line` parameters when a URL needs to be generated. - # - # Your proc should take care to escape `file` appropriately with - # `URI.encode_www_form_component` (please note that `URI.escape` is **not** - # a suitable substitute.) - # - # @example - # BetterErrors.editor = proc { |file, line| - # "my-editor://open?url=#{URI.encode_www_form_component file}&line=#{line}" - # } - # - # @param [Proc] proc - # - def self.editor=(editor) - POSSIBLE_EDITOR_PRESETS.each do |config| - if config[:symbols].include?(editor) - return self.editor = config[:url] - end - end - - if editor.is_a? String - self.editor = proc { |file, line| editor % { file: URI.encode_www_form_component(file), line: line } } - else - if editor.respond_to? :call - @editor = editor - else - raise TypeError, "Expected editor to be a valid editor key, a format string or a callable." - end - end - end - - # Enables experimental Pry support in the inline REPL - # - # If you encounter problems while using Pry, *please* file a bug report at - # https://github.com/charliesome/better_errors/issues - def self.use_pry! - REPL::PROVIDERS.unshift const: :Pry, impl: "better_errors/repl/pry" - end - - # Automatically sniffs a default editor preset based on the EDITOR - # environment variable. - # - # @return [Symbol] - def self.default_editor - POSSIBLE_EDITOR_PRESETS.detect(-> { {} }) { |config| - ENV["EDITOR"] =~ config[:sniff] - }[:url] || :textmate - end - - BetterErrors.editor = default_editor -end - -begin - require "binding_of_caller" - require "better_errors/exception_extension" - BetterErrors.binding_of_caller_available = true -rescue LoadError => e - BetterErrors.binding_of_caller_available = false -end - -require "better_errors/rails" if defined? Rails::Railtie diff --git a/lib/better_errors/lib/better_errors/code_formatter.rb b/lib/better_errors/lib/better_errors/code_formatter.rb deleted file mode 100644 index 77827241e..000000000 --- a/lib/better_errors/lib/better_errors/code_formatter.rb +++ /dev/null @@ -1,63 +0,0 @@ -module BetterErrors - # @private - class CodeFormatter - require "better_errors/code_formatter/html" - require "better_errors/code_formatter/text" - - FILE_TYPES = { - ".rb" => :ruby, - "" => :ruby, - ".html" => :html, - ".erb" => :erb, - ".haml" => :haml - } - - attr_reader :filename, :line, :context - - def initialize(filename, line, context = 5) - @filename = filename - @line = line - @context = context - end - - def output - formatted_code - rescue Errno::ENOENT, Errno::EINVAL - source_unavailable - end - - def formatted_code - formatted_lines.join - end - - def coderay_scanner - ext = File.extname(filename) - FILE_TYPES[ext] || :text - end - - def each_line_of(lines, &blk) - line_range.zip(lines).map { |current_line, str| - yield (current_line == line), current_line, str - } - end - - def highlighted_lines - CodeRay.scan(context_lines.join, coderay_scanner).div(wrap: nil).lines - end - - def context_lines - range = line_range - source_lines[(range.begin - 1)..(range.end - 1)] or raise Errno::EINVAL - end - - def source_lines - @source_lines ||= File.readlines(filename) - end - - def line_range - min = [line - context, 1].max - max = [line + context, source_lines.count].min - min..max - end - end -end diff --git a/lib/better_errors/lib/better_errors/code_formatter/html.rb b/lib/better_errors/lib/better_errors/code_formatter/html.rb deleted file mode 100644 index b3ab05430..000000000 --- a/lib/better_errors/lib/better_errors/code_formatter/html.rb +++ /dev/null @@ -1,26 +0,0 @@ -module BetterErrors - # @private - class CodeFormatter::HTML < CodeFormatter - def source_unavailable - "

    Source is not available

    " - end - - def formatted_lines - each_line_of(highlighted_lines) { |highlight, current_line, str| - class_name = highlight ? "highlight" : "" - sprintf '
    %s
    ', class_name, str - } - end - - def formatted_nums - each_line_of(highlighted_lines) { |highlight, current_line, str| - class_name = highlight ? "highlight" : "" - sprintf '%5d', class_name, current_line - } - end - - def formatted_code - %{
    #{formatted_nums.join}
    #{super}
    } - end - end -end diff --git a/lib/better_errors/lib/better_errors/code_formatter/text.rb b/lib/better_errors/lib/better_errors/code_formatter/text.rb deleted file mode 100644 index cd63806d8..000000000 --- a/lib/better_errors/lib/better_errors/code_formatter/text.rb +++ /dev/null @@ -1,14 +0,0 @@ -module BetterErrors - # @private - class CodeFormatter::Text < CodeFormatter - def source_unavailable - "# Source is not available" - end - - def formatted_lines - each_line_of(context_lines) { |highlight, current_line, str| - sprintf '%s %3d %s', (highlight ? '>' : ' '), current_line, str - } - end - end -end diff --git a/lib/better_errors/lib/better_errors/error_page.rb b/lib/better_errors/lib/better_errors/error_page.rb deleted file mode 100644 index 849020f19..000000000 --- a/lib/better_errors/lib/better_errors/error_page.rb +++ /dev/null @@ -1,110 +0,0 @@ -require "cgi" -require "json" -require "securerandom" - -module BetterErrors - # @private - class ErrorPage - def self.template_path(template_name) - File.expand_path("../templates/#{template_name}.erb", __FILE__) - end - - def self.template(template_name) - Erubis::EscapedEruby.new(File.read(template_path(template_name))) - end - - attr_reader :exception, :env, :repls - - def initialize(exception, env) - @exception = RaisedException.new(exception) - @env = env - @start_time = Time.now.to_f - @repls = [] - end - - def id - @id ||= SecureRandom.hex(8) - end - - def render(template_name = "main") - self.class.template(template_name).result binding - end - - def do_variables(opts) - index = opts["index"].to_i - @frame = backtrace_frames[index] - @var_start_time = Time.now.to_f - { html: render("variable_info") } - end - - def do_eval(opts) - index = opts["index"].to_i - code = opts["source"] - - unless binding = backtrace_frames[index].frame_binding - return { error: "REPL unavailable in this stack frame" } - end - - result, prompt, prefilled_input = - (@repls[index] ||= REPL.provider.new(binding)).send_input(code) - - { result: result, - prompt: prompt, - prefilled_input: prefilled_input, - highlighted_input: CodeRay.scan(code, :ruby).div(wrap: nil) } - end - - def backtrace_frames - exception.backtrace - end - - def application_frames - backtrace_frames.select(&:application?) - end - - def first_frame - application_frames.first || backtrace_frames.first - end - - private - def editor_url(frame) - BetterErrors.editor[frame.filename, frame.line] - end - - def rack_session - env['rack.session'] - end - - def rails_params - env['action_dispatch.request.parameters'] - end - - def uri_prefix - env["SCRIPT_NAME"] || "" - end - - def request_path - env["PATH_INFO"] - end - - def html_formatted_code_block(frame) - CodeFormatter::HTML.new(frame.filename, frame.line).output - end - - def text_formatted_code_block(frame) - CodeFormatter::Text.new(frame.filename, frame.line).output - end - - def text_heading(char, str) - str + "\n" + char*str.size - end - - def inspect_value(obj) - CGI.escapeHTML(obj.inspect) - rescue NoMethodError - "(object doesn't support inspect)" - rescue Exception => e - "(exception was raised in inspect)" - end - end -end diff --git a/lib/better_errors/lib/better_errors/exception_extension.rb b/lib/better_errors/lib/better_errors/exception_extension.rb deleted file mode 100644 index e97b052f3..000000000 --- a/lib/better_errors/lib/better_errors/exception_extension.rb +++ /dev/null @@ -1,17 +0,0 @@ -module BetterErrors - module ExceptionExtension - prepend_features Exception - - def set_backtrace(*) - if caller_locations.none? { |loc| loc.path == __FILE__ } - @__better_errors_bindings_stack = binding.callers.drop(1) - end - - super - end - - def __better_errors_bindings_stack - @__better_errors_bindings_stack || [] - end - end -end diff --git a/lib/better_errors/lib/better_errors/middleware.rb b/lib/better_errors/lib/better_errors/middleware.rb deleted file mode 100644 index ce9aaad4b..000000000 --- a/lib/better_errors/lib/better_errors/middleware.rb +++ /dev/null @@ -1,141 +0,0 @@ -require "json" -require "ipaddr" -require "set" - -module BetterErrors - # Better Errors' error handling middleware. Including this in your middleware - # stack will show a Better Errors error page for exceptions raised below this - # middleware. - # - # If you are using Ruby on Rails, you do not need to manually insert this - # middleware into your middleware stack. - # - # @example Sinatra - # require "better_errors" - # - # if development? - # use BetterErrors::Middleware - # end - # - # @example Rack - # require "better_errors" - # if ENV["RACK_ENV"] == "development" - # use BetterErrors::Middleware - # end - # - class Middleware - # The set of IP addresses that are allowed to access Better Errors. - # - # Set to `{ "127.0.0.1/8", "::1/128" }` by default. - ALLOWED_IPS = Set.new - - # Adds an address to the set of IP addresses allowed to access Better - # Errors. - def self.allow_ip!(addr) - ALLOWED_IPS << IPAddr.new(addr) - end - - allow_ip! "127.0.0.0/8" - allow_ip! "::1/128" rescue nil # windows ruby doesn't have ipv6 support - - # A new instance of BetterErrors::Middleware - # - # @param app The Rack app/middleware to wrap with Better Errors - # @param handler The error handler to use. - def initialize(app, handler = ErrorPage) - @app = app - @handler = handler - end - - # Calls the Better Errors middleware - # - # @param [Hash] env - # @return [Array] - def call(env) - if allow_ip? env - better_errors_call env - else - @app.call env - end - end - - private - - def allow_ip?(env) - # REMOTE_ADDR is not in the rack spec, so some application servers do - # not provide it. - return true unless env["REMOTE_ADDR"] and !env["REMOTE_ADDR"].strip.empty? - ip = IPAddr.new env["REMOTE_ADDR"].split("%").first - ALLOWED_IPS.any? { |subnet| subnet.include? ip } - end - - def better_errors_call(env) - case env["PATH_INFO"] - when %r{/__better_errors/(?.+?)/(?\w+)\z} - internal_call env, $~ - when %r{/__better_errors/?\z} - show_error_page env - else - protected_app_call env - end - end - - def protected_app_call(env) - @app.call env - rescue Exception => ex - @error_page = @handler.new ex, env - log_exception - show_error_page(env, ex) - end - - def show_error_page(env, exception=nil) - type, content = if @error_page - if text?(env) - [ 'plain', @error_page.render('text') ] - else - [ 'html', @error_page.render ] - end - else - [ 'html', no_errors_page ] - end - - status_code = 500 - if defined? ActionDispatch::ExceptionWrapper - status_code = ActionDispatch::ExceptionWrapper.new(env, exception).status_code - end - - [status_code, { "Content-Type" => "text/#{type}; charset=utf-8" }, [content]] - end - - def text?(env) - env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" || - !env["HTTP_ACCEPT"].to_s.include?('html') - end - - def log_exception - return unless BetterErrors.logger - - message = "\n#{@error_page.exception.type} - #{@error_page.exception.message}:\n" - @error_page.backtrace_frames.each do |frame| - message << " #{frame}\n" - end - - BetterErrors.logger.fatal message - end - - def internal_call(env, opts) - if opts[:id] != @error_page.id - return [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(error: "Session expired")]] - end - - env["rack.input"].rewind - response = @error_page.send("do_#{opts[:method]}", JSON.parse(env["rack.input"].read)) - [200, { "Content-Type" => "text/plain; charset=utf-8" }, [JSON.dump(response)]] - end - - def no_errors_page - "

    No errors

    No errors have been recorded yet.


    " + - "Better Errors v#{BetterErrors::VERSION}" - end - end -end diff --git a/lib/better_errors/lib/better_errors/rails.rb b/lib/better_errors/lib/better_errors/rails.rb deleted file mode 100644 index 36e386a55..000000000 --- a/lib/better_errors/lib/better_errors/rails.rb +++ /dev/null @@ -1,28 +0,0 @@ -module BetterErrors - # @private - class Railtie < Rails::Railtie - initializer "better_errors.configure_rails_initialization" do - if use_better_errors? - insert_middleware - BetterErrors.logger = Rails.logger - BetterErrors.application_root = Rails.root.to_s - end - end - - def insert_middleware - if defined? ActionDispatch::DebugExceptions - app.middleware.insert_after ActionDispatch::DebugExceptions, BetterErrors::Middleware - else - app.middleware.use BetterErrors::Middleware - end - end - - def use_better_errors? - !Rails.env.production? and app.config.consider_all_requests_local - end - - def app - Rails.application - end - end -end diff --git a/lib/better_errors/lib/better_errors/raised_exception.rb b/lib/better_errors/lib/better_errors/raised_exception.rb deleted file mode 100644 index 07d0d7b28..000000000 --- a/lib/better_errors/lib/better_errors/raised_exception.rb +++ /dev/null @@ -1,66 +0,0 @@ -# @private -module BetterErrors - class RaisedException - attr_reader :exception, :message, :backtrace - - def initialize(exception) - if exception.respond_to?(:original_exception) && exception.original_exception - exception = exception.original_exception - end - - @exception = exception - @message = exception.message - - setup_backtrace - massage_syntax_error - end - - def type - exception.class - end - - private - def has_bindings? - exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any? - end - - def setup_backtrace - if has_bindings? - setup_backtrace_from_bindings - else - setup_backtrace_from_backtrace - end - end - - def setup_backtrace_from_bindings - @backtrace = exception.__better_errors_bindings_stack.map { |binding| - file = binding.eval "__FILE__" - line = binding.eval "__LINE__" - name = binding.frame_description - StackFrame.new(file, line, name, binding) - } - end - - def setup_backtrace_from_backtrace - @backtrace = (exception.backtrace || []).map { |frame| - if /\A(?.*?):(?\d+)(:in `(?.*)')?/ =~ frame - StackFrame.new(file, line.to_i, name) - end - }.compact - end - - def massage_syntax_error - case exception.class.to_s - when "Haml::SyntaxError" - if /\A(.+?):(\d+)/ =~ exception.backtrace.first - backtrace.unshift(StackFrame.new($1, $2.to_i, "")) - end - when "SyntaxError" - if /\A(.+?):(\d+): (.*)/m =~ exception.message - backtrace.unshift(StackFrame.new($1, $2.to_i, "")) - @message = $3 - end - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/repl.rb b/lib/better_errors/lib/better_errors/repl.rb deleted file mode 100644 index c0f6463ed..000000000 --- a/lib/better_errors/lib/better_errors/repl.rb +++ /dev/null @@ -1,30 +0,0 @@ -module BetterErrors - # @private - module REPL - PROVIDERS = [ - { impl: "better_errors/repl/basic", - const: :Basic }, - ] - - def self.provider - @provider ||= const_get detect[:const] - end - - def self.provider=(prov) - @provider = prov - end - - def self.detect - PROVIDERS.find { |prov| - test_provider prov - } - end - - def self.test_provider(provider) - require provider[:impl] - true - rescue LoadError - false - end - end -end diff --git a/lib/better_errors/lib/better_errors/repl/basic.rb b/lib/better_errors/lib/better_errors/repl/basic.rb deleted file mode 100644 index 7011e4488..000000000 --- a/lib/better_errors/lib/better_errors/repl/basic.rb +++ /dev/null @@ -1,20 +0,0 @@ -module BetterErrors - module REPL - class Basic - def initialize(binding) - @binding = binding - end - - def send_input(str) - [execute(str), ">>", ""] - end - - private - def execute(str) - "=> #{@binding.eval(str).inspect}\n" - rescue Exception => e - "!! #{e.inspect rescue e.class.to_s rescue "Exception"}\n" - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/repl/pry.rb b/lib/better_errors/lib/better_errors/repl/pry.rb deleted file mode 100644 index 412be013d..000000000 --- a/lib/better_errors/lib/better_errors/repl/pry.rb +++ /dev/null @@ -1,78 +0,0 @@ -require "fiber" -require "pry" - -module BetterErrors - module REPL - class Pry - class Input - def readline - Fiber.yield - end - end - - class Output - def initialize - @buffer = "" - end - - def puts(*args) - args.each do |arg| - @buffer << "#{arg.chomp}\n" - end - end - - def tty? - false - end - - def read_buffer - @buffer - ensure - @buffer = "" - end - end - - def initialize(binding) - @fiber = Fiber.new do - @pry.repl binding - end - @input = Input.new - @output = Output.new - @pry = ::Pry.new input: @input, output: @output - @pry.hooks.clear_all if defined?(@pry.hooks.clear_all) - @fiber.resume - end - - def send_input(str) - local ::Pry.config, color: false, pager: false do - @fiber.resume "#{str}\n" - [@output.read_buffer, *prompt] - end - end - - def prompt - if indent = @pry.instance_variable_get(:@indent) and !indent.indent_level.empty? - ["..", indent.indent_level] - else - [">>", ""] - end - rescue - [">>", ""] - end - - private - def local(obj, attrs) - old_attrs = {} - attrs.each do |k, v| - old_attrs[k] = obj.send k - obj.send "#{k}=", v - end - yield - ensure - old_attrs.each do |k, v| - obj.send "#{k}=", v - end - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/stack_frame.rb b/lib/better_errors/lib/better_errors/stack_frame.rb deleted file mode 100644 index 4130425f7..000000000 --- a/lib/better_errors/lib/better_errors/stack_frame.rb +++ /dev/null @@ -1,111 +0,0 @@ -require "set" - -module BetterErrors - # @private - class StackFrame - def self.from_exception(exception) - RaisedException.new(exception).backtrace - end - - attr_reader :filename, :line, :name, :frame_binding - - def initialize(filename, line, name, frame_binding = nil) - @filename = filename - @line = line - @name = name - @frame_binding = frame_binding - - set_pretty_method_name if frame_binding - end - - def application? - if root = BetterErrors.application_root - filename.index(root) == 0 && filename.index("#{root}/vendor") != 0 - end - end - - def application_path - filename[(BetterErrors.application_root.length+1)..-1] - end - - def gem? - Gem.path.any? { |path| filename.index(path) == 0 } - end - - def gem_path - if path = Gem.path.detect { |path| filename.index(path) == 0 } - gem_name_and_version, path = filename.sub("#{path}/gems/", "").split("/", 2) - /(?.+)-(?[\w.]+)/ =~ gem_name_and_version - "#{gem_name} (#{gem_version}) #{path}" - end - end - - def class_name - @class_name - end - - def method_name - @method_name || @name - end - - def context - if gem? - :gem - elsif application? - :application - else - :dunno - end - end - - def pretty_path - case context - when :application; application_path - when :gem; gem_path - else filename - end - end - - def local_variables - return {} unless frame_binding - frame_binding.eval("local_variables").each_with_object({}) do |name, hash| - if defined?(frame_binding.local_variable_get) - hash[name] = frame_binding.local_variable_get(name) - else - hash[name] = frame_binding.eval(name.to_s) - end - end - end - - def instance_variables - return {} unless frame_binding - Hash[visible_instance_variables.map { |x| - [x, frame_binding.eval(x.to_s)] - }] - end - - def visible_instance_variables - frame_binding.eval("instance_variables") - BetterErrors.ignored_instance_variables - end - - def to_s - "#{pretty_path}:#{line}:in `#{name}'" - end - - private - def set_pretty_method_name - name =~ /\A(block (\([^)]+\) )?in )?/ - recv = frame_binding.eval("self") - - return unless method_name = frame_binding.eval("::Kernel.__method__") - - if Module === recv - @class_name = "#{$1}#{recv}" - @method_name = ".#{method_name}" - else - @class_name = "#{$1}#{Kernel.instance_method(:class).bind(recv).call}" - @method_name = "##{method_name}" - end - end - end -end diff --git a/lib/better_errors/lib/better_errors/templates/main.erb b/lib/better_errors/lib/better_errors/templates/main.erb deleted file mode 100644 index 7c3ff9fe1..000000000 --- a/lib/better_errors/lib/better_errors/templates/main.erb +++ /dev/null @@ -1,1031 +0,0 @@ - - - - <%= exception.type %> at <%= request_path %> - - - <%# Stylesheets are placed in the for Turbolinks compatibility. %> - - - <%# IE8 compatibility crap %> - - - <%# - If Rails's Turbolinks is used, the Better Errors page is probably - rendered in the host app's layout. Let's empty out the styles of the - host app. - %> - - -
    -
    -

    <%= exception.type %> at <%= request_path %>

    -

    <%= exception.message %>

    -
    -
    - -
    - - - <% backtrace_frames.each_with_index do |frame, index| %> - - <% end %> -
    - - - - - diff --git a/lib/better_errors/lib/better_errors/templates/text.erb b/lib/better_errors/lib/better_errors/templates/text.erb deleted file mode 100644 index fe9068bbb..000000000 --- a/lib/better_errors/lib/better_errors/templates/text.erb +++ /dev/null @@ -1,21 +0,0 @@ -<%== text_heading("=", "%s at %s" % [exception.type, request_path]) %> - -> <%== exception.message %> -<% if backtrace_frames.any? %> - -<%== text_heading("-", "%s, line %i" % [first_frame.pretty_path, first_frame.line]) %> - -``` ruby -<%== text_formatted_code_block(first_frame) %>``` - -App backtrace -------------- - -<%== application_frames.map { |s| " - #{s}" }.join("\n") %> - -Full backtrace --------------- - -<%== backtrace_frames.map { |s| " - #{s}" }.join("\n") %> - -<% end %> diff --git a/lib/better_errors/lib/better_errors/templates/variable_info.erb b/lib/better_errors/lib/better_errors/templates/variable_info.erb deleted file mode 100644 index bde5daab8..000000000 --- a/lib/better_errors/lib/better_errors/templates/variable_info.erb +++ /dev/null @@ -1,70 +0,0 @@ -
    -
    -

    <%= @frame.name %>

    - -
    -
    - <%== html_formatted_code_block @frame %> -
    - - <% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
    -
    -
    
    -                
    >>
    -
    -
    - <% end %> -
    - -<% if BetterErrors.binding_of_caller_available? && @frame.frame_binding %> -
    - This is a live shell. Type in here. -
    - -
    -<% end %> - -<% unless BetterErrors.binding_of_caller_available? %> -
    - Tip: add gem "binding_of_caller" to your Gemfile to enable the REPL and local/instance variable inspection. -
    -<% end %> - -
    -

    Request info

    -
    - - <% if rails_params %> - - <% end %> - <% if rack_session %> - - <% end %> -
    Request parameters
    <%== inspect_value rails_params %>
    Rack session
    <%== inspect_value rack_session %>
    -
    -
    - -
    -

    Local Variables

    -
    - - <% @frame.local_variables.each do |name, value| %> - - <% end %> -
    <%= name %>
    <%== inspect_value value %>
    -
    -
    - -
    -

    Instance Variables

    -
    - - <% @frame.instance_variables.each do |name, value| %> - - <% end %> -
    <%= name %>
    <%== inspect_value value %>
    -
    -
    - - diff --git a/lib/better_errors/lib/better_errors/version.rb b/lib/better_errors/lib/better_errors/version.rb deleted file mode 100644 index 81769ce8b..000000000 --- a/lib/better_errors/lib/better_errors/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module BetterErrors - VERSION = "1.1.0" -end diff --git a/lib/better_errors/spec/better_errors/code_formatter_spec.rb b/lib/better_errors/spec/better_errors/code_formatter_spec.rb deleted file mode 100644 index c084e2f91..000000000 --- a/lib/better_errors/spec/better_errors/code_formatter_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe CodeFormatter do - let(:filename) { File.expand_path("../support/my_source.rb", __FILE__) } - - let(:formatter) { CodeFormatter.new(filename, 8) } - - it "picks an appropriate scanner" do - formatter.coderay_scanner.should == :ruby - end - - it "shows 5 lines of context" do - formatter.line_range.should == (3..13) - - formatter.context_lines.should == [ - "three\n", - "four\n", - "five\n", - "six\n", - "seven\n", - "eight\n", - "nine\n", - "ten\n", - "eleven\n", - "twelve\n", - "thirteen\n" - ] - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter.new(filename, 20) - formatter.line_range.should == (15..20) - end - - describe CodeFormatter::HTML do - it "highlights the erroring line" do - formatter = CodeFormatter::HTML.new(filename, 8) - formatter.output.should =~ /highlight.*eight/ - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter::HTML.new(filename, 20) - formatter.output.should_not == formatter.source_unavailable - end - - it "doesn't barf when the lines don't make any sense" do - formatter = CodeFormatter::HTML.new(filename, 999) - formatter.output.should == formatter.source_unavailable - end - - it "doesn't barf when the file doesn't exist" do - formatter = CodeFormatter::HTML.new("fkdguhskd7e l", 1) - formatter.output.should == formatter.source_unavailable - end - end - - describe CodeFormatter::Text do - it "highlights the erroring line" do - formatter = CodeFormatter::Text.new(filename, 8) - formatter.output.should == <<-TEXT.gsub(/^ /, "") - 3 three - 4 four - 5 five - 6 six - 7 seven - > 8 eight - 9 nine - 10 ten - 11 eleven - 12 twelve - 13 thirteen - TEXT - end - - it "works when the line is right on the edge" do - formatter = CodeFormatter::Text.new(filename, 20) - formatter.output.should_not == formatter.source_unavailable - end - - it "doesn't barf when the lines don't make any sense" do - formatter = CodeFormatter::Text.new(filename, 999) - formatter.output.should == formatter.source_unavailable - end - - it "doesn't barf when the file doesn't exist" do - formatter = CodeFormatter::Text.new("fkdguhskd7e l", 1) - formatter.output.should == formatter.source_unavailable - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/error_page_spec.rb b/lib/better_errors/spec/better_errors/error_page_spec.rb deleted file mode 100644 index daea57be6..000000000 --- a/lib/better_errors/spec/better_errors/error_page_spec.rb +++ /dev/null @@ -1,76 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe ErrorPage do - let!(:exception) { raise ZeroDivisionError, "you divided by zero you silly goose!" rescue $! } - - let(:error_page) { ErrorPage.new exception, { "PATH_INFO" => "/some/path" } } - - let(:response) { error_page.render } - - let(:empty_binding) { - local_a = :value_for_local_a - local_b = :value_for_local_b - - @inst_c = :value_for_inst_c - @inst_d = :value_for_inst_d - - binding - } - - it "includes the error message" do - response.should include("you divided by zero you silly goose!") - end - - it "includes the request path" do - response.should include("/some/path") - end - - it "includes the exception class" do - response.should include("ZeroDivisionError") - end - - context "variable inspection" do - let(:exception) { empty_binding.eval("raise") rescue $! } - - if BetterErrors.binding_of_caller_available? - it "shows local variables" do - html = error_page.do_variables("index" => 0)[:html] - html.should include("local_a") - html.should include(":value_for_local_a") - html.should include("local_b") - html.should include(":value_for_local_b") - end - else - it "tells the user to add binding_of_caller to their gemfile to get fancy features" do - html = error_page.do_variables("index" => 0)[:html] - html.should include(%{gem "binding_of_caller"}) - end - end - - it "shows instance variables" do - html = error_page.do_variables("index" => 0)[:html] - html.should include("inst_c") - html.should include(":value_for_inst_c") - html.should include("inst_d") - html.should include(":value_for_inst_d") - end - - it "shows filter instance variables" do - BetterErrors.stub(:ignored_instance_variables).and_return([ :@inst_d ]) - html = error_page.do_variables("index" => 0)[:html] - html.should include("inst_c") - html.should include(":value_for_inst_c") - html.should_not include('@inst_d') - html.should_not include("
    :value_for_inst_d
    ") - end - end - - it "doesn't die if the source file is not a real filename" do - exception.stub(:backtrace).and_return([ - ":10:in `spawn_rack_application'" - ]) - response.should include("Source unavailable") - end - end -end diff --git a/lib/better_errors/spec/better_errors/middleware_spec.rb b/lib/better_errors/spec/better_errors/middleware_spec.rb deleted file mode 100644 index 2c638bfab..000000000 --- a/lib/better_errors/spec/better_errors/middleware_spec.rb +++ /dev/null @@ -1,146 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe Middleware do - let(:app) { Middleware.new(->env { ":)" }) } - let(:exception) { RuntimeError.new("oh no :(") } - - it "passes non-error responses through" do - app.call({}).should == ":)" - end - - it "calls the internal methods" do - app.should_receive :internal_call - app.call("PATH_INFO" => "/__better_errors/1/preform_awesomness") - end - - it "calls the internal methods on any subfolder path" do - app.should_receive :internal_call - app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/1/preform_awesomness") - end - - it "shows the error page" do - app.should_receive :show_error_page - app.call("PATH_INFO" => "/__better_errors/") - end - - it "shows the error page on any subfolder path" do - app.should_receive :show_error_page - app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors/") - end - - it "doesn't show the error page to a non-local address" do - app.should_not_receive :better_errors_call - app.call("REMOTE_ADDR" => "1.2.3.4") - end - - it "shows to a whitelisted IP" do - BetterErrors::Middleware.allow_ip! '77.55.33.11' - app.should_receive :better_errors_call - app.call("REMOTE_ADDR" => "77.55.33.11") - end - - it "doesn't blow up when given a blank REMOTE_ADDR" do - expect { app.call("REMOTE_ADDR" => " ") }.to_not raise_error - end - - it "doesn't blow up when given an IP address with a zone index" do - expect { app.call("REMOTE_ADDR" => "0:0:0:0:0:0:0:1%0" ) }.to_not raise_error - end - - context "when requesting the /__better_errors manually" do - let(:app) { Middleware.new(->env { ":)" }) } - - it "shows that no errors have been recorded" do - status, headers, body = app.call("PATH_INFO" => "/__better_errors") - body.join.should match /No errors have been recorded yet./ - end - - it "shows that no errors have been recorded on any subfolder path" do - status, headers, body = app.call("PATH_INFO" => "/any_sub/folder/path/__better_errors") - body.join.should match /No errors have been recorded yet./ - end - end - - context "when handling an error" do - let(:app) { Middleware.new(->env { raise exception }) } - - it "returns status 500" do - status, headers, body = app.call({}) - - status.should == 500 - end - - context "original_exception" do - class OriginalExceptionException < Exception - attr_reader :original_exception - - def initialize(message, original_exception = nil) - super(message) - @original_exception = original_exception - end - end - - it "shows Original Exception if it responds_to and has an original_exception" do - app = Middleware.new(->env { - raise OriginalExceptionException.new("Other Exception", Exception.new("Original Exception")) - }) - - status, _, body = app.call({}) - - status.should == 500 - body.join.should_not match(/Other Exception/) - body.join.should match(/Original Exception/) - end - - it "won't crash if the exception responds_to but doesn't have an original_exception" do - app = Middleware.new(->env { - raise OriginalExceptionException.new("Other Exception") - }) - - status, _, body = app.call({}) - - status.should == 500 - body.join.should match(/Other Exception/) - end - end - - it "returns ExceptionWrapper's status_code" do - ad_ew = double("ActionDispatch::ExceptionWrapper") - ad_ew.stub('new').with({}, exception ){ double("ExceptionWrapper", status_code: 404) } - stub_const('ActionDispatch::ExceptionWrapper', ad_ew) - - status, headers, body = app.call({}) - - status.should == 404 - end - - it "returns UTF-8 error pages" do - status, headers, body = app.call({}) - - headers["Content-Type"].should match /charset=utf-8/ - end - - it "returns text pages by default" do - status, headers, body = app.call({}) - - headers["Content-Type"].should match /text\/plain/ - end - - it "returns HTML pages by default" do - # Chrome's 'Accept' header looks similar this. - status, headers, body = app.call("HTTP_ACCEPT" => "text/html,application/xhtml+xml;q=0.9,*/*") - - headers["Content-Type"].should match /text\/html/ - end - - it "logs the exception" do - logger = Object.new - logger.should_receive :fatal - BetterErrors.stub(:logger).and_return(logger) - - app.call({}) - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/raised_exception_spec.rb b/lib/better_errors/spec/better_errors/raised_exception_spec.rb deleted file mode 100644 index 605ab409c..000000000 --- a/lib/better_errors/spec/better_errors/raised_exception_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe RaisedException do - let(:exception) { RuntimeError.new("whoops") } - subject { RaisedException.new(exception) } - - its(:exception) { should == exception } - its(:message) { should == "whoops" } - its(:type) { should == RuntimeError } - - context "when the exception wraps another exception" do - let(:original_exception) { RuntimeError.new("something went wrong!") } - let(:exception) { double(:original_exception => original_exception) } - - its(:exception) { should == original_exception } - its(:message) { should == "something went wrong!" } - end - - context "when the exception is a syntax error" do - let(:exception) { SyntaxError.new("foo.rb:123: you made a typo!") } - - its(:message) { should == "you made a typo!" } - its(:type) { should == SyntaxError } - - it "has the right filename and line number in the backtrace" do - subject.backtrace.first.filename.should == "foo.rb" - subject.backtrace.first.line.should == 123 - end - end - - context "when the exception is a HAML syntax error" do - before do - stub_const("Haml::SyntaxError", Class.new(SyntaxError)) - end - - let(:exception) { - Haml::SyntaxError.new("you made a typo!").tap do |ex| - ex.set_backtrace(["foo.rb:123", "haml/internals/blah.rb:123456"]) - end - } - - its(:message) { should == "you made a typo!" } - its(:type) { should == Haml::SyntaxError } - - it "has the right filename and line number in the backtrace" do - subject.backtrace.first.filename.should == "foo.rb" - subject.backtrace.first.line.should == 123 - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/basic_spec.rb b/lib/better_errors/spec/better_errors/repl/basic_spec.rb deleted file mode 100644 index c533f632c..000000000 --- a/lib/better_errors/spec/better_errors/repl/basic_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "spec_helper" -require "better_errors/repl/basic" -require "better_errors/repl/shared_examples" - -module BetterErrors - module REPL - describe Basic do - let(:fresh_binding) { - local_a = 123 - binding - } - - let(:repl) { Basic.new fresh_binding } - - it_behaves_like "a REPL provider" - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/pry_spec.rb b/lib/better_errors/spec/better_errors/repl/pry_spec.rb deleted file mode 100644 index 1aa502c56..000000000 --- a/lib/better_errors/spec/better_errors/repl/pry_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require "spec_helper" -require "pry" -require "better_errors/repl/pry" -require "better_errors/repl/shared_examples" - -module BetterErrors - module REPL - describe Pry do - let(:fresh_binding) { - local_a = 123 - binding - } - - let(:repl) { Pry.new fresh_binding } - - it "does line continuation" do - output, prompt, filled = repl.send_input "" - output.should == "=> nil\n" - prompt.should == ">>" - filled.should == "" - - output, prompt, filled = repl.send_input "def f(x)" - output.should == "" - prompt.should == ".." - filled.should == " " - - output, prompt, filled = repl.send_input "end" - if RUBY_VERSION >= "2.1.0" - output.should == "=> :f\n" - else - output.should == "=> nil\n" - end - prompt.should == ">>" - filled.should == "" - end - - it_behaves_like "a REPL provider" - end - end -end diff --git a/lib/better_errors/spec/better_errors/repl/shared_examples.rb b/lib/better_errors/spec/better_errors/repl/shared_examples.rb deleted file mode 100644 index 0154851db..000000000 --- a/lib/better_errors/spec/better_errors/repl/shared_examples.rb +++ /dev/null @@ -1,18 +0,0 @@ -shared_examples_for "a REPL provider" do - it "evaluates ruby code in a given context" do - repl.send_input("local_a = 456") - fresh_binding.eval("local_a").should == 456 - end - - it "returns a tuple of output and the new prompt" do - output, prompt = repl.send_input("1 + 2") - output.should == "=> 3\n" - prompt.should == ">>" - end - - it "doesn't barf if the code throws an exception" do - output, prompt = repl.send_input("raise Exception") - output.should include "Exception: Exception" - prompt.should == ">>" - end -end diff --git a/lib/better_errors/spec/better_errors/stack_frame_spec.rb b/lib/better_errors/spec/better_errors/stack_frame_spec.rb deleted file mode 100644 index 420111eec..000000000 --- a/lib/better_errors/spec/better_errors/stack_frame_spec.rb +++ /dev/null @@ -1,157 +0,0 @@ -require "spec_helper" - -module BetterErrors - describe StackFrame do - context "#application?" do - it "is true for application filenames" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application?.should be_true - end - - it "is false for everything else" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/nope", 123, "foo") - - frame.application?.should be_false - end - - it "doesn't care if no application_root is set" do - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application?.should be_false - end - end - - context "#gem?" do - it "is true for gem filenames" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem?.should be_true - end - - it "is false for everything else" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/nope", 123, "foo") - - frame.gem?.should be_false - end - end - - context "#application_path" do - it "chops off the application root" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - - frame.application_path.should == "app/controllers/crap_controller.rb" - end - end - - context "#gem_path" do - it "chops of the gem path and stick (gem) there" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb" - end - - it "prioritizes gem path over application path" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - Gem.stub(:path).and_return(["/abc/xyz/vendor"]) - frame = StackFrame.new("/abc/xyz/vendor/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.gem_path.should == "whatever (1.2.3) lib/whatever.rb" - end - end - - context "#pretty_path" do - it "returns #application_path for application paths" do - BetterErrors.stub(:application_root).and_return("/abc/xyz") - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index") - frame.pretty_path.should == frame.application_path - end - - it "returns #gem_path for gem paths" do - Gem.stub(:path).and_return(["/abc/xyz"]) - frame = StackFrame.new("/abc/xyz/gems/whatever-1.2.3/lib/whatever.rb", 123, "foo") - - frame.pretty_path.should == frame.gem_path - end - end - - it "special cases SyntaxErrors" do - begin - eval(%{ raise SyntaxError, "you wrote bad ruby!" }, nil, "my_file.rb", 123) - rescue SyntaxError => syntax_error - end - frames = StackFrame.from_exception(syntax_error) - frames.first.filename.should == "my_file.rb" - frames.first.line.should == 123 - end - - it "doesn't blow up if no method name is given" do - error = StandardError.allocate - - error.stub(:backtrace).and_return(["foo.rb:123"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "foo.rb" - frames.first.line.should == 123 - - error.stub(:backtrace).and_return(["foo.rb:123: this is an error message"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "foo.rb" - frames.first.line.should == 123 - end - - it "ignores a backtrace line if its format doesn't make any sense at all" do - error = StandardError.allocate - error.stub(:backtrace).and_return(["foo.rb:123:in `foo'", "C:in `find'", "bar.rb:123:in `bar'"]) - frames = StackFrame.from_exception(error) - frames.count.should == 2 - end - - it "doesn't blow up if a filename contains a colon" do - error = StandardError.allocate - error.stub(:backtrace).and_return(["crap:filename.rb:123"]) - frames = StackFrame.from_exception(error) - frames.first.filename.should == "crap:filename.rb" - end - - it "doesn't blow up with a BasicObject as frame binding" do - obj = BasicObject.new - def obj.my_binding - ::Kernel.binding - end - frame = StackFrame.new("/abc/xyz/app/controllers/crap_controller.rb", 123, "index", obj.my_binding) - frame.class_name.should == 'BasicObject' - end - - it "sets method names properly" do - obj = "string" - def obj.my_method - begin - raise "foo" - rescue => err - err - end - end - - frame = StackFrame.from_exception(obj.my_method).first - if BetterErrors.binding_of_caller_available? - frame.method_name.should == "#my_method" - frame.class_name.should == "String" - else - frame.method_name.should == "my_method" - frame.class_name.should == nil - end - end - - if RUBY_ENGINE == "java" - it "doesn't blow up on a native Java exception" do - expect { StackFrame.from_exception(java.lang.Exception.new) }.to_not raise_error - end - end - end -end diff --git a/lib/better_errors/spec/better_errors/support/my_source.rb b/lib/better_errors/spec/better_errors/support/my_source.rb deleted file mode 100644 index 6dfea0f66..000000000 --- a/lib/better_errors/spec/better_errors/support/my_source.rb +++ /dev/null @@ -1,20 +0,0 @@ -one -two -three -four -five -six -seven -eight -nine -ten -eleven -twelve -thirteen -fourteen -fifteen -sixteen -seventeen -eighteen -nineteen -twenty diff --git a/lib/better_errors/spec/better_errors_spec.rb b/lib/better_errors/spec/better_errors_spec.rb deleted file mode 100644 index e9b26b67d..000000000 --- a/lib/better_errors/spec/better_errors_spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -require "spec_helper" - -describe BetterErrors do - context ".editor" do - it "defaults to textmate" do - subject.editor["foo.rb", 123].should == "txmt://open?url=file://foo.rb&line=123" - end - - it "url escapes the filename" do - subject.editor["&.rb", 0].should == "txmt://open?url=file://%26.rb&line=0" - end - - [:emacs, :emacsclient].each do |editor| - it "uses emacs:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "emacs://" - end - end - - [:macvim, :mvim].each do |editor| - it "uses mvim:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "mvim://" - end - end - - [:sublime, :subl, :st].each do |editor| - it "uses subl:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "subl://" - end - end - - [:textmate, :txmt, :tm].each do |editor| - it "uses txmt:// scheme when set to #{editor.inspect}" do - subject.editor = editor - subject.editor[].should start_with "txmt://" - end - end - - ["emacsclient", "/usr/local/bin/emacsclient"].each do |editor| - it "uses emacs:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "emacs://" - end - end - - ["mvim -f", "/usr/local/bin/mvim -f"].each do |editor| - it "uses mvim:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "mvim://" - end - end - - ["subl -w", "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl"].each do |editor| - it "uses mvim:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "subl://" - end - end - - ["mate -w", "/usr/bin/mate -w"].each do |editor| - it "uses txmt:// scheme when EDITOR=#{editor}" do - ENV["EDITOR"] = editor - subject.editor = subject.default_editor - subject.editor[].should start_with "txmt://" - end - end - end -end diff --git a/lib/better_errors/spec/spec_helper.rb b/lib/better_errors/spec/spec_helper.rb deleted file mode 100644 index 40d63261e..000000000 --- a/lib/better_errors/spec/spec_helper.rb +++ /dev/null @@ -1,5 +0,0 @@ -$: << File.expand_path("../../lib", __FILE__) - -ENV["EDITOR"] = nil - -require "better_errors" diff --git a/lib/better_errors/spec/without_binding_of_caller.rb b/lib/better_errors/spec/without_binding_of_caller.rb deleted file mode 100644 index 035e2e90f..000000000 --- a/lib/better_errors/spec/without_binding_of_caller.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Kernel - alias_method :require_with_binding_of_caller, :require - - def require(feature) - raise LoadError if feature == "binding_of_caller" - - require_with_binding_of_caller(feature) - end -end diff --git a/lib/git_refresh_changes.py b/lib/git_refresh_changes.py new file mode 100644 index 000000000..a0250243e --- /dev/null +++ b/lib/git_refresh_changes.py @@ -0,0 +1,30 @@ +#coding=utf-8 +#!/usr/bin/env python + +# 脚本用于刷新版本库,由git hooks里进行调用,传入参数为git仓库路径 +# 需要配置rails项目地址 +# 必须装此文件放在git的存放目录,现在是 /home/pdl/redmine-2.3.2-0/apache2/htdocs + +import sys +import os +import urllib +import urllib2 + +RAILS_URL = 'http://192.168.128.128:3000/' + +def get_git_path(): + return sys.argv[1] + path=os.path.realpath(sys.argv[0]) + if os.path.isfile(path): + path=os.path.dirname(os.path.dirname(path)) + return os.path.abspath(path) + +def post_http_data(url, data): + data_urlencode = urllib.urlencode(data) + req = urllib2.Request(url = url,data =data_urlencode) + res_data = urllib2.urlopen(req) + #res = res_data.read() + #return res + +path = get_git_path() +post_http_data(RAILS_URL + 'git_callback/post_update', {'root_url': path}) diff --git a/lib/rack-mini-profiler/.travis.yml b/lib/rack-mini-profiler/.travis.yml deleted file mode 100644 index 61ab0d68e..000000000 --- a/lib/rack-mini-profiler/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: ruby -rvm: - - 1.9.3 - - 2.0.0 - - 2.1.1 -bundler_args: "" -services: - - redis - - memcached diff --git a/lib/rack-mini-profiler/CHANGELOG b/lib/rack-mini-profiler/CHANGELOG deleted file mode 100644 index 7c08a89e1..000000000 --- a/lib/rack-mini-profiler/CHANGELOG +++ /dev/null @@ -1,181 +0,0 @@ -28-June-2012 - Sam - - * Started change log - * Corrected profiler so it properly captures POST requests (was supressing non 200s) - * Amended Rack.MiniProfiler.config[:user_provider] to use ip addres for identity - * Fixed bug where unviewed missing ids never got cleared - * Supress all '/assets/' in the rails tie (makes debugging easier) - * record_sql was mega buggy - * added MemcacheStore - -9-July-2012 - Sam - - * Cleaned up mechanism for profiling in production, all you need to do now - is call Rack::MiniProfiler.authorize_request to get profiling working in - production - * Added option to display full backtraces pp=full-backtrace - * Cleaned up railties, got rid of the post authorize callback - * Version 0.1.3 - -12-July-2012 - Sam - - * Fixed incorrect profiling steps (was not indenting or measuring start time right - * Implemented native PG and MySql2 interceptors, this gives way more accurate times - * Refactored context so its a proper class and not a hash - * Added some more client probing built in to rails - * More tests - -18-July-2012 - Sam - - * Added First Paint time for chrome - * Bug fix to ensure non Rails installs have mini profiler - * Version 0.1.7 - -30-July-2012 - Sam - - * Made compliant with ancient versions of Rack (including Rack used by Rails2) - * Fixed broken share link - * Fixed crashes on startup (in MemoryStore and FileStore) - * Version 0.1.8 - * Unicode fix - * Version 0.1.9 - -7-August-2012 - Sam - - * Added option to disable profiler for the current session (pp=disable / pp=enable) - * yajl compatability contributed by Sven Riedel - -10-August-2012 - Sam - - * Added basic prepared statement profiling for postgres - -20-August-2012 - Sam - - * 1.12.pre - * Cap X-MiniProfiler-Ids at 10, otherwise the header can get killed - -3-September-2012 - Sam - - * 1.13.pre - * pg gem prepared statements were not being logged correctly - * added setting config.backtrace_ignores = [] - an array of regexes that match on caller lines that get ignored - * added setting config.backtrace_includes = [] - an array of regexes that get included in the trace by default - * cleaned up the way client settings are stored - * made pp=full-backtrace "sticky" - * added pp=normal-backtrace to clear the "sticky" state - * change "pp=sample" to work with "caller" no need for stack trace gem - -4-September-2012 - Sam - - * 1.15.pre - * fixed annoying bug where client settings were not sticking - * fixed long standing issue with Rack::ConditionalGet stopping MiniProfiler from working properly - -5-September-2012 - Sam - - * 1.16 - * fixed long standing problem specs (issue with memory store) - * fixed issue where profiler would be dumped when you got a 404 in production (and any time rails is bypassed) - * implemented stacktrace properly - -9-September-2012 - Sam - - * 1.17 - * pp=sample was bust unless stacktrace was installed - -10-September-2012 - Sam - - * 1.19 - * fix compat issue with 1.8.7 - -12-September-2012 - Sam - - * 1.20 - * Added pp=profile-gc , it allows you to profile the GC in Ruby 1.9.3 - -17-September-2012 - * 1.21 - * New MemchacedStore - * Rails 4 support - -17-September-2012 - * Allow rack-mini-profiler to be sourced from github - * Extracted the pp=profile-gc-time out, the object space profiler needs to disable gc - -20-September-2012 - * 1.22 - * Fix permission issue in the gem - -8-April-2013 - * 1.24 - * Flame Graph Support see: http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler - * Fix file retention leak in file_store - * New toggle_shortcut and start_hidden options - * Fix for AngularJS support and MooTools - * More robust gc profiling - * Mongoid support - * Fix for html5 implicit body tags - * script tag initialized via data-attributes - * new - Rack::MiniProfiler.counter counter_name {} - * Allow usage of existing jQuery if its already loaded - * Fix pp=enable - * 1.8.7 support ... grrr - * Net:HTTP profiling - * pre authorize to run in all non development? and production? modes - -8-April-2013 - * 1.25 - * Missed flamegraph.html from build - -11-April-2013 - * 1.26 - * (minor) allow Rack::MiniProfilerRails.initialize!(Rails.application), for post config intialization - -26-June-2013 - * 1.27 - * Disable global ajax handlers on MP requests @JP - * Add Rack::MiniProfiler.config.backtrace_threshold_ms - * jQuery 2.0 support - -18-July-2013 - * 1.28 - * diagnostics in abstract storage was raising not implemented killing - ?pp=env and others - * SOLR xml unescaped by mistake - -20-August-2013 - * 1.29 - * Bugfix: SOLR patching had an incorrect monkey patch - * Implemented exception tracing using TracePoint see pp=trace-exceptions - -30-August-2013 - - * 1.30 - * Feature: Added Rack::MiniProfiler.counter_method(klass,name) for injecting counters - * Bug: Counters were not shifting the table correctly - -3-September-2013 - - * Ripped out flamegraph so it can be isolated into a gem - * Flamegraph now has much increased fidelity - * Ripped out pp=sample it just was never really used - -17-September-2013 - Ross Wilson - * Instead of supressing all "/assets/" requests we now check the configured - config.assets.prefix path since developers can rename the path to serve Asset Pipeline - files from - -12-December-2013 - Sam Saffron - * Version 0.9.0.pre (bumped up to reflect the stability of the project) - * Improved reports for pp=profile-gc - * pp=flamegraph&flamegraph_sample_rate=1 , allow you to specify sampling rates - -13-March-2014 - Sam Saffron - * Version 0.9.1 - * Added back Ruby 1.8 support (thanks Malet) - * Corrected Rails 3.0 support (thanks Zlatko) - * Corrected fix possible XSS (admin only) - * Amend Railstie so MiniProfiler can be launched with action view or action controller (Thanks Akira) - * Corrected Sql patching to avoid setting instance vars on nil which is frozen (thanks Andy, huoxito) - - diff --git a/lib/rack-mini-profiler/Gemfile b/lib/rack-mini-profiler/Gemfile deleted file mode 100644 index d65e2a669..000000000 --- a/lib/rack-mini-profiler/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'http://rubygems.org' - -gemspec diff --git a/lib/rack-mini-profiler/README.md b/lib/rack-mini-profiler/README.md deleted file mode 100644 index 550dc1e07..000000000 --- a/lib/rack-mini-profiler/README.md +++ /dev/null @@ -1,271 +0,0 @@ -# rack-mini-profiler - -[![Code Climate](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler.png)](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler) [![Build Status](https://travis-ci.org/MiniProfiler/rack-mini-profiler.png)](https://travis-ci.org/MiniProfiler/rack-mini-profiler) - -Middleware that displays speed badge for every html page. Designed to work both in production and in development. - -#### Features - -* database profiling. Currently supports Mysql2, Postgres, and Mongoid3 (with fallback support to ActiveRecord) - -#### Learn more - -* [Visit our community](http://community.miniprofiler.com) -* [Watch the RailsCast](http://railscasts.com/episodes/368-miniprofiler) -* [Read about Flame graphs in rack-mini-profiler](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler) -* [Read the announcement posts from 2012](http://samsaffron.com/archive/2012/07/12/miniprofiler-ruby-edition) - -## rack-mini-profiler needs your help - -We have decided to restructure our repository so there is a central UI repo and the various language implementation have their own. - -**WE NEED HELP.** - -- Setting up a build that reuses https://github.com/MiniProfiler/ui -- Migrating the internal data structures [per the spec](https://github.com/MiniProfiler/ui) -- Cleaning up the [horrendous class structure that is using strings as keys and crazy non-objects](https://github.com/MiniProfiler/rack-mini-profiler/blob/master/lib/mini_profiler/sql_timer_struct.rb#L36-L44) - -If you feel like taking on any of this start an issue and update us on your progress. - -## Installation - -Install/add to Gemfile - -```ruby -gem 'rack-mini-profiler' -``` - -NOTE: Be sure to require rack_mini_profiler below the `pg` and `mysql` gems in your Gemfile. rack_mini_profiler will identify these gems if they are loaded to insert instrumentation. If included too early no SQL will show up. - -#### Rails - -All you have to do is include the Gem and you're good to go in development. See notes below for use in production. - -#### Rails and manual initialization - -In case you need to make sure rack_mini_profiler initialized after all other gems. -Or you want to execute some code before rack_mini_profiler required. - -```ruby -gem 'rack-mini-profiler', require: false -``` -Note the `require: false` part - if omitted, it will cause the Railtie for the mino-profiler to -be loaded outright, and an attempt to re-initialize it manually will raise an exception. - -Then put initialize code in file like `config/initializers/rack_profiler.rb` - -```ruby -if Rails.env == 'development' - require 'rack-mini-profiler' - - # initialization is skipped so trigger it - Rack::MiniProfilerRails.initialize!(Rails.application) -end -``` - -#### Rack Builder - -```ruby -require 'rack-mini-profiler' -builder = Rack::Builder.new do - use Rack::MiniProfiler - - map('/') { run get } -end -``` - -#### Sinatra - -```ruby -require 'rack-mini-profiler' -class MyApp < Sinatra::Base - use Rack::MiniProfiler -end -``` - -### Flamegraphs - -To generate [flamegraphs](http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler): - -* add the **flamegraph** gem to your Gemfile -* visit a page in your app with `?pp=flamegraph` - -Flamegraph generation is supported in MRI 2.0 and 2.1 only. - - -## Access control in production - -rack-mini-profiler is designed with production profiling in mind. To enable that just run `Rack::MiniProfiler.authorize_request` once you know a request is allowed to profile. - -```ruby -# A hook in your ApplicationController -def authorize - if current_user.is_admin? - Rack::MiniProfiler.authorize_request - end -end -``` - -## Configuration - -Various aspects of rack-mini-profiler's behavior can be configured when your app boots. -For example in a Rails app, this should be done in an initializer: -**config/initializers/mini_profiler.rb** - -### Storage - -rack-mini-profiler stores its results so they can be shared later and aren't lost at the end of the request. - -There are 4 storage options: `MemoryStore`, `RedisStore`, `MemcacheStore`, and `FileStore`. - -`FileStore` is the default in Rails environments and will write files to `tmp/miniprofiler/*`. `MemoryStore` is the default otherwise. - -```ruby -# set MemoryStore -Rack::MiniProfiler.config.storage = Rack::MiniProfiler::MemoryStore - -# set RedisStore -if Rails.env.production? - uri = URI.parse(ENV["REDIS_SERVER_URL"]) - Rack::MiniProfiler.config.storage_options = { :host => uri.host, :port => uri.port, :password => uri.password } - Rack::MiniProfiler.config.storage = Rack::MiniProfiler::RedisStore -end -``` - -MemoryStore stores results in a processes heap - something that does not work well in a multi process environment. -FileStore stores results in the file system - something that may not work well in a multi machine environment. -RedisStore/MemcacheStore work in multi process and multi machine environments (RedisStore only saves results for up to 24 hours so it won't continue to fill up Redis). - -Additionally you may implement an AbstractStore for your own provider. - -### User result segregation - -MiniProfiler will attempt to keep all user results isolated, out-of-the-box the user provider uses the ip address: - -```ruby -Rack::MiniProfiler.config.user_provider = Proc.new{|env| Rack::Request.new(env).ip} -``` - -You can override (something that is very important in a multi-machine production setup): - -```ruby -Rack::MiniProfiler.config.user_provider = Proc.new{ |env| CurrentUser.get(env) } -``` - -The string this function returns should be unique for each user on the system (for anonymous you may need to fall back to ip address) - -### Configuration Options - -You can set configuration options using the configuration accessor on `Rack::MiniProfiler`. -For example: - -```ruby -Rack::MiniProfiler.config.position = 'right' -Rack::MiniProfiler.config.start_hidden = true -``` -The available configuration options are: - -* pre_authorize_cb - A lambda callback you can set to determine whether or not mini_profiler should be visible on a given request. Default in a Rails environment is only on in development mode. If in a Rack app, the default is always on. -* position - Can either be 'right' or 'left'. Default is 'left'. -* skip_schema_queries - Whether or not you want to log the queries about the schema of your tables. Default is 'false', 'true' in rails development. -* auto_inject (default true) - when false the miniprofiler script is not injected in the page -* backtrace_filter - a regex you can use to filter out unwanted lines from the backtraces -* toggle_shortcut (default Alt+P) - a jquery.hotkeys.js-style keyboard shortcut, used to toggle the mini_profiler's visibility. See http://code.google.com/p/js-hotkeys/ for more info. -* start_hidden (default false) - Whether or not you want the mini_profiler to be visible when loading a page -* backtrace_threshold_ms (default zero) - Minimum SQL query elapsed time before a backtrace is recorded. Backtrace recording can take a couple of milliseconds on rubies earlier than 2.0, impacting performance for very small queries. -* flamegraph_sample_rate (default 0.5ms) - How often fast_stack should get stack trace info to generate flamegraphs - -### Custom middleware ordering (required if using `Rack::Deflate` with Rails) - -If you are using `Rack::Deflate` with rails and rack-mini-profiler in its default configuration, -`Rack::MiniProfiler` will be injected (as always) at position 0 in the middleware stack. This -will result in it attempting to inject html into the already-compressed response body. To fix this, -the middleware ordering must be overriden. - -To do this, first add `, require: false` to the gemfile entry for rack-mini-profiler. -This will prevent the railtie from running. Then, customize the initialization -in the initializer like so: - -```ruby -require 'rack-mini-profiler' - -Rack::MiniProfilerRails.initialize!(Rails.application) - -Rails.application.middleware.delete(Rack::MiniProfiler) -Rails.application.middleware.insert_after(Rack::Deflater, Rack::MiniProfiler) -``` - -Deleting the middleware and then reinserting it is a bit inelegant, but -a sufficient and costless solution. It is possible that rack-mini-profiler might -support this scenario more directly if it is found that -there is significant need for this confriguration or that -the above recipe causes problems. - - -## Special query strings - -If you include the query string `pp=help` at the end of your request you will see the various options available. You can use these options to extend or contract the amount of diagnostics rack-mini-profiler gathers. - - -## Rails 2.X support - -To get MiniProfiler working with Rails 2.3.X you need to do the initialization manually as well as monkey patch away an incompatibility between activesupport and json_pure. - -Add the following code to your environment.rb (or just in a specific environment such as development.rb) for initialization and configuration of MiniProfiler. - -```ruby -# configure and initialize MiniProfiler -require 'rack-mini-profiler' -c = ::Rack::MiniProfiler.config -c.pre_authorize_cb = lambda { |env| - Rails.env.development? || Rails.env.production? -} -tmp = Rails.root.to_s + "/tmp/miniprofiler" -FileUtils.mkdir_p(tmp) unless File.exists?(tmp) -c.storage_options = {:path => tmp} -c.storage = ::Rack::MiniProfiler::FileStore -config.middleware.use(::Rack::MiniProfiler) -::Rack::MiniProfiler.profile_method(ActionController::Base, :process) {|action| "Executing action: #{action}"} -::Rack::MiniProfiler.profile_method(ActionView::Template, :render) {|x,y| "Rendering: #{path_without_format_and_extension}"} - -# monkey patch away an activesupport and json_pure incompatability -# http://pivotallabs.com/users/alex/blog/articles/1332-monkey-patch-of-the-day-activesupport-vs-json-pure-vs-ruby-1-8 -if JSON.const_defined?(:Pure) - class JSON::Pure::Generator::State - include ActiveSupport::CoreExtensions::Hash::Except - end -end -``` - -## Running the Specs - -``` -$ rake build -$ rake spec -``` - -Additionally you can also run `autotest` if you like. - -## Licence - -The MIT License (MIT) - -Copyright (c) 2013 Sam Saffron - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/rack-mini-profiler/Rakefile b/lib/rack-mini-profiler/Rakefile deleted file mode 100644 index a908b5b62..000000000 --- a/lib/rack-mini-profiler/Rakefile +++ /dev/null @@ -1,46 +0,0 @@ -# Rakefile -require 'rubygems' -require 'bundler' -Bundler.setup(:default, :test) - -task :default => [:spec] - -require 'rspec/core' -require 'rspec/core/rake_task' -RSpec::Core::RakeTask.new(:spec) do |spec| - spec.pattern = FileList['spec/**/*_spec.rb'] -end - -desc "builds a gem" -task :build => :update_asset_version do - `gem build rack-mini-profiler.gemspec 1>&2` -end - -desc "compile less" -task :compile_less => :copy_files do - `lessc lib/html/includes.less > lib/html/includes.css` -end - -desc "update asset version file" -task :update_asset_version => :compile_less do - require 'digest/md5' - h = [] - Dir.glob('lib/html/*.{js,html,css,tmpl}').each do |f| - h << Digest::MD5.hexdigest(::File.read(f)) - end - File.open('lib/mini_profiler/version.rb','w') do |f| - f.write \ -"module Rack - class MiniProfiler - VERSION = '#{Digest::MD5.hexdigest(h.sort.join(''))}'.freeze - end -end" - end -end - - -desc "copy files from other parts of the tree" -task :copy_files do - # TODO grab files from MiniProfiler/UI -end - diff --git a/lib/rack-mini-profiler/autotest/discover.rb b/lib/rack-mini-profiler/autotest/discover.rb deleted file mode 100644 index de32a0121..000000000 --- a/lib/rack-mini-profiler/autotest/discover.rb +++ /dev/null @@ -1,2 +0,0 @@ -Autotest.add_discovery { "rspec2" } - diff --git a/lib/rack-mini-profiler/lib/html/includes.css b/lib/rack-mini-profiler/lib/html/includes.css deleted file mode 100644 index d96528b8d..000000000 --- a/lib/rack-mini-profiler/lib/html/includes.css +++ /dev/null @@ -1,451 +0,0 @@ -.profiler-result, -.profiler-queries { - color: #555; - line-height: 1; - font-size: 12px; -} -.profiler-result pre, -.profiler-queries pre, -.profiler-result code, -.profiler-queries code, -.profiler-result label, -.profiler-queries label, -.profiler-result table, -.profiler-queries table, -.profiler-result tbody, -.profiler-queries tbody, -.profiler-result thead, -.profiler-queries thead, -.profiler-result tfoot, -.profiler-queries tfoot, -.profiler-result tr, -.profiler-queries tr, -.profiler-result th, -.profiler-queries th, -.profiler-result td, -.profiler-queries td { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; - background-color: transparent; - overflow: visible; - max-height: none; -} -.profiler-result table, -.profiler-queries table { - border-collapse: collapse; - border-spacing: 0; -} -.profiler-result a, -.profiler-queries a, -.profiler-result a:hover, -.profiler-queries a:hover { - cursor: pointer; - color: #0077cc; -} -.profiler-result a, -.profiler-queries a { - text-decoration: none; -} -.profiler-result a:hover, -.profiler-queries a:hover { - text-decoration: underline; -} -.profiler-result { - font-family: Helvetica, Arial, sans-serif; -} -.profiler-result .profiler-toggle-duration-with-children { - float: right; -} -.profiler-result table.profiler-client-timings { - margin-top: 10px; -} -.profiler-result .profiler-label { - color: #555555; - overflow: hidden; - text-overflow: ellipsis; -} -.profiler-result .profiler-unit { - color: #aaaaaa; -} -.profiler-result .profiler-trivial { - display: none; -} -.profiler-result .profiler-trivial td, -.profiler-result .profiler-trivial td * { - color: #aaaaaa !important; -} -.profiler-result pre, -.profiler-result code, -.profiler-result .profiler-number, -.profiler-result .profiler-unit { - font-family: Consolas, monospace, serif; -} -.profiler-result .profiler-number { - color: #111111; -} -.profiler-result .profiler-info { - text-align: right; -} -.profiler-result .profiler-info .profiler-name { - float: left; -} -.profiler-result .profiler-info .profiler-server-time { - white-space: nowrap; -} -.profiler-result .profiler-timings th { - background-color: #fff; - color: #aaaaaa; - text-align: right; -} -.profiler-result .profiler-timings th, -.profiler-result .profiler-timings td { - white-space: nowrap; -} -.profiler-result .profiler-timings .profiler-duration-with-children { - display: none; -} -.profiler-result .profiler-timings .profiler-duration { - font-family: Consolas, monospace, serif; - color: #111111; - text-align: right; -} -.profiler-result .profiler-timings .profiler-indent { - letter-spacing: 4px; -} -.profiler-result .profiler-timings .profiler-queries-show .profiler-number, -.profiler-result .profiler-timings .profiler-queries-show .profiler-unit { - color: #0077cc; -} -.profiler-result .profiler-timings .profiler-queries-duration { - padding-left: 6px; -} -.profiler-result .profiler-timings .profiler-percent-in-sql { - white-space: nowrap; - text-align: right; -} -.profiler-result .profiler-timings tfoot td { - padding-top: 10px; - text-align: right; -} -.profiler-result .profiler-timings tfoot td a { - font-size: 95%; - display: inline-block; - margin-left: 12px; -} -.profiler-result .profiler-timings tfoot td a:first-child { - float: left; - margin-left: 0px; -} -.profiler-result .profiler-timings tfoot td a.profiler-custom-link { - float: left; -} -.profiler-result .profiler-queries { - font-family: Helvetica, Arial, sans-serif; -} -.profiler-result .profiler-queries .profiler-stack-trace { - margin-bottom: 15px; -} -.profiler-result .profiler-queries pre { - font-family: Consolas, monospace, serif; - white-space: pre-wrap; -} -.profiler-result .profiler-queries th { - background-color: #fff; - border-bottom: 1px solid #555; - font-weight: bold; - padding: 15px; - white-space: nowrap; -} -.profiler-result .profiler-queries td { - padding: 15px; - text-align: left; - background-color: #fff; -} -.profiler-result .profiler-queries td:last-child { - padding-right: 25px; -} -.profiler-result .profiler-queries .profiler-odd td { - background-color: #e5e5e5; -} -.profiler-result .profiler-queries .profiler-since-start, -.profiler-result .profiler-queries .profiler-duration { - text-align: right; -} -.profiler-result .profiler-queries .profiler-info div { - text-align: right; - margin-bottom: 5px; -} -.profiler-result .profiler-queries .profiler-gap-info, -.profiler-result .profiler-queries .profiler-gap-info td { - background-color: #ccc; -} -.profiler-result .profiler-queries .profiler-gap-info .profiler-unit { - color: #777; -} -.profiler-result .profiler-queries .profiler-gap-info .profiler-info { - text-align: right; -} -.profiler-result .profiler-queries .profiler-gap-info.profiler-trivial-gaps { - display: none; -} -.profiler-result .profiler-queries .profiler-trivial-gap-container { - text-align: center; -} -.profiler-result .profiler-queries .str { - color: #800000; -} -.profiler-result .profiler-queries .kwd { - color: #00008b; -} -.profiler-result .profiler-queries .com { - color: #808080; -} -.profiler-result .profiler-queries .typ { - color: #2b91af; -} -.profiler-result .profiler-queries .lit { - color: #800000; -} -.profiler-result .profiler-queries .pun { - color: #000000; -} -.profiler-result .profiler-queries .pln { - color: #000000; -} -.profiler-result .profiler-queries .tag { - color: #800000; -} -.profiler-result .profiler-queries .atn { - color: #ff0000; -} -.profiler-result .profiler-queries .atv { - color: #0000ff; -} -.profiler-result .profiler-queries .dec { - color: #800080; -} -.profiler-result .profiler-warning, -.profiler-result .profiler-warning *, -.profiler-result .profiler-warning .profiler-queries-show, -.profiler-result .profiler-warning .profiler-queries-show .profiler-unit { - color: #f00; -} -.profiler-result .profiler-warning:hover, -.profiler-result .profiler-warning *:hover, -.profiler-result .profiler-warning .profiler-queries-show:hover, -.profiler-result .profiler-warning .profiler-queries-show .profiler-unit:hover { - color: #f00; -} -.profiler-result .profiler-nuclear { - color: #f00; - font-weight: bold; - padding-right: 2px; -} -.profiler-result .profiler-nuclear:hover { - color: #f00; -} -.profiler-results { - z-index: 2147483643; - position: fixed; - top: 0px; -} -.profiler-results.profiler-left { - left: 0px; -} -.profiler-results.profiler-left.profiler-no-controls .profiler-result:last-child .profiler-button, -.profiler-results.profiler-left .profiler-controls { - -webkit-border-bottom-right-radius: 10px; - -moz-border-radius-bottomright: 10px; - border-bottom-right-radius: 10px; -} -.profiler-results.profiler-left .profiler-button, -.profiler-results.profiler-left .profiler-controls { - border-right: 1px solid #888888; -} -.profiler-results.profiler-right { - right: 0px; -} -.profiler-results.profiler-right.profiler-no-controls .profiler-result:last-child .profiler-button, -.profiler-results.profiler-right .profiler-controls { - -webkit-border-bottom-left-radius: 10px; - -moz-border-radius-bottomleft: 10px; - border-bottom-left-radius: 10px; -} -.profiler-results.profiler-right .profiler-button, -.profiler-results.profiler-right .profiler-controls { - border-left: 1px solid #888888; -} -.profiler-results .profiler-button, -.profiler-results .profiler-controls { - display: none; - z-index: 2147483640; - border-bottom: 1px solid #888888; - background-color: #fff; - padding: 4px 7px; - text-align: right; - cursor: pointer; -} -.profiler-results .profiler-button.profiler-button-active, -.profiler-results .profiler-controls.profiler-button-active { - background-color: maroon; -} -.profiler-results .profiler-button.profiler-button-active .profiler-number, -.profiler-results .profiler-controls.profiler-button-active .profiler-number, -.profiler-results .profiler-button.profiler-button-active .profiler-nuclear, -.profiler-results .profiler-controls.profiler-button-active .profiler-nuclear { - color: #fff; - font-weight: bold; -} -.profiler-results .profiler-button.profiler-button-active .profiler-unit, -.profiler-results .profiler-controls.profiler-button-active .profiler-unit { - color: #fff; - font-weight: normal; -} -.profiler-results .profiler-controls { - display: block; - font-size: 12px; - font-family: Consolas, monospace, serif; - cursor: default; - text-align: center; -} -.profiler-results .profiler-controls span { - border-right: 1px solid #aaaaaa; - padding-right: 5px; - margin-right: 5px; - cursor: pointer; -} -.profiler-results .profiler-controls span:last-child { - border-right: none; -} -.profiler-results .profiler-popup { - display: none; - z-index: 2147483641; - position: absolute; - background-color: #fff; - border: 1px solid #aaa; - padding: 5px 10px; - text-align: left; - line-height: 18px; - overflow: auto; - -moz-box-shadow: 0px 1px 15px #555555; - -webkit-box-shadow: 0px 1px 15px #555555; - box-shadow: 0px 1px 15px #555555; -} -.profiler-results .profiler-popup .profiler-info { - margin-bottom: 3px; - padding-bottom: 2px; - border-bottom: 1px solid #ddd; -} -.profiler-results .profiler-popup .profiler-info .profiler-name { - font-size: 110%; - font-weight: bold; -} -.profiler-results .profiler-popup .profiler-info .profiler-name .profiler-overall-duration { - display: none; -} -.profiler-results .profiler-popup .profiler-info .profiler-server-time { - font-size: 95%; -} -.profiler-results .profiler-popup .profiler-timings th, -.profiler-results .profiler-popup .profiler-timings td { - padding-left: 6px; - padding-right: 6px; -} -.profiler-results .profiler-popup .profiler-timings th { - font-size: 95%; - padding-bottom: 3px; -} -.profiler-results .profiler-popup .profiler-timings .profiler-label { - max-width: 275px; -} -.profiler-results .profiler-queries { - display: none; - z-index: 2147483643; - position: absolute; - overflow-y: auto; - overflow-x: auto; - background-color: #fff; -} -.profiler-results .profiler-queries th { - font-size: 17px; -} -.profiler-results.profiler-min .profiler-result { - display: none; -} -.profiler-results.profiler-min .profiler-controls span { - display: none; -} -.profiler-results.profiler-min .profiler-controls .profiler-min-max { - border-right: none; - padding: 0px; - margin: 0px; -} -.profiler-queries-bg { - z-index: 2147483642; - display: none; - background: #000; - opacity: 0.7; - position: absolute; - top: 0px; - left: 0px; - min-width: 100%; -} -.profiler-result-full .profiler-result { - width: 950px; - margin: 30px auto; -} -.profiler-result-full .profiler-result .profiler-button { - display: none; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-info { - font-size: 25px; - border-bottom: 1px solid #aaaaaa; - padding-bottom: 3px; - margin-bottom: 25px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-info .profiler-overall-duration { - padding-right: 20px; - font-size: 80%; - color: #888; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td, -.profiler-result-full .profiler-result .profiler-popup .profiler-timings th { - padding-left: 8px; - padding-right: 8px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings th { - padding-bottom: 7px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td { - font-size: 14px; - padding-bottom: 4px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings td:first-child { - padding-left: 10px; -} -.profiler-result-full .profiler-result .profiler-popup .profiler-timings .profiler-label { - max-width: 550px; -} -.profiler-result-full .profiler-result .profiler-queries { - margin: 25px 0; -} -.profiler-result-full .profiler-result .profiler-queries table { - width: 100%; -} -.profiler-result-full .profiler-result .profiler-queries th { - font-size: 16px; - color: #555; - line-height: 20px; -} -.profiler-result-full .profiler-result .profiler-queries td { - padding: 15px 10px; - text-align: left; -} -.profiler-result-full .profiler-result .profiler-queries .profiler-info div { - text-align: right; - margin-bottom: 5px; -} diff --git a/lib/rack-mini-profiler/lib/html/includes.js b/lib/rack-mini-profiler/lib/html/includes.js deleted file mode 100644 index d8b4de083..000000000 --- a/lib/rack-mini-profiler/lib/html/includes.js +++ /dev/null @@ -1,960 +0,0 @@ -"use strict"; -var MiniProfiler = (function () { - var $; - - var options, - container, - controls, - fetchedIds = [], - fetchingIds = [], // so we never pull down a profiler twice - ajaxStartTime - ; - - var hasLocalStorage = function () { - try { - return 'localStorage' in window && window['localStorage'] !== null; - } catch (e) { - return false; - } - }; - - var getVersionedKey = function (keyPrefix) { - return keyPrefix + '-' + options.version; - }; - - var save = function (keyPrefix, value) { - if (!hasLocalStorage()) { return; } - - // clear old keys with this prefix, if any - for (var i = 0; i < localStorage.length; i++) { - if ((localStorage.key(i) || '').indexOf(keyPrefix) > -1) { - localStorage.removeItem(localStorage.key(i)); - } - } - - // save under this version - localStorage[getVersionedKey(keyPrefix)] = value; - }; - - var load = function (keyPrefix) { - if (!hasLocalStorage()) { return null; } - - return localStorage[getVersionedKey(keyPrefix)]; - }; - - var fetchTemplates = function (success) { - var key = 'templates', - cached = load(key); - - if (cached) { - $('body').append(cached); - success(); - } - else { - $.get(options.path + 'includes.tmpl?v=' + options.version, function (data) { - if (data) { - save(key, data); - $('body').append(data); - success(); - } - }); - } - }; - - var getClientPerformance = function() { - return window.performance == null ? null : window.performance; - }; - - var fetchResults = function (ids) { - var clientPerformance, clientProbes, i, j, p, id, idx; - - for (i = 0; i < ids.length; i++) { - id = ids[i]; - - clientPerformance = null; - clientProbes = null; - - if (window.mPt) { - clientProbes = mPt.results(); - for (j = 0; j < clientProbes.length; j++) { - clientProbes[j].d = clientProbes[j].d.getTime(); - } - mPt.flush(); - } - - if (id == options.currentId) { - - clientPerformance = getClientPerformance(); - - if (clientPerformance != null) { - // ie is buggy strip out functions - var copy = { navigation: {}, timing: {} }; - - var timing = $.extend({}, clientPerformance.timing); - - for (p in timing) { - if (timing.hasOwnProperty(p) && !$.isFunction(timing[p])) { - copy.timing[p] = timing[p]; - } - } - if (clientPerformance.navigation) { - copy.navigation.redirectCount = clientPerformance.navigation.redirectCount; - } - clientPerformance = copy; - - // hack to add chrome timings - if (window.chrome && window.chrome.loadTimes) { - var chromeTimes = window.chrome.loadTimes(); - if (chromeTimes.firstPaintTime) { - clientPerformance.timing["First Paint Time"] = Math.round(chromeTimes.firstPaintTime * 1000); - } - if (chromeTimes.firstPaintTime) { - clientPerformance.timing["First Paint After Load Time"] = Math.round(chromeTimes.firstPaintAfterLoadTime * 1000); - } - - } - } - } else if (ajaxStartTime != null && clientProbes && clientProbes.length > 0) { - clientPerformance = { timing: { navigationStart: ajaxStartTime.getTime() } }; - ajaxStartTime = null; - } - - if ($.inArray(id, fetchedIds) < 0 && $.inArray(id, fetchingIds) < 0) { - idx = fetchingIds.push(id) - 1; - - $.ajax({ - url: options.path + 'results', - data: { id: id, clientPerformance: clientPerformance, clientProbes: clientProbes, popup: 1 }, - dataType: 'json', - global: false, - type: 'POST', - success: function (json) { - fetchedIds.push(id); - if (json != "hidden") { - buttonShow(json); - } - }, - complete: function () { - fetchingIds.splice(idx, 1); - } - }); - } - } - }; - - var renderTemplate = function (json) { - return $('#profilerTemplate').tmpl(json); - }; - - var buttonShow = function (json) { - var result = renderTemplate(json); - - if (controls) - result.insertBefore(controls); - else - result.appendTo(container); - - var button = result.find('.profiler-button'), - popup = result.find('.profiler-popup'); - - // button will appear in corner with the total profiling duration - click to show details - button.click(function () { buttonClick(button, popup); }); - - // small duration steps and the column with aggregate durations are hidden by default; allow toggling - toggleHidden(popup); - - // lightbox in the queries - popup.find('.profiler-queries-show').click(function () { queriesShow($(this), result); }); - - // limit count - if (container.find('.profiler-result').length > options.maxTracesToShow) - container.find('.profiler-result').first().remove(); - button.show(); - }; - - var toggleHidden = function (popup) { - var trivial = popup.find('.profiler-toggle-trivial'); - var childrenTime = popup.find('.profiler-toggle-duration-with-children'); - var trivialGaps = popup.parent().find('.profiler-toggle-trivial-gaps'); - - var toggleIt = function (node) { - var link = $(node), - klass = "profiler-" + link.attr('class').substr('profiler-toggle-'.length), - isHidden = link.text().indexOf('show') > -1; - - popup.parent().find('.' + klass).toggle(isHidden); - link.text(link.text().replace(isHidden ? 'show' : 'hide', isHidden ? 'hide' : 'show')); - - popupPreventHorizontalScroll(popup); - }; - - childrenTime.add(trivial).add(trivialGaps).click(function () { - toggleIt(this); - }); - - // if option is set or all our timings are trivial, go ahead and show them - if (options.showTrivial || trivial.data('show-on-load')) { - toggleIt(trivial); - } - // if option is set, go ahead and show time with children - if (options.showChildrenTime) { - toggleIt(childrenTime); - } - }; - - var buttonClick = function (button, popup) { - // we're toggling this button/popup - if (popup.is(':visible')) { - popupHide(button, popup); - } - else { - var visiblePopups = container.find('.profiler-popup:visible'), - theirButtons = visiblePopups.siblings('.profiler-button'); - - // hide any other popups - popupHide(theirButtons, visiblePopups); - - // before showing the one we clicked - popupShow(button, popup); - } - }; - - var popupShow = function (button, popup) { - button.addClass('profiler-button-active'); - - popupSetDimensions(button, popup); - - popup.show(); - - popupPreventHorizontalScroll(popup); - }; - - var popupSetDimensions = function (button, popup) { - var top = button.position().top - 1, // position next to the button we clicked - windowHeight = $(window).height(), - maxHeight = windowHeight - top - 40; // make sure the popup doesn't extend below the fold - - popup - .css({ 'top': top, 'max-height': maxHeight }) - .css(options.renderPosition, button.outerWidth() - 3); // move left or right, based on config - }; - - var popupPreventHorizontalScroll = function (popup) { - var childrenHeight = 0; - - popup.children().each(function () { childrenHeight += $(this).height(); }); - - popup.css({ 'padding-right': childrenHeight > popup.height() ? 40 : 10 }); - }; - - var popupHide = function (button, popup) { - button.removeClass('profiler-button-active'); - popup.hide(); - }; - - var queriesShow = function (link, result) { - - var px = 30, - win = $(window), - width = win.width() - 2 * px, - height = win.height() - 2 * px, - queries = result.find('.profiler-queries'); - - // opaque background - $('
    ').appendTo('body').css({ 'height': $(document).height() }).show(); - - // center the queries and ensure long content is scrolled - queries.css({ 'top': px, 'max-height': height, 'width': width }).css(options.renderPosition, px) - .find('table').css({ 'width': width }); - - // have to show everything before we can get a position for the first query - queries.show(); - - queriesScrollIntoView(link, queries, queries); - - // syntax highlighting - prettyPrint(); - }; - - var queriesScrollIntoView = function (link, queries, whatToScroll) { - var id = link.closest('tr').attr('data-timing-id'), - cells = queries.find('tr[data-timing-id="' + id + '"] td'); - - // ensure they're in view - whatToScroll.scrollTop(whatToScroll.scrollTop() + cells.first().position().top - 100); - - // highlight and then fade back to original bg color; do it ourselves to prevent any conflicts w/ jquery.UI or other implementations of Resig's color plugin - cells.each(function () { - var cell = $(this), - highlightHex = '#FFFFBB', - highlightRgb = getRGB(highlightHex), - originalRgb = getRGB(cell.css('background-color')), - getColorDiff = function (fx, i) { - // adapted from John Resig's color plugin: http://plugins.jquery.com/project/color - return Math.max(Math.min(parseInt((fx.pos * (originalRgb[i] - highlightRgb[i])) + highlightRgb[i], 10), 255), 0); - }; - - // we need to animate some other property to piggy-back on the step function, so I choose you, opacity! - cell.css({ 'opacity': 1, 'background-color': highlightHex }) - .animate({ 'opacity': 1 }, { duration: 2000, step: function (now, fx) { - fx.elem.style.backgroundColor = "rgb(" + [getColorDiff(fx, 0), getColorDiff(fx, 1), getColorDiff(fx, 2)].join(",") + ")"; - } - }); - }); - }; - - // Color Conversion functions from highlightFade - // By Blair Mitchelmore - // http://jquery.offput.ca/highlightFade/ - // Parse strings looking for color tuples [255,255,255] - var getRGB = function (color) { - var result; - - // Check if we're already dealing with an array of colors - if (color && color.constructor == Array && color.length == 3) return color; - - // Look for rgb(num,num,num) - if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])]; - - // Look for rgb(num%,num%,num%) - if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55, parseFloat(result[3]) * 2.55]; - - // Look for #a0b1c2 - if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]; - - // Look for #fff - if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16), parseInt(result[3] + result[3], 16)]; - - // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 - if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) return colors['transparent']; - - return null; - }; - - var bindDocumentEvents = function () { - $(document).bind('click keyup', function (e) { - - // this happens on every keystroke, and :visible is crazy expensive in IE <9 - // and in this case, the display:none check is sufficient. - var popup = $('.profiler-popup').filter(function () { return $(this).css("display") !== "none"; }); - - if (!popup.length) { - return; - } - - var button = popup.siblings('.profiler-button'), - queries = popup.closest('.profiler-result').find('.profiler-queries'), - bg = $('.profiler-queries-bg'), - isEscPress = e.type == 'keyup' && e.which == 27, - hidePopup = false, - hideQueries = false; - - if (bg.is(':visible')) { - hideQueries = isEscPress || (e.type == 'click' && !$.contains(queries[0], e.target) && !$.contains(popup[0], e.target)); - } - else if (popup.is(':visible')) { - hidePopup = isEscPress || (e.type == 'click' && !$.contains(popup[0], e.target) && !$.contains(button[0], e.target) && button[0] != e.target); - } - - if (hideQueries) { - bg.remove(); - queries.hide(); - } - - if (hidePopup) { - popupHide(button, popup); - } - }); - $(document).bind('keydown', options.toggleShortcut, function(e) { - $('.profiler-results').toggle(); - }); - }; - - var initFullView = function () { - - // first, get jquery tmpl, then render and bind handlers - fetchTemplates(function () { - - // profiler will be defined in the full page's head - renderTemplate(profiler).appendTo(container); - - var popup = $('.profiler-popup'); - - toggleHidden(popup); - - prettyPrint(); - - // since queries are already shown, just highlight and scroll when clicking a "1 sql" link - popup.find('.profiler-queries-show').click(function () { - queriesScrollIntoView($(this), $('.profiler-queries'), $(document)); - }); - }); - }; - - var initControls = function (container) { - if (options.showControls) { - controls = $('
    mc
    ').appendTo(container); - - $('.profiler-controls .profiler-min-max').click(function () { - container.toggleClass('profiler-min'); - }); - - container.hover(function () { - if ($(this).hasClass('profiler-min')) { - $(this).find('.profiler-min-max').show(); - } - }, - function () { - if ($(this).hasClass('profiler-min')) { - $(this).find('.profiler-min-max').hide(); - } - }); - - $('.profiler-controls .profiler-clear').click(function () { - container.find('.profiler-result').remove(); - }); - } - else { - container.addClass('profiler-no-controls'); - } - }; - - var initPopupView = function () { - - if (options.authorized) { - // all fetched profilings will go in here - container = $('
    ').appendTo('body'); - - // MiniProfiler.RenderIncludes() sets which corner to render in - default is upper left - container.addClass("profiler-" + options.renderPosition); - - //initialize the controls - initControls(container); - - // we'll render results json via a jquery.tmpl - after we get the templates, we'll fetch the initial json to populate it - fetchTemplates(function () { - // get master page profiler results - fetchResults(options.ids); - }); - if (options.startHidden) container.hide(); - } - else { - fetchResults(options.ids); - } - - var jQueryAjaxComplete = function (e, xhr, settings) { - if (xhr) { - // should be an array of strings, e.g. ["008c4813-9bd7-443d-9376-9441ec4d6a8c","16ff377b-8b9c-4c20-a7b5-97cd9fa7eea7"] - var stringIds = xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - }; - - // fetch profile results for any ajax calls - // note, this does not use $ cause we want to hook into the main jQuery - if (jQuery && jQuery(document) && jQuery(document).ajaxComplete) { - jQuery(document).ajaxComplete(jQueryAjaxComplete); - } - - if (jQuery && jQuery(document).ajaxStart) - jQuery(document).ajaxStart(function () { ajaxStartTime = new Date(); }); - - // fetch results after ASP Ajax calls - if (typeof (Sys) != 'undefined' && typeof (Sys.WebForms) != 'undefined' && typeof (Sys.WebForms.PageRequestManager) != 'undefined') { - // Get the instance of PageRequestManager. - var PageRequestManager = Sys.WebForms.PageRequestManager.getInstance(); - - PageRequestManager.add_endRequest(function (sender, args) { - if (args) { - var response = args.get_response(); - if (response.get_responseAvailable() && response._xmlHttpRequest != null) { - var stringIds = args.get_response().getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - } - }); - } - - // more Asp.Net callbacks - if (typeof (WebForm_ExecuteCallback) == "function") { - WebForm_ExecuteCallback = (function (callbackObject) { - // Store original function - var original = WebForm_ExecuteCallback; - - return function (callbackObject) { - original(callbackObject); - - var stringIds = callbackObject.xmlRequest.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - }; - - })(); - } - - // also fetch results after ExtJS requests, in case it is being used - if (typeof (Ext) != 'undefined' && typeof (Ext.Ajax) != 'undefined' && typeof (Ext.Ajax.on) != 'undefined') { - // Ext.Ajax is a singleton, so we just have to attach to its 'requestcomplete' event - Ext.Ajax.on('requestcomplete', function (e, xhr, settings) { - //iframed file uploads don't have headers - if (!xhr || !xhr.getResponseHeader) { - return; - } - - var stringIds = xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - }); - } - - if (typeof (MooTools) != 'undefined' && typeof (Request) != 'undefined') { - Request.prototype.addEvents({ - onComplete: function() { - var stringIds = this.xhr.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - }); - } - - // add support for AngularJS, which use the basic XMLHttpRequest object. - if (window.angular && typeof (XMLHttpRequest) != 'undefined') { - var _send = XMLHttpRequest.prototype.send; - - XMLHttpRequest.prototype.send = function sendReplacement(data) { - this._onreadystatechange = this.onreadystatechange; - - this.onreadystatechange = function onReadyStateChangeReplacement() { - if (this.readyState == 4) { - var stringIds = this.getResponseHeader('X-MiniProfiler-Ids'); - if (stringIds) { - var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds); - fetchResults(ids); - } - } - - return this._onreadystatechange.apply(this, arguments); - }; - - return _send.apply(this, arguments); - }; - } - - // some elements want to be hidden on certain doc events - bindDocumentEvents(); - }; - - return { - - init: function () { - var script = document.getElementById('mini-profiler'); - if (!script || !script.getAttribute) return; - - options = (function () { - var version = script.getAttribute('data-version'); - var path = script.getAttribute('data-path'); - - var currentId = script.getAttribute('data-current-id'); - - var ids = script.getAttribute('data-ids'); - if (ids) ids = ids.split(','); - - var position = script.getAttribute('data-position'); - - var toggleShortcut = script.getAttribute('data-toggle-shortcut'); - - if (script.getAttribute('data-max-traces')) { - var maxTraces = parseInt(script.getAttribute('data-max-traces'), 10); - } - - if (script.getAttribute('data-trivial') === 'true') var trivial = true; - if (script.getAttribute('data-children') == 'true') var children = true; - if (script.getAttribute('data-controls') == 'true') var controls = true; - if (script.getAttribute('data-authorized') == 'true') var authorized = true; - if (script.getAttribute('data-start-hidden') == 'true') var startHidden = true; - - return { - ids: ids, - path: path, - version: version, - renderPosition: position, - showTrivial: trivial, - showChildrenTime: children, - maxTracesToShow: maxTraces, - showControls: controls, - currentId: currentId, - authorized: authorized, - toggleShortcut: toggleShortcut, - startHidden: startHidden - }; - })(); - - var doInit = function () { - // when rendering a shared, full page, this div will exist - container = $('.profiler-result-full'); - if (container.length) { - if (window.location.href.indexOf("&trivial=1") > 0) { - options.showTrivial = true; - } - initFullView(); - } - else { - initPopupView(); - } - }; - - // this preserves debugging - var load = function (s, f) { - var sc = document.createElement("script"); - sc.async = "async"; - sc.type = "text/javascript"; - sc.src = s; - var done = false; - sc.onload = sc.onreadystatechange = function (_, abort) { - if (!sc.readyState || /loaded|complete/.test(sc.readyState)) { - if (!abort && !done) { done = true; f(); } - } - }; - document.getElementsByTagName('head')[0].appendChild(sc); - }; - - var wait = 0; - var finish = false; - var deferInit = function() { - if (finish) return; - if (window.performance && window.performance.timing && window.performance.timing.loadEventEnd === 0 && wait < 10000) { - setTimeout(deferInit, 100); - wait += 100; - } else { - finish = true; - init(); - } - }; - - var init = function() { - if (options.authorized) { - var url = options.path + "includes.css?v=" + options.version; - if (document.createStyleSheet) { - document.createStyleSheet(url); - } else { - $('head').append($('')); - } - if (!$.tmpl) { - load(options.path + 'jquery.tmpl.js?v=' + options.version, doInit); - } else { - doInit(); - } - } else { - doInit(); - } - - // jquery.hotkeys.js - // https://github.com/jeresig/jquery.hotkeys/blob/master/jquery.hotkeys.js - - (function(d){function h(g){if("string"===typeof g.data){var h=g.handler,j=g.data.toLowerCase().split(" ");g.handler=function(b){if(!(this!==b.target&&(/textarea|select/i.test(b.target.nodeName)||"text"===b.target.type))){var c="keypress"!==b.type&&d.hotkeys.specialKeys[b.which],e=String.fromCharCode(b.which).toLowerCase(),a="",f={};b.altKey&&"alt"!==c&&(a+="alt+");b.ctrlKey&&"ctrl"!==c&&(a+="ctrl+");b.metaKey&&(!b.ctrlKey&&"meta"!==c)&&(a+="meta+");b.shiftKey&&"shift"!==c&&(a+="shift+");c?f[a+c]= - !0:(f[a+e]=!0,f[a+d.hotkeys.shiftNums[e]]=!0,"shift+"===a&&(f[d.hotkeys.shiftNums[e]]=!0));c=0;for(e=j.length;c","/":"?","\\":"|"}};d.each(["keydown","keyup","keypress"],function(){d.event.special[this]={add:h}})})(MiniProfiler.jQuery); - - }; - - var major, minor; - if (typeof(jQuery) == 'function') { - var jQueryVersion = jQuery.fn.jquery.split('.'); - major = parseInt(jQueryVersion[0], 10); - minor = parseInt(jQueryVersion[1], 10); - } - - - if (major === 2 || (major === 1 && minor >= 7)) { - MiniProfiler.jQuery = $ = jQuery; - $(deferInit); - } else { - load(options.path + "jquery.1.7.1.js?v=" + options.version, function() { - MiniProfiler.jQuery = $ = jQuery.noConflict(true); - $(deferInit); - }); - } - }, - - getClientTimingByName: function (clientTiming, name) { - - for (var i = 0; i < clientTiming.Timings.length; i++) { - if (clientTiming.Timings[i].Name == name) { - return clientTiming.Timings[i]; - } - } - return { Name: name, Duration: "", Start: "" }; - }, - - renderDate: function (jsonDate) { // JavaScriptSerializer sends dates as /Date(1308024322065)/ - if (jsonDate) { - return (typeof jsonDate === 'string') ? new Date(parseInt(jsonDate.replace("/Date(", "").replace(")/", ""), 10)).toUTCString() : jsonDate; - } - }, - - renderIndent: function (depth) { - var result = ''; - for (var i = 0; i < depth; i++) { - result += ' '; - } - return result; - }, - - renderExecuteType: function (typeId) { - // see StackExchange.Profiling.ExecuteType enum - switch (typeId) { - case 0: return 'None'; - case 1: return 'NonQuery'; - case 2: return 'Scalar'; - case 3: return 'Reader'; - } - }, - - shareUrl: function (id) { - return options.path + 'results?id=' + id; - }, - - getClientTimings: function (clientTimings) { - var list = []; - var t; - - if (!clientTimings.Timings) return []; - - for (var i = 0; i < clientTimings.Timings.length; i++) { - t = clientTimings.Timings[i]; - var trivial = t.Name != "Dom Complete" && t.Name != "Response" && t.Name != "First Paint Time"; - trivial = t.Duration < 2 ? trivial : false; - list.push( - { - isTrivial: trivial, - name: t.Name, - duration: t.Duration, - start: t.Start - }); - } - - list.sort(function (a, b) { return a.start - b.start; }); - return list; - }, - - getSqlTimings: function (root) { - var result = [], - addToResults = function (timing) { - if (timing.SqlTimings) { - for (var i = 0, sqlTiming; i < timing.SqlTimings.length; i++) { - sqlTiming = timing.SqlTimings[i]; - - // HACK: add info about the parent Timing to each SqlTiming so UI can render - sqlTiming.ParentTimingName = timing.Name; - result.push(sqlTiming); - } - } - - if (timing.Children) { - for (var i = 0; i < timing.Children.length; i++) { - addToResults(timing.Children[i]); - } - } - }; - - // start adding at the root and recurse down - addToResults(root); - - var removeDuration = function(list, duration) { - - var newList = []; - for (var i = 0; i < list.length; i++) { - - var item = list[i]; - if (duration.start > item.start) { - if (duration.start > item.finish) { - newList.push(item); - continue; - } - newList.push({ start: item.start, finish: duration.start }); - } - - if (duration.finish < item.finish) { - if (duration.finish < item.start) { - newList.push(item); - continue; - } - newList.push({ start: duration.finish, finish: item.finish }); - } - } - - return newList; - }; - - var processTimes = function (elem, parent) { - var duration = { start: elem.StartMilliseconds, finish: (elem.StartMilliseconds + elem.DurationMilliseconds) }; - elem.richTiming = [duration]; - if (parent != null) { - elem.parent = parent; - elem.parent.richTiming = removeDuration(elem.parent.richTiming, duration); - } - - if (elem.Children) { - for (var i = 0; i < elem.Children.length; i++) { - processTimes(elem.Children[i], elem); - } - } - }; - - processTimes(root, null); - - // sort results by time - result.sort(function (a, b) { return a.StartMilliseconds - b.StartMilliseconds; }); - - var determineOverlap = function(gap, node) { - var overlap = 0; - for (var i = 0; i < node.richTiming.length; i++) { - var current = node.richTiming[i]; - if (current.start > gap.finish) { - break; - } - if (current.finish < gap.start) { - continue; - } - - overlap += Math.min(gap.finish, current.finish) - Math.max(gap.start, current.start); - } - return overlap; - }; - - var determineGap = function (gap, node, match) { - var overlap = determineOverlap(gap, node); - if (match == null || overlap > match.duration) { - match = { name: node.Name, duration: overlap }; - } - else if (match.name == node.Name) { - match.duration += overlap; - } - - if (node.Children) { - for (var i = 0; i < node.Children.length; i++) { - match = determineGap(gap, node.Children[i], match); - } - } - return match; - }; - - var time = 0; - var prev = null; - $.each(result, function () { - this.prevGap = { - duration: (this.StartMilliseconds - time).toFixed(2), - start: time, - finish: this.StartMilliseconds - }; - - this.prevGap.topReason = determineGap(this.prevGap, root, null); - - time = this.StartMilliseconds + this.DurationMilliseconds; - prev = this; - }); - - - if (result.length > 0) { - var me = result[result.length - 1]; - me.nextGap = { - duration: (root.DurationMilliseconds - time).toFixed(2), - start: time, - finish: root.DurationMilliseconds - }; - me.nextGap.topReason = determineGap(me.nextGap, root, null); - } - - return result; - }, - - getSqlTimingsCount: function (root) { - var result = 0, - countSql = function (timing) { - if (timing.SqlTimings) { - result += timing.SqlTimings.length; - } - - if (timing.Children) { - for (var i = 0; i < timing.Children.length; i++) { - countSql(timing.Children[i]); - } - } - }; - countSql(root); - return result; - }, - - fetchResultsExposed: function (ids) { - return fetchResults(ids); - }, - - formatDuration: function (duration) { - return (duration || 0).toFixed(1); - } - }; -})(); - -MiniProfiler.init(); - -if (typeof prettyPrint === "undefined") { - - // prettify.js - // http://code.google.com/p/google-code-prettify/ - - window.PR_SHOULD_USE_CONTINUATION=true;window.PR_TAB_WIDTH=8;window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void 0;window._pr_isIE6=function(){var y=navigator&&navigator.userAgent&&navigator.userAgent.match(/\bMSIE ([678])\./);y=y?+y[1]:false;window._pr_isIE6=function(){return y};return y}; - (function(){function y(b){return b.replace(L,"&").replace(M,"<").replace(N,">")}function H(b,f,i){switch(b.nodeType){case 1:var o=b.tagName.toLowerCase();f.push("<",o);var l=b.attributes,n=l.length;if(n){if(i){for(var r=[],j=n;--j>=0;)r[j]=l[j];r.sort(function(q,m){return q.name"); - for(l=b.firstChild;l;l=l.nextSibling)H(l,f,i);if(b.firstChild||!/^(?:br|link|img)$/.test(o))f.push("");break;case 3:case 4:f.push(y(b.nodeValue));break}}function O(b){function f(c){if(c.charAt(0)!=="\\")return c.charCodeAt(0);switch(c.charAt(1)){case "b":return 8;case "t":return 9;case "n":return 10;case "v":return 11;case "f":return 12;case "r":return 13;case "u":case "x":return parseInt(c.substring(2),16)||c.charCodeAt(1);case "0":case "1":case "2":case "3":case "4":case "5":case "6":case "7":return parseInt(c.substring(1), - 8);default:return c.charCodeAt(1)}}function i(c){if(c<32)return(c<16?"\\x0":"\\x")+c.toString(16);c=String.fromCharCode(c);if(c==="\\"||c==="-"||c==="["||c==="]")c="\\"+c;return c}function o(c){var d=c.substring(1,c.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));c=[];for(var a=[],k=d[0]==="^",e=k?1:0,h=d.length;e122)){s<65||g>90||a.push([Math.max(65,g)|32,Math.min(s,90)|32]);s<97||g>122||a.push([Math.max(97,g)&-33,Math.min(s,122)&-33])}}a.sort(function(v,w){return v[0]-w[0]||w[1]-v[1]});d=[];g=[NaN,NaN];for(e=0;eh[0]){h[1]+1>h[0]&&a.push("-"); - a.push(i(h[1]))}}a.push("]");return a.join("")}function l(c){for(var d=c.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),a=d.length,k=[],e=0,h=0;e=2&&c==="[")d[e]=o(g);else if(c!=="\\")d[e]=g.replace(/[a-zA-Z]/g,function(s){s=s.charCodeAt(0);return"["+String.fromCharCode(s&-33,s|32)+"]"})}return d.join("")}for(var n=0,r=false,j=false,q=0,m=b.length;q=0;l-=16)o.push(" ".substring(0,l));l=n+1;break;case "\n":f=0;break;default:++f}if(!o)return i;o.push(i.substring(l));return o.join("")}}function I(b, - f,i,o){if(f){b={source:f,c:b};i(b);o.push.apply(o,b.d)}}function B(b,f){var i={},o;(function(){for(var r=b.concat(f),j=[],q={},m=0,t=r.length;m=0;)i[c.charAt(d)]=p;p=p[1];c=""+p;if(!q.hasOwnProperty(c)){j.push(p);q[c]=null}}j.push(/[\0-\uffff]/);o=O(j)})();var l=f.length;function n(r){for(var j=r.c,q=[j,z],m=0,t=r.source.match(o)||[],p={},c=0,d=t.length;c=5&&"lang-"===k.substring(0,5))&&!(e&&typeof e[1]==="string")){h=false;k=P}h||(p[a]=k)}g=m;m+=a.length;if(h){h=e[1];var s=a.indexOf(h),v=s+h.length;if(e[2]){v=a.length-e[2].length;s=v-h.length}k=k.substring(5);I(j+g,a.substring(0,s),n,q);I(j+g+s,h,Q(k,h),q);I(j+g+v,a.substring(v),n,q)}else q.push(j+g,k)}r.d=q}return n}function x(b){var f=[],i=[];if(b.tripleQuotedStrings)f.push([A,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, - null,"'\""]);else b.multiLineStrings?f.push([A,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):f.push([A,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);b.verbatimStrings&&i.push([A,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);if(b.hashComments)if(b.cStyleComments){f.push([C,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]);i.push([A,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/, - null])}else f.push([C,/^#[^\r\n]*/,null,"#"]);if(b.cStyleComments){i.push([C,/^\/\/[^\r\n]*/,null]);i.push([C,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}b.regexLiterals&&i.push(["lang-regex",RegExp("^"+Z+"(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)")]);b=b.keywords.replace(/^\s+|\s+$/g,"");b.length&&i.push([R,RegExp("^(?:"+b.replace(/\s+/g,"|")+")\\b"),null]);f.push([z,/^\s+/,null," \r\n\t\u00a0"]);i.push([J,/^@[a-z_$][a-z_$@0-9]*/i,null],[S,/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/, - null],[z,/^[a-z_$][a-z_$@0-9]*/i,null],[J,/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],[E,/^.[^\s\w\.$@\'\"\`\/\#]*/,null]);return B(f,i)}function $(b){function f(D){if(D>r){if(j&&j!==q){n.push("");j=null}if(!j&&q){j=q;n.push('')}var T=y(p(i.substring(r,D))).replace(e?d:c,"$1 ");e=k.test(T);n.push(T.replace(a,s));r=D}}var i=b.source,o=b.g,l=b.d,n=[],r=0,j=null,q=null,m=0,t=0,p=Y(window.PR_TAB_WIDTH),c=/([\r\n ]) /g, - d=/(^| ) /gm,a=/\r\n?|\n/g,k=/[ \r\n]$/,e=true,h=window._pr_isIE6();h=h?b.b.tagName==="PRE"?h===6?" \r\n":h===7?" 
    \r":" \r":" 
    ":"
    ";var g=b.b.className.match(/\blinenums\b(?::(\d+))?/),s;if(g){for(var v=[],w=0;w<10;++w)v[w]=h+'
  • ';var F=g[1]&&g[1].length?g[1]-1:0;n.push('
    1. ");s=function(){var D=v[++F%10];return j?""+D+'':D}}else s=h; - for(;;)if(m");j=null}n.push(o[m+1]);m+=2}else if(t");g&&n.push("
    ");b.a=n.join("")}function u(b,f){for(var i=f.length;--i>=0;){var o=f[i];if(G.hasOwnProperty(o))"console"in window&&console.warn("cannot override language handler %s",o);else G[o]=b}}function Q(b,f){b&&G.hasOwnProperty(b)||(b=/^\s*1&&m.charAt(0)==="<"){if(!ba.test(m))if(ca.test(m)){f.push(m.substring(9,m.length-3));n+=m.length-12}else if(da.test(m)){f.push("\n");++n}else if(m.indexOf(V)>=0&&m.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)){var t=m.match(W)[2],p=1,c;c=j+1;a:for(;c=0;){var e=p.indexOf(";",k);if(e>=0){var h=p.substring(k+3,e),g=10;if(h&&h.charAt(0)==="x"){h=h.substring(1);g=16}var s=parseInt(h,g);isNaN(s)||(p=p.substring(0,k)+String.fromCharCode(s)+p.substring(e+1))}}a=p.replace(ea,"<").replace(fa,">").replace(ga,"'").replace(ha,'"').replace(ia," ").replace(ja, - "&")}f.push(a);n+=a.length}}o={source:f.join(""),h:r};var v=o.source;b.source=v;b.c=0;b.g=o.h;Q(i,v)(b);$(b)}catch(w){if("console"in window)console.log(w&&w.stack?w.stack:w)}}var A="str",R="kwd",C="com",S="typ",J="lit",E="pun",z="pln",P="src",V="nocode",Z=function(){for(var b=["!","!=","!==","#","%","%=","&","&&","&&=","&=","(","*","*=","+=",",","-=","->","/","/=",":","::",";","<","<<","<<=","<=","=","==","===",">",">=",">>",">>=",">>>",">>>=","?","@","[","^","^=","^^","^^=","{","|","|=","||","||=", - "~","break","case","continue","delete","do","else","finally","instanceof","return","throw","try","typeof"],f="(?:^^|[+-]",i=0;i:&a-z])/g,"\\$1");f+=")\\s*";return f}(),L=/&/g,M=//g,X=/\"/g,ea=/</g,fa=/>/g,ga=/'/g,ha=/"/g,ja=/&/g,ia=/ /g,ka=/[\r\n]/g,K=null,aa=RegExp("[^<]+| + + + + + + +
    + + + \ No newline at end of file diff --git a/public/assets/kindeditor/plugins/baidumap/map.html b/public/assets/kindeditor/plugins/baidumap/map.html new file mode 100644 index 000000000..b65ea1d6b --- /dev/null +++ b/public/assets/kindeditor/plugins/baidumap/map.html @@ -0,0 +1,43 @@ + + + + + Baidu Maps + + + + + +
    + + diff --git a/public/assets/kindeditor/plugins/clearhtml/clearhtml.js b/public/assets/kindeditor/plugins/clearhtml/clearhtml.js new file mode 100644 index 000000000..1bf0e5dca --- /dev/null +++ b/public/assets/kindeditor/plugins/clearhtml/clearhtml.js @@ -0,0 +1,29 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('clearhtml', function(K) { + var self = this, name = 'clearhtml'; + self.clickToolbar(name, function() { + self.focus(); + var html = self.html(); + html = html.replace(/(]*>)([\s\S]*?)(<\/script>)/ig, ''); + html = html.replace(/(]*>)([\s\S]*?)(<\/style>)/ig, ''); + html = K.formatHtml(html, { + a : ['href', 'target'], + embed : ['src', 'width', 'height', 'type', 'loop', 'autostart', 'quality', '.width', '.height', 'align', 'allowscriptaccess'], + img : ['src', 'width', 'height', 'border', 'alt', 'title', '.width', '.height'], + table : ['border'], + 'td,th' : ['rowspan', 'colspan'], + 'div,hr,br,tbody,tr,p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6' : [] + }); + self.html(html); + self.cmd.selection(true); + self.addBookmark(); + }); +}); diff --git a/public/assets/kindeditor/plugins/code/code.js b/public/assets/kindeditor/plugins/code/code.js new file mode 100644 index 000000000..85e42259b --- /dev/null +++ b/public/assets/kindeditor/plugins/code/code.js @@ -0,0 +1,62 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +// google code prettify: http://google-code-prettify.googlecode.com/ +// http://google-code-prettify.googlecode.com/ + +KindEditor.plugin('code', function(K) { + var self = this, name = 'code'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = ['
    ', + '
    ', + '', + '
    ', + '', + '
    '].join(''), + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var type = K('.ke-code-type', dialog.div).val(), + code = textarea.val(), + cls = type === '' ? '' : ' lang-' + type, + html = '
    \n' + K.escape(code) + '
    '; + if (K.trim(code) === '') { + alert(lang.pleaseInput); + textarea[0].focus(); + return; + } + self.insertHtml(html).hideDialog().focus(); + } + } + }), + textarea = K('textarea', dialog.div); + textarea[0].focus(); + }); +}); diff --git a/public/assets/kindeditor/plugins/code/prettify.css b/public/assets/kindeditor/plugins/code/prettify.css new file mode 100644 index 000000000..b8287e5f6 --- /dev/null +++ b/public/assets/kindeditor/plugins/code/prettify.css @@ -0,0 +1,13 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} + +pre.prettyprint { + border: 0; + border-left: 3px solid rgb(204, 204, 204); + margin-left: 2em; + padding: 0.5em; + font-size: 110%; + display: block; + font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; + margin: 1em 0px; + white-space: pre; +} diff --git a/public/assets/kindeditor/plugins/code/prettify.js b/public/assets/kindeditor/plugins/code/prettify.js new file mode 100644 index 000000000..eef5ad7e6 --- /dev/null +++ b/public/assets/kindeditor/plugins/code/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('emoticons', function(K) { + var self = this, name = 'emoticons', + path = (self.emoticonsPath || self.pluginsPath + 'emoticons/images/'), + allowPreview = self.allowPreviewEmoticons === undefined ? true : self.allowPreviewEmoticons, + currentPageNum = 1; + self.clickToolbar(name, function() { + var rows = 5, cols = 9, total = 135, startNum = 0, + cells = rows * cols, pages = Math.ceil(total / cells), + colsHalf = Math.floor(cols / 2), + wrapperDiv = K('
    '), + elements = [], + menu = self.createMenu({ + name : name, + beforeRemove : function() { + removeEvent(); + } + }); + menu.div.append(wrapperDiv); + var previewDiv, previewImg; + if (allowPreview) { + previewDiv = K('
    ').css('right', 0); + previewImg = K(''); + wrapperDiv.append(previewDiv); + previewDiv.append(previewImg); + } + function bindCellEvent(cell, j, num) { + if (previewDiv) { + cell.mouseover(function() { + if (j > colsHalf) { + previewDiv.css('left', 0); + previewDiv.css('right', ''); + } else { + previewDiv.css('left', ''); + previewDiv.css('right', 0); + } + previewImg.attr('src', path + num + '.gif'); + K(this).addClass('ke-on'); + }); + } else { + cell.mouseover(function() { + K(this).addClass('ke-on'); + }); + } + cell.mouseout(function() { + K(this).removeClass('ke-on'); + }); + cell.click(function(e) { + self.insertHtml('').hideMenu().focus(); + e.stop(); + }); + } + function createEmoticonsTable(pageNum, parentDiv) { + var table = document.createElement('table'); + parentDiv.append(table); + if (previewDiv) { + K(table).mouseover(function() { + previewDiv.show('block'); + }); + K(table).mouseout(function() { + previewDiv.hide(); + }); + elements.push(K(table)); + } + table.className = 'ke-table'; + table.cellPadding = 0; + table.cellSpacing = 0; + table.border = 0; + var num = (pageNum - 1) * cells + startNum; + for (var i = 0; i < rows; i++) { + var row = table.insertRow(i); + for (var j = 0; j < cols; j++) { + var cell = K(row.insertCell(j)); + cell.addClass('ke-cell'); + bindCellEvent(cell, j, num); + var span = K('') + .css('background-position', '-' + (24 * num) + 'px 0px') + .css('background-image', 'url(' + path + 'static.gif)'); + cell.append(span); + elements.push(cell); + num++; + } + } + return table; + } + var table = createEmoticonsTable(currentPageNum, wrapperDiv); + function removeEvent() { + K.each(elements, function() { + this.unbind(); + }); + } + var pageDiv; + function bindPageEvent(el, pageNum) { + el.click(function(e) { + removeEvent(); + table.parentNode.removeChild(table); + pageDiv.remove(); + table = createEmoticonsTable(pageNum, wrapperDiv); + createPageTable(pageNum); + currentPageNum = pageNum; + e.stop(); + }); + } + function createPageTable(currentPageNum) { + pageDiv = K('
    '); + wrapperDiv.append(pageDiv); + for (var pageNum = 1; pageNum <= pages; pageNum++) { + if (currentPageNum !== pageNum) { + var a = K('[' + pageNum + ']'); + bindPageEvent(a, pageNum); + pageDiv.append(a); + elements.push(a); + } else { + pageDiv.append(K('@[' + pageNum + ']')); + } + pageDiv.append(K('@ ')); + } + } + createPageTable(currentPageNum); + }); +}); diff --git a/public/assets/kindeditor/plugins/emoticons/images/0.gif b/public/assets/kindeditor/plugins/emoticons/images/0.gif new file mode 100644 index 000000000..5be27cb0e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/0.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/1.gif b/public/assets/kindeditor/plugins/emoticons/images/1.gif new file mode 100644 index 000000000..a2644a9ee Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/1.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/10.gif b/public/assets/kindeditor/plugins/emoticons/images/10.gif new file mode 100644 index 000000000..905c15be3 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/10.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/100.gif b/public/assets/kindeditor/plugins/emoticons/images/100.gif new file mode 100644 index 000000000..92ad35d2b Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/100.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/101.gif b/public/assets/kindeditor/plugins/emoticons/images/101.gif new file mode 100644 index 000000000..1f27663ae Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/101.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/102.gif b/public/assets/kindeditor/plugins/emoticons/images/102.gif new file mode 100644 index 000000000..748ded1ac Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/102.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/103.gif b/public/assets/kindeditor/plugins/emoticons/images/103.gif new file mode 100644 index 000000000..be9eaa054 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/103.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/104.gif b/public/assets/kindeditor/plugins/emoticons/images/104.gif new file mode 100644 index 000000000..d7c206631 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/104.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/105.gif b/public/assets/kindeditor/plugins/emoticons/images/105.gif new file mode 100644 index 000000000..2f353cadc Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/105.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/106.gif b/public/assets/kindeditor/plugins/emoticons/images/106.gif new file mode 100644 index 000000000..51935349b Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/106.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/107.gif b/public/assets/kindeditor/plugins/emoticons/images/107.gif new file mode 100644 index 000000000..70d38d3bb Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/107.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/108.gif b/public/assets/kindeditor/plugins/emoticons/images/108.gif new file mode 100644 index 000000000..749d50083 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/108.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/109.gif b/public/assets/kindeditor/plugins/emoticons/images/109.gif new file mode 100644 index 000000000..6f57d5642 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/109.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/11.gif b/public/assets/kindeditor/plugins/emoticons/images/11.gif new file mode 100644 index 000000000..b512dd5da Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/11.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/110.gif b/public/assets/kindeditor/plugins/emoticons/images/110.gif new file mode 100644 index 000000000..e253abcff Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/110.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/111.gif b/public/assets/kindeditor/plugins/emoticons/images/111.gif new file mode 100644 index 000000000..0c567233d Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/111.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/112.gif b/public/assets/kindeditor/plugins/emoticons/images/112.gif new file mode 100644 index 000000000..c8ddce88a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/112.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/113.gif b/public/assets/kindeditor/plugins/emoticons/images/113.gif new file mode 100644 index 000000000..272710453 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/113.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/114.gif b/public/assets/kindeditor/plugins/emoticons/images/114.gif new file mode 100644 index 000000000..53918e2ae Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/114.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/115.gif b/public/assets/kindeditor/plugins/emoticons/images/115.gif new file mode 100644 index 000000000..4db336973 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/115.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/116.gif b/public/assets/kindeditor/plugins/emoticons/images/116.gif new file mode 100644 index 000000000..57326bd2f Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/116.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/117.gif b/public/assets/kindeditor/plugins/emoticons/images/117.gif new file mode 100644 index 000000000..14611b6ef Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/117.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/118.gif b/public/assets/kindeditor/plugins/emoticons/images/118.gif new file mode 100644 index 000000000..8c255004c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/118.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/119.gif b/public/assets/kindeditor/plugins/emoticons/images/119.gif new file mode 100644 index 000000000..65bb468b9 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/119.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/12.gif b/public/assets/kindeditor/plugins/emoticons/images/12.gif new file mode 100644 index 000000000..547529cab Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/12.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/120.gif b/public/assets/kindeditor/plugins/emoticons/images/120.gif new file mode 100644 index 000000000..5ce77c05f Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/120.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/121.gif b/public/assets/kindeditor/plugins/emoticons/images/121.gif new file mode 100644 index 000000000..a021abaa6 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/121.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/122.gif b/public/assets/kindeditor/plugins/emoticons/images/122.gif new file mode 100644 index 000000000..9a79e111c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/122.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/123.gif b/public/assets/kindeditor/plugins/emoticons/images/123.gif new file mode 100644 index 000000000..b9480be25 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/123.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/124.gif b/public/assets/kindeditor/plugins/emoticons/images/124.gif new file mode 100644 index 000000000..7fed47728 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/124.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/125.gif b/public/assets/kindeditor/plugins/emoticons/images/125.gif new file mode 100644 index 000000000..e2c3c11c9 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/125.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/126.gif b/public/assets/kindeditor/plugins/emoticons/images/126.gif new file mode 100644 index 000000000..24105c988 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/126.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/127.gif b/public/assets/kindeditor/plugins/emoticons/images/127.gif new file mode 100644 index 000000000..0cead364a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/127.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/128.gif b/public/assets/kindeditor/plugins/emoticons/images/128.gif new file mode 100644 index 000000000..318586181 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/128.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/129.gif b/public/assets/kindeditor/plugins/emoticons/images/129.gif new file mode 100644 index 000000000..ffd7c6ba3 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/129.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/13.gif b/public/assets/kindeditor/plugins/emoticons/images/13.gif new file mode 100644 index 000000000..34753001e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/13.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/130.gif b/public/assets/kindeditor/plugins/emoticons/images/130.gif new file mode 100644 index 000000000..d828e3da1 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/130.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/131.gif b/public/assets/kindeditor/plugins/emoticons/images/131.gif new file mode 100644 index 000000000..dcb096f0d Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/131.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/132.gif b/public/assets/kindeditor/plugins/emoticons/images/132.gif new file mode 100644 index 000000000..1b272a690 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/132.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/133.gif b/public/assets/kindeditor/plugins/emoticons/images/133.gif new file mode 100644 index 000000000..0d0e86426 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/133.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/134.gif b/public/assets/kindeditor/plugins/emoticons/images/134.gif new file mode 100644 index 000000000..cf48356e3 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/134.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/14.gif b/public/assets/kindeditor/plugins/emoticons/images/14.gif new file mode 100644 index 000000000..6a788f8be Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/14.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/15.gif b/public/assets/kindeditor/plugins/emoticons/images/15.gif new file mode 100644 index 000000000..debab8ed0 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/15.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/16.gif b/public/assets/kindeditor/plugins/emoticons/images/16.gif new file mode 100644 index 000000000..ed5d29f42 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/16.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/17.gif b/public/assets/kindeditor/plugins/emoticons/images/17.gif new file mode 100644 index 000000000..85886fef9 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/17.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/18.gif b/public/assets/kindeditor/plugins/emoticons/images/18.gif new file mode 100644 index 000000000..b6af2189c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/18.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/19.gif b/public/assets/kindeditor/plugins/emoticons/images/19.gif new file mode 100644 index 000000000..e045ff2af Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/19.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/2.gif b/public/assets/kindeditor/plugins/emoticons/images/2.gif new file mode 100644 index 000000000..40cfda436 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/2.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/20.gif b/public/assets/kindeditor/plugins/emoticons/images/20.gif new file mode 100644 index 000000000..efd650f55 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/20.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/21.gif b/public/assets/kindeditor/plugins/emoticons/images/21.gif new file mode 100644 index 000000000..cb8cf6d2a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/21.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/22.gif b/public/assets/kindeditor/plugins/emoticons/images/22.gif new file mode 100644 index 000000000..96b04df86 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/22.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/23.gif b/public/assets/kindeditor/plugins/emoticons/images/23.gif new file mode 100644 index 000000000..96516b8d9 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/23.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/24.gif b/public/assets/kindeditor/plugins/emoticons/images/24.gif new file mode 100644 index 000000000..5f925c7bc Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/24.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/25.gif b/public/assets/kindeditor/plugins/emoticons/images/25.gif new file mode 100644 index 000000000..97f8b1afa Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/25.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/26.gif b/public/assets/kindeditor/plugins/emoticons/images/26.gif new file mode 100644 index 000000000..a7cded731 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/26.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/27.gif b/public/assets/kindeditor/plugins/emoticons/images/27.gif new file mode 100644 index 000000000..bb468901e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/27.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/28.gif b/public/assets/kindeditor/plugins/emoticons/images/28.gif new file mode 100644 index 000000000..f59dd5825 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/28.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/29.gif b/public/assets/kindeditor/plugins/emoticons/images/29.gif new file mode 100644 index 000000000..3c5227e8e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/29.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/3.gif b/public/assets/kindeditor/plugins/emoticons/images/3.gif new file mode 100644 index 000000000..6d6f76299 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/3.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/30.gif b/public/assets/kindeditor/plugins/emoticons/images/30.gif new file mode 100644 index 000000000..e24a1801c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/30.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/31.gif b/public/assets/kindeditor/plugins/emoticons/images/31.gif new file mode 100644 index 000000000..073e743ce Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/31.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/32.gif b/public/assets/kindeditor/plugins/emoticons/images/32.gif new file mode 100644 index 000000000..772eff23e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/32.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/33.gif b/public/assets/kindeditor/plugins/emoticons/images/33.gif new file mode 100644 index 000000000..217c1c581 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/33.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/34.gif b/public/assets/kindeditor/plugins/emoticons/images/34.gif new file mode 100644 index 000000000..e9d42131a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/34.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/35.gif b/public/assets/kindeditor/plugins/emoticons/images/35.gif new file mode 100644 index 000000000..d6da2c33a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/35.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/36.gif b/public/assets/kindeditor/plugins/emoticons/images/36.gif new file mode 100644 index 000000000..c1e6ac913 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/36.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/37.gif b/public/assets/kindeditor/plugins/emoticons/images/37.gif new file mode 100644 index 000000000..92efec6ae Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/37.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/38.gif b/public/assets/kindeditor/plugins/emoticons/images/38.gif new file mode 100644 index 000000000..489f0f948 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/38.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/39.gif b/public/assets/kindeditor/plugins/emoticons/images/39.gif new file mode 100644 index 000000000..734f6d82e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/39.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/4.gif b/public/assets/kindeditor/plugins/emoticons/images/4.gif new file mode 100644 index 000000000..6ccdaa2c9 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/4.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/40.gif b/public/assets/kindeditor/plugins/emoticons/images/40.gif new file mode 100644 index 000000000..24a8eb691 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/40.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/41.gif b/public/assets/kindeditor/plugins/emoticons/images/41.gif new file mode 100644 index 000000000..99139e1d1 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/41.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/42.gif b/public/assets/kindeditor/plugins/emoticons/images/42.gif new file mode 100644 index 000000000..f60897e40 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/42.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/43.gif b/public/assets/kindeditor/plugins/emoticons/images/43.gif new file mode 100644 index 000000000..435049100 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/43.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/44.gif b/public/assets/kindeditor/plugins/emoticons/images/44.gif new file mode 100644 index 000000000..650d3dd84 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/44.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/45.gif b/public/assets/kindeditor/plugins/emoticons/images/45.gif new file mode 100644 index 000000000..5c8e07181 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/45.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/46.gif b/public/assets/kindeditor/plugins/emoticons/images/46.gif new file mode 100644 index 000000000..f3cb0742d Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/46.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/47.gif b/public/assets/kindeditor/plugins/emoticons/images/47.gif new file mode 100644 index 000000000..5b3057ab7 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/47.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/48.gif b/public/assets/kindeditor/plugins/emoticons/images/48.gif new file mode 100644 index 000000000..27a30c15c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/48.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/49.gif b/public/assets/kindeditor/plugins/emoticons/images/49.gif new file mode 100644 index 000000000..dcfa48af0 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/49.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/5.gif b/public/assets/kindeditor/plugins/emoticons/images/5.gif new file mode 100644 index 000000000..ab0b81ba4 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/5.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/50.gif b/public/assets/kindeditor/plugins/emoticons/images/50.gif new file mode 100644 index 000000000..029cf0fea Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/50.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/51.gif b/public/assets/kindeditor/plugins/emoticons/images/51.gif new file mode 100644 index 000000000..69f183f04 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/51.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/52.gif b/public/assets/kindeditor/plugins/emoticons/images/52.gif new file mode 100644 index 000000000..d41e8aab1 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/52.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/53.gif b/public/assets/kindeditor/plugins/emoticons/images/53.gif new file mode 100644 index 000000000..56352dde4 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/53.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/54.gif b/public/assets/kindeditor/plugins/emoticons/images/54.gif new file mode 100644 index 000000000..b28d8481e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/54.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/55.gif b/public/assets/kindeditor/plugins/emoticons/images/55.gif new file mode 100644 index 000000000..e18da84c6 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/55.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/56.gif b/public/assets/kindeditor/plugins/emoticons/images/56.gif new file mode 100644 index 000000000..edf96f0a6 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/56.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/57.gif b/public/assets/kindeditor/plugins/emoticons/images/57.gif new file mode 100644 index 000000000..3f0e2b9af Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/57.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/58.gif b/public/assets/kindeditor/plugins/emoticons/images/58.gif new file mode 100644 index 000000000..47b1aaa34 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/58.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/59.gif b/public/assets/kindeditor/plugins/emoticons/images/59.gif new file mode 100644 index 000000000..918288b00 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/59.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/6.gif b/public/assets/kindeditor/plugins/emoticons/images/6.gif new file mode 100644 index 000000000..ceab12242 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/6.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/60.gif b/public/assets/kindeditor/plugins/emoticons/images/60.gif new file mode 100644 index 000000000..66d21136d Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/60.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/61.gif b/public/assets/kindeditor/plugins/emoticons/images/61.gif new file mode 100644 index 000000000..034933ec3 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/61.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/62.gif b/public/assets/kindeditor/plugins/emoticons/images/62.gif new file mode 100644 index 000000000..8d5c4fd39 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/62.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/63.gif b/public/assets/kindeditor/plugins/emoticons/images/63.gif new file mode 100644 index 000000000..d58fcf671 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/63.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/64.gif b/public/assets/kindeditor/plugins/emoticons/images/64.gif new file mode 100644 index 000000000..c4e00bdfd Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/64.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/65.gif b/public/assets/kindeditor/plugins/emoticons/images/65.gif new file mode 100644 index 000000000..da23bfaac Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/65.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/66.gif b/public/assets/kindeditor/plugins/emoticons/images/66.gif new file mode 100644 index 000000000..310ec65f1 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/66.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/67.gif b/public/assets/kindeditor/plugins/emoticons/images/67.gif new file mode 100644 index 000000000..51761ba45 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/67.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/68.gif b/public/assets/kindeditor/plugins/emoticons/images/68.gif new file mode 100644 index 000000000..345cb4391 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/68.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/69.gif b/public/assets/kindeditor/plugins/emoticons/images/69.gif new file mode 100644 index 000000000..e0f28a073 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/69.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/7.gif b/public/assets/kindeditor/plugins/emoticons/images/7.gif new file mode 100644 index 000000000..2f4539998 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/7.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/70.gif b/public/assets/kindeditor/plugins/emoticons/images/70.gif new file mode 100644 index 000000000..24284cf39 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/70.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/71.gif b/public/assets/kindeditor/plugins/emoticons/images/71.gif new file mode 100644 index 000000000..a0ccf2edf Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/71.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/72.gif b/public/assets/kindeditor/plugins/emoticons/images/72.gif new file mode 100644 index 000000000..7e113eead Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/72.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/73.gif b/public/assets/kindeditor/plugins/emoticons/images/73.gif new file mode 100644 index 000000000..c0293c3ab Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/73.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/74.gif b/public/assets/kindeditor/plugins/emoticons/images/74.gif new file mode 100644 index 000000000..1c52bde9c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/74.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/75.gif b/public/assets/kindeditor/plugins/emoticons/images/75.gif new file mode 100644 index 000000000..9cb9aa796 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/75.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/76.gif b/public/assets/kindeditor/plugins/emoticons/images/76.gif new file mode 100644 index 000000000..27019f8ff Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/76.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/77.gif b/public/assets/kindeditor/plugins/emoticons/images/77.gif new file mode 100644 index 000000000..8f882f531 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/77.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/78.gif b/public/assets/kindeditor/plugins/emoticons/images/78.gif new file mode 100644 index 000000000..d0d085604 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/78.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/79.gif b/public/assets/kindeditor/plugins/emoticons/images/79.gif new file mode 100644 index 000000000..61652a716 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/79.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/8.gif b/public/assets/kindeditor/plugins/emoticons/images/8.gif new file mode 100644 index 000000000..f6c883447 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/8.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/80.gif b/public/assets/kindeditor/plugins/emoticons/images/80.gif new file mode 100644 index 000000000..9a779364b Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/80.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/81.gif b/public/assets/kindeditor/plugins/emoticons/images/81.gif new file mode 100644 index 000000000..2329101a7 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/81.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/82.gif b/public/assets/kindeditor/plugins/emoticons/images/82.gif new file mode 100644 index 000000000..644748a96 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/82.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/83.gif b/public/assets/kindeditor/plugins/emoticons/images/83.gif new file mode 100644 index 000000000..fbf275ba5 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/83.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/84.gif b/public/assets/kindeditor/plugins/emoticons/images/84.gif new file mode 100644 index 000000000..076f0c65c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/84.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/85.gif b/public/assets/kindeditor/plugins/emoticons/images/85.gif new file mode 100644 index 000000000..d254af442 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/85.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/86.gif b/public/assets/kindeditor/plugins/emoticons/images/86.gif new file mode 100644 index 000000000..8f09d336a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/86.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/87.gif b/public/assets/kindeditor/plugins/emoticons/images/87.gif new file mode 100644 index 000000000..df70756f0 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/87.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/88.gif b/public/assets/kindeditor/plugins/emoticons/images/88.gif new file mode 100644 index 000000000..4d8b15e7e Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/88.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/89.gif b/public/assets/kindeditor/plugins/emoticons/images/89.gif new file mode 100644 index 000000000..05726dc4a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/89.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/9.gif b/public/assets/kindeditor/plugins/emoticons/images/9.gif new file mode 100644 index 000000000..c2d845075 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/9.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/90.gif b/public/assets/kindeditor/plugins/emoticons/images/90.gif new file mode 100644 index 000000000..adaf20e8b Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/90.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/91.gif b/public/assets/kindeditor/plugins/emoticons/images/91.gif new file mode 100644 index 000000000..608d0ad87 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/91.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/92.gif b/public/assets/kindeditor/plugins/emoticons/images/92.gif new file mode 100644 index 000000000..b909e16a8 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/92.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/93.gif b/public/assets/kindeditor/plugins/emoticons/images/93.gif new file mode 100644 index 000000000..7f71a8c94 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/93.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/94.gif b/public/assets/kindeditor/plugins/emoticons/images/94.gif new file mode 100644 index 000000000..4f26d7d73 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/94.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/95.gif b/public/assets/kindeditor/plugins/emoticons/images/95.gif new file mode 100644 index 000000000..5ef6d3823 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/95.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/96.gif b/public/assets/kindeditor/plugins/emoticons/images/96.gif new file mode 100644 index 000000000..2b709e15b Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/96.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/97.gif b/public/assets/kindeditor/plugins/emoticons/images/97.gif new file mode 100644 index 000000000..cf29be87c Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/97.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/98.gif b/public/assets/kindeditor/plugins/emoticons/images/98.gif new file mode 100644 index 000000000..c70e7d339 Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/98.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/99.gif b/public/assets/kindeditor/plugins/emoticons/images/99.gif new file mode 100644 index 000000000..05c18635d Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/99.gif differ diff --git a/public/assets/kindeditor/plugins/emoticons/images/static.gif b/public/assets/kindeditor/plugins/emoticons/images/static.gif new file mode 100644 index 000000000..b8c444b5a Binary files /dev/null and b/public/assets/kindeditor/plugins/emoticons/images/static.gif differ diff --git a/public/assets/kindeditor/plugins/filemanager/filemanager.js b/public/assets/kindeditor/plugins/filemanager/filemanager.js new file mode 100644 index 000000000..fd899af56 --- /dev/null +++ b/public/assets/kindeditor/plugins/filemanager/filemanager.js @@ -0,0 +1,189 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('filemanager', function(K) { + var self = this, name = 'filemanager', + fileManagerJson = K.undef(self.fileManagerJson, self.basePath + 'php/file_manager_json.php'), + imgPath = self.pluginsPath + name + '/images/', + lang = self.lang(name + '.'); + function makeFileTitle(filename, filesize, datetime) { + return filename + ' (' + Math.ceil(filesize / 1024) + 'KB, ' + datetime + ')'; + } + function bindTitle(el, data) { + if (data.is_dir) { + el.attr('title', data.filename); + } else { + el.attr('title', makeFileTitle(data.filename, data.filesize, data.datetime)); + } + } + self.plugin.filemanagerDialog = function(options) { + var width = K.undef(options.width, 650), + height = K.undef(options.height, 510), + dirName = K.undef(options.dirName, ''), + viewType = K.undef(options.viewType, 'VIEW').toUpperCase(), // "LIST" or "VIEW" + clickFn = options.clickFn; + var html = [ + '
    ', + // header start + '
    ', + // left start + '
    ', + ' ', + '' + lang.moveup + '', + '
    ', + // right start + '
    ', + lang.viewType + ' ', + lang.orderType + ' ', + '
    ', + '
    ', + '
    ', + // body start + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : width, + height : height, + title : self.lang(name), + body : html + }), + div = dialog.div, + bodyDiv = K('.ke-plugin-filemanager-body', div), + moveupImg = K('[name="moveupImg"]', div), + moveupLink = K('[name="moveupLink"]', div), + viewServerBtn = K('[name="viewServer"]', div), + viewTypeBox = K('[name="viewType"]', div), + orderTypeBox = K('[name="orderType"]', div); + function reloadPage(path, order, func) { + var param = 'path=' + path + '&order=' + order + '&dir=' + dirName; + dialog.showLoading(self.lang('ajaxLoading')); + K.ajax(K.addParam(fileManagerJson, param + '&' + new Date().getTime()), function(data) { + dialog.hideLoading(); + func(data); + }); + } + var elList = []; + function bindEvent(el, result, data, createFunc) { + var fileUrl = K.formatUrl(result.current_url + data.filename, 'absolute'), + dirPath = encodeURIComponent(result.current_dir_path + data.filename + '/'); + if (data.is_dir) { + el.click(function(e) { + reloadPage(dirPath, orderTypeBox.val(), createFunc); + }); + } else if (data.is_photo) { + el.click(function(e) { + clickFn.call(this, fileUrl, data.filename); + }); + } else { + el.click(function(e) { + clickFn.call(this, fileUrl, data.filename); + }); + } + elList.push(el); + } + function createCommon(result, createFunc) { + // remove events + K.each(elList, function() { + this.unbind(); + }); + moveupLink.unbind(); + viewTypeBox.unbind(); + orderTypeBox.unbind(); + // add events + if (result.current_dir_path) { + moveupLink.click(function(e) { + reloadPage(result.moveup_dir_path, orderTypeBox.val(), createFunc); + }); + } + function changeFunc() { + if (viewTypeBox.val() == 'VIEW') { + reloadPage(result.current_dir_path, orderTypeBox.val(), createView); + } else { + reloadPage(result.current_dir_path, orderTypeBox.val(), createList); + } + } + viewTypeBox.change(changeFunc); + orderTypeBox.change(changeFunc); + bodyDiv.html(''); + } + function createList(result) { + createCommon(result, createList); + var table = document.createElement('table'); + table.className = 'ke-table'; + table.cellPadding = 0; + table.cellSpacing = 0; + table.border = 0; + bodyDiv.append(table); + var fileList = result.file_list; + for (var i = 0, len = fileList.length; i < len; i++) { + var data = fileList[i], row = K(table.insertRow(i)); + row.mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + var iconUrl = imgPath + (data.is_dir ? 'folder-16.gif' : 'file-16.gif'), + img = K('' + data.filename + ''), + cell0 = K(row[0].insertCell(0)).addClass('ke-cell ke-name').append(img).append(document.createTextNode(' ' + data.filename)); + if (!data.is_dir || data.has_file) { + row.css('cursor', 'pointer'); + cell0.attr('title', data.filename); + bindEvent(cell0, result, data, createList); + } else { + cell0.attr('title', lang.emptyFolder); + } + K(row[0].insertCell(1)).addClass('ke-cell ke-size').html(data.is_dir ? '-' : Math.ceil(data.filesize / 1024) + 'KB'); + K(row[0].insertCell(2)).addClass('ke-cell ke-datetime').html(data.datetime); + } + } + function createView(result) { + createCommon(result, createView); + var fileList = result.file_list; + for (var i = 0, len = fileList.length; i < len; i++) { + var data = fileList[i], + div = K('
    '); + bodyDiv.append(div); + var photoDiv = K('
    ') + .mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + div.append(photoDiv); + var fileUrl = result.current_url + data.filename, + iconUrl = data.is_dir ? imgPath + 'folder-64.gif' : (data.is_photo ? fileUrl : imgPath + 'file-64.gif'); + var img = K('' + data.filename + ''); + if (!data.is_dir || data.has_file) { + photoDiv.css('cursor', 'pointer'); + bindTitle(photoDiv, data); + bindEvent(photoDiv, result, data, createView); + } else { + photoDiv.attr('title', lang.emptyFolder); + } + photoDiv.append(img); + div.append('
    ' + data.filename + '
    '); + } + } + viewTypeBox.val(viewType); + reloadPage('', orderTypeBox.val(), viewType == 'VIEW' ? createView : createList); + return dialog; + } + +}); diff --git a/public/assets/kindeditor/plugins/filemanager/images/file-16.gif b/public/assets/kindeditor/plugins/filemanager/images/file-16.gif new file mode 100644 index 000000000..2cf6e47ed Binary files /dev/null and b/public/assets/kindeditor/plugins/filemanager/images/file-16.gif differ diff --git a/public/assets/kindeditor/plugins/filemanager/images/file-64.gif b/public/assets/kindeditor/plugins/filemanager/images/file-64.gif new file mode 100644 index 000000000..2e211da0e Binary files /dev/null and b/public/assets/kindeditor/plugins/filemanager/images/file-64.gif differ diff --git a/public/assets/kindeditor/plugins/filemanager/images/folder-16.gif b/public/assets/kindeditor/plugins/filemanager/images/folder-16.gif new file mode 100644 index 000000000..850b5a350 Binary files /dev/null and b/public/assets/kindeditor/plugins/filemanager/images/folder-16.gif differ diff --git a/public/assets/kindeditor/plugins/filemanager/images/folder-64.gif b/public/assets/kindeditor/plugins/filemanager/images/folder-64.gif new file mode 100644 index 000000000..e8a1b09c0 Binary files /dev/null and b/public/assets/kindeditor/plugins/filemanager/images/folder-64.gif differ diff --git a/public/assets/kindeditor/plugins/filemanager/images/go-up.gif b/public/assets/kindeditor/plugins/filemanager/images/go-up.gif new file mode 100644 index 000000000..92ae23d76 Binary files /dev/null and b/public/assets/kindeditor/plugins/filemanager/images/go-up.gif differ diff --git a/public/assets/kindeditor/plugins/flash/flash.js b/public/assets/kindeditor/plugins/flash/flash.js new file mode 100644 index 000000000..d5d465e16 --- /dev/null +++ b/public/assets/kindeditor/plugins/flash/flash.js @@ -0,0 +1,161 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('flash', function(K) { + var self = this, name = 'flash', lang = self.lang(name + '.'), + allowFlashUpload = K.undef(self.allowFlashUpload, true), + allowFileManager = K.undef(self.allowFileManager, false), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'); + self.plugin.flash = { + edit : function() { + var html = [ + '
    ', + //url + '
    ', + '', + '  ', + '  ', + '', + '', + '', + '
    ', + //width + '
    ', + '', + ' ', + '
    ', + //height + '
    ', + '', + ' ', + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()), + width = widthBox.val(), + height = heightBox.val(); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + var html = K.mediaImg(self.themesPath + 'common/blank.gif', { + src : url, + type : K.mediaType('.swf'), + width : width, + height : height, + quality : 'high' + }); + self.insertHtml(html).hideDialog().focus(); + } + } + }), + div = dialog.div, + urlBox = K('[name="url"]', div), + viewServerBtn = K('[name="viewServer"]', div), + widthBox = K('[name="width"]', div), + heightBox = K('[name="height"]', div); + urlBox.val('http://'); + + if (allowFlashUpload) { + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + extraParams : extraParams, + url : K.addParam(uploadJson, 'dir=flash'), + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + urlBox.val(url); + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + alert(self.lang('uploadSuccess')); + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + }); + } else { + K('.ke-upload-button', div).hide(); + } + + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'LIST', + dirName : 'flash', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + + var img = self.plugin.getSelectedFlash(); + if (img) { + var attrs = K.mediaAttrs(img.attr('data-ke-tag')); + urlBox.val(attrs.src); + widthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0); + heightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0); + } + urlBox[0].focus(); + urlBox[0].select(); + }, + 'delete' : function() { + self.plugin.getSelectedFlash().remove(); + // [IE] 删除图片后立即点击图片按钮出错 + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.flash.edit); +}); diff --git a/public/assets/kindeditor/plugins/image/image.js b/public/assets/kindeditor/plugins/image/image.js new file mode 100644 index 000000000..fd7f5a501 --- /dev/null +++ b/public/assets/kindeditor/plugins/image/image.js @@ -0,0 +1,372 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('image', function(K) { + var self = this, name = 'image', + allowImageUpload = K.undef(self.allowImageUpload, true), + allowImageRemote = K.undef(self.allowImageRemote, true), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + allowFileManager = K.undef(self.allowFileManager, false), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + imageTabIndex = K.undef(self.imageTabIndex, 0), + imgPath = self.pluginsPath + 'image/images/', + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + fillDescAfterUploadImage = K.undef(self.fillDescAfterUploadImage, false), + lang = self.lang(name + '.'); + + self.plugin.imageDialog = function(options) { + var imageUrl = options.imageUrl, + imageWidth = K.undef(options.imageWidth, ''), + imageHeight = K.undef(options.imageHeight, ''), + imageTitle = K.undef(options.imageTitle, ''), + imageAlign = K.undef(options.imageAlign, ''), + showRemote = K.undef(options.showRemote, true), + showLocal = K.undef(options.showLocal, true), + tabIndex = K.undef(options.tabIndex, 0), + clickFn = options.clickFn; + var target = 'kindeditor_upload_iframe_' + new Date().getTime(); + var hiddenElements = []; + for(var k in extraParams){ + hiddenElements.push(''); + } + var html = [ + '
    ', + //tabs + '
    ', + //remote image - start + '', + //remote image - end + //local upload - start + '', + //local upload - end + '
    ' + ].join(''); + var dialogWidth = showLocal || allowFileManager ? 450 : 400, + dialogHeight = showLocal && showRemote ? 300 : 250; + var dialog = self.createDialog({ + name : name, + width : dialogWidth, + height : dialogHeight, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + // Bugfix: http://code.google.com/p/kindeditor/issues/detail?id=319 + if (dialog.isLoading) { + return; + } + // insert local image + if (showLocal && showRemote && tabs && tabs.selectedIndex === 1 || !showRemote) { + if (uploadbutton.fileBox.val() == '') { + alert(self.lang('pleaseSelectFile')); + return; + } + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + localUrlBox.val(''); + return; + } + // insert remote image + var url = K.trim(urlBox.val()), + width = widthBox.val(), + height = heightBox.val(), + title = titleBox.val(), + align = ''; + alignBox.each(function() { + if (this.checked) { + align = this.value; + return false; + } + }); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + clickFn.call(self, url, title, width, height, 0, align); + } + }, + beforeRemove : function() { + viewServerBtn.unbind(); + widthBox.unbind(); + heightBox.unbind(); + refreshBtn.unbind(); + } + }), + div = dialog.div; + + var urlBox = K('[name="url"]', div), + localUrlBox = K('[name="localUrl"]', div), + viewServerBtn = K('[name="viewServer"]', div), + widthBox = K('.tab1 [name="width"]', div), + heightBox = K('.tab1 [name="height"]', div), + refreshBtn = K('.ke-refresh-btn', div), + titleBox = K('.tab1 [name="title"]', div), + alignBox = K('.tab1 [name="align"]', div); + + var tabs; + if (showRemote && showLocal) { + tabs = K.tabs({ + src : K('.tabs', div), + afterSelect : function(i) {} + }); + tabs.add({ + title : lang.remoteImage, + panel : K('.tab1', div) + }); + tabs.add({ + title : lang.localImage, + panel : K('.tab2', div) + }); + tabs.select(tabIndex); + } else if (showRemote) { + K('.tab1', div).show(); + } else if (showLocal) { + K('.tab2', div).show(); + } + + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + form : K('.ke-form', div), + target : target, + width: 60, + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + if (!fillDescAfterUploadImage) { + clickFn.call(self, url, data.title, data.width, data.height, data.border, data.align); + } else { + K(".ke-dialog-row #remoteUrl", div).val(url); + K(".ke-tabs-li", div)[0].click(); + K(".ke-refresh-btn", div).click(); + } + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + //localUrlBox.val(uploadbutton.fileBox.val()); + if (dialog.isLoading) { + return; + } + // insert local image + if (showLocal && showRemote && tabs && tabs.selectedIndex === 1 || !showRemote) { + if (uploadbutton.fileBox.val() == '') { + alert(self.lang('pleaseSelectFile')); + return; + } + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + localUrlBox.val(''); + return; + } + // insert remote image + var url = K.trim(urlBox.val()), + width = widthBox.val(), + height = heightBox.val(), + title = titleBox.val(), + align = ''; + alignBox.each(function() { + if (this.checked) { + align = this.value; + return false; + } + }); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + clickFn.call(self, url, title, width, height, 0, align); + + + }); + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'VIEW', + dirName : 'image', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + var originalWidth = 0, originalHeight = 0; + function setSize(width, height) { + widthBox.val(width); + heightBox.val(height); + originalWidth = width; + originalHeight = height; + } + refreshBtn.click(function(e) { + var tempImg = K('', document).css({ + position : 'absolute', + visibility : 'hidden', + top : 0, + left : '-1000px' + }); + tempImg.bind('load', function() { + setSize(tempImg.width(), tempImg.height()); + tempImg.remove(); + }); + K(document.body).append(tempImg); + }); + widthBox.change(function(e) { + if (originalWidth > 0) { + heightBox.val(Math.round(originalHeight / originalWidth * parseInt(this.value, 10))); + } + }); + heightBox.change(function(e) { + if (originalHeight > 0) { + widthBox.val(Math.round(originalWidth / originalHeight * parseInt(this.value, 10))); + } + }); + urlBox.val(options.imageUrl); + setSize(options.imageWidth, options.imageHeight); + titleBox.val(options.imageTitle); + alignBox.each(function() { + if (this.value === options.imageAlign) { + this.checked = true; + return false; + } + }); + if (showRemote && tabIndex === 0) { + urlBox[0].focus(); + urlBox[0].select(); + } + return dialog; + }; + self.plugin.image = { + edit : function() { + var img = self.plugin.getSelectedImage(); + self.plugin.imageDialog({ + imageUrl : img ? img.attr('data-ke-src') : 'http://', + imageWidth : img ? img.width() : '', + imageHeight : img ? img.height() : '', + imageTitle : img ? img.attr('title') : '', + imageAlign : img ? img.attr('align') : '', + showRemote : allowImageRemote, + showLocal : allowImageUpload, + tabIndex: img ? 0 : imageTabIndex, + clickFn : function(url, title, width, height, border, align) { + if (img) { + img.attr('src', url); + img.attr('data-ke-src', url); + img.attr('width', width); + img.attr('height', height); + img.attr('title', title); + img.attr('align', align); + img.attr('alt', title); + } else { + self.exec('insertimage', url, title, width, height, border, align); + } + // Bugfix: [Firefox] 上传图片后,总是出现正在加载的样式,需要延迟执行hideDialog + setTimeout(function() { + self.hideDialog().focus(); + }, 0); + } + }); + }, + 'delete' : function() { + var target = self.plugin.getSelectedImage(); + if (target.parent().name == 'a') { + target = target.parent(); + } + target.remove(); + // [IE] 删除图片后立即点击图片按钮出错 + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.image.edit); +}); diff --git a/public/assets/kindeditor/plugins/image/images/align_left.gif b/public/assets/kindeditor/plugins/image/images/align_left.gif new file mode 100644 index 000000000..ab17f5679 Binary files /dev/null and b/public/assets/kindeditor/plugins/image/images/align_left.gif differ diff --git a/public/assets/kindeditor/plugins/image/images/align_right.gif b/public/assets/kindeditor/plugins/image/images/align_right.gif new file mode 100644 index 000000000..e8ebe6a63 Binary files /dev/null and b/public/assets/kindeditor/plugins/image/images/align_right.gif differ diff --git a/public/assets/kindeditor/plugins/image/images/align_top.gif b/public/assets/kindeditor/plugins/image/images/align_top.gif new file mode 100644 index 000000000..d8826a5bc Binary files /dev/null and b/public/assets/kindeditor/plugins/image/images/align_top.gif differ diff --git a/public/assets/kindeditor/plugins/image/images/refresh.png b/public/assets/kindeditor/plugins/image/images/refresh.png new file mode 100644 index 000000000..77e12d1c6 Binary files /dev/null and b/public/assets/kindeditor/plugins/image/images/refresh.png differ diff --git a/public/assets/kindeditor/plugins/insertfile/insertfile.js b/public/assets/kindeditor/plugins/insertfile/insertfile.js new file mode 100644 index 000000000..b8c523e77 --- /dev/null +++ b/public/assets/kindeditor/plugins/insertfile/insertfile.js @@ -0,0 +1,138 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('insertfile', function(K) { + var self = this, name = 'insertfile', + allowFileUpload = K.undef(self.allowFileUpload, true), + allowFileManager = K.undef(self.allowFileManager, false), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + lang = self.lang(name + '.'); + self.plugin.fileDialog = function(options) { + var fileUrl = K.undef(options.fileUrl, 'http://'), + fileTitle = K.undef(options.fileTitle, ''), + clickFn = options.clickFn; + var html = [ + '
    ', + '
    ', + '', + '  ', + '  ', + '', + '', + '', + '
    ', + //title + '
    ', + '', + '
    ', + '
    ', + //form end + '', + '
  • ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()), + title = titleBox.val(); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (K.trim(title) === '') { + title = url; + } + clickFn.call(self, url, title); + } + } + }), + div = dialog.div; + + var urlBox = K('[name="url"]', div), + viewServerBtn = K('[name="viewServer"]', div), + titleBox = K('[name="title"]', div); + + if (allowFileUpload) { + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + url : K.addParam(uploadJson, 'dir=file'), + extraParams : extraParams, + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + urlBox.val(url); + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + alert(self.lang('uploadSuccess')); + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + }); + } else { + K('.ke-upload-button', div).hide(); + } + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'LIST', + dirName : 'file', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + urlBox.val(fileUrl); + titleBox.val(fileTitle); + urlBox[0].focus(); + urlBox[0].select(); + }; + self.clickToolbar(name, function() { + self.plugin.fileDialog({ + clickFn : function(url, title) { + var html = '' + title + ''; + self.insertHtml(html).hideDialog().focus(); + } + }); + }); +}); diff --git a/public/assets/kindeditor/plugins/lineheight/lineheight.js b/public/assets/kindeditor/plugins/lineheight/lineheight.js new file mode 100644 index 000000000..ae679d788 --- /dev/null +++ b/public/assets/kindeditor/plugins/lineheight/lineheight.js @@ -0,0 +1,38 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('lineheight', function(K) { + var self = this, name = 'lineheight', lang = self.lang(name + '.'); + self.clickToolbar(name, function() { + var curVal = '', commonNode = self.cmd.commonNode({'*' : '.line-height'}); + if (commonNode) { + curVal = commonNode.css('line-height'); + } + var menu = self.createMenu({ + name : name, + width : 150 + }); + K.each(lang.lineHeight, function(i, row) { + K.each(row, function(key, val) { + menu.addItem({ + title : val, + checked : curVal === key, + click : function() { + self.cmd.toggle('', { + span : '.line-height=' + key + }); + self.updateState(); + self.addBookmark(); + self.hideMenu(); + } + }); + }); + }); + }); +}); diff --git a/public/assets/kindeditor/plugins/link/link.js b/public/assets/kindeditor/plugins/link/link.js new file mode 100644 index 000000000..352fa3c64 --- /dev/null +++ b/public/assets/kindeditor/plugins/link/link.js @@ -0,0 +1,66 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('link', function(K) { + var self = this, name = 'link'; + self.plugin.link = { + edit : function() { + var lang = self.lang(name + '.'), + html = '
    ' + + //url + '
    ' + + '' + + '
    ' + + //type + '
    ' + + '' + + '' + + '
    ' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + self.exec('createlink', url, typeBox.val()).hideDialog().focus(); + } + } + }), + div = dialog.div, + urlBox = K('input[name="url"]', div), + typeBox = K('select[name="type"]', div); + urlBox.val('http://'); + typeBox[0].options[0] = new Option(lang.newWindow, '_blank'); + typeBox[0].options[1] = new Option(lang.selfWindow, ''); + self.cmd.selection(); + var a = self.plugin.getSelectedLink(); + if (a) { + self.cmd.range.selectNode(a[0]); + self.cmd.select(); + urlBox.val(a.attr('data-ke-src')); + typeBox.val(a.attr('target')); + } + urlBox[0].focus(); + urlBox[0].select(); + }, + 'delete' : function() { + self.exec('unlink', null); + } + }; + self.clickToolbar(name, self.plugin.link.edit); +}); diff --git a/public/assets/kindeditor/plugins/map/map.html b/public/assets/kindeditor/plugins/map/map.html new file mode 100644 index 000000000..1a9ad7d7b --- /dev/null +++ b/public/assets/kindeditor/plugins/map/map.html @@ -0,0 +1,57 @@ + + + + + + + + + +
    + + \ No newline at end of file diff --git a/public/assets/kindeditor/plugins/map/map.js b/public/assets/kindeditor/plugins/map/map.js new file mode 100644 index 000000000..529087525 --- /dev/null +++ b/public/assets/kindeditor/plugins/map/map.js @@ -0,0 +1,137 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +// Google Maps: http://code.google.com/apis/maps/index.html + +KindEditor.plugin('map', function(K) { + var self = this, name = 'map', lang = self.lang(name + '.'); + self.clickToolbar(name, function() { + var html = ['
    ', + '
    ', + lang.address + ' ', + '', + '', + '', + '
    ', + '
    ', + '
    '].join(''); + var dialog = self.createDialog({ + name : name, + width : 600, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var geocoder = win.geocoder, + map = win.map, + center = map.getCenter().lat() + ',' + map.getCenter().lng(), + zoom = map.getZoom(), + maptype = map.getMapTypeId(), + url = 'http://maps.googleapis.com/maps/api/staticmap'; + url += '?center=' + encodeURIComponent(center); + url += '&zoom=' + encodeURIComponent(zoom); + url += '&size=558x360'; + url += '&maptype=' + encodeURIComponent(maptype); + url += '&markers=' + encodeURIComponent(center); + url += '&language=' + self.langType; + url += '&sensor=false'; + self.exec('insertimage', url).hideDialog().focus(); + } + }, + beforeRemove : function() { + searchBtn.remove(); + if (doc) { + doc.write(''); + } + iframe.remove(); + } + }); + var div = dialog.div, + addressBox = K('[name="address"]', div), + searchBtn = K('[name="searchBtn"]', div), + win, doc; + var iframeHtml = ['', + '', + '', + '', + '', + '', + '', + '
    ', + ''].join('\n'); + // TODO:用doc.write(iframeHtml)方式加载时,在IE6上第一次加载报错,暂时使用src方式 + var iframe = K(''); + function ready() { + win = iframe[0].contentWindow; + doc = K.iframeDoc(iframe); + //doc.open(); + //doc.write(iframeHtml); + //doc.close(); + } + iframe.bind('load', function() { + iframe.unbind('load'); + if (K.IE) { + ready(); + } else { + setTimeout(ready, 0); + } + }); + K('.ke-map', div).replaceWith(iframe); + // search map + searchBtn.click(function() { + win.search(addressBox.val()); + }); + }); +}); diff --git a/public/assets/kindeditor/plugins/media/media.js b/public/assets/kindeditor/plugins/media/media.js new file mode 100644 index 000000000..58034662a --- /dev/null +++ b/public/assets/kindeditor/plugins/media/media.js @@ -0,0 +1,170 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('media', function(K) { + var self = this, name = 'media', lang = self.lang(name + '.'), + allowMediaUpload = K.undef(self.allowMediaUpload, true), + allowFileManager = K.undef(self.allowFileManager, false), + formatUploadUrl = K.undef(self.formatUploadUrl, true), + extraParams = K.undef(self.extraFileUploadParams, {}), + filePostName = K.undef(self.filePostName, 'imgFile'), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'); + self.plugin.media = { + edit : function() { + var html = [ + '
    ', + //url + '
    ', + '', + '  ', + '  ', + '', + '', + '', + '
    ', + //width + '
    ', + '', + '', + '
    ', + //height + '
    ', + '', + '', + '
    ', + //autostart + '
    ', + '', + ' ', + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 450, + height : 230, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var url = K.trim(urlBox.val()), + width = widthBox.val(), + height = heightBox.val(); + if (url == 'http://' || K.invalidUrl(url)) { + alert(self.lang('invalidUrl')); + urlBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + var html = K.mediaImg(self.themesPath + 'common/blank.gif', { + src : url, + type : K.mediaType(url), + width : width, + height : height, + autostart : autostartBox[0].checked ? 'true' : 'false', + loop : 'true' + }); + self.insertHtml(html).hideDialog().focus(); + } + } + }), + div = dialog.div, + urlBox = K('[name="url"]', div), + viewServerBtn = K('[name="viewServer"]', div), + widthBox = K('[name="width"]', div), + heightBox = K('[name="height"]', div), + autostartBox = K('[name="autostart"]', div); + urlBox.val('http://'); + + if (allowMediaUpload) { + var uploadbutton = K.uploadbutton({ + button : K('.ke-upload-button', div)[0], + fieldName : filePostName, + extraParams : extraParams, + url : K.addParam(uploadJson, 'dir=media'), + afterUpload : function(data) { + dialog.hideLoading(); + if (data.error === 0) { + var url = data.url; + if (formatUploadUrl) { + url = K.formatUrl(url, 'absolute'); + } + urlBox.val(url); + if (self.afterUpload) { + self.afterUpload.call(self, url, data, name); + } + alert(self.lang('uploadSuccess')); + } else { + alert(data.message); + } + }, + afterError : function(html) { + dialog.hideLoading(); + self.errorDialog(html); + } + }); + uploadbutton.fileBox.change(function(e) { + dialog.showLoading(self.lang('uploadLoading')); + uploadbutton.submit(); + }); + } else { + K('.ke-upload-button', div).hide(); + } + + if (allowFileManager) { + viewServerBtn.click(function(e) { + self.loadPlugin('filemanager', function() { + self.plugin.filemanagerDialog({ + viewType : 'LIST', + dirName : 'media', + clickFn : function(url, title) { + if (self.dialogs.length > 1) { + K('[name="url"]', div).val(url); + if (self.afterSelectFile) { + self.afterSelectFile.call(self, url); + } + self.hideDialog(); + } + } + }); + }); + }); + } else { + viewServerBtn.hide(); + } + + var img = self.plugin.getSelectedMedia(); + if (img) { + var attrs = K.mediaAttrs(img.attr('data-ke-tag')); + urlBox.val(attrs.src); + widthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0); + heightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0); + autostartBox[0].checked = (attrs.autostart === 'true'); + } + urlBox[0].focus(); + urlBox[0].select(); + }, + 'delete' : function() { + self.plugin.getSelectedMedia().remove(); + // [IE] 删除图片后立即点击图片按钮出错 + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.media.edit); +}); diff --git a/public/assets/kindeditor/plugins/multiimage/images/image.png b/public/assets/kindeditor/plugins/multiimage/images/image.png new file mode 100644 index 000000000..fe79cf0ad Binary files /dev/null and b/public/assets/kindeditor/plugins/multiimage/images/image.png differ diff --git a/public/assets/kindeditor/plugins/multiimage/images/select-files-en.png b/public/assets/kindeditor/plugins/multiimage/images/select-files-en.png new file mode 100644 index 000000000..a926a6e3a Binary files /dev/null and b/public/assets/kindeditor/plugins/multiimage/images/select-files-en.png differ diff --git a/public/assets/kindeditor/plugins/multiimage/images/select-files-zh_CN.png b/public/assets/kindeditor/plugins/multiimage/images/select-files-zh_CN.png new file mode 100644 index 000000000..5a31d364b Binary files /dev/null and b/public/assets/kindeditor/plugins/multiimage/images/select-files-zh_CN.png differ diff --git a/public/assets/kindeditor/plugins/multiimage/images/swfupload.swf b/public/assets/kindeditor/plugins/multiimage/images/swfupload.swf new file mode 100644 index 000000000..e3f767031 Binary files /dev/null and b/public/assets/kindeditor/plugins/multiimage/images/swfupload.swf differ diff --git a/public/assets/kindeditor/plugins/multiimage/multiimage.js b/public/assets/kindeditor/plugins/multiimage/multiimage.js new file mode 100644 index 000000000..5e6ecf8ec --- /dev/null +++ b/public/assets/kindeditor/plugins/multiimage/multiimage.js @@ -0,0 +1,1384 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + + +(function(K) { + +function KSWFUpload(options) { + this.init(options); +} +K.extend(KSWFUpload, { + init : function(options) { + var self = this; + options.afterError = options.afterError || function(str) { + alert(str); + }; + self.options = options; + self.progressbars = {}; + // template + self.div = K(options.container).html([ + '
    ', + '
    ', + '
    ', + '', + '
    ', + '
    ' + options.uploadDesc + '
    ', + '', + '', + '', + '
    ', + '
    ', + '
    ' + ].join('')); + self.bodyDiv = K('.ke-swfupload-body', self.div); + + function showError(itemDiv, msg) { + K('.ke-status > div', itemDiv).hide(); + K('.ke-message', itemDiv).addClass('ke-error').show().html(K.escape(msg)); + } + + var settings = { + debug : false, + upload_url : options.uploadUrl, + flash_url : options.flashUrl, + file_post_name : options.filePostName, + button_placeholder : K('.ke-swfupload-button > input', self.div)[0], + button_image_url: options.buttonImageUrl, + button_width: options.buttonWidth, + button_height: options.buttonHeight, + button_cursor : SWFUpload.CURSOR.HAND, + file_types : options.fileTypes, + file_types_description : options.fileTypesDesc, + file_upload_limit : options.fileUploadLimit, + file_size_limit : options.fileSizeLimit, + post_params : options.postParams, + file_queued_handler : function(file) { + file.url = self.options.fileIconUrl; + self.appendFile(file); + }, + file_queue_error_handler : function(file, errorCode, message) { + var errorName = ''; + switch (errorCode) { + case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED: + errorName = options.queueLimitExceeded; + break; + case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: + errorName = options.fileExceedsSizeLimit; + break; + case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: + errorName = options.zeroByteFile; + break; + case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: + errorName = options.invalidFiletype; + break; + default: + errorName = options.unknownError; + break; + } + K.DEBUG && alert(errorName); + }, + upload_start_handler : function(file) { + var self = this; + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv); + K('.ke-status > div', itemDiv).hide(); + K('.ke-progressbar', itemDiv).show(); + }, + upload_progress_handler : function(file, bytesLoaded, bytesTotal) { + var percent = Math.round(bytesLoaded * 100 / bytesTotal); + var progressbar = self.progressbars[file.id]; + progressbar.bar.css('width', Math.round(percent * 80 / 100) + 'px'); + progressbar.percent.html(percent + '%'); + }, + upload_error_handler : function(file, errorCode, message) { + if (file && file.filestatus == SWFUpload.FILE_STATUS.ERROR) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + showError(itemDiv, self.options.errorMessage); + } + }, + upload_success_handler : function(file, serverData) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + var data = {}; + try { + data = K.json(serverData); + } catch (e) { + self.options.afterError.call(this, '' + serverData + ''); + } + if (data.error !== 0) { + showError(itemDiv, K.DEBUG ? data.message : self.options.errorMessage); + return; + } + file.url = data.url; + K('.ke-img', itemDiv).attr('src', file.url).attr('data-status', file.filestatus).data('data', data); + K('.ke-status > div', itemDiv).hide(); + } + }; + self.swfu = new SWFUpload(settings); + + K('.ke-swfupload-startupload input', self.div).click(function() { + self.swfu.startUpload(); + }); + }, + getUrlList : function() { + var list = []; + K('.ke-img', self.bodyDiv).each(function() { + var img = K(this); + var status = img.attr('data-status'); + if (status == SWFUpload.FILE_STATUS.COMPLETE) { + list.push(img.data('data')); + } + }); + return list; + }, + removeFile : function(fileId) { + var self = this; + self.swfu.cancelUpload(fileId); + var itemDiv = K('div[data-id="' + fileId + '"]', self.bodyDiv); + K('.ke-photo', itemDiv).unbind(); + K('.ke-delete', itemDiv).unbind(); + itemDiv.remove(); + }, + removeFiles : function() { + var self = this; + K('.ke-item', self.bodyDiv).each(function() { + self.removeFile(K(this).attr('data-id')); + }); + }, + appendFile : function(file) { + var self = this; + var itemDiv = K('
    '); + self.bodyDiv.append(itemDiv); + var photoDiv = K('
    ') + .mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + itemDiv.append(photoDiv); + + var img = K('' + file.name + ''); + photoDiv.append(img); + K('').appendTo(photoDiv).click(function() { + self.removeFile(file.id); + }); + var statusDiv = K('
    ').appendTo(photoDiv); + // progressbar + K(['
    ', + '
    ', + '
    0%
    '].join('')).hide().appendTo(statusDiv); + // message + K('
    ' + self.options.pendingMessage + '
    ').appendTo(statusDiv); + + itemDiv.append('
    ' + file.name + '
    '); + + self.progressbars[file.id] = { + bar : K('.ke-progressbar-bar-inner', photoDiv), + percent : K('.ke-progressbar-percent', photoDiv) + }; + }, + remove : function() { + this.removeFiles(); + this.swfu.destroy(); + this.div.html(''); + } +}); + +K.swfupload = function(element, options) { + return new KSWFUpload(element, options); +}; + +})(KindEditor); + +KindEditor.plugin('multiimage', function(K) { + var self = this, name = 'multiimage', + formatUploadUrl = K.undef(self.formatUploadUrl, true), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + imgPath = self.pluginsPath + 'multiimage/images/', + imageSizeLimit = K.undef(self.imageSizeLimit, '1MB'), + imageFileTypes = K.undef(self.imageFileTypes, '*.jpg;*.gif;*.png'), + imageUploadLimit = K.undef(self.imageUploadLimit, 20), + filePostName = K.undef(self.filePostName, 'imgFile'), + lang = self.lang(name + '.'); + + self.plugin.multiImageDialog = function(options) { + var clickFn = options.clickFn, + uploadDesc = K.tmpl(lang.uploadDesc, {uploadLimit : imageUploadLimit, sizeLimit : imageSizeLimit}); + var html = [ + '
    ', + '
    ', + '
    ', + '
    ' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 650, + height : 510, + title : self.lang(name), + body : html, + previewBtn : { + name : lang.insertAll, + click : function(e) { + clickFn.call(self, swfupload.getUrlList()); + } + }, + yesBtn : { + name : lang.clearAll, + click : function(e) { + swfupload.removeFiles(); + } + }, + beforeRemove : function() { + // IE9 bugfix: https://github.com/kindsoft/kindeditor/issues/72 + if (!K.IE || K.V <= 8) { + swfupload.remove(); + } + } + }), + div = dialog.div; + + var swfupload = K.swfupload({ + container : K('.swfupload', div), + buttonImageUrl : imgPath + (self.langType == 'zh_CN' ? 'select-files-zh_CN.png' : 'select-files-en.png'), + buttonWidth : self.langType == 'zh_CN' ? 72 : 88, + buttonHeight : 23, + fileIconUrl : imgPath + 'image.png', + uploadDesc : uploadDesc, + startButtonValue : lang.startUpload, + uploadUrl : K.addParam(uploadJson, 'dir=image'), + flashUrl : imgPath + 'swfupload.swf', + filePostName : filePostName, + fileTypes : '*.jpg;*.jpeg;*.gif;*.png;*.bmp', + fileTypesDesc : 'Image Files', + fileUploadLimit : imageUploadLimit, + fileSizeLimit : imageSizeLimit, + postParams : K.undef(self.extraFileUploadParams, {}), + queueLimitExceeded : lang.queueLimitExceeded, + fileExceedsSizeLimit : lang.fileExceedsSizeLimit, + zeroByteFile : lang.zeroByteFile, + invalidFiletype : lang.invalidFiletype, + unknownError : lang.unknownError, + pendingMessage : lang.pending, + errorMessage : lang.uploadError, + afterError : function(html) { + self.errorDialog(html); + } + }); + + return dialog; + }; + self.clickToolbar(name, function() { + self.plugin.multiImageDialog({ + clickFn : function (urlList) { + if (urlList.length === 0) { + return; + } + K.each(urlList, function(i, data) { + if (self.afterUpload) { + self.afterUpload.call(self, data.url, data, 'multiimage'); + } + self.exec('insertimage', data.url, data.title, data.width, data.height, data.border, data.align); + }); + // Bugfix: [Firefox] 上传图片后,总是出现正在加载的样式,需要延迟执行hideDialog + setTimeout(function() { + self.hideDialog().focus(); + }, 0); + } + }); + }); +}); + + +/** + * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com + * + * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/ + * + * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz閚 and Mammon Media and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + */ + + +/* ******************* */ +/* Constructor & Init */ +/* ******************* */ + +(function() { + +window.SWFUpload = function (settings) { + this.initSWFUpload(settings); +}; + +SWFUpload.prototype.initSWFUpload = function (settings) { + try { + this.customSettings = {}; // A container where developers can place their own settings associated with this instance. + this.settings = settings; + this.eventQueue = []; + this.movieName = "KindEditor_SWFUpload_" + SWFUpload.movieCount++; + this.movieElement = null; + + + // Setup global control tracking + SWFUpload.instances[this.movieName] = this; + + // Load the settings. Load the Flash movie. + this.initSettings(); + this.loadFlash(); + this.displayDebugInfo(); + } catch (ex) { + delete SWFUpload.instances[this.movieName]; + throw ex; + } +}; + +/* *************** */ +/* Static Members */ +/* *************** */ +SWFUpload.instances = {}; +SWFUpload.movieCount = 0; +SWFUpload.version = "2.2.0 2009-03-25"; +SWFUpload.QUEUE_ERROR = { + QUEUE_LIMIT_EXCEEDED : -100, + FILE_EXCEEDS_SIZE_LIMIT : -110, + ZERO_BYTE_FILE : -120, + INVALID_FILETYPE : -130 +}; +SWFUpload.UPLOAD_ERROR = { + HTTP_ERROR : -200, + MISSING_UPLOAD_URL : -210, + IO_ERROR : -220, + SECURITY_ERROR : -230, + UPLOAD_LIMIT_EXCEEDED : -240, + UPLOAD_FAILED : -250, + SPECIFIED_FILE_ID_NOT_FOUND : -260, + FILE_VALIDATION_FAILED : -270, + FILE_CANCELLED : -280, + UPLOAD_STOPPED : -290 +}; +SWFUpload.FILE_STATUS = { + QUEUED : -1, + IN_PROGRESS : -2, + ERROR : -3, + COMPLETE : -4, + CANCELLED : -5 +}; +SWFUpload.BUTTON_ACTION = { + SELECT_FILE : -100, + SELECT_FILES : -110, + START_UPLOAD : -120 +}; +SWFUpload.CURSOR = { + ARROW : -1, + HAND : -2 +}; +SWFUpload.WINDOW_MODE = { + WINDOW : "window", + TRANSPARENT : "transparent", + OPAQUE : "opaque" +}; + +// Private: takes a URL, determines if it is relative and converts to an absolute URL +// using the current site. Only processes the URL if it can, otherwise returns the URL untouched +SWFUpload.completeURL = function(url) { + if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) { + return url; + } + + var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : ""); + + var indexSlash = window.location.pathname.lastIndexOf("/"); + if (indexSlash <= 0) { + path = "/"; + } else { + path = window.location.pathname.substr(0, indexSlash) + "/"; + } + + return /*currentURL +*/ path + url; + +}; + + +/* ******************** */ +/* Instance Members */ +/* ******************** */ + +// Private: initSettings ensures that all the +// settings are set, getting a default value if one was not assigned. +SWFUpload.prototype.initSettings = function () { + this.ensureDefault = function (settingName, defaultValue) { + this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName]; + }; + + // Upload backend settings + this.ensureDefault("upload_url", ""); + this.ensureDefault("preserve_relative_urls", false); + this.ensureDefault("file_post_name", "Filedata"); + this.ensureDefault("post_params", {}); + this.ensureDefault("use_query_string", false); + this.ensureDefault("requeue_on_error", false); + this.ensureDefault("http_success", []); + this.ensureDefault("assume_success_timeout", 0); + + // File Settings + this.ensureDefault("file_types", "*.*"); + this.ensureDefault("file_types_description", "All Files"); + this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited" + this.ensureDefault("file_upload_limit", 0); + this.ensureDefault("file_queue_limit", 0); + + // Flash Settings + this.ensureDefault("flash_url", "swfupload.swf"); + this.ensureDefault("prevent_swf_caching", true); + + // Button Settings + this.ensureDefault("button_image_url", ""); + this.ensureDefault("button_width", 1); + this.ensureDefault("button_height", 1); + this.ensureDefault("button_text", ""); + this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;"); + this.ensureDefault("button_text_top_padding", 0); + this.ensureDefault("button_text_left_padding", 0); + this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES); + this.ensureDefault("button_disabled", false); + this.ensureDefault("button_placeholder_id", ""); + this.ensureDefault("button_placeholder", null); + this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW); + this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW); + + // Debug Settings + this.ensureDefault("debug", false); + this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API + + // Event Handlers + this.settings.return_upload_start_handler = this.returnUploadStart; + this.ensureDefault("swfupload_loaded_handler", null); + this.ensureDefault("file_dialog_start_handler", null); + this.ensureDefault("file_queued_handler", null); + this.ensureDefault("file_queue_error_handler", null); + this.ensureDefault("file_dialog_complete_handler", null); + + this.ensureDefault("upload_start_handler", null); + this.ensureDefault("upload_progress_handler", null); + this.ensureDefault("upload_error_handler", null); + this.ensureDefault("upload_success_handler", null); + this.ensureDefault("upload_complete_handler", null); + + this.ensureDefault("debug_handler", this.debugMessage); + + this.ensureDefault("custom_settings", {}); + + // Other settings + this.customSettings = this.settings.custom_settings; + + // Update the flash url if needed + if (!!this.settings.prevent_swf_caching) { + this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime(); + } + + if (!this.settings.preserve_relative_urls) { + //this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it + this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url); + this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url); + } + + delete this.ensureDefault; +}; + +// Private: loadFlash replaces the button_placeholder element with the flash movie. +SWFUpload.prototype.loadFlash = function () { + var targetElement, tempParent; + + // Make sure an element with the ID we are going to use doesn't already exist + if (document.getElementById(this.movieName) !== null) { + throw "ID " + this.movieName + " is already in use. The Flash Object could not be added"; + } + + // Get the element where we will be placing the flash movie + targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder; + + if (targetElement == undefined) { + throw "Could not find the placeholder element: " + this.settings.button_placeholder_id; + } + + // Append the container and load the flash + tempParent = document.createElement("div"); + tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers) + targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement); + + // Fix IE Flash/Form bug + if (window[this.movieName] == undefined) { + window[this.movieName] = this.getMovieElement(); + } + +}; + +// Private: getFlashHTML generates the object tag needed to embed the flash in to the document +SWFUpload.prototype.getFlashHTML = function () { + // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay + // Fix bug for IE9 + // http://www.kindsoft.net/view.php?bbsid=7&postid=5825&pagenum=1 + var classid = ''; + if (KindEditor.IE && KindEditor.V > 8) { + classid = ' classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"'; + } + return ['', + '', + '', + '', + '', + '', + '', + ''].join(""); +}; + +// Private: getFlashVars builds the parameter string that will be passed +// to flash in the flashvars param. +SWFUpload.prototype.getFlashVars = function () { + // Build a string from the post param object + var paramString = this.buildParamString(); + var httpSuccessString = this.settings.http_success.join(","); + + // Build the parameter string + return ["movieName=", encodeURIComponent(this.movieName), + "&uploadURL=", encodeURIComponent(this.settings.upload_url), + "&useQueryString=", encodeURIComponent(this.settings.use_query_string), + "&requeueOnError=", encodeURIComponent(this.settings.requeue_on_error), + "&httpSuccess=", encodeURIComponent(httpSuccessString), + "&assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout), + "&params=", encodeURIComponent(paramString), + "&filePostName=", encodeURIComponent(this.settings.file_post_name), + "&fileTypes=", encodeURIComponent(this.settings.file_types), + "&fileTypesDescription=", encodeURIComponent(this.settings.file_types_description), + "&fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit), + "&fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit), + "&fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit), + "&debugEnabled=", encodeURIComponent(this.settings.debug_enabled), + "&buttonImageURL=", encodeURIComponent(this.settings.button_image_url), + "&buttonWidth=", encodeURIComponent(this.settings.button_width), + "&buttonHeight=", encodeURIComponent(this.settings.button_height), + "&buttonText=", encodeURIComponent(this.settings.button_text), + "&buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding), + "&buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding), + "&buttonTextStyle=", encodeURIComponent(this.settings.button_text_style), + "&buttonAction=", encodeURIComponent(this.settings.button_action), + "&buttonDisabled=", encodeURIComponent(this.settings.button_disabled), + "&buttonCursor=", encodeURIComponent(this.settings.button_cursor) + ].join(""); +}; + +// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload +// The element is cached after the first lookup +SWFUpload.prototype.getMovieElement = function () { + if (this.movieElement == undefined) { + this.movieElement = document.getElementById(this.movieName); + } + + if (this.movieElement === null) { + throw "Could not find Flash element"; + } + + return this.movieElement; +}; + +// Private: buildParamString takes the name/value pairs in the post_params setting object +// and joins them up in to a string formatted "name=value&name=value" +SWFUpload.prototype.buildParamString = function () { + var postParams = this.settings.post_params; + var paramStringPairs = []; + + if (typeof(postParams) === "object") { + for (var name in postParams) { + if (postParams.hasOwnProperty(name)) { + paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString())); + } + } + } + + return paramStringPairs.join("&"); +}; + +// Public: Used to remove a SWFUpload instance from the page. This method strives to remove +// all references to the SWF, and other objects so memory is properly freed. +// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state. +// Credits: Major improvements provided by steffen +SWFUpload.prototype.destroy = function () { + try { + // Make sure Flash is done before we try to remove it + this.cancelUpload(null, false); + + + // Remove the SWFUpload DOM nodes + var movieElement = null; + movieElement = this.getMovieElement(); + + if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround) + for (var i in movieElement) { + try { + if (typeof(movieElement[i]) === "function") { + movieElement[i] = null; + } + } catch (ex1) {} + } + + // Remove the Movie Element from the page + try { + movieElement.parentNode.removeChild(movieElement); + } catch (ex) {} + } + + // Remove IE form fix reference + window[this.movieName] = null; + + // Destroy other references + SWFUpload.instances[this.movieName] = null; + delete SWFUpload.instances[this.movieName]; + + this.movieElement = null; + this.settings = null; + this.customSettings = null; + this.eventQueue = null; + this.movieName = null; + + + return true; + } catch (ex2) { + return false; + } +}; + + +// Public: displayDebugInfo prints out settings and configuration +// information about this SWFUpload instance. +// This function (and any references to it) can be deleted when placing +// SWFUpload in production. +SWFUpload.prototype.displayDebugInfo = function () { + this.debug( + [ + "---SWFUpload Instance Info---\n", + "Version: ", SWFUpload.version, "\n", + "Movie Name: ", this.movieName, "\n", + "Settings:\n", + "\t", "upload_url: ", this.settings.upload_url, "\n", + "\t", "flash_url: ", this.settings.flash_url, "\n", + "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n", + "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n", + "\t", "http_success: ", this.settings.http_success.join(", "), "\n", + "\t", "assume_success_timeout: ", this.settings.assume_success_timeout, "\n", + "\t", "file_post_name: ", this.settings.file_post_name, "\n", + "\t", "post_params: ", this.settings.post_params.toString(), "\n", + "\t", "file_types: ", this.settings.file_types, "\n", + "\t", "file_types_description: ", this.settings.file_types_description, "\n", + "\t", "file_size_limit: ", this.settings.file_size_limit, "\n", + "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n", + "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n", + "\t", "debug: ", this.settings.debug.toString(), "\n", + + "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n", + + "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n", + "\t", "button_placeholder: ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n", + "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n", + "\t", "button_width: ", this.settings.button_width.toString(), "\n", + "\t", "button_height: ", this.settings.button_height.toString(), "\n", + "\t", "button_text: ", this.settings.button_text.toString(), "\n", + "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n", + "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n", + "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n", + "\t", "button_action: ", this.settings.button_action.toString(), "\n", + "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n", + + "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n", + "Event Handlers:\n", + "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n", + "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n", + "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n", + "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n", + "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n", + "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n", + "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n", + "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n", + "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n", + "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n" + ].join("") + ); +}; + +/* Note: addSetting and getSetting are no longer used by SWFUpload but are included + the maintain v2 API compatibility +*/ +// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used. +SWFUpload.prototype.addSetting = function (name, value, default_value) { + if (value == undefined) { + return (this.settings[name] = default_value); + } else { + return (this.settings[name] = value); + } +}; + +// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found. +SWFUpload.prototype.getSetting = function (name) { + if (this.settings[name] != undefined) { + return this.settings[name]; + } + + return ""; +}; + + + +// Private: callFlash handles function calls made to the Flash element. +// Calls are made with a setTimeout for some functions to work around +// bugs in the ExternalInterface library. +SWFUpload.prototype.callFlash = function (functionName, argumentArray) { + argumentArray = argumentArray || []; + + var movieElement = this.getMovieElement(); + var returnValue, returnString; + + // Flash's method if calling ExternalInterface methods (code adapted from MooTools). + try { + returnString = movieElement.CallFunction('' + __flash__argumentsToXML(argumentArray, 0) + ''); + returnValue = eval(returnString); + } catch (ex) { + throw "Call to " + functionName + " failed"; + } + + // Unescape file post param values + if (returnValue != undefined && typeof returnValue.post === "object") { + returnValue = this.unescapeFilePostParams(returnValue); + } + + return returnValue; +}; + +/* ***************************** + -- Flash control methods -- + Your UI should use these + to operate SWFUpload + ***************************** */ + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFile causes a File Selection Dialog window to appear. This +// dialog only allows 1 file to be selected. +SWFUpload.prototype.selectFile = function () { + this.callFlash("SelectFile"); +}; + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFiles causes a File Selection Dialog window to appear/ This +// dialog allows the user to select any number of files +// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names. +// If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around +// for this bug. +SWFUpload.prototype.selectFiles = function () { + this.callFlash("SelectFiles"); +}; + + +// Public: startUpload starts uploading the first file in the queue unless +// the optional parameter 'fileID' specifies the ID +SWFUpload.prototype.startUpload = function (fileID) { + this.callFlash("StartUpload", [fileID]); +}; + +// Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index. +// If you do not specify a fileID the current uploading file or first file in the queue is cancelled. +// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter. +SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) { + if (triggerErrorEvent !== false) { + triggerErrorEvent = true; + } + this.callFlash("CancelUpload", [fileID, triggerErrorEvent]); +}; + +// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue. +// If nothing is currently uploading then nothing happens. +SWFUpload.prototype.stopUpload = function () { + this.callFlash("StopUpload"); +}; + +/* ************************ + * Settings methods + * These methods change the SWFUpload settings. + * SWFUpload settings should not be changed directly on the settings object + * since many of the settings need to be passed to Flash in order to take + * effect. + * *********************** */ + +// Public: getStats gets the file statistics object. +SWFUpload.prototype.getStats = function () { + return this.callFlash("GetStats"); +}; + +// Public: setStats changes the SWFUpload statistics. You shouldn't need to +// change the statistics but you can. Changing the statistics does not +// affect SWFUpload accept for the successful_uploads count which is used +// by the upload_limit setting to determine how many files the user may upload. +SWFUpload.prototype.setStats = function (statsObject) { + this.callFlash("SetStats", [statsObject]); +}; + +// Public: getFile retrieves a File object by ID or Index. If the file is +// not found then 'null' is returned. +SWFUpload.prototype.getFile = function (fileID) { + if (typeof(fileID) === "number") { + return this.callFlash("GetFileByIndex", [fileID]); + } else { + return this.callFlash("GetFile", [fileID]); + } +}; + +// Public: addFileParam sets a name/value pair that will be posted with the +// file specified by the Files ID. If the name already exists then the +// exiting value will be overwritten. +SWFUpload.prototype.addFileParam = function (fileID, name, value) { + return this.callFlash("AddFileParam", [fileID, name, value]); +}; + +// Public: removeFileParam removes a previously set (by addFileParam) name/value +// pair from the specified file. +SWFUpload.prototype.removeFileParam = function (fileID, name) { + this.callFlash("RemoveFileParam", [fileID, name]); +}; + +// Public: setUploadUrl changes the upload_url setting. +SWFUpload.prototype.setUploadURL = function (url) { + this.settings.upload_url = url.toString(); + this.callFlash("SetUploadURL", [url]); +}; + +// Public: setPostParams changes the post_params setting +SWFUpload.prototype.setPostParams = function (paramsObject) { + this.settings.post_params = paramsObject; + this.callFlash("SetPostParams", [paramsObject]); +}; + +// Public: addPostParam adds post name/value pair. Each name can have only one value. +SWFUpload.prototype.addPostParam = function (name, value) { + this.settings.post_params[name] = value; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: removePostParam deletes post name/value pair. +SWFUpload.prototype.removePostParam = function (name) { + delete this.settings.post_params[name]; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: setFileTypes changes the file_types setting and the file_types_description setting +SWFUpload.prototype.setFileTypes = function (types, description) { + this.settings.file_types = types; + this.settings.file_types_description = description; + this.callFlash("SetFileTypes", [types, description]); +}; + +// Public: setFileSizeLimit changes the file_size_limit setting +SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) { + this.settings.file_size_limit = fileSizeLimit; + this.callFlash("SetFileSizeLimit", [fileSizeLimit]); +}; + +// Public: setFileUploadLimit changes the file_upload_limit setting +SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) { + this.settings.file_upload_limit = fileUploadLimit; + this.callFlash("SetFileUploadLimit", [fileUploadLimit]); +}; + +// Public: setFileQueueLimit changes the file_queue_limit setting +SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) { + this.settings.file_queue_limit = fileQueueLimit; + this.callFlash("SetFileQueueLimit", [fileQueueLimit]); +}; + +// Public: setFilePostName changes the file_post_name setting +SWFUpload.prototype.setFilePostName = function (filePostName) { + this.settings.file_post_name = filePostName; + this.callFlash("SetFilePostName", [filePostName]); +}; + +// Public: setUseQueryString changes the use_query_string setting +SWFUpload.prototype.setUseQueryString = function (useQueryString) { + this.settings.use_query_string = useQueryString; + this.callFlash("SetUseQueryString", [useQueryString]); +}; + +// Public: setRequeueOnError changes the requeue_on_error setting +SWFUpload.prototype.setRequeueOnError = function (requeueOnError) { + this.settings.requeue_on_error = requeueOnError; + this.callFlash("SetRequeueOnError", [requeueOnError]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) { + if (typeof http_status_codes === "string") { + http_status_codes = http_status_codes.replace(" ", "").split(","); + } + + this.settings.http_success = http_status_codes; + this.callFlash("SetHTTPSuccess", [http_status_codes]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) { + this.settings.assume_success_timeout = timeout_seconds; + this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]); +}; + +// Public: setDebugEnabled changes the debug_enabled setting +SWFUpload.prototype.setDebugEnabled = function (debugEnabled) { + this.settings.debug_enabled = debugEnabled; + this.callFlash("SetDebugEnabled", [debugEnabled]); +}; + +// Public: setButtonImageURL loads a button image sprite +SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) { + if (buttonImageURL == undefined) { + buttonImageURL = ""; + } + + this.settings.button_image_url = buttonImageURL; + this.callFlash("SetButtonImageURL", [buttonImageURL]); +}; + +// Public: setButtonDimensions resizes the Flash Movie and button +SWFUpload.prototype.setButtonDimensions = function (width, height) { + this.settings.button_width = width; + this.settings.button_height = height; + + var movie = this.getMovieElement(); + if (movie != undefined) { + movie.style.width = width + "px"; + movie.style.height = height + "px"; + } + + this.callFlash("SetButtonDimensions", [width, height]); +}; +// Public: setButtonText Changes the text overlaid on the button +SWFUpload.prototype.setButtonText = function (html) { + this.settings.button_text = html; + this.callFlash("SetButtonText", [html]); +}; +// Public: setButtonTextPadding changes the top and left padding of the text overlay +SWFUpload.prototype.setButtonTextPadding = function (left, top) { + this.settings.button_text_top_padding = top; + this.settings.button_text_left_padding = left; + this.callFlash("SetButtonTextPadding", [left, top]); +}; + +// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button +SWFUpload.prototype.setButtonTextStyle = function (css) { + this.settings.button_text_style = css; + this.callFlash("SetButtonTextStyle", [css]); +}; +// Public: setButtonDisabled disables/enables the button +SWFUpload.prototype.setButtonDisabled = function (isDisabled) { + this.settings.button_disabled = isDisabled; + this.callFlash("SetButtonDisabled", [isDisabled]); +}; +// Public: setButtonAction sets the action that occurs when the button is clicked +SWFUpload.prototype.setButtonAction = function (buttonAction) { + this.settings.button_action = buttonAction; + this.callFlash("SetButtonAction", [buttonAction]); +}; + +// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button +SWFUpload.prototype.setButtonCursor = function (cursor) { + this.settings.button_cursor = cursor; + this.callFlash("SetButtonCursor", [cursor]); +}; + +/* ******************************* + Flash Event Interfaces + These functions are used by Flash to trigger the various + events. + + All these functions a Private. + + Because the ExternalInterface library is buggy the event calls + are added to a queue and the queue then executed by a setTimeout. + This ensures that events are executed in a determinate order and that + the ExternalInterface bugs are avoided. +******************************* */ + +SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + if (argumentArray == undefined) { + argumentArray = []; + } else if (!(argumentArray instanceof Array)) { + argumentArray = [argumentArray]; + } + + var self = this; + if (typeof this.settings[handlerName] === "function") { + // Queue the event + this.eventQueue.push(function () { + this.settings[handlerName].apply(this, argumentArray); + }); + + // Execute the next queued event + setTimeout(function () { + self.executeNextEvent(); + }, 0); + + } else if (this.settings[handlerName] !== null) { + throw "Event handler " + handlerName + " is unknown or is not a function"; + } +}; + +// Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout +// we must queue them in order to garentee that they are executed in order. +SWFUpload.prototype.executeNextEvent = function () { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + var f = this.eventQueue ? this.eventQueue.shift() : null; + if (typeof(f) === "function") { + f.apply(this); + } +}; + +// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have +// properties that contain characters that are not valid for JavaScript identifiers. To work around this +// the Flash Component escapes the parameter names and we must unescape again before passing them along. +SWFUpload.prototype.unescapeFilePostParams = function (file) { + var reg = /[$]([0-9a-f]{4})/i; + var unescapedPost = {}; + var uk; + + if (file != undefined) { + for (var k in file.post) { + if (file.post.hasOwnProperty(k)) { + uk = k; + var match; + while ((match = reg.exec(uk)) !== null) { + uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16))); + } + unescapedPost[uk] = file.post[k]; + } + } + + file.post = unescapedPost; + } + + return file; +}; + +// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working) +SWFUpload.prototype.testExternalInterface = function () { + try { + return this.callFlash("TestExternalInterface"); + } catch (ex) { + return false; + } +}; + +// Private: This event is called by Flash when it has finished loading. Don't modify this. +// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded. +SWFUpload.prototype.flashReady = function () { + // Check that the movie element is loaded correctly with its ExternalInterface methods defined + var movieElement = this.getMovieElement(); + + if (!movieElement) { + this.debug("Flash called back ready but the flash movie can't be found."); + return; + } + + this.cleanUp(movieElement); + + this.queueEvent("swfupload_loaded_handler"); +}; + +// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE. +// This function is called by Flash each time the ExternalInterface functions are created. +SWFUpload.prototype.cleanUp = function (movieElement) { + // Pro-actively unhook all the Flash functions + try { + if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)"); + for (var key in movieElement) { + try { + if (typeof(movieElement[key]) === "function") { + movieElement[key] = null; + } + } catch (ex) { + } + } + } + } catch (ex1) { + + } + + // Fix Flashes own cleanup code so if the SWFMovie was removed from the page + // it doesn't display errors. + window["__flash__removeCallback"] = function (instance, name) { + try { + if (instance) { + instance[name] = null; + } + } catch (flashEx) { + + } + }; + +}; + + +/* This is a chance to do something before the browse window opens */ +SWFUpload.prototype.fileDialogStart = function () { + this.queueEvent("file_dialog_start_handler"); +}; + + +/* Called when a file is successfully added to the queue. */ +SWFUpload.prototype.fileQueued = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queued_handler", file); +}; + + +/* Handle errors that occur when an attempt to queue a file fails. */ +SWFUpload.prototype.fileQueueError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queue_error_handler", [file, errorCode, message]); +}; + +/* Called after the file dialog has closed and the selected files have been queued. + You could call startUpload here if you want the queued files to begin uploading immediately. */ +SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) { + this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]); +}; + +SWFUpload.prototype.uploadStart = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("return_upload_start_handler", file); +}; + +SWFUpload.prototype.returnUploadStart = function (file) { + var returnValue; + if (typeof this.settings.upload_start_handler === "function") { + file = this.unescapeFilePostParams(file); + returnValue = this.settings.upload_start_handler.call(this, file); + } else if (this.settings.upload_start_handler != undefined) { + throw "upload_start_handler must be a function"; + } + + // Convert undefined to true so if nothing is returned from the upload_start_handler it is + // interpretted as 'true'. + if (returnValue === undefined) { + returnValue = true; + } + + returnValue = !!returnValue; + + this.callFlash("ReturnUploadStart", [returnValue]); +}; + + + +SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]); +}; + +SWFUpload.prototype.uploadError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_error_handler", [file, errorCode, message]); +}; + +SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_success_handler", [file, serverData, responseReceived]); +}; + +SWFUpload.prototype.uploadComplete = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_complete_handler", file); +}; + +/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the + internal debug console. You can override this event and have messages written where you want. */ +SWFUpload.prototype.debug = function (message) { + this.queueEvent("debug_handler", message); +}; + + +/* ********************************** + Debug Console + The debug console is a self contained, in page location + for debug message to be sent. The Debug Console adds + itself to the body if necessary. + + The console is automatically scrolled as messages appear. + + If you are using your own debug handler or when you deploy to production and + have debug disabled you can remove these functions to reduce the file size + and complexity. +********************************** */ + +// Private: debugMessage is the default debug_handler. If you want to print debug messages +// call the debug() function. When overriding the function your own function should +// check to see if the debug setting is true before outputting debug information. +SWFUpload.prototype.debugMessage = function (message) { + if (this.settings.debug) { + var exceptionMessage, exceptionValues = []; + + // Check for an exception object and print it nicely + if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") { + for (var key in message) { + if (message.hasOwnProperty(key)) { + exceptionValues.push(key + ": " + message[key]); + } + } + exceptionMessage = exceptionValues.join("\n") || ""; + exceptionValues = exceptionMessage.split("\n"); + exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: "); + SWFUpload.Console.writeLine(exceptionMessage); + } else { + SWFUpload.Console.writeLine(message); + } + } +}; + +SWFUpload.Console = {}; +SWFUpload.Console.writeLine = function (message) { + var console, documentForm; + + try { + console = document.getElementById("SWFUpload_Console"); + + if (!console) { + documentForm = document.createElement("form"); + document.getElementsByTagName("body")[0].appendChild(documentForm); + + console = document.createElement("textarea"); + console.id = "SWFUpload_Console"; + console.style.fontFamily = "monospace"; + console.setAttribute("wrap", "off"); + console.wrap = "off"; + console.style.overflow = "auto"; + console.style.width = "700px"; + console.style.height = "350px"; + console.style.margin = "5px"; + documentForm.appendChild(console); + } + + console.value += message + "\n"; + + console.scrollTop = console.scrollHeight - console.clientHeight; + } catch (ex) { + alert("Exception: " + ex.name + " Message: " + ex.message); + } +}; + +})(); + +(function() { +/* + Queue Plug-in + + Features: + *Adds a cancelQueue() method for cancelling the entire queue. + *All queued files are uploaded when startUpload() is called. + *If false is returned from uploadComplete then the queue upload is stopped. + If false is not returned (strict comparison) then the queue upload is continued. + *Adds a QueueComplete event that is fired when all the queued files have finished uploading. + Set the event handler with the queue_complete_handler setting. + + */ + +if (typeof(SWFUpload) === "function") { + SWFUpload.queue = {}; + + SWFUpload.prototype.initSettings = (function (oldInitSettings) { + return function () { + if (typeof(oldInitSettings) === "function") { + oldInitSettings.call(this); + } + + this.queueSettings = {}; + + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + + this.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler; + this.queueSettings.user_upload_start_handler = this.settings.upload_start_handler; + this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler; + this.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler; + + this.settings.queue_complete_handler = this.settings.queue_complete_handler || null; + }; + })(SWFUpload.prototype.initSettings); + + SWFUpload.prototype.startUpload = function (fileID) { + this.queueSettings.queue_cancelled_flag = false; + this.callFlash("StartUpload", [fileID]); + }; + + SWFUpload.prototype.cancelQueue = function () { + this.queueSettings.queue_cancelled_flag = true; + this.stopUpload(); + + var stats = this.getStats(); + while (stats.files_queued > 0) { + this.cancelUpload(); + stats = this.getStats(); + } + }; + + SWFUpload.queue.uploadStartHandler = function (file) { + var returnValue; + if (typeof(this.queueSettings.user_upload_start_handler) === "function") { + returnValue = this.queueSettings.user_upload_start_handler.call(this, file); + } + + // To prevent upload a real "FALSE" value must be returned, otherwise default to a real "TRUE" value. + returnValue = (returnValue === false) ? false : true; + + this.queueSettings.queue_cancelled_flag = !returnValue; + + return returnValue; + }; + + SWFUpload.queue.uploadCompleteHandler = function (file) { + var user_upload_complete_handler = this.queueSettings.user_upload_complete_handler; + var continueUpload; + + if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) { + this.queueSettings.queue_upload_count++; + } + + if (typeof(user_upload_complete_handler) === "function") { + continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true; + } else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) { + // If the file was stopped and re-queued don't restart the upload + continueUpload = false; + } else { + continueUpload = true; + } + + if (continueUpload) { + var stats = this.getStats(); + if (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) { + this.startUpload(); + } else if (this.queueSettings.queue_cancelled_flag === false) { + this.queueEvent("queue_complete_handler", [this.queueSettings.queue_upload_count]); + this.queueSettings.queue_upload_count = 0; + } else { + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + } + } + }; +} + +})(); diff --git a/public/assets/kindeditor/plugins/pagebreak/pagebreak.js b/public/assets/kindeditor/plugins/pagebreak/pagebreak.js new file mode 100644 index 000000000..dfa883afc --- /dev/null +++ b/public/assets/kindeditor/plugins/pagebreak/pagebreak.js @@ -0,0 +1,27 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('pagebreak', function(K) { + var self = this; + var name = 'pagebreak'; + var pagebreakHtml = K.undef(self.pagebreakHtml, '
    '); + + self.clickToolbar(name, function() { + var cmd = self.cmd, range = cmd.range; + self.focus(); + var tail = self.newlineTag == 'br' || K.WEBKIT ? '' : ''; + self.insertHtml(pagebreakHtml + tail); + if (tail !== '') { + var p = K('#__kindeditor_tail_tag__', self.edit.doc); + range.selectNodeContents(p[0]); + p.removeAttr('id'); + cmd.select(); + } + }); +}); diff --git a/public/assets/kindeditor/plugins/plainpaste/plainpaste.js b/public/assets/kindeditor/plugins/plainpaste/plainpaste.js new file mode 100644 index 000000000..8f7bed803 --- /dev/null +++ b/public/assets/kindeditor/plugins/plainpaste/plainpaste.js @@ -0,0 +1,41 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('plainpaste', function(K) { + var self = this, name = 'plainpaste'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '
    ' + + '
    ' + lang.comment + '
    ' + + '' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var html = textarea.val(); + html = K.escape(html); + html = html.replace(/ {2}/g, '  '); + if (self.newlineTag == 'p') { + html = html.replace(/^/, '

    ').replace(/$/, '

    ').replace(/\n/g, '

    '); + } else { + html = html.replace(/\n/g, '
    $&'); + } + self.insertHtml(html).hideDialog().focus(); + } + } + }), + textarea = K('textarea', dialog.div); + textarea[0].focus(); + }); +}); diff --git a/public/assets/kindeditor/plugins/preview/preview.js b/public/assets/kindeditor/plugins/preview/preview.js new file mode 100644 index 000000000..ef6e2cf16 --- /dev/null +++ b/public/assets/kindeditor/plugins/preview/preview.js @@ -0,0 +1,31 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('preview', function(K) { + var self = this, name = 'preview', undefined; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '

    ' + + '' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 750, + title : self.lang(name), + body : html + }), + iframe = K('iframe', dialog.div), + doc = K.iframeDoc(iframe); + doc.open(); + doc.write(self.fullHtml()); + doc.close(); + K(doc.body).css('background-color', '#FFF'); + iframe[0].contentWindow.focus(); + }); +}); diff --git a/public/assets/kindeditor/plugins/quickformat/quickformat.js b/public/assets/kindeditor/plugins/quickformat/quickformat.js new file mode 100644 index 000000000..5b98c7227 --- /dev/null +++ b/public/assets/kindeditor/plugins/quickformat/quickformat.js @@ -0,0 +1,81 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('quickformat', function(K) { + var self = this, name = 'quickformat', + blockMap = K.toMap('blockquote,center,div,h1,h2,h3,h4,h5,h6,p'); + function getFirstChild(knode) { + var child = knode.first(); + while (child && child.first()) { + child = child.first(); + } + return child; + } + self.clickToolbar(name, function() { + self.focus(); + var doc = self.edit.doc, + range = self.cmd.range, + child = K(doc.body).first(), next, + nodeList = [], subList = [], + bookmark = range.createBookmark(true); + while(child) { + next = child.next(); + var firstChild = getFirstChild(child); + if (!firstChild || firstChild.name != 'img') { + if (blockMap[child.name]) { + child.html(child.html().replace(/^(\s| | )+/ig, '')); + child.css('text-indent', '2em'); + } else { + subList.push(child); + } + if (!next || (blockMap[next.name] || blockMap[child.name] && !blockMap[next.name])) { + if (subList.length > 0) { + nodeList.push(subList); + } + subList = []; + } + } + child = next; + } + K.each(nodeList, function(i, subList) { + var wrapper = K('

    ', doc); + subList[0].before(wrapper); + K.each(subList, function(i, knode) { + wrapper.append(knode); + }); + }); + range.moveToBookmark(bookmark); + self.addBookmark(); + }); +}); + +/** +-------------------------- +abcd
    +1234
    + +to + +

    + abcd
    + 1234
    +

    + +-------------------------- + +  abcd1233 +

    1234

    + +to + +

    abcd1233

    +

    1234

    + +-------------------------- +*/ \ No newline at end of file diff --git a/public/assets/kindeditor/plugins/table/table.js b/public/assets/kindeditor/plugins/table/table.js new file mode 100644 index 000000000..4033b6ae3 --- /dev/null +++ b/public/assets/kindeditor/plugins/table/table.js @@ -0,0 +1,712 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('table', function(K) { + var self = this, name = 'table', lang = self.lang(name + '.'), zeroborder = 'ke-zeroborder'; + // 设置颜色 + function _setColor(box, color) { + color = color.toUpperCase(); + box.css('background-color', color); + box.css('color', color === '#000000' ? '#FFFFFF' : '#000000'); + box.html(color); + } + // 初始化取色器 + var pickerList = []; + function _initColorPicker(dialogDiv, colorBox) { + colorBox.bind('click,mousedown', function(e){ + e.stopPropagation(); + }); + function removePicker() { + K.each(pickerList, function() { + this.remove(); + }); + pickerList = []; + K(document).unbind('click,mousedown', removePicker); + dialogDiv.unbind('click,mousedown', removePicker); + } + colorBox.click(function(e) { + removePicker(); + var box = K(this), + pos = box.pos(); + var picker = K.colorpicker({ + x : pos.x, + y : pos.y + box.height(), + z : 811214, + selectedColor : K(this).html(), + colors : self.colorTable, + noColor : self.lang('noColor'), + shadowMode : self.shadowMode, + click : function(color) { + _setColor(box, color); + removePicker(); + } + }); + pickerList.push(picker); + K(document).bind('click,mousedown', removePicker); + dialogDiv.bind('click,mousedown', removePicker); + }); + } + // 取得下一行cell的index + function _getCellIndex(table, row, cell) { + var rowSpanCount = 0; + for (var i = 0, len = row.cells.length; i < len; i++) { + if (row.cells[i] == cell) { + break; + } + rowSpanCount += row.cells[i].rowSpan - 1; + } + return cell.cellIndex - rowSpanCount; + } + self.plugin.table = { + //insert or modify table + prop : function(isInsert) { + var html = [ + '
    ', + //rows, cols + '
    ', + '', + lang.rows + '   ', + lang.cols + ' ', + '
    ', + //width, height + '
    ', + '', + lang.width + '   ', + '   ', + lang.height + '   ', + '', + '
    ', + //space, padding + '
    ', + '', + lang.padding + '   ', + lang.spacing + ' ', + '
    ', + //align + '
    ', + '', + '', + '
    ', + //border + '
    ', + '', + lang.borderWidth + '   ', + lang.borderColor + ' ', + '
    ', + //background color + '
    ', + '', + '', + '
    ', + '
    ' + ].join(''); + var bookmark = self.cmd.range.createBookmark(); + var dialog = self.createDialog({ + name : name, + width : 500, + title : self.lang(name), + body : html, + beforeRemove : function() { + colorBox.unbind(); + }, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var rows = rowsBox.val(), + cols = colsBox.val(), + width = widthBox.val(), + height = heightBox.val(), + widthType = widthTypeBox.val(), + heightType = heightTypeBox.val(), + padding = paddingBox.val(), + spacing = spacingBox.val(), + align = alignBox.val(), + border = borderBox.val(), + borderColor = K(colorBox[0]).html() || '', + bgColor = K(colorBox[1]).html() || ''; + if (rows == 0 || !/^\d+$/.test(rows)) { + alert(self.lang('invalidRows')); + rowsBox[0].focus(); + return; + } + if (cols == 0 || !/^\d+$/.test(cols)) { + alert(self.lang('invalidRows')); + colsBox[0].focus(); + return; + } + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + if (!/^\d*$/.test(padding)) { + alert(self.lang('invalidPadding')); + paddingBox[0].focus(); + return; + } + if (!/^\d*$/.test(spacing)) { + alert(self.lang('invalidSpacing')); + spacingBox[0].focus(); + return; + } + if (!/^\d*$/.test(border)) { + alert(self.lang('invalidBorder')); + borderBox[0].focus(); + return; + } + //modify table + if (table) { + if (width !== '') { + table.width(width + widthType); + } else { + table.css('width', ''); + } + if (table[0].width !== undefined) { + table.removeAttr('width'); + } + if (height !== '') { + table.height(height + heightType); + } else { + table.css('height', ''); + } + if (table[0].height !== undefined) { + table.removeAttr('height'); + } + table.css('background-color', bgColor); + if (table[0].bgColor !== undefined) { + table.removeAttr('bgColor'); + } + if (padding !== '') { + table[0].cellPadding = padding; + } else { + table.removeAttr('cellPadding'); + } + if (spacing !== '') { + table[0].cellSpacing = spacing; + } else { + table.removeAttr('cellSpacing'); + } + if (align !== '') { + table[0].align = align; + } else { + table.removeAttr('align'); + } + if (border !== '') { + table.attr('border', border); + } else { + table.removeAttr('border'); + } + if (border === '' || border === '0') { + table.addClass(zeroborder); + } else { + table.removeClass(zeroborder); + } + if (borderColor !== '') { + table.attr('borderColor', borderColor); + } else { + table.removeAttr('borderColor'); + } + self.hideDialog().focus(); + self.cmd.range.moveToBookmark(bookmark); + self.cmd.select(); + self.addBookmark(); + return; + } + //insert new table + var style = ''; + if (width !== '') { + style += 'width:' + width + widthType + ';'; + } + if (height !== '') { + style += 'height:' + height + heightType + ';'; + } + if (bgColor !== '') { + style += 'background-color:' + bgColor + ';'; + } + var html = '') + ''; + } + html += ''; + } + html += ''; + if (!K.IE) { + html += '
    '; + } + self.insertHtml(html); + self.select().hideDialog().focus(); + self.addBookmark(); + } + } + }), + div = dialog.div, + rowsBox = K('[name="rows"]', div).val(3), + colsBox = K('[name="cols"]', div).val(2), + widthBox = K('[name="width"]', div).val(100), + heightBox = K('[name="height"]', div), + widthTypeBox = K('[name="widthType"]', div), + heightTypeBox = K('[name="heightType"]', div), + paddingBox = K('[name="padding"]', div).val(2), + spacingBox = K('[name="spacing"]', div).val(0), + alignBox = K('[name="align"]', div), + borderBox = K('[name="border"]', div).val(1), + colorBox = K('.ke-input-color', div); + _initColorPicker(div, colorBox.eq(0)); + _initColorPicker(div, colorBox.eq(1)); + _setColor(colorBox.eq(0), '#000000'); + _setColor(colorBox.eq(1), ''); + // foucs and select + rowsBox[0].focus(); + rowsBox[0].select(); + var table; + if (isInsert) { + return; + } + //get selected table node + table = self.plugin.getSelectedTable(); + if (table) { + rowsBox.val(table[0].rows.length); + colsBox.val(table[0].rows.length > 0 ? table[0].rows[0].cells.length : 0); + rowsBox.attr('disabled', true); + colsBox.attr('disabled', true); + var match, + tableWidth = table[0].style.width || table[0].width, + tableHeight = table[0].style.height || table[0].height; + if (tableWidth !== undefined && (match = /^(\d+)((?:px|%)*)$/.exec(tableWidth))) { + widthBox.val(match[1]); + widthTypeBox.val(match[2]); + } else { + widthBox.val(''); + } + if (tableHeight !== undefined && (match = /^(\d+)((?:px|%)*)$/.exec(tableHeight))) { + heightBox.val(match[1]); + heightTypeBox.val(match[2]); + } + paddingBox.val(table[0].cellPadding || ''); + spacingBox.val(table[0].cellSpacing || ''); + alignBox.val(table[0].align || ''); + borderBox.val(table[0].border === undefined ? '' : table[0].border); + _setColor(colorBox.eq(0), K.toHex(table.attr('borderColor') || '')); + _setColor(colorBox.eq(1), K.toHex(table[0].style.backgroundColor || table[0].bgColor || '')); + widthBox[0].focus(); + widthBox[0].select(); + } + }, + //modify cell + cellprop : function() { + var html = [ + '
    ', + //width, height + '
    ', + '', + lang.width + '   ', + '   ', + lang.height + '   ', + '', + '
    ', + //align + '
    ', + '', + lang.textAlign + ' ', + lang.verticalAlign + ' ', + '
    ', + //border + '
    ', + '', + lang.borderWidth + '   ', + lang.borderColor + ' ', + '
    ', + //background color + '
    ', + '', + '', + '
    ', + '
    ' + ].join(''); + var bookmark = self.cmd.range.createBookmark(); + var dialog = self.createDialog({ + name : name, + width : 500, + title : self.lang('tablecell'), + body : html, + beforeRemove : function() { + colorBox.unbind(); + }, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var width = widthBox.val(), + height = heightBox.val(), + widthType = widthTypeBox.val(), + heightType = heightTypeBox.val(), + padding = paddingBox.val(), + spacing = spacingBox.val(), + textAlign = textAlignBox.val(), + verticalAlign = verticalAlignBox.val(), + border = borderBox.val(), + borderColor = K(colorBox[0]).html() || '', + bgColor = K(colorBox[1]).html() || ''; + if (!/^\d*$/.test(width)) { + alert(self.lang('invalidWidth')); + widthBox[0].focus(); + return; + } + if (!/^\d*$/.test(height)) { + alert(self.lang('invalidHeight')); + heightBox[0].focus(); + return; + } + if (!/^\d*$/.test(border)) { + alert(self.lang('invalidBorder')); + borderBox[0].focus(); + return; + } + cell.css({ + width : width !== '' ? (width + widthType) : '', + height : height !== '' ? (height + heightType) : '', + 'background-color' : bgColor, + 'text-align' : textAlign, + 'vertical-align' : verticalAlign, + 'border-width' : border, + 'border-style' : border !== '' ? 'solid' : '', + 'border-color' : borderColor + }); + self.hideDialog().focus(); + self.cmd.range.moveToBookmark(bookmark); + self.cmd.select(); + self.addBookmark(); + } + } + }), + div = dialog.div, + widthBox = K('[name="width"]', div).val(100), + heightBox = K('[name="height"]', div), + widthTypeBox = K('[name="widthType"]', div), + heightTypeBox = K('[name="heightType"]', div), + paddingBox = K('[name="padding"]', div).val(2), + spacingBox = K('[name="spacing"]', div).val(0), + textAlignBox = K('[name="textAlign"]', div), + verticalAlignBox = K('[name="verticalAlign"]', div), + borderBox = K('[name="border"]', div).val(1), + colorBox = K('.ke-input-color', div); + _initColorPicker(div, colorBox.eq(0)); + _initColorPicker(div, colorBox.eq(1)); + _setColor(colorBox.eq(0), '#000000'); + _setColor(colorBox.eq(1), ''); + // foucs and select + widthBox[0].focus(); + widthBox[0].select(); + // get selected cell + var cell = self.plugin.getSelectedCell(); + var match, + cellWidth = cell[0].style.width || cell[0].width || '', + cellHeight = cell[0].style.height || cell[0].height || ''; + if ((match = /^(\d+)((?:px|%)*)$/.exec(cellWidth))) { + widthBox.val(match[1]); + widthTypeBox.val(match[2]); + } else { + widthBox.val(''); + } + if ((match = /^(\d+)((?:px|%)*)$/.exec(cellHeight))) { + heightBox.val(match[1]); + heightTypeBox.val(match[2]); + } + textAlignBox.val(cell[0].style.textAlign || ''); + verticalAlignBox.val(cell[0].style.verticalAlign || ''); + var border = cell[0].style.borderWidth || ''; + if (border) { + border = parseInt(border); + } + borderBox.val(border); + _setColor(colorBox.eq(0), K.toHex(cell[0].style.borderColor || '')); + _setColor(colorBox.eq(1), K.toHex(cell[0].style.backgroundColor || '')); + widthBox[0].focus(); + widthBox[0].select(); + }, + insert : function() { + this.prop(true); + }, + 'delete' : function() { + var table = self.plugin.getSelectedTable(); + self.cmd.range.setStartBefore(table[0]).collapse(true); + self.cmd.select(); + table.remove(); + self.addBookmark(); + }, + colinsert : function(offset) { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + index = cell.cellIndex + offset; + // 取得第一行的index + index += table.rows[0].cells.length - row.cells.length; + + for (var i = 0, len = table.rows.length; i < len; i++) { + var newRow = table.rows[i], + newCell = newRow.insertCell(index); + newCell.innerHTML = K.IE ? '' : '
    '; + // 调整下一行的单元格index + index = _getCellIndex(table, newRow, newCell); + } + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + colinsertleft : function() { + this.colinsert(0); + }, + colinsertright : function() { + this.colinsert(1); + }, + rowinsert : function(offset) { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0]; + var rowIndex = row.rowIndex; + if (offset === 1) { + rowIndex = row.rowIndex + (cell.rowSpan - 1) + offset; + } + var newRow = table.insertRow(rowIndex); + + for (var i = 0, len = row.cells.length; i < len; i++) { + // 调整cell个数 + if (row.cells[i].rowSpan > 1) { + len -= row.cells[i].rowSpan - 1; + } + var newCell = newRow.insertCell(i); + // copy colspan + if (offset === 1 && row.cells[i].colSpan > 1) { + newCell.colSpan = row.cells[i].colSpan; + } + newCell.innerHTML = K.IE ? '' : '
    '; + } + // 调整rowspan + for (var j = rowIndex; j >= 0; j--) { + var cells = table.rows[j].cells; + if (cells.length > i) { + for (var k = cell.cellIndex; k >= 0; k--) { + if (cells[k].rowSpan > 1) { + cells[k].rowSpan += 1; + } + } + break; + } + } + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + rowinsertabove : function() { + this.rowinsert(0); + }, + rowinsertbelow : function() { + this.rowinsert(1); + }, + rowmerge : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex, // 当前行的index + nextRowIndex = rowIndex + cell.rowSpan, // 下一行的index + nextRow = table.rows[nextRowIndex]; // 下一行 + // 最后一行不能合并 + if (table.rows.length <= nextRowIndex) { + return; + } + var cellIndex = cell.cellIndex; // 下一行单元格的index + if (nextRow.cells.length <= cellIndex) { + return; + } + var nextCell = nextRow.cells[cellIndex]; // 下一行单元格 + // 上下行的colspan不一致时不能合并 + if (cell.colSpan !== nextCell.colSpan) { + return; + } + cell.rowSpan += nextCell.rowSpan; + nextRow.deleteCell(cellIndex); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + colmerge : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex, // 当前行的index + cellIndex = cell.cellIndex, + nextCellIndex = cellIndex + 1; + // 最后一列不能合并 + if (row.cells.length <= nextCellIndex) { + return; + } + var nextCell = row.cells[nextCellIndex]; + // 左右列的rowspan不一致时不能合并 + if (cell.rowSpan !== nextCell.rowSpan) { + return; + } + cell.colSpan += nextCell.colSpan; + row.deleteCell(nextCellIndex); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + rowsplit : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex; + // 不是可分割单元格 + if (cell.rowSpan === 1) { + return; + } + var cellIndex = _getCellIndex(table, row, cell); + for (var i = 1, len = cell.rowSpan; i < len; i++) { + var newRow = table.rows[rowIndex + i], + newCell = newRow.insertCell(cellIndex); + if (cell.colSpan > 1) { + newCell.colSpan = cell.colSpan; + } + newCell.innerHTML = K.IE ? '' : '
    '; + // 调整下一行的单元格index + cellIndex = _getCellIndex(table, newRow, newCell); + } + K(cell).removeAttr('rowSpan'); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + colsplit : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + cellIndex = cell.cellIndex; + // 不是可分割单元格 + if (cell.colSpan === 1) { + return; + } + for (var i = 1, len = cell.colSpan; i < len; i++) { + var newCell = row.insertCell(cellIndex + i); + if (cell.rowSpan > 1) { + newCell.rowSpan = cell.rowSpan; + } + newCell.innerHTML = K.IE ? '' : '
    '; + } + K(cell).removeAttr('colSpan'); + self.cmd.range.selectNodeContents(cell).collapse(true); + self.cmd.select(); + self.addBookmark(); + }, + coldelete : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + index = cell.cellIndex; + for (var i = 0, len = table.rows.length; i < len; i++) { + var newRow = table.rows[i], + newCell = newRow.cells[index]; + if (newCell.colSpan > 1) { + newCell.colSpan -= 1; + if (newCell.colSpan === 1) { + K(newCell).removeAttr('colSpan'); + } + } else { + newRow.deleteCell(index); + } + // 跳过不需要删除的行 + if (newCell.rowSpan > 1) { + i += newCell.rowSpan - 1; + } + } + if (row.cells.length === 0) { + self.cmd.range.setStartBefore(table).collapse(true); + self.cmd.select(); + K(table).remove(); + } else { + self.cmd.selection(true); + } + self.addBookmark(); + }, + rowdelete : function() { + var table = self.plugin.getSelectedTable()[0], + row = self.plugin.getSelectedRow()[0], + cell = self.plugin.getSelectedCell()[0], + rowIndex = row.rowIndex; + // 从下到上删除 + for (var i = cell.rowSpan - 1; i >= 0; i--) { + table.deleteRow(rowIndex + i); + } + if (table.rows.length === 0) { + self.cmd.range.setStartBefore(table).collapse(true); + self.cmd.select(); + K(table).remove(); + } else { + self.cmd.selection(true); + } + self.addBookmark(); + } + }; + self.clickToolbar(name, self.plugin.table.prop); +}); diff --git a/public/assets/kindeditor/plugins/template/html/1.html b/public/assets/kindeditor/plugins/template/html/1.html new file mode 100644 index 000000000..034126b72 --- /dev/null +++ b/public/assets/kindeditor/plugins/template/html/1.html @@ -0,0 +1,14 @@ + + + + + + +

    + 在此处输入标题 +

    +

    + 在此处输入内容 +

    + + \ No newline at end of file diff --git a/public/assets/kindeditor/plugins/template/html/2.html b/public/assets/kindeditor/plugins/template/html/2.html new file mode 100644 index 000000000..dc2584a0d --- /dev/null +++ b/public/assets/kindeditor/plugins/template/html/2.html @@ -0,0 +1,42 @@ + + + + + + +

    + 标题 +

    + + + + + + + + + + + + + + + +
    +

    标题1

    +
    +

    标题1

    +
    + 内容1 + + 内容2 +
    + 内容3 + + 内容4 +
    +

    + 表格说明 +

    + + \ No newline at end of file diff --git a/public/assets/kindeditor/plugins/template/html/3.html b/public/assets/kindeditor/plugins/template/html/3.html new file mode 100644 index 000000000..873f0c65d --- /dev/null +++ b/public/assets/kindeditor/plugins/template/html/3.html @@ -0,0 +1,36 @@ + + + + + + +

    + 在此处输入内容 +

    +
      +
    1. + 描述1 +
    2. +
    3. + 描述2 +
    4. +
    5. + 描述3 +
    6. +
    +

    + 在此处输入内容 +

    +
      +
    • + 描述1 +
    • +
    • + 描述2 +
    • +
    • + 描述3 +
    • +
    + + \ No newline at end of file diff --git a/public/assets/kindeditor/plugins/template/template.js b/public/assets/kindeditor/plugins/template/template.js new file mode 100644 index 000000000..4029e8716 --- /dev/null +++ b/public/assets/kindeditor/plugins/template/template.js @@ -0,0 +1,58 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('template', function(K) { + var self = this, name = 'template', lang = self.lang(name + '.'), + htmlPath = self.pluginsPath + name + '/html/'; + function getFilePath(fileName) { + return htmlPath + fileName + '?ver=' + encodeURIComponent(K.DEBUG ? K.TIME : K.VERSION); + } + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + arr = ['
    ', + '
    ', + // left start + '
    ', + lang. selectTemplate + '
    ', + // right start + '
    ', + ' ', + '
    ', + '
    ', + '
    ', + '', + '
    '].join(''); + var dialog = self.createDialog({ + name : name, + width : 500, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var doc = K.iframeDoc(iframe); + self[checkbox[0].checked ? 'html' : 'insertHtml'](doc.body.innerHTML).hideDialog().focus(); + } + } + }); + var selectBox = K('select', dialog.div), + checkbox = K('[name="replaceFlag"]', dialog.div), + iframe = K('iframe', dialog.div); + checkbox[0].checked = true; + iframe.attr('src', getFilePath(selectBox.val())); + selectBox.change(function() { + iframe.attr('src', getFilePath(this.value)); + }); + }); +}); diff --git a/public/assets/kindeditor/plugins/wordpaste/wordpaste.js b/public/assets/kindeditor/plugins/wordpaste/wordpaste.js new file mode 100644 index 000000000..22061e15e --- /dev/null +++ b/public/assets/kindeditor/plugins/wordpaste/wordpaste.js @@ -0,0 +1,51 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('wordpaste', function(K) { + var self = this, name = 'wordpaste'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '
    ' + + '
    ' + lang.comment + '
    ' + + '' + + '
    ', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var str = doc.body.innerHTML; + str = K.clearMsWord(str, self.filterMode ? self.htmlTags : K.options.htmlTags); + self.insertHtml(str).hideDialog().focus(); + } + } + }), + div = dialog.div, + iframe = K('iframe', div), + doc = K.iframeDoc(iframe); + if (!K.IE) { + doc.designMode = 'on'; + } + doc.open(); + doc.write('WordPaste'); + doc.write(''); + if (!K.IE) { + doc.write('
    '); + } + doc.write(''); + doc.close(); + if (K.IE) { + doc.body.contentEditable = 'true'; + } + iframe[0].contentWindow.focus(); + }); +}); diff --git a/public/assets/kindeditor/themes/common/anchor.gif b/public/assets/kindeditor/themes/common/anchor.gif new file mode 100644 index 000000000..61145ea78 Binary files /dev/null and b/public/assets/kindeditor/themes/common/anchor.gif differ diff --git a/public/assets/kindeditor/themes/common/blank.gif b/public/assets/kindeditor/themes/common/blank.gif new file mode 100644 index 000000000..5bfd67a2d Binary files /dev/null and b/public/assets/kindeditor/themes/common/blank.gif differ diff --git a/public/assets/kindeditor/themes/common/flash.gif b/public/assets/kindeditor/themes/common/flash.gif new file mode 100644 index 000000000..2cb12b284 Binary files /dev/null and b/public/assets/kindeditor/themes/common/flash.gif differ diff --git a/public/assets/kindeditor/themes/common/loading.gif b/public/assets/kindeditor/themes/common/loading.gif new file mode 100644 index 000000000..c69e93723 Binary files /dev/null and b/public/assets/kindeditor/themes/common/loading.gif differ diff --git a/public/assets/kindeditor/themes/common/media.gif b/public/assets/kindeditor/themes/common/media.gif new file mode 100644 index 000000000..e1c0e30af Binary files /dev/null and b/public/assets/kindeditor/themes/common/media.gif differ diff --git a/public/assets/kindeditor/themes/common/rm.gif b/public/assets/kindeditor/themes/common/rm.gif new file mode 100644 index 000000000..d013d551d Binary files /dev/null and b/public/assets/kindeditor/themes/common/rm.gif differ diff --git a/public/assets/kindeditor/themes/default/background.png b/public/assets/kindeditor/themes/default/background.png new file mode 100644 index 000000000..bbfb056bd Binary files /dev/null and b/public/assets/kindeditor/themes/default/background.png differ diff --git a/public/assets/kindeditor/themes/default/default.css b/public/assets/kindeditor/themes/default/default.css new file mode 100644 index 000000000..428b6c8b5 --- /dev/null +++ b/public/assets/kindeditor/themes/default/default.css @@ -0,0 +1,1149 @@ +/* common */ +.ke-inline-block { + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; + zoom: 1; + *display: inline; +} +.ke-clearfix { + zoom: 1; +} +.ke-clearfix:after { + content: "."; + display: block; + clear: both; + font-size: 0; + height: 0; + line-height: 0; + visibility: hidden; +} +.ke-shadow { + box-shadow: 1px 1px 3px #A0A0A0; + -moz-box-shadow: 1px 1px 3px #A0A0A0; + -webkit-box-shadow: 1px 1px 3px #A0A0A0; + filter: progid:DXImageTransform.Microsoft.Shadow(color='#A0A0A0', Direction=135, Strength=3); + background-color: #F0F0EE; +} +.ke-menu a, +.ke-menu a:hover, +.ke-dialog a, +.ke-dialog a:hover { + color: #337FE5; + text-decoration: none; +} +/* icons */ +.ke-icon-source { + background-position: 0px 0px; + width: 16px; + height: 16px; +} +.ke-icon-preview { + background-position: 0px -16px; + width: 16px; + height: 16px; +} +.ke-icon-print { + background-position: 0px -32px; + width: 16px; + height: 16px; +} +.ke-icon-undo { + background-position: 0px -48px; + width: 16px; + height: 16px; +} +.ke-icon-redo { + background-position: 0px -64px; + width: 16px; + height: 16px; +} +.ke-icon-cut { + background-position: 0px -80px; + width: 16px; + height: 16px; +} +.ke-icon-copy { + background-position: 0px -96px; + width: 16px; + height: 16px; +} +.ke-icon-paste { + background-position: 0px -112px; + width: 16px; + height: 16px; +} +.ke-icon-selectall { + background-position: 0px -128px; + width: 16px; + height: 16px; +} +.ke-icon-justifyleft { + background-position: 0px -144px; + width: 16px; + height: 16px; +} +.ke-icon-justifycenter { + background-position: 0px -160px; + width: 16px; + height: 16px; +} +.ke-icon-justifyright { + background-position: 0px -176px; + width: 16px; + height: 16px; +} +.ke-icon-justifyfull { + background-position: 0px -192px; + width: 16px; + height: 16px; +} +.ke-icon-insertorderedlist { + background-position: 0px -208px; + width: 16px; + height: 16px; +} +.ke-icon-insertunorderedlist { + background-position: 0px -224px; + width: 16px; + height: 16px; +} +.ke-icon-indent { + background-position: 0px -240px; + width: 16px; + height: 16px; +} +.ke-icon-outdent { + background-position: 0px -256px; + width: 16px; + height: 16px; +} +.ke-icon-subscript { + background-position: 0px -272px; + width: 16px; + height: 16px; +} +.ke-icon-superscript { + background-position: 0px -288px; + width: 16px; + height: 16px; +} +.ke-icon-date { + background-position: 0px -304px; + width: 25px; + height: 16px; +} +.ke-icon-time { + background-position: 0px -320px; + width: 25px; + height: 16px; +} +.ke-icon-formatblock { + background-position: 0px -336px; + width: 25px; + height: 16px; +} +.ke-icon-fontname { + background-position: 0px -352px; + width: 21px; + height: 16px; +} +.ke-icon-fontsize { + background-position: 0px -368px; + width: 23px; + height: 16px; +} +.ke-icon-forecolor { + background-position: 0px -384px; + width: 20px; + height: 16px; +} +.ke-icon-hilitecolor { + background-position: 0px -400px; + width: 23px; + height: 16px; +} +.ke-icon-bold { + background-position: 0px -416px; + width: 16px; + height: 16px; +} +.ke-icon-italic { + background-position: 0px -432px; + width: 16px; + height: 16px; +} +.ke-icon-underline { + background-position: 0px -448px; + width: 16px; + height: 16px; +} +.ke-icon-strikethrough { + background-position: 0px -464px; + width: 16px; + height: 16px; +} +.ke-icon-removeformat { + background-position: 0px -480px; + width: 16px; + height: 16px; +} +.ke-icon-image { + background-position: 0px -496px; + width: 16px; + height: 16px; +} +.ke-icon-flash { + background-position: 0px -512px; + width: 16px; + height: 16px; +} +.ke-icon-media { + background-position: 0px -528px; + width: 16px; + height: 16px; +} +.ke-icon-div { + background-position: 0px -544px; + width: 16px; + height: 16px; +} +.ke-icon-formula { + background-position: 0px -576px; + width: 16px; + height: 16px; +} +.ke-icon-hr { + background-position: 0px -592px; + width: 16px; + height: 16px; +} +.ke-icon-emoticons { + background-position: 0px -608px; + width: 16px; + height: 16px; +} +.ke-icon-link { + background-position: 0px -624px; + width: 16px; + height: 16px; +} +.ke-icon-unlink { + background-position: 0px -640px; + width: 16px; + height: 16px; +} +.ke-icon-fullscreen { + background-position: 0px -656px; + width: 16px; + height: 16px; +} +.ke-icon-about { + background-position: 0px -672px; + width: 16px; + height: 16px; +} +.ke-icon-plainpaste { + background-position: 0px -704px; + width: 16px; + height: 16px; +} +.ke-icon-wordpaste { + background-position: 0px -720px; + width: 16px; + height: 16px; +} +.ke-icon-table { + background-position: 0px -784px; + width: 16px; + height: 16px; +} +.ke-icon-tablemenu { + background-position: 0px -768px; + width: 16px; + height: 16px; +} +.ke-icon-tableinsert { + background-position: 0px -784px; + width: 16px; + height: 16px; +} +.ke-icon-tabledelete { + background-position: 0px -800px; + width: 16px; + height: 16px; +} +.ke-icon-tablecolinsertleft { + background-position: 0px -816px; + width: 16px; + height: 16px; +} +.ke-icon-tablecolinsertright { + background-position: 0px -832px; + width: 16px; + height: 16px; +} +.ke-icon-tablerowinsertabove { + background-position: 0px -848px; + width: 16px; + height: 16px; +} +.ke-icon-tablerowinsertbelow { + background-position: 0px -864px; + width: 16px; + height: 16px; +} +.ke-icon-tablecoldelete { + background-position: 0px -880px; + width: 16px; + height: 16px; +} +.ke-icon-tablerowdelete { + background-position: 0px -896px; + width: 16px; + height: 16px; +} +.ke-icon-tablecellprop { + background-position: 0px -912px; + width: 16px; + height: 16px; +} +.ke-icon-tableprop { + background-position: 0px -928px; + width: 16px; + height: 16px; +} +.ke-icon-checked { + background-position: 0px -944px; + width: 16px; + height: 16px; +} +.ke-icon-code { + background-position: 0px -960px; + width: 16px; + height: 16px; +} +.ke-icon-map { + background-position: 0px -976px; + width: 16px; + height: 16px; +} +.ke-icon-baidumap { + background-position: 0px -976px; + width: 16px; + height: 16px; +} +.ke-icon-lineheight { + background-position: 0px -992px; + width: 16px; + height: 16px; +} +.ke-icon-clearhtml { + background-position: 0px -1008px; + width: 16px; + height: 16px; +} +.ke-icon-pagebreak { + background-position: 0px -1024px; + width: 16px; + height: 16px; +} +.ke-icon-insertfile { + background-position: 0px -1040px; + width: 16px; + height: 16px; +} +.ke-icon-quickformat { + background-position: 0px -1056px; + width: 16px; + height: 16px; +} +.ke-icon-template { + background-position: 0px -1072px; + width: 16px; + height: 16px; +} +.ke-icon-tablecellsplit { + background-position: 0px -1088px; + width: 16px; + height: 16px; +} +.ke-icon-tablerowmerge { + background-position: 0px -1104px; + width: 16px; + height: 16px; +} +.ke-icon-tablerowsplit { + background-position: 0px -1120px; + width: 16px; + height: 16px; +} +.ke-icon-tablecolmerge { + background-position: 0px -1136px; + width: 16px; + height: 16px; +} +.ke-icon-tablecolsplit { + background-position: 0px -1152px; + width: 16px; + height: 16px; +} +.ke-icon-anchor { + background-position: 0px -1168px; + width: 16px; + height: 16px; +} +.ke-icon-search { + background-position: 0px -1184px; + width: 16px; + height: 16px; +} +.ke-icon-new { + background-position: 0px -1200px; + width: 16px; + height: 16px; +} +.ke-icon-specialchar { + background-position: 0px -1216px; + width: 16px; + height: 16px; +} +.ke-icon-multiimage { + background-position: 0px -1232px; + width: 16px; + height: 16px; +} +/* container */ +.ke-container { + display: block; + border: 1px solid #CCCCCC; + background-color: #FFF; + overflow: hidden; + margin: 0; + padding: 0; +} +/* toolbar */ +.ke-toolbar { + border-bottom: 1px solid #CCC; + background-color: #F0F0EE; + padding: 2px 5px; + text-align: left; + overflow: hidden; + zoom: 1; +} +.ke-toolbar-icon { + background-repeat: no-repeat; + font-size: 0; + line-height: 0; + overflow: hidden; + display: block; +} +.ke-toolbar-icon-url { + background-image: url(default.png); +} +.ke-toolbar .ke-outline { + border: 1px solid #F0F0EE; + margin: 1px; + padding: 1px 2px; + font-size: 0; + line-height: 0; + overflow: hidden; + cursor: pointer; + display: block; + float: left; +} +.ke-toolbar .ke-on { + border: 1px solid #5690D2; +} +.ke-toolbar .ke-selected { + border: 1px solid #5690D2; + background-color: #E9EFF6; +} +.ke-toolbar .ke-disabled { + cursor: default; +} +.ke-toolbar .ke-separator { + height: 16px; + margin: 2px 3px; + border-left: 1px solid #A0A0A0; + border-right: 1px solid #FFFFFF; + border-top:0; + border-bottom:0; + width: 0; + font-size: 0; + line-height: 0; + overflow: hidden; + display: block; + float: left; +} +.ke-toolbar .ke-hr { + overflow: hidden; + height: 1px; + clear: both; +} +/* edit */ +.ke-edit { + padding: 0; +} +.ke-edit-iframe, +.ke-edit-textarea { + border: 0; + margin: 0; + padding: 0; + overflow: auto; +} +.ke-edit-textarea { + font: 12px/1.5 "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; + color: #000; + overflow: auto; + resize: none; +} +.ke-edit-textarea:focus { + outline: none; +} +/* statusbar */ +.ke-statusbar { + position: relative; + background-color: #F0F0EE; + border-top: 1px solid #CCCCCC; + font-size: 0; + line-height: 0; + *height: 12px; + overflow: hidden; + text-align: center; + cursor: s-resize; +} +.ke-statusbar-center-icon { + background-position: -0px -754px; + width: 15px; + height: 11px; + background-image: url(default.png); +} +.ke-statusbar-right-icon { + position: absolute; + right: 0; + bottom: 0; + cursor: se-resize; + background-position: -5px -741px; + width: 11px; + height: 11px; + background-image: url(default.png); +} +/* menu */ +.ke-menu { + border: 1px solid #A0A0A0; + background-color: #F1F1F1; + color: #222222; + padding: 2px; + font-family: "sans serif",tahoma,verdana,helvetica; + font-size: 12px; + text-align: left; + overflow: hidden; +} +.ke-menu-item { + border: 1px solid #F1F1F1; + background-color: #F1F1F1; + color: #222222; + height: 24px; + overflow: hidden; + cursor: pointer; +} +.ke-menu-item-on { + border: 1px solid #5690D2; + background-color: #E9EFF6; +} +.ke-menu-item-left { + width: 27px; + text-align: center; + overflow: hidden; +} +.ke-menu-item-center { + width: 0; + height: 24px; + border-left: 1px solid #E3E3E3; + border-right: 1px solid #FFFFFF; + border-top: 0; + border-bottom: 0; +} +.ke-menu-item-center-on { + border-left: 1px solid #E9EFF6; + border-right: 1px solid #E9EFF6; +} +.ke-menu-item-right { + border: 0; + padding: 0 0 0 5px; + line-height: 24px; + text-align: left; + overflow: hidden; +} +.ke-menu-separator { + margin: 2px 0; + height: 0; + overflow: hidden; + border-top: 1px solid #CCCCCC; + border-bottom: 1px solid #FFFFFF; + border-left: 0; + border-right: 0; +} +/* colorpicker */ +.ke-colorpicker { + border: 1px solid #A0A0A0; + background-color: #F1F1F1; + color: #222222; + padding: 2px; +} +.ke-colorpicker-table { + border:0; + margin:0; + padding:0; + border-collapse: separate; +} +.ke-colorpicker-cell { + font-size: 0; + line-height: 0; + border: 1px solid #F0F0EE; + cursor: pointer; + margin:3px; + padding:0; +} +.ke-colorpicker-cell-top { + font-family: "sans serif",tahoma,verdana,helvetica; + font-size: 12px; + line-height: 24px; + border: 1px solid #F0F0EE; + cursor: pointer; + margin:0; + padding:0; + text-align: center; +} +.ke-colorpicker-cell-on { + border: 1px solid #5690D2; +} +.ke-colorpicker-cell-selected { + border: 1px solid #2446AB; +} +.ke-colorpicker-cell-color { + width: 14px; + height: 14px; + margin: 3px; + padding: 0; + border: 0; +} +/* dialog */ +.ke-dialog { + position: absolute; + margin: 0; + padding: 0; +} +.ke-dialog .ke-header { + width: 100%; + margin-bottom: 10px; +} +.ke-dialog .ke-header .ke-left { + float: left; +} +.ke-dialog .ke-header .ke-right { + float: right; +} +.ke-dialog .ke-header label { + margin-right: 0; + cursor: pointer; + font-weight: normal; + display: inline; + vertical-align: top; +} +.ke-dialog-content { + background-color: #FFF; + width: 100%; + height: 100%; + color: #333; + border: 1px solid #A0A0A0; +} +.ke-dialog-shadow { + position: absolute; + z-index: -1; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: 3px 3px 7px #999; + -moz-box-shadow: 3px 3px 7px #999; + -webkit-box-shadow: 3px 3px 7px #999; + filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius='3', MakeShadow='true', ShadowOpacity='0.4'); + background-color: #F0F0EE; +} +.ke-dialog-header { + border:0; + margin:0; + padding: 0 10px; + background: url(background.png) repeat scroll 0 0 #F0F0EE; + border-bottom: 1px solid #CFCFCF; + height: 24px; + font: 12px/24px "sans serif",tahoma,verdana,helvetica; + text-align: left; + color: #222; + cursor: move; +} +.ke-dialog-icon-close { + display: block; + background: url(default.png) no-repeat scroll 0px -688px; + width: 16px; + height: 16px; + position: absolute; + right: 6px; + top: 6px; + cursor: pointer; +} +.ke-dialog-body { + font: 12px/1.5 "sans serif",tahoma,verdana,helvetica; + text-align: left; + overflow: hidden; + width: 100%; +} +.ke-dialog-body textarea { + display: block; + overflow: auto; + padding: 0; + resize: none; +} +.ke-dialog-body textarea:focus, +.ke-dialog-body input:focus, +.ke-dialog-body select:focus { + outline: none; +} +.ke-dialog-body label { + margin-right: 10px; + cursor: pointer; + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; + zoom: 1; + *display: inline; +} +.ke-dialog-body img { + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; + zoom: 1; + *display: inline; +} +.ke-dialog-body select { + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; + zoom: 1; + *display: inline; + width: auto; +} +.ke-dialog-body .ke-textarea { + display: block; + width: 408px; + height: 260px; + font-family: "sans serif",tahoma,verdana,helvetica; + font-size: 12px; + border-color: #848484 #E0E0E0 #E0E0E0 #848484; + border-style: solid; + border-width: 1px; +} +.ke-dialog-body .ke-form { + margin: 0; + padding: 0; +} +.ke-dialog-loading { + position: absolute; + top: 0; + left: 1px; + z-index: 1; + text-align: center; +} +.ke-dialog-loading-content { + background: url("../common/loading.gif") no-repeat; + color: #666; + font-size: 14px; + font-weight: bold; + height: 31px; + line-height: 31px; + padding-left: 36px; +} +.ke-dialog-row { + margin-bottom: 10px; +} +.ke-dialog-footer { + font: 12px/1 "sans serif",tahoma,verdana,helvetica; + text-align: right; + padding:0 0 5px 0; + background-color: #FFF; + width: 100%; +} +.ke-dialog-preview, +.ke-dialog-yes { + margin: 5px; +} +.ke-dialog-no { + margin: 5px 10px 5px 5px; +} +.ke-dialog-mask { + background-color:#FFF; + filter:alpha(opacity=50); + opacity:0.5; +} +.ke-button-common { + background: url(background.png) no-repeat scroll 0 -25px transparent; + cursor: pointer; + height: 23px; + line-height: 23px; + overflow: visible; + display: inline-block; + vertical-align: top; + cursor: pointer; +} +.ke-button-outer { + background-position: 0 -25px; + padding: 0; + position: relative; + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; + zoom: 1; + *display: inline; +} +.ke-button { + background-position: right -25px; + padding: 0 12px; + margin: 0; + font-family: "sans serif",tahoma,verdana,helvetica; + border: 0 none; + color: #333; + font-size: 12px; + left: 2px; + text-decoration: none; +} +/* inputbox */ +.ke-input-text { + background-color:#FFFFFF; + font-family: "sans serif",tahoma,verdana,helvetica; + font-size: 12px; + line-height: 17px; + height: 17px; + padding: 2px 4px; + border-color: #848484 #E0E0E0 #E0E0E0 #848484; + border-style: solid; + border-width: 1px; + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; + zoom: 1; + *display: inline; +} +.ke-input-number { + width: 50px; +} +.ke-input-color { + border: 1px solid #A0A0A0; + background-color: #FFFFFF; + font-size: 12px; + width: 60px; + height: 20px; + line-height: 20px; + padding-left: 5px; + overflow: hidden; + cursor: pointer; + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; + zoom: 1; + *display: inline; +} +.ke-upload-button { + position: relative; +} +.ke-upload-area { + position: relative; + overflow: hidden; + margin: 0; + padding: 0; + *height: 25px; +} +.ke-upload-area .ke-upload-file { + position: absolute; + font-size: 60px; + top: 0; + right: 0; + padding: 0; + margin: 0; + z-index: 811212; + border: 0 none; + opacity: 0; + filter: alpha(opacity=0); +} +/* tabs */ +.ke-tabs { + font: 12px/1 "sans serif",tahoma,verdana,helvetica; + border-bottom:1px solid #A0A0A0; + padding-left:5px; + margin-bottom:20px; +} +.ke-tabs-ul { + list-style-image:none; + list-style-position:outside; + list-style-type:none; + margin:0; + padding:0; +} +.ke-tabs-li { + position: relative; + border: 1px solid #A0A0A0; + background-color: #F0F0EE; + margin: 0 2px -1px 0; + padding: 0 20px; + float: left; + line-height: 25px; + text-align: center; + color: #555555; + cursor: pointer; +} +.ke-tabs-li-selected { + background-color: #FFF; + border-bottom: 1px solid #FFF; + color: #000; + cursor: default; +} +.ke-tabs-li-on { + background-color: #FFF; + color: #000; +} +/* progressbar */ +.ke-progressbar { + position: relative; + margin: 0; + padding: 0; +} +.ke-progressbar-bar { + border: 1px solid #6FA5DB; + width: 80px; + height: 5px; + margin: 10px 10px 0 10px; + padding: 0; +} +.ke-progressbar-bar-inner { + width: 0; + height: 5px; + background-color: #6FA5DB; + overflow: hidden; + margin: 0; + padding: 0; +} +.ke-progressbar-percent { + position: absolute; + top: 0; + left: 40%; + display: none; +} +/* swfupload */ +.ke-swfupload-top { + position: relative; + margin-bottom: 10px; + _width: 608px; +} +.ke-swfupload-button { + height: 23px; + line-height: 23px; +} +.ke-swfupload-desc { + padding: 0 10px; + height: 23px; + line-height: 23px; +} +.ke-swfupload-startupload { + position: absolute; + top: 0; + right: 0; +} +.ke-swfupload-body { + overflow: scroll; + background-color:#FFFFFF; + border-color: #848484 #E0E0E0 #E0E0E0 #848484; + border-style: solid; + border-width: 1px; + width: auto; + height: 370px; + padding: 5px; +} +.ke-swfupload-body .ke-item { + width: 100px; + margin: 5px; +} +.ke-swfupload-body .ke-photo { + position: relative; + border: 1px solid #DDDDDD; + background-color:#FFFFFF; + padding: 10px; +} +.ke-swfupload-body .ke-delete { + display: block; + background: url(default.png) no-repeat scroll 0px -688px; + width: 16px; + height: 16px; + position: absolute; + right: 0; + top: 0; + cursor: pointer; +} +.ke-swfupload-body .ke-status { + position: absolute; + left: 0; + bottom: 5px; + width: 100px; + height: 17px; +} +.ke-swfupload-body .ke-message { + width: 100px; + text-align: center; + overflow: hidden; + height:17px; +} +.ke-swfupload-body .ke-error { + color: red; +} +.ke-swfupload-body .ke-name { + width: 100px; + text-align: center; + overflow: hidden; + height:16px; +} +.ke-swfupload-body .ke-on { + border: 1px solid #5690D2; + background-color: #E9EFF6; +} + +/* emoticons */ +.ke-plugin-emoticons { + position: relative; +} +.ke-plugin-emoticons .ke-preview { + position: absolute; + text-align: center; + margin: 2px; + padding: 10px; + top: 0; + border: 1px solid #A0A0A0; + background-color: #FFFFFF; + display: none; +} +.ke-plugin-emoticons .ke-preview-img { + border:0; + margin:0; + padding:0; +} +.ke-plugin-emoticons .ke-table { + border:0; + margin:0; + padding:0; + border-collapse:separate; +} +.ke-plugin-emoticons .ke-cell { + margin:0; + padding:1px; + border:1px solid #F0F0EE; + cursor:pointer; +} +.ke-plugin-emoticons .ke-on { + border: 1px solid #5690D2; + background-color: #E9EFF6; +} +.ke-plugin-emoticons .ke-img { + display:block; + background-repeat:no-repeat; + overflow:hidden; + margin:2px; + width:24px; + height:24px; + margin: 0; + padding: 0; + border: 0; +} +.ke-plugin-emoticons .ke-page { + text-align: right; + margin: 5px; + padding: 0; + border: 0; + font: 12px/1 "sans serif",tahoma,verdana,helvetica; + color: #333; + text-decoration: none; +} +.ke-plugin-plainpaste-textarea, +.ke-plugin-wordpaste-iframe { + display: block; + width: 408px; + height: 260px; + font-family: "sans serif",tahoma,verdana,helvetica; + font-size: 12px; + border-color: #848484 #E0E0E0 #E0E0E0 #848484; + border-style: solid; + border-width: 1px; +} +/* filemanager */ +.ke-plugin-filemanager-header { + width: 100%; + margin-bottom: 10px; +} +.ke-plugin-filemanager-header .ke-left { + float: left; +} +.ke-plugin-filemanager-header .ke-right { + float: right; +} +.ke-plugin-filemanager-body { + overflow: scroll; + background-color:#FFFFFF; + border-color: #848484 #E0E0E0 #E0E0E0 #848484; + border-style: solid; + border-width: 1px; + width: auto; + height: 370px; + padding: 5px; +} +.ke-plugin-filemanager-body .ke-item { + width: 100px; + margin: 5px; +} +.ke-plugin-filemanager-body .ke-photo { + border: 1px solid #DDDDDD; + background-color:#FFFFFF; + padding: 10px; +} +.ke-plugin-filemanager-body .ke-name { + width: 100px; + text-align: center; + overflow: hidden; + height:16px; +} +.ke-plugin-filemanager-body .ke-on { + border: 1px solid #5690D2; + background-color: #E9EFF6; +} +.ke-plugin-filemanager-body .ke-table { + width: 95%; + border: 0; + margin: 0; + padding: 0; + border-collapse: separate; +} +.ke-plugin-filemanager-body .ke-table .ke-cell { + margin: 0; + padding: 0; + border: 0; +} +.ke-plugin-filemanager-body .ke-table .ke-name { + width: 55%; + text-align: left; +} +.ke-plugin-filemanager-body .ke-table .ke-size { + width: 15%; + text-align: left; +} +.ke-plugin-filemanager-body .ke-table .ke-datetime { + width: 30%; + text-align: center; +} + diff --git a/public/assets/kindeditor/themes/default/default.png b/public/assets/kindeditor/themes/default/default.png new file mode 100644 index 000000000..cc9e72d2b Binary files /dev/null and b/public/assets/kindeditor/themes/default/default.png differ diff --git a/public/assets/kindeditor/themes/qq/editor.gif b/public/assets/kindeditor/themes/qq/editor.gif new file mode 100644 index 000000000..b256841f3 Binary files /dev/null and b/public/assets/kindeditor/themes/qq/editor.gif differ diff --git a/public/assets/kindeditor/themes/qq/qq.css b/public/assets/kindeditor/themes/qq/qq.css new file mode 100644 index 000000000..a45e08c69 --- /dev/null +++ b/public/assets/kindeditor/themes/qq/qq.css @@ -0,0 +1,143 @@ +/* container */ +.ke-container-qq { + display: block; + border: 1px solid #c3c3c3; + background-color: #FFF; + overflow: hidden; + margin: 0; + padding: 0; +} +/* toolbar */ +.ke-container-qq .ke-toolbar { + border-bottom: 1px solid #c3c3c3; + background-color: #FFFFFF; + padding: 2px 5px; + text-align: left; + overflow: hidden; + zoom: 1; +} +.ke-toolbar-icon-url { + background-image: url(editor.gif); + width:18px; + *xwidth:20px; + height:18px; + *xheight:20px; +} +.ke-icon-checked{ + background-image: url(../default/default.png); + width:16px; + height:16px; +} +.ke-container-qq .ke-icon-bold{ + background-position: 4px 1px; +} +.ke-container-qq .ke-icon-italic{ + background-position: -27px 1px; +} +.ke-container-qq .ke-icon-italic{ + background-position: -28px 1px; +} +.ke-container-qq .ke-icon-underline{ + background-position: -60px 1px; +} +.ke-container-qq .ke-icon-fontname{ + background-position: -95px 1px; +} +.ke-container-qq .ke-icon-fontsize{ + background-position: -128px 1px; +} +.ke-container-qq .ke-icon-forecolor{ + background-position: -159px 1px; +} +.ke-container-qq .ke-icon-hilitecolor{ + background-position: -190px 1px; +} +.ke-container-qq .ke-icon-plug-align{ + background-position: -223px 1px; +} +.plug-align-justifyleft{ + background-position: -350px 1px; +} +.plug-align-justifycenter{ + background-position: -382px 1px; +} +.plug-align-justifyright{ + background-position: -414px 1px; +} +.plug-order-insertorderedlist{ + background-position: -446px 1px; +} +.plug-order-insertunorderedlist{ + background-position: -477px 1px; +} +.plug-indent-indent{ + background-position: -513px 1px; +} +.plug-indent-outdent{ + background-position: -545px 1px; +} +.ke-container-qq .ke-icon-plug-order{ + background-position: -255px 1px; +} +.ke-container-qq .ke-icon-plug-indent{ + background-position: -287px 1px; +} +.ke-container-qq .ke-icon-link{ + background-position: -319px 1px; +} + +.ke-container-qq .ke-toolbar .ke-outline { + cursor: default; + padding:0px; + border:1px solid #fff; +} +.ke-container-qq .ke-toolbar .ke-on { + border-left:1px solid white; + border-top:1px solid white; + border-right:1px solid gray; + border-bottom:1px solid gray; + background-color: #FFFFFF; +} +.ke-container-qq .ke-toolbar .ke-selected { + border-left:1px solid gray; + border-top:1px solid gray; + border-right:1px solid white; + border-bottom:1px solid white; + background-color: #FFFFFF; +} +.ke-container-qq .ke-toolbar .ke-disabled { + cursor: default; +} + +.ke-colorpicker-qq{ + background:#fff; +} +/* statusbar */ +.ke-container-qq .ke-statusbar { + display:none; +} +/* menu */ +.ke-menu-qq { + border:1px solid #a6a6a6; + position:absolute; + background:#fff; + -moz-box-shadow:2px 2px 4px #DDDDDD; + z-index:999; + left:-400px; + top:-386px; + right:218px; + width:130px; +} +.ke-menu-qq .ke-menu-item { + padding:0px; + background:#fff; +} +.ke-menu-qq .ke-menu-item-on { + border:1px solid #000080;background:#FFEEC2;color:#036; +} +.ke-menu-qq .ke-toolbar .ke-selected { + border:1px solid #9a9afb; +} +.ke-menu-qq .ke-menu-item-left{ + width:auto; +} diff --git a/public/assets/kindeditor/themes/simple/simple.css b/public/assets/kindeditor/themes/simple/simple.css new file mode 100644 index 000000000..4c76cf9d7 --- /dev/null +++ b/public/assets/kindeditor/themes/simple/simple.css @@ -0,0 +1,100 @@ +/* container */ +.ke-container-simple { + display: block; + border: 1px solid #CCC; + background-color: #FFF; + overflow: hidden; +} +/* toolbar */ +.ke-container-simple .ke-toolbar { + border-bottom: 1px solid #CCC; + background-color: #FFF; + padding: 2px 5px; + overflow: hidden; +} +.ke-container-simple .ke-toolbar .ke-outline { + border: 1px solid #FFF; + background-color: transparent; + margin: 1px; + padding: 1px 2px; + font-size: 0; + line-height: 0; + overflow: hidden; + cursor: pointer; +} +.ke-container-simple .ke-toolbar .ke-on { + border: 1px solid #5690D2; +} +.ke-container-simple .ke-toolbar .ke-selected { + border: 1px solid #5690D2; + background-color: #E9EFF6; +} +.ke-container-simple .ke-toolbar .ke-disabled { + cursor: default; +} +/* statusbar */ +.ke-container-simple .ke-statusbar { + position: relative; + background-color: #FFF; + border-top: 1px solid #CCCCCC; + font-size: 0; + line-height: 0; + *height: 12px; + overflow: hidden; + text-align: center; + cursor: s-resize; +} +/* menu */ +.ke-menu-simple { + border: 1px solid #A0A0A0; + background-color: #FFF; + color: #222222; + padding: 2px; + font-family: "sans serif",tahoma,verdana,helvetica; + font-size: 12px; + text-align: left; + overflow: hidden; +} +.ke-menu-simple .ke-menu-item { + border: 1px solid #FFF; + background-color: #FFF; + color: #222222; + height: 24px; + overflow: hidden; + cursor: pointer; +} +.ke-menu-simple .ke-menu-item-on { + border: 1px solid #5690D2; + background-color: #FFF; +} +/* colorpicker */ +.ke-colorpicker-simple { + border: 1px solid #A0A0A0; + background-color: #FEFEFE; + color: #222222; + padding: 2px; +} +.ke-colorpicker-simple .ke-colorpicker-cell { + font-size: 0; + line-height: 0; + border: 1px solid #FEFEFE; + cursor: pointer; + margin:3px; + padding:0; +} +.ke-colorpicker-simple .ke-colorpicker-cell-top { + font-family: "sans serif",tahoma,verdana,helvetica; + font-size: 12px; + line-height: 24px; + border: 1px solid #FEFEFE; + cursor: pointer; + margin:0; + padding:0; + text-align: center; +} +.ke-colorpicker-simple .ke-colorpicker-cell-on { + border: 1px solid #5690D2; +} +.ke-colorpicker-simple .ke-colorpicker-cell-selected { + border: 1px solid #2446AB; +} diff --git a/public/images/sidebar_bg.png b/public/images/sidebar_bg.png index cc57f3870..014b14466 100644 Binary files a/public/images/sidebar_bg.png and b/public/images/sidebar_bg.png differ diff --git a/public/javascripts/attachments.js b/public/javascripts/attachments.js index 8ea71909b..8fbaa5981 100644 --- a/public/javascripts/attachments.js +++ b/public/javascripts/attachments.js @@ -135,8 +135,11 @@ function uploadBlob(blob, uploadUrl, attachmentId, options) { loadstartEventHandler: $.noop, progressEventHandler: $.noop }, options); - - uploadUrl = uploadUrl + '?attachment_id=' + attachmentId; + if(uploadUrl.indexOf('?') > 0){ + uploadUrl = uploadUrl + '&attachment_id=' + attachmentId; + }else{ + uploadUrl = uploadUrl + '?attachment_id=' + attachmentId; + } if (blob instanceof window.File) { uploadUrl += '&filename=' + encodeURIComponent(blob.name); } diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 5786c5758..ca8f0c3b6 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -13,7 +13,7 @@ ul.wlist{ margin-left: -40px; border-bottom:none; } ul.wlist li{float: left;} ul.wlist li a{ border:1px solid #15bccf; padding:4px; margin-left:3px;} ul.wlist li a:hover{ background:#15bccf; color:#fff; text-decoration:none;} -.wlist_select { background-color:#64bdd9; color:#fff; padding: 4px 3px 3px 3px; margin-left:3px;margin-top: -5px; border:1px solid #64bdd9;} +.wlist_select { background-color:#64bdd9; color:#fff; padding: 5px 3px 3px 3px; margin-left:3px;margin-top: 0px; border:1px solid #64bdd9;} /*20150203项目界面优化样式 By: huangjignquan*/ .project_new{font-size: 15px; padding: 5px;} @@ -69,15 +69,23 @@ a.ml105{ margin-left:120px;} a:hover.subnav_green{ background:#14ad5a;} /*简介*/ -.project_intro{ width:220px; padding:10px; background:#fff; padding-top:5px; color:#6d6d6d;} -.course_description{max-height: 105px;overflow:hidden;} +.project_intro{ width:220px; padding:5px 0px 10px 10px; background:#fff; color:#6d6d6d;} +.course_description{max-height: 103px;overflow:hidden;} .course_description_none{max-height: none;} .lg-foot{ border:1px solid #e8eef2; color: #929598; text-align:center; width:220px; height:23px; cursor:pointer;} .lg-foot:hover{ color:#787b7e;} +/****标签(和资源库的tag样式一致)***/ +.project_Label{ width:220px; padding-left:10px; padding-right:10px; background:#fff; margin-top:10px;} +a.yellowBtn{ display:inline-block;color:#0d90c3; height:22px;} +.submit{height:21px;border:0; cursor:pointer; background:url(../images/btn.png) no-repeat 0 0;width:42px; margin-top:2px; margin-left:3px; } +.isTxt{background:#fbfbfb url(../images/inputBg.png) repeat-x left top;height:22px;line-height:22px;border:1px solid #c1c1c1;padding:0 5px;color:#666666;} +.re_tag{ width: auto; padding-left:4px;padding-right: 4px; height:22px; border:1px solid #f8df8c; background:#fffce6; margin-right:5px;font-size:12px; } +.re_tag a{ color:#0d90c3;} +.tag_h span,.tag_h a{ margin-top:5px;} /*右侧内容--动态*/ - -.project_r_h{ height:40px; background:#eaeaea; margin-bottom: 5px;} -.project_h2{ background:#64bdd9; color:#fff; height:30px; width:90px; text-align:center; font-weight:normal; padding-top:3px; font-size:16px; padding-top:9px;} +/*右侧内容--动态*/ +.project_r_h{height:40px; background:#eaeaea; margin-bottom:10px;} +.project_h2{ background:#64bdd9; color:#fff; height:29px; width:90px; text-align:center; font-weight:normal; padding-top:10px; font-size:16px;padding-left:10px;} .project_r_box{ border:1px solid #e2e1e1; width:670px; margin-top:10px;} .project_h3 { color:#646464; font-size:14px; padding:0 10px; border-bottom:1px solid #e2e1e1;} a.more{ float:right; font-size:12px; font-weight:normal; color:#a9a9a9; margin-top:3px;} @@ -100,42 +108,124 @@ a:hover.more{ color:#64bdd9;} .box_close{ display:block; float:right; width:16px; height:16px; background:url(../images/img_floatbox.png) 0 0 no-repeat;} .box_close:hover{background:url(../images/img_floatbox.png) -22px 0 no-repeat;} /*邮件邀请*/ -.box_main{ width:345px; margin:0 auto;padding-left:28px;} -.box_h3{ color:#15bccf; text-align:center; font-size:16px;margin-right:40px;} +.box_main{ width:345px; margin:0 auto;} +.box_main02{ width:390px; margin:15px auto;} +.box_h3{ color:#15bccf; text-align:center; font-size:16px;} .box_p{ color:#404040; margin-bottom:5px;} -.fb_item{ color:#919191; border:1px solid #919191; height:28px; margin-bottom:10px; padding-left:5px; width:290px;} +.fb_item{ color:#919191; border:1px solid #919191; height:25px; margin-bottom:10px; padding-left:5px; width:290px;} .icon_addm{ background:url(../images/img_floatbox.png) 0 -33px no-repeat; width:16px; height:16px; display:block; margin:5px 0 0 5px;} .icon_addm:hover{background:url(../images/img_floatbox.png) 0 -61px no-repeat; } .icon_removem{ background:url(../images/img_floatbox.png) -22px -33px no-repeat;width:16px; height:16px; display:block; margin:5px 0 0 5px} .icon_removem:hover{background:url(../images/img_floatbox.png) -22px -61px no-repeat;} -.btn_free{ background:#ff5722; display:block; width:80px; text-align:center; color:#fff !important; height:26px; padding-top:8px; margin-bottom:10px;} -.btn_free:hover{ background:#d63502;} +.btn_free{ background:#ff5722; display:block; width:80px; text-align:center; color:#fff !important; height:25px; padding-top:5px; margin-bottom:10px;} +.btn_free:hover{ background:#d63502;text-decoration:none;} /*成员邀请*/ -.invi_search{ width:345px; margin:0 auto;} -.invi_search_input{ border:1px solid #15bccf; width:180px; height:24px; color:#9b9b9b; padding-left:5px; margin-bottom:10px;} +.invi_search{ margin-left:25px;} +.invi_search_input{ border:1px solid #15bccf; width:180px; height:24px; color:#9b9b9b; padding-left:5px;} .invi_search_btn{ background:#15bccf; color:#fff; text-align: center; width:40px; height:22px;border:1px solid #15bccf; padding-top:2px; cursor:pointer;} .invi_search_btn:hover{ background:#0da1b2; border:1px solid #0da1b2;} -.rolebox{ margin-left: -40px;} +.rolebox{ margin:10px 0;margin-left:-38px;} /*问题跟踪*/ .problem_top{ margin:10px 0 ;} .problem_search_input{ border:1px solid #64bdd9; width:180px; height:24px; color:#9b9b9b; padding-left:5px; margin-bottom:10px;} .problem_search_btn{ background:#64bdd9; color:#fff; text-align: center; width:40px; height:22px;border:1px solid #64bdd9; padding-top:2px; cursor:pointer;} .problem_search_btn:hover{ background:#3da1c1; border:1px solid #3da1c1;} -.problem_new_btn{ margin-left:10px; border:1px solid #ff7143; color:#ff7143; width:60px; height:22px; text-align:center; padding-top:2px;} -.problem_new_btn:hover{ background:#ff7143; color:#fff;} -.problem_p{ color:#535252; margin-right: 8px;} +.problem_new_btn{ margin-left:10px; border:1px solid #ff7143; color:#ff7143 !important; width:60px; height:19px; font-size:12px; text-align:center; padding-top:4px;margin-top:-2px;} +.problem_new_btn:hover{ background:#ff7143; color:#fff !important;} +.problem_p{ color:#535252; margin-top:5px;} .problem_p span{ color:#ff3e00;} -.problem_pic{ display:block; width:42px; height:42px; padding:3px; border:1px solid #e3e3e3;} +.problem_pic{ display:block; width:42px; height:42px; padding:3px; border:1px solid #e3e3e3; margin-top:5px;} +.problem_pic:hover{border:1px solid #64bdd9;} +.problem_txt{ width:610px; margin-left:10px; color:#777777;} +.problem_name{ color:#ff5722 !important;} +.problem_line{margin-top:5px;} +.problem_name:hover{ color:#d33503;} +.problem_tit{ color:#0781b4 !important; width:430px; display:block; overflow:hidden; white-space: nowrap; text-overflow:ellipsis;} +.problem_tit:hover{ color:#09658c !important; } +.problem_main{ border-bottom:1px dashed #d4d4d4; padding-bottom:10px; margin-bottom:10px;} +/****翻页***/ +.wlist{} +.wlist a{ float:right; border:1px solid #64bdd9; padding:0 5px; margin-left:3px; color:#64bdd9;} +.wlist_l a{ float:left; margin-right:3px; margin-left:0px;} +.wlist a:hover{border:1px solid #64bdd9; background-color:#64bdd9; color:#fff; text-decoration:none;} +.wlist_select a { background-color:#48aac9; color:#fff;} +/****讨论区***/ +.talk_top{ margin:10px 0; font-size:14px; color:#4c4c4c;} +.talk_top span{ color:#ff7143;} +.talk_txt{ width:460px; margin-left:10px; color:#676868;} +.talk_up{ color:#f63c00;} +.talk_pic{width:32px; height:32px; padding:2px;} +.talk_btn{ background:#64bdd9; width:50px; height:22px; color:#fff; text-align:center; margin-top:9px; padding-top:2px;} +.talk_btn:hover{ background:#2a9dc1;} +/****讨论区内页***/ +.mt0{ margin-top:0px;} +.talk_info{ color:#7d7d7d; margin-left:50px; margin-top:10px;} +.talk_edit{ color:#426e9a; margin-right:5px;} +.talk_edit:hover{ color:#ff5722;} +.talk_reply { background:#eeeeee; padding:10px; margin-bottom:10px;} +.talkpage_text{ border:1px solid #64bdd9; width:600px; color:#7d7d7d; padding:5px; margin:10px 0 10px 50px;} +/****新建讨论***/ +.talk_new{ padding-left:15px; color:#4c4c4c;} +.c_red{ color:#F00;} +.talk_input{ border:1px solid #64bdd9; height:22px; width:595px; margin-bottom:10px;} +.talk_text{ border:1px solid #64bdd9; height:100px;width:595px; margin-bottom:10px;} +.talk_new ul li{ } +.view_span{font-weight:normal; color:#999;} +.sb{width:70px; height:26px; color:#606060;} +.ml60{ margin-left:60px;} +.blue_btn{ background:#64bdd9; display:block; font-size:14px;color:#fff; height:28px; width:50px; text-align:center; margin-left:10px; margin-top:10px;} +.blue_btn:hover{ background:#329cbd;} +.grey_btn{ background:#d9d9d9; color:#656565;} +.grey_btn:hover{ background:#717171; color:#fff;} +/****资源库***/ +.f_l{ float:left;} +.f_r{ float:right;} +.resource a{ text-align:center;} +.b_lblue{ background:#64bdd9;} +.b_dblue{ background:#55a1b9; cursor:pointer;} +.f_b{ font-weight: bold;} +.c_blue{ color:#64bdd9;} +a.c_dblue{ color: #3ca5c6;} +a:hover.c_dblue{ color: #0781b4;} +.c_grey{ color:#999999;} +.c_grey02{ color:#666666;} +.f_14{ font-size:14px;} +.c_dblue{ color:#3e6d8e;} +.w90{width:90px;} +.ml10{margin-left:10px;} +.resource{ width:670px;} +.re_top{width:660px; height:40px; background:#eaeaea; padding:5px;} +.re_top input{ float:left;} +.re_search{ margin-top:7px; margin-left:5px;} +.re_schbox{ width:240px; height:24px; border:1px solid #64bdd9; color:#666666;} +.re_schbtn{ width:60px; height:26px; color:#fff; margin-right:5px; border:none; margin-left:0px; } +a.re_fabu { display:block; width:90px; height:35px; font-size:14px; color:#fff; text-align:center; padding-top:5px; } +a:hover.re_fabu{background:#55a1b9;} +.re_con{ margin:5px; width:665px;} +.re_con_top{color:#494949; } +.re_con_top span{ color:#999999; font-weight:bold;} +a.re_select{ display:block; width:88px; height:22px; border:1px solid #ff9900; color:#ff9900; margin-left:10px;} +a:hover.re_select{ background:#ff9900; color:#fff; text-decoration:none;} +.re_open{display:block; width:46px; height:22px; border:1px solid #64bdd9; color:#64bdd9; margin-left:10px;} +a:hover.re_open{ background:#64bdd9; color:#fff; text-decoration:none;} +a.re_de{ color:#6883b6; margin-left:15px;} +.re_con_box{ border-bottom:1px dashed #dadada; padding-bottom:10px; margin-bottom:10px;} + +.upload_con { } +.upload_con h2{ display:block; background:#eaeaea; font-size:14px; color:#343333; height:31px; width: auto; margin-top:25px; padding-left:20px; padding-top:5px;} +.upload_box{ width:430px; height:80px;} +a.upload_btn02{ display:block; float:left; margin-top:15px; width:80px; height:30px; text-align: center; color:#fff; font-size:14px; background:#15bccf; margin-right:15px;} +a:hover.upload_btn02{ background:#55a1b9;} +a.upload_btn_grey{background:#a3a3a3;} +a:hover.upload_btn_grey{background:#8a8a8a;} +.upload_btn{width:80px; height:26px;} +.upload_check{ margin-top:4px;} +/****其他未更新页面***/ +.setting{ background:url(../images/setting.jpg) 0 0 no-repeat; width:670px; height:443px;} +.newproblem{} + -/****标签(和资源库的tag样式一致)***/ -.project_Label{ width:220px; padding:10px; background:#fff; margin-top:0px; padding-top:5px;} -a.yellowBtn{ display:inline-block;color:#0d90c3; height:22px;} -.submit{height:21px;border:0; cursor:pointer; background:url(../images/btn.png) no-repeat 0 0;width:42px; margin-top:2px; margin-left:3px; } -.isTxt{background:#fbfbfb url(../images/inputBg.png) repeat-x left top;height:22px;line-height:22px;border:1px solid #c1c1c1;padding:0 5px;color:#666666;} -.re_tag{ width: auto; padding:0 5px; height:22px; border:1px solid #f8df8c; background:#fffce6; margin-right:10px; } -.re_tag a{ color:#0d90c3;} -.tag_h span,.tag_h a{ margin-bottom:0px;} /*企业版样式*/ .content_syqy{ width:940px; height:400px; border:1px;} .content_syqy .list{ font-size:14px; font-weight:normal; margin-left:10px; font-weight:bold; padding-top:10px} @@ -1414,8 +1504,8 @@ input#openid_url { background: url(../images/openid-bg.gif) no-repeat; backgroun .clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; } /***** Links *****/ -a, a:link, a:visited{ color: #169 ; text-decoration: none; } -a:hover, a:active{ color: #c61a1a; text-decoration: underline;} +a, a:link, a:visited{ color: #0781B4 ; text-decoration: none; } +a:hover, a:active{ color: #09658c;} a img{ border: 0; } a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; } @@ -3086,3 +3176,4 @@ input[class~='m3p10'], .m3p10 { } */ + diff --git a/public/themes/redpenny-master/stylesheets/application.css b/public/themes/redpenny-master/stylesheets/application.css index 88506989c..6d4cc658e 100644 --- a/public/themes/redpenny-master/stylesheets/application.css +++ b/public/themes/redpenny-master/stylesheets/application.css @@ -488,7 +488,7 @@ color: #000000; background:#fff; /*主题框架背景yanse*/ margin-bottom: 30px; border-right:1px solid #C6E9F1; - overflow:auto; + /*overflow:auto;*/ word-wrap:break-word; /*by young*/ -moz-box-shadow:#C6E9F1 1px 1px 2px;