diff --git a/app/controllers/bidding_users_controller.rb b/app/controllers/bidding_users_controller.rb
index ad0de6587..5fbecd885 100644
--- a/app/controllers/bidding_users_controller.rb
+++ b/app/controllers/bidding_users_controller.rb
@@ -9,8 +9,7 @@ class BiddingUsersController < ApplicationController
end
def win
- package = current_user.project_packages.find(params[:project_package_id])
- ProjectPackages::WinBiddingService.call(package, params)
+ ProjectPackages::WinBiddingService.call(current_package, current_user, params)
render_ok
rescue ProjectPackages::WinBiddingService::Error => ex
render_error(ex.message)
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index abc3e4856..8ea6df506 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -234,6 +234,8 @@ class CoursesController < ApplicationController
def destroy
if @course.is_delete == 0
@course.delete!
+ Tiding.create!(user_id: @course.tea_id, trigger_user_id: 1, container_id: @course.id,
+ container_type: 'Course', tiding_type: 'Delete', extra: @course.name)
normal_status(0, "成功")
else
normal_status(-1, "课堂已删除,无需重复操作")
@@ -296,7 +298,13 @@ class CoursesController < ApplicationController
@applications = CourseMessage.unhandled_join_course_requests_by_course(@course).
joins("join users on course_messages.course_message_id=users.id").
where("LOWER(concat(users.lastname, users.firstname)) LIKE ?", "%#{search_str}%")
- @teacher_list_size = @course.teachers.size
+ if @course.try(:id) != 1309 || current_user.admin? || current_user.try(:id) == 15582
+ teacher_list = @course.course_members.where("course_members.role in (1, 2, 3)")
+ else
+ teacher_list = @course.course_members.where("(course_members.role in (1, 3) or (course_members.user_id = #{current_user.id}
+ and course_members.role = 2))")
+ end
+ @teacher_list_size = teacher_list.size
@applications_size = CourseMessage.unhandled_join_course_requests_by_course(@course).size
@is_admin = @user_course_identity < Course::PROFESSOR
end
@@ -909,6 +917,7 @@ class CoursesController < ApplicationController
CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
end
+ student_role = 1
end
# 创建教师身份
@@ -921,24 +930,33 @@ class CoursesController < ApplicationController
course_message = CourseMessage.new(course_id: course.id, user_id: course.tea_id, status: 0,
course_message_id: current_user.id, course_message_type: "JoinCourseRequest",
viewed: false)
- course_message.content = 2 if params[:professor].present? && params[:professor].to_i == 1
- course_message.content = 3 if params[:assistant_professor].present? && params[:assistant_professor].to_i == 1
+ if params[:professor].present? && params[:professor].to_i == 1
+ course_message.content = 2
+ role = 9
+ message = "教师申请已提交,请等待审核"
+ else
+ course_message.content = 3
+ role = 7
+ message = "助教申请已提交,请等待审核"
+ end
course_message.save!
- role = course_message.content == 2 ? '7' : '9' # 7:助教 9:教师
+ # role = course_message.content == 2 ? '9' : '7' # 7:助教 9:教师
ApplyTeacherRoleJoinCourseNotifyJob.perform_later(current_user.id, course.id, role)
- message = "#{course_message.content == 2 ? '助教' : '教师'}申请已提交,请等待审核"
+ # message = "#{course_message.content == 2 ? '教师' : '助教'}申请已提交,请等待审核"
else
- message = "#{existing_course_message.content == 2 ? '助教' : '教师'}申请已提交,请等待审核"
+ message = "#{existing_course_message.content == '2' ? '教师' : '助教'}申请已提交,请等待审核"
end
+ else
+ message = "您已是课堂成员"
end
teacher_role = 1
end
- if teacher_role && current_user.student_of_course?(course)
+ if teacher_role && student_role
render json: { status: 0, message: message, course_id: course.id}
- elsif current_user.student_of_course?(course)
+ elsif student_role
render json: { status: 0, message: "加入成功", course_id: course.id}
else
normal_status(message)
diff --git a/app/controllers/discusses_controller.rb b/app/controllers/discusses_controller.rb
index 6a270f619..4af27b919 100644
--- a/app/controllers/discusses_controller.rb
+++ b/app/controllers/discusses_controller.rb
@@ -1,7 +1,7 @@
class DiscussesController < ApplicationController
LIMIT = 10
before_action :find_container, only: [:index, :hidden]
- before_action :find_discuss, except: [:create, :index, :new_message, :reward_code, :forum_discusses]
+ before_action :find_discuss, except: [:create, :index, :new_message, :reward_code, :forum_discusses, :plus]
def index
page = params[:page].to_i
diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb
index 6f121db5f..e92c3b266 100644
--- a/app/controllers/exercises_controller.rb
+++ b/app/controllers/exercises_controller.rb
@@ -703,12 +703,14 @@ class ExercisesController < ApplicationController
end
if ex_status == 1 #如果试卷存在已发布的,或者是已截止的,那么则直接跳过
g_course = params[:group_ids] #表示是否传入分班参数,如果传入分班的参数,那么试卷的统一设置需修改
+ tiding_group_ids = g_course
if g_course
user_course_groups = @course.charge_group_ids(current_user)
if g_course.map(&:to_i).sort == user_course_groups.sort # 如果是设置为全部班级,则试卷不用分组,且试卷设定为统一设置,否则则分组设置
exercise.exercise_group_settings.destroy_all
ex_unified = true
e_time = ex_end_time
+ tiding_group_ids = []
else
ex_unified = false
g_course.each do |i|
@@ -748,7 +750,7 @@ class ExercisesController < ApplicationController
if exercise.course_acts.size == 0
exercise.course_acts << CourseActivity.new(:user_id => exercise.user_id,:course_id => exercise.course_id)
end
- ExercisePublishNotifyJob.perform_later(exercise.id, g_course)
+ ExercisePublishNotifyJob.perform_later(exercise.id, tiding_group_ids)
end
end
end
@@ -1084,6 +1086,7 @@ class ExercisesController < ApplicationController
:subjective_score => subjective_score
}
@answer_committed_user.update_attributes(commit_option)
+ CommitExercsieNotifyJobJob.perform_later(@exercise.id, current_user.id)
normal_status(0,"试卷提交成功!")
end
rescue Exception => e
diff --git a/app/controllers/files_controller.rb b/app/controllers/files_controller.rb
index d090ae253..2cfa61cc9 100644
--- a/app/controllers/files_controller.rb
+++ b/app/controllers/files_controller.rb
@@ -17,8 +17,8 @@ class FilesController < ApplicationController
sort_type = params[:sort_type] || 'created_on' # created_on:时间排序, downloads:下载次数排序; quotes: 引用次数排序
course_second_category_id = params[:course_second_category_id] || 0 # 0: 为主目录, 其他为次目录id
@user = current_user
- @attachments = @course.attachments.by_course_second_category_id(course_second_category_id)
- .includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members])
+ @attachments = course_second_category_id.to_i == 0 ? @course.attachments : @course.attachments.by_course_second_category_id(course_second_category_id)
+ @attachments = @attachments.includes(attachment_group_settings: :course_group, author: [:user_extension, :course_members])
.ordered(sort: sort.to_i, sort_type: sort_type.strip)
get_category(@course, course_second_category_id)
diff --git a/app/controllers/libraries_controller.rb b/app/controllers/libraries_controller.rb
index 55894aaa6..c7c6029da 100644
--- a/app/controllers/libraries_controller.rb
+++ b/app/controllers/libraries_controller.rb
@@ -22,7 +22,7 @@ class LibrariesController < ApplicationController
end
@count = libraries.count
- @libraries = paginate libraries.includes(:library_tags, :praise_tread_cache, user: :user_extension)
+ @libraries = paginate libraries.includes(:library_tags, user: :user_extension)
ids = @libraries.map(&:id)
@download_count_map = Attachment.where(container_type: 'Library', container_id: ids)
diff --git a/app/controllers/memos_controller.rb b/app/controllers/memos_controller.rb
index 66adcc46b..4720210e3 100644
--- a/app/controllers/memos_controller.rb
+++ b/app/controllers/memos_controller.rb
@@ -3,7 +3,7 @@ class MemosController < ApplicationController
before_action :set_memo, only: [:show, :edit, :update, :destroy, :sticky_or_cancel, :hidden, :more_reply]
before_action :validate_memo_params, only: [:create, :update]
before_action :owner_or_admin, only: [:edit, :update, :destroy]
- before_action :is_admin, only: [:sticky_or_cancel, :hidden]
+ before_action :require_business, only: [:sticky_or_cancel, :hidden]
include ApplicationHelper
# GET /memos
@@ -85,7 +85,7 @@ class MemosController < ApplicationController
params[:tags].each do |tag|
MemoTagRepertoire.create!(memo_id: @memo.id, tag_repertoire_id: tag)
end
- normal_status("帖子创建成功")
+ render :json => {memo_id: @memo.id, status: 0, message: "帖子创建成功"}
rescue Exception => e
tip_exception("帖子创建失败,原因:#{e}")
raise ActiveRecord::Rollback
@@ -132,7 +132,7 @@ class MemosController < ApplicationController
def hidden
tip_exception("不能对主贴进行隐藏操作") if @memo.parent_id.nil?
begin
- @memo.update_attributes!(hidden: !@memo.hidden)
+ @memo.update_attributes!(hidden: @memo.hidden == 0 ? 1 : 0)
normal_status("更新成功")
rescue Exception => e
tip_exception("更新失败,原因:#{e}")
@@ -147,16 +147,15 @@ class MemosController < ApplicationController
ActiveRecord::Base.transaction do
begin
memo = Memo.find_by!(id: params[:parent_id])
- reply = Memo.new
- reply.content = params[:content]
- reply.author = current_user
- reply.forum_id = memo.forum_id
- reply.subject = memo.subject
- reply.root_id = memo.root_id || memo.id
- memo.children << reply
- m = Memo.find_by!(id: reply.root_id)
+ @reply = Memo.new
+ @reply.content = params[:content]
+ @reply.author = current_user
+ @reply.forum_id = memo.forum_id
+ @reply.subject = memo.subject
+ @reply.root_id = memo.root_id || memo.id
+ memo.children << @reply
+ m = Memo.find_by!(id: @reply.root_id)
m.increment!(:all_replies_count)
- normal_status("回复成功")
rescue Exception => e
tip_exception("回复失败,原因:#{e}")
raise ActiveRecord::Rollback
@@ -183,10 +182,6 @@ class MemosController < ApplicationController
tip_exception(403, "无权限操作") unless @memo.author == current_user || current_user.admin? || current_user.business?
end
- def is_admin
- tip_exception(403, "无权限操作") unless current_user.admin? || current_user.business?
- end
-
# Never trust parameters from the scary internet, only allow the white list through.
def memo_params
params.require(:memo).permit(:subject, :content, :forum_id)
@@ -196,7 +191,7 @@ class MemosController < ApplicationController
tip_exception("话题名称不能为空") if params[:subject].blank?
tip_exception("话题内容不能为空") if params[:content].blank?
tip_exception("话题类型不能为空") if params[:forum_id].blank?
- tip_exception("技术标签不能为空") if params[:tags].blank?
+ tip_exception("技术标签不能为空") if params[:forum_id].to_i == 5 && params[:tags].blank?
end
end
diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb
index 1d6b15969..7ae9df5e3 100644
--- a/app/controllers/myshixuns_controller.rb
+++ b/app/controllers/myshixuns_controller.rb
@@ -265,6 +265,7 @@ class MyshixunsController < ApplicationController
# params[:evaluate] 实训评测时更新必须给的参数,需要依据该参数做性能统计,其它类型的更新可以跳过
# 自动保存的时候evaluate为0;点评测的时候为1
if params[:evaluate] == 1
+ #exec_time = game.challenge.try(:exec_time)
@sec_key = generate_identifier(EvaluateRecord, 12)
record = EvaluateRecord.create!(:user_id => current_user.id, :shixun_id => @myshixun.shixun_id, :game_id => game_id,
:identifier => @sec_key)
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 7d978d722..ba3030424 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -919,6 +919,7 @@ class PollsController < ApplicationController
:end_at => Time.now
}
poll_user_current.update_attributes(poll_user_params)
+ CommitPollNotifyJobJob.perform_later(@poll.id, current_user.id)
normal_status(0, "问卷提交成功!")
end
## 需添加发送消息的接口,稍后添加
diff --git a/app/controllers/project_packages_controller.rb b/app/controllers/project_packages_controller.rb
index de896c920..3cc7e79cb 100644
--- a/app/controllers/project_packages_controller.rb
+++ b/app/controllers/project_packages_controller.rb
@@ -1,7 +1,7 @@
class ProjectPackagesController < ApplicationController
include PaginateHelper
- before_action :require_login, :check_auth, only: %i[create update destroy]
+ before_action :require_login, :check_auth, only: %i[show create update destroy]
helper_method :current_package, :package_manageable?
diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb
index fca143623..a0377e4e4 100644
--- a/app/controllers/shixuns_controller.rb
+++ b/app/controllers/shixuns_controller.rb
@@ -164,7 +164,7 @@ class ShixunsController < ApplicationController
@new_shixun = Shixun.new
@new_shixun.attributes = @shixun.attributes.dup.except("id","user_id","visits","gpid","status", "identifier", "averge_star",
"homepage_show","repo_name", "myshixuns_count", "challenges_count",
- "can_copy")
+ "can_copy", "created_at", "updated_at")
@new_shixun.user_id = User.current.id
@new_shixun.averge_star = 5
@new_shixun.identifier = generate_identifier Shixun, 8
@@ -406,9 +406,10 @@ class ShixunsController < ApplicationController
end
end
@shixun.update_attributes(shixun_params)
+ logger.info("##########shixun_info_params: #{shixun_info_params}")
+ logger.info("##########params[:shixun_info][:evaluate_script]: #{params[:shixun_info][:evaluate_script]}")
@shixun.shixun_info.update_attributes(shixun_info_params)
@shixun.shixun_schools.delete_all
- logger.info("##########scope_partment:###{params[:scope_partment]}")
# scope_partment: 高校的名称
if params[:scope_partment].present?
arr = []
diff --git a/app/controllers/tidings_controller.rb b/app/controllers/tidings_controller.rb
index 795010b3f..9324b2755 100644
--- a/app/controllers/tidings_controller.rb
+++ b/app/controllers/tidings_controller.rb
@@ -1,6 +1,7 @@
class TidingsController < ApplicationController
include PaginateHelper
+ before_action :require_login
after_action :update_onclick_time!, only: [:index]
def index
diff --git a/app/controllers/users/private_messages_controller.rb b/app/controllers/users/private_messages_controller.rb
index b80b6152b..3a5635ef7 100644
--- a/app/controllers/users/private_messages_controller.rb
+++ b/app/controllers/users/private_messages_controller.rb
@@ -9,6 +9,8 @@ class Users::PrivateMessagesController < Users::BaseController
query = "SELECT subquery.*, COUNT(*) message_count FROM (#{subquery}) subquery "\
"GROUP BY subquery.target_id ORDER BY subquery.send_time desc LIMIT #{limit_value} OFFSET #{offset_value}"
@messages = PrivateMessage.select('*').from("(#{query}) AS query").includes(target: :user_extension)
+
+ observed_user.private_messages.only_unread.update_all(status: 1)
end
def create
diff --git a/app/decorators/course_decorator.rb b/app/decorators/course_decorator.rb
index 9c76b058a..9c3340bbf 100644
--- a/app/decorators/course_decorator.rb
+++ b/app/decorators/course_decorator.rb
@@ -1,5 +1,5 @@
module CourseDecorator
def can_visited?
- is_public == 1 || User.current.admin? || User.current.member_of_course?(self)
+ is_public == 1 || User.current.admin_or_business? || User.current.member_of_course?(self)
end
end
\ No newline at end of file
diff --git a/app/decorators/tiding_decorator.rb b/app/decorators/tiding_decorator.rb
index c9ad806ee..d1f6f08e6 100644
--- a/app/decorators/tiding_decorator.rb
+++ b/app/decorators/tiding_decorator.rb
@@ -2,6 +2,9 @@ module TidingDecorator
def content
method_name = "#{container_type.underscore}_content"
respond_to?(method_name) ? send(method_name) : ''
+ rescue => ex
+ Util.logger_error(ex)
+ ''
end
def how_long_time
@@ -27,6 +30,7 @@ module TidingDecorator
end
def strip_html(text, len = 0, suffix = "...")
+ text = text.to_s
str = ""
if !text.nil? && text.length > 0
str = text.gsub(/<\/?.*?>/, '').strip
@@ -43,13 +47,13 @@ module TidingDecorator
# ================ 各种类消息内容方法 ================
def apply_user_authentication_content
- return if trigger_user_id.zero?
+ t_user = trigger_user || User.find(1)
if tiding_type == 'Apply'
str1, str2 = if container.auth_type == 1
- [trigger_user.show_real_name, trigger_user.ID_number]
+ [t_user.show_real_name, t_user.ID_number]
elsif container.auth_type == 2
- ue = trigger_user.user_extension
+ ue = t_user.user_extension
[[ue.school&.name, ue.department&.name].join('_'), ue.identity_text]
end
I18n.t(locale_format(tiding_type, container.auth_type)) % [str1, str2]
@@ -93,7 +97,7 @@ module TidingDecorator
elsif status == 2
I18n.t(locale_format(tiding_type, "#{status}_#{extra.nil?}"), reason: extra) % [name, second_name]
else
- I18n.t(locale_format(tiding_type, status)) % [name, second_name]
+ I18n.t(locale_format(tiding_type, status), reason: extra) % [name, second_name]
end
end
@@ -102,9 +106,9 @@ module TidingDecorator
if tiding_type == 'Apply'
I18n.t(locale_format(tiding_type)) % name
elsif status == 2
- I18n.t(locale_format(tiding_type, "#{status}_#{extra.nil?}"), reason: extra) % name
+ I18n.t(locale_format(tiding_type, "#{status}_#{extra.nil?}"), name: name, reason: extra)
else
- I18n.t(locale_format(tiding_type, status)) % name
+ I18n.t(locale_format(tiding_type, status), name: name, reason: extra)
end
end
@@ -123,7 +127,11 @@ module TidingDecorator
end
def course_content
- I18n.t(locale_format) % container.name
+ if tiding_type == 'Delete'
+ I18n.t(locale_format(tiding_type)) % extra
+ else
+ I18n.t(locale_format) % container.name
+ end
end
def shixun_content
@@ -261,16 +269,16 @@ module TidingDecorator
def journal_content
case tiding_type
when 'Mentioned' then
- I18n.t(locale_format(tiding_type)) % message_content_helper(container.notes)
+ I18n.t(locale_format(tiding_type)) % message_content_helper(container&.notes)
when 'Comment' then
- I18n.t(locale_format(tiding_type, container.parent.present?)) % message_content_helper(container.notes)
+ I18n.t(locale_format(tiding_type, container.parent.present?)) % message_content_helper(container&.notes)
else
- I18n.t(locale_format) % container.issue.subject
+ I18n.t(locale_format) % container&.issue&.subject
end
end
def issue_content
- I18n.t(locale_format) % container.subject
+ I18n.t(locale_format) % container&.subject
end
def pull_request_content
@@ -291,15 +299,15 @@ module TidingDecorator
end
def poll_content
- I18n.t(locale_format(parent_container_type)) % container.polls_name
+ I18n.t(locale_format(parent_container_type)) % container&.polls_name
end
def exercise_content
- I18n.t(locale_format(parent_container_type)) % container.exercise_name
+ I18n.t(locale_format(parent_container_type)) % container&.exercise_name
end
def student_graduation_topic_content
- I18n.t(locale_format) % container.graduation_topic.try(:name)
+ I18n.t(locale_format) % container&.graduation_topic.try(:name)
end
def deal_student_topic_select_content
@@ -307,27 +315,27 @@ module TidingDecorator
end
def graduation_task_content
- I18n.t(locale_format(parent_container_type)) % container.name
+ I18n.t(locale_format(parent_container_type)) % container&.name
end
def graduation_work_content
- I18n.t(locale_format(extra.nil?)) % container.graduation_task.try(:name)
+ I18n.t(locale_format(extra.nil?)) % container&.graduation_task.try(:name)
end
def graduation_work_score_content
- I18n.t(locale_format) % container.graduation_work.graduation_task.try(:name)
+ I18n.t(locale_format) % container&.graduation_work&.graduation_task.try(:name)
end
def homework_common_content
- I18n.t(locale_format(parent_container_type), name: container.name, reason: extra)
+ I18n.t(locale_format(parent_container_type), name: container&.name, reason: extra)
end
def student_work_content
- I18n.t(locale_format(extra.nil?)) % container.homework_common.try(:name)
+ I18n.t(locale_format(extra.nil?)) % container&.homework_common.try(:name)
end
def student_works_score_content
- I18n.t(locale_format(extra)) % container.student_work.homework_common.try(:name)
+ I18n.t(locale_format(extra)) % container&.student_work&.homework_common.try(:name)
end
def challenge_work_score_content
diff --git a/app/forms/users/update_account_form.rb b/app/forms/users/update_account_form.rb
index d82459fcf..16c3c8013 100644
--- a/app/forms/users/update_account_form.rb
+++ b/app/forms/users/update_account_form.rb
@@ -5,8 +5,8 @@ class Users::UpdateAccountForm
attr_accessor :nickname, :name, :show_realname, :gender, :location, :location_city,
:identity, :student_id, :technical_title, :school_id, :department_id
- validates :nickname, presence: true
- validates :name, presence: true
+ validates :nickname, presence: true, length: { maximum: 20 }
+ validates :name, presence: true, length: { maximum: 10 }
validates :gender, presence: true, numericality: { only_integer: true }, inclusion: { in: [0, 1] }
validates :location, presence: true
validates :location_city, presence: true
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 7e9fd652b..099d45406 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -62,15 +62,18 @@ module ApplicationHelper
# shixun开启挑战对应的行为名及url
def task_operation_url current_myshixun, shixun
- url = "/shixuns/#{shixun.identifier}/shixun_exec"
- name =
- if current_myshixun.blank?
- shixun.status == 0 ? "模拟实战" : "开启挑战"
- elsif current_myshixun.status == 1
- "查看实战"
+ if current_myshixun.blank?
+ name = shixun.status == 0 ? "模拟实战" : "开启挑战"
+ url = "/shixuns/#{shixun.identifier}/shixun_exec"
+ else
+ identifier = current_myshixun.current_task(current_myshixun.games).try(:identifier)
+ if current_myshixun.status == 1
+ name = "查看实战"
else
- "继续挑战"
+ name = "继续挑战"
end
+ url = identifier
+ end
[name, url]
end
diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb
index 8c2aeb479..f14159cc2 100644
--- a/app/helpers/courses_helper.rb
+++ b/app/helpers/courses_helper.rb
@@ -194,7 +194,7 @@ module CoursesHelper
# 获取课堂的资源数
def get_attachment_count(course, category_id)
- course.attachments.where(course_second_category_id: category_id).size
+ category_id.to_i == 0 ? course.attachments.size : course.attachments.where(course_second_category_id: category_id).size
end
# 获取课堂的作业数
diff --git a/app/jobs/commit_exercsie_notify_job_job.rb b/app/jobs/commit_exercsie_notify_job_job.rb
new file mode 100644
index 000000000..1be0bb2bc
--- /dev/null
+++ b/app/jobs/commit_exercsie_notify_job_job.rb
@@ -0,0 +1,26 @@
+class CommitExercsieNotifyJobJob < ApplicationJob
+ queue_as :notify
+
+ def perform(exercise_id, user_id)
+ exercise = Exercise.find_by(id: exercise_id)
+ user = User.find_by(id: user_id)
+ return if [exercise, user].any?(&:blank?)
+ course = exercise.course
+
+ attrs = %i[user_id trigger_user_id container_id container_type parent_container_id parent_container_type
+ belong_container_id belong_container_type tiding_type viewed status created_at updated_at]
+
+ same_attrs = {
+ trigger_user_id: user.id,
+ container_id: exercise.id, container_type: 'Exercise',
+ parent_container_id: exercise.id, parent_container_type: 'CommitExercise',
+ belong_container_id: course.id, belong_container_type: 'Course',
+ tiding_type: 'Exercise', viewed: 0, status: 0
+ }
+ Tiding.bulk_insert(*attrs) do |worker|
+ course.course_member(user).member_teachers.each do |teacher|
+ worker.add same_attrs.merge(user_id: teacher.user_id)
+ end
+ end
+ end
+end
diff --git a/app/jobs/commit_poll_notify_job_job.rb b/app/jobs/commit_poll_notify_job_job.rb
new file mode 100644
index 000000000..6953fa9e9
--- /dev/null
+++ b/app/jobs/commit_poll_notify_job_job.rb
@@ -0,0 +1,26 @@
+class CommitPollNotifyJobJob < ApplicationJob
+ queue_as :notify
+
+ def perform(poll_id, user_id)
+ poll = Poll.find_by(id: poll_id)
+ user = User.find_by(id: user_id)
+ return if [poll, user].any?(&:blank?)
+ course = poll.course
+
+ attrs = %i[user_id trigger_user_id container_id container_type parent_container_id parent_container_type
+ belong_container_id belong_container_type tiding_type viewed status created_at updated_at]
+
+ same_attrs = {
+ trigger_user_id: user.id,
+ container_id: poll.id, container_type: 'Poll',
+ parent_container_id: poll.id, parent_container_type: 'CommitPoll',
+ belong_container_id: course.id, belong_container_type: 'Course',
+ tiding_type: 'Poll', viewed: 0, status: 0
+ }
+ Tiding.bulk_insert(*attrs) do |worker|
+ course.course_member(user).member_teachers.each do |teacher|
+ worker.add same_attrs.merge(user_id: teacher.user_id)
+ end
+ end
+ end
+end
diff --git a/app/models/apply_add_school.rb b/app/models/apply_add_school.rb
index bae65d24f..c303283ca 100644
--- a/app/models/apply_add_school.rb
+++ b/app/models/apply_add_school.rb
@@ -9,6 +9,7 @@ class ApplyAddSchool < ApplicationRecord
private
def send_notify
- tidings.create!(user_id: 1, status: 0, trigger_user_id: user_id, belong_container: school, tiding_type: 'Apply')
+ Tiding.create!(user_id: 1, status: 0, container_id: id, container_type: 'ApplyAddSchools',
+ trigger_user_id: user_id, belong_container: school, tiding_type: 'Apply')
end
end
\ No newline at end of file
diff --git a/app/models/apply_user_authentication.rb b/app/models/apply_user_authentication.rb
index c7fb5019e..d467eb850 100644
--- a/app/models/apply_user_authentication.rb
+++ b/app/models/apply_user_authentication.rb
@@ -3,8 +3,18 @@
class ApplyUserAuthentication < ApplicationRecord
belongs_to :user
+ has_many :tidings, :as => :container, :dependent => :destroy
+
scope :real_name_auth, -> { where(auth_type: 1) }
scope :professional_auth, -> { where(auth_type: 2) }
scope :processing, -> { where(status: 0) }
scope :passed, -> { where(status: 1) }
+
+ after_create :send_tiding
+
+ private
+
+ def send_tiding
+ self.tidings << Tiding.new(:user_id => '1', :status=> 0, :trigger_user_id => user_id, :belong_container_id => 1, :belong_container_type =>'User', :tiding_type => "Apply")
+ end
end
diff --git a/app/models/course_message.rb b/app/models/course_message.rb
index acb45d5f4..42cbe00c8 100644
--- a/app/models/course_message.rb
+++ b/app/models/course_message.rb
@@ -11,7 +11,7 @@ class CourseMessage < ApplicationRecord
def pass!
update!(status: :PASSED)
- send_deal_tiding
+ send_deal_tiding(1)
end
def application_user
@@ -20,16 +20,16 @@ class CourseMessage < ApplicationRecord
def reject!
update!(status: :REJECTED)
- send_deal_tiding
+ send_deal_tiding(2)
end
private
- def send_deal_tiding
+ def send_deal_tiding deal_status
# 发送申请处理结果消息
Tiding.create!(
- user_id: user_id, trigger_user: User.current, container_id: course_id, container_type: 'DealCourse',
- belong_container: course, extra: content.to_i == 2 ? '7' : '9', tiding_type: 'System', status: status == :PASSED ? 1 : 2
+ user_id: course_message_id, trigger_user: User.current, container_id: course_id, container_type: 'DealCourse',
+ belong_container: course, extra: content.to_i == 2 ? '9' : '7', tiding_type: 'System', status: deal_status
)
# 将申请消息置为已处理
Tiding.where(trigger_user_id: user_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1)
diff --git a/app/models/journals_for_message.rb b/app/models/journals_for_message.rb
index 1da26fd22..4300ae9cc 100644
--- a/app/models/journals_for_message.rb
+++ b/app/models/journals_for_message.rb
@@ -11,6 +11,7 @@ class JournalsForMessage < ApplicationRecord
scope :parent_comment, -> { where(m_parent_id: nil)}
scope :search_by_jour_type, lambda{|type,ids| where(jour_type:type,jour_id: ids)}
+ has_many :tidings, as: :container, dependent: :destroy
# "jour_type", # 留言所属类型
# "jour_id", # 留言所属类型的id
@@ -25,6 +26,8 @@ class JournalsForMessage < ApplicationRecord
# "is_comprehensive_evaluation", # 1 教师评论、2 匿评、3 留言
# "hidden", 隐藏
+ after_create :send_tiding
+
# course_identity 课堂用户身份
def contents_show course_identity
@@ -47,4 +50,29 @@ class JournalsForMessage < ApplicationRecord
JournalsForMessage.includes(:user).where(m_parent_id: self.id).page(page).per(limit).reorder("created_on asc")
end
+
+ def send_tiding
+ # 回复和@同一个人时:只发@的消息(因@的消息先创建)
+ case self.jour_type
+ # 用户留言当做私信处理 不发消息
+ when "Principal"
+=begin
+ user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : self.jour_id
+ if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
+ self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => self.jour_id, :belong_container_type => "User", :viewed => 0, :tiding_type => self.m_parent_id.present? ? "Comment" : "Journal")
+ end
+=end
+ when "HomeworkCommon", "GraduationTopic"
+ user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : (self.jour_type == "HomeworkCommon" ? self.jour.user_id : self.jour.tea_id)
+ if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
+ self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => self.jour.course_id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "Comment")
+ end
+ when "StudentWorksScore"
+ course_id = self.jour.try(:student_work).try(:homework_common).try(:course_id)
+ user_id = self.m_parent_id.present? ? JournalsForMessage.find(self.m_parent_id).user_id : self.jour.user_id
+ if user_id != self.user_id && !self.tidings.where(:user_id => user_id, :trigger_user_id => self.user_id, :tiding_type => "Mentioned").first.present?
+ self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => user_id, :parent_container_id => self.jour_id, :parent_container_type => self.jour_type, :belong_container_id => course_id, :belong_container_type => "Course", :viewed => 0, :tiding_type => "Comment")
+ end
+ end
+ end
end
diff --git a/app/models/library.rb b/app/models/library.rb
index 894dcdac0..13a5c3243 100644
--- a/app/models/library.rb
+++ b/app/models/library.rb
@@ -10,6 +10,8 @@ class Library < ApplicationRecord
has_many :attachments, as: :container
has_one :praise_tread_cache, foreign_key: :object_id
+ has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
+
validates :uuid, presence: true, uniqueness: true
diff --git a/app/models/shixun.rb b/app/models/shixun.rb
index 82f689e3f..61d15de55 100644
--- a/app/models/shixun.rb
+++ b/app/models/shixun.rb
@@ -38,6 +38,7 @@ class Shixun < ApplicationRecord
belongs_to :user
# 实训服务配置
has_many :shixun_service_configs, :dependent => :destroy
+ has_many :tidings, as: :container, dependent: :destroy
scope :search_by_name, ->(keyword) { where("name like ? or description like ? ",
"%#{keyword}%", "%#{keyword}%") }
@@ -62,6 +63,8 @@ class Shixun < ApplicationRecord
scope :field_for_recommend, lambda{ select([:id, :name, :identifier, :myshixuns_count]) }
scope :find_by_ids,lambda{|k| where(id:k)}
+ after_create :send_tiding
+
# REDO:
def propaedeutics
shixun_info.try(:propaedeutics)
@@ -242,4 +245,11 @@ class Shixun < ApplicationRecord
def finished_challenges_count(user)
Game.joins(:myshixun).where(user_id: user.id, status: 2, myshixuns: { shixun_id: id }).count
end
+
+ private
+
+ def send_tiding
+ self.tidings << Tiding.new(:user_id => user_id, :trigger_user_id => 1, :belong_container_id => id, :belong_container_type =>'Shixun', :tiding_type => "System", :viewed => 0)
+ end
+
end
diff --git a/app/models/student_graduation_topic.rb b/app/models/student_graduation_topic.rb
index ea1774695..50f150f92 100644
--- a/app/models/student_graduation_topic.rb
+++ b/app/models/student_graduation_topic.rb
@@ -17,7 +17,12 @@ class StudentGraduationTopic < ApplicationRecord
scope :is_refused, -> {where(status: 2)}
scope :is_accepted, -> {where(status: 1)}
scope :is_accepting, -> {where(status: 0)}
+ after_create :send_tiding
+ def send_tiding
+ self.tidings << Tiding.new(:user_id => self.graduation_topic.tea_id, :trigger_user_id => self.user_id, :parent_container_id => self.graduation_topic_id, :parent_container_type => "GraduationTopic",
+ :belong_container_id => self.graduation_topic.course_id, :belong_container_type => "Course", :viewed => 0, :status => 0, :tiding_type => "GraduationTopic")
+ end
# 学生名称
def name
diff --git a/app/models/tiding.rb b/app/models/tiding.rb
index 90abdf809..d885f93fd 100644
--- a/app/models/tiding.rb
+++ b/app/models/tiding.rb
@@ -9,16 +9,15 @@ class Tiding < ApplicationRecord
def identifier
value = nil
- if Object.const_defined?(container_type)
- value = container.try(:identifier)
- end
- if value.blank? && parent_container_type && Object.const_defined?(parent_container_type)
- value = parent_container_type.try(:identifier)
+ value = container.try(:identifier) rescue nil
+
+ if value.blank? && parent_container_type
+ value = parent_container_type.try(:identifier) rescue nil
end
- if value.blank? && belong_container_type && Object.const_defined?(belong_container_type)
- value = belong_container.try(:identifier)
+ if value.blank? && belong_container_type
+ value = belong_container.try(:identifier) rescue nil
end
value
diff --git a/app/models/user.rb b/app/models/user.rb
index b453f9998..e9d6ce54b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -234,7 +234,7 @@ class User < ApplicationRecord
# 课堂的老师(创建者、老师、助教),不用考虑当前身份
def teacher_of_course_non_active?(course)
- course.course_members.exists?(user_id: id, role: [1,2,3]) || admin? || business?
+ course.course_members.exists?(user_id: id, role: [1,2,3])
end
# 是否是教师,课堂管理员或者超级管理员
diff --git a/app/services/project_packages/save_service.rb b/app/services/project_packages/save_service.rb
index a876f56b3..8385ac5dd 100644
--- a/app/services/project_packages/save_service.rb
+++ b/app/services/project_packages/save_service.rb
@@ -54,7 +54,7 @@ class ProjectPackages::SaveService < ApplicationService
raise Error, '验证码不能为空' if params[:code].blank?
code = VerificationCode.where(phone: params[:contact_phone], code_type: 9, code: params[:code]).last
- raise Error, '无效的验证码' if code.blank? || !code.valid_code?
+ raise Error, '无效的验证码' if code.blank? || !code.effective?
end
def deal_attachments
diff --git a/app/services/project_packages/win_bidding_service.rb b/app/services/project_packages/win_bidding_service.rb
index 831c29449..54cb1e883 100644
--- a/app/services/project_packages/win_bidding_service.rb
+++ b/app/services/project_packages/win_bidding_service.rb
@@ -1,14 +1,16 @@
class ProjectPackages::WinBiddingService < ApplicationService
Error = Class.new(StandardError)
- attr_reader :package, :params
+ attr_reader :package, :user, :params
- def initialize(package, params)
+ def initialize(package, user, params)
@package = package
+ @user = user
@params = params
end
def call
+ raise Error, '没有权限' unless package.creator_id == user.id || user.admin_or_business?
raise Error, '竞标报名还未结束' unless package.bidding_end?
raise Error, '该状态下不能选择中标者' unless package.may_finish_bidding?
diff --git a/app/views/courses/create.json.jbuilder b/app/views/courses/create.json.jbuilder
index baf14da46..be20a994b 100644
--- a/app/views/courses/create.json.jbuilder
+++ b/app/views/courses/create.json.jbuilder
@@ -1 +1,2 @@
-json.course_id @course.id
\ No newline at end of file
+json.course_id @course.id
+json.first_category_url module_url(@course.none_hidden_course_modules.first, @course)
\ No newline at end of file
diff --git a/app/views/courses/index.json.jbuilder b/app/views/courses/index.json.jbuilder
index 32a7047b7..7b404211b 100644
--- a/app/views/courses/index.json.jbuilder
+++ b/app/views/courses/index.json.jbuilder
@@ -4,7 +4,7 @@ json.courses @courses do |course|
json.avatar_url url_to_avatar(course.teacher)
json.creator course.teacher.real_name
json.school course.school&.name
- json.technical_title course.teacher.identity
+ json.technical_title "" # course.teacher.identity
json.course_members_count course.course_members_count
json.tasks_count get_tasks_count course
json.visits course.visits
diff --git a/app/views/graduation_topics/_graduation_comments.json.jbuilder b/app/views/graduation_topics/_graduation_comments.json.jbuilder
index ee9ed7529..51551d95d 100644
--- a/app/views/graduation_topics/_graduation_comments.json.jbuilder
+++ b/app/views/graduation_topics/_graduation_comments.json.jbuilder
@@ -11,6 +11,6 @@ if message.m_parent_id
json.can_delete message.can_delete(identity)
else
json.praise_count message.praise_treads.select{|pt| pt.praise_or_tread == 1}.count
- json.user_praise message.praise_treads.select{|pt| pt.praise_or_tread == 1 && user_id == current_user.id}.count
+ json.user_praise message.praise_treads.select{|pt| pt.praise_or_tread == 1 && pt.user_id == current_user.id}.count
json.child_message_count message.m_reply_count
end
diff --git a/app/views/libraries/index.json.jbuilder b/app/views/libraries/index.json.jbuilder
index c58d390b0..8774b72ae 100644
--- a/app/views/libraries/index.json.jbuilder
+++ b/app/views/libraries/index.json.jbuilder
@@ -5,12 +5,17 @@ json.libraries do
json.cover_url library.cover_id.present? ? download_url(library.cover) : nil
- json.praise_count library.praise_tread_cache&.praise_num || 0
+ json.praise_count library.praises_count
json.download_count @download_count_map.fetch(library.id, 0)
json.published_at library.display_published_at
json.created_at library.display_created_at
- json.tags library.library_tags.map(&:name)
+ # 标签
+ json.tags do
+ json.array! library.library_tags.each do |tag|
+ json.extract! tag, :id, :name
+ end
+ end
end
end
\ No newline at end of file
diff --git a/app/views/libraries/show.json.jbuilder b/app/views/libraries/show.json.jbuilder
index 0f4b6ea17..fd20d7bf2 100644
--- a/app/views/libraries/show.json.jbuilder
+++ b/app/views/libraries/show.json.jbuilder
@@ -2,7 +2,7 @@ library = current_library
json.extract! library, :id, :uuid, :title, :content, :author_name, :author_school_name, :status, :visited_count
-json.praise_count library.praise_tread_cache&.praise_num || 0
+json.praise_count library.praises_count
json.published_at library.display_published_at
json.created_at library.display_created_at
@@ -10,6 +10,7 @@ json.created_at library.display_created_at
# 创建者
json.creator do
json.partial! 'users/user_simple', user: library.user
+ json.school_name library.user.school_name
end
# 封面
@@ -37,7 +38,7 @@ json.operation do
json.can_deletable manageable
json.can_editable manageable
- json.user_praised PraiseTread.exists?(user_id: current_user&.id)
+ json.user_praised library.praise_treads.exists?(user_id: current_user&.id)
else
json.can_deletable false
json.can_editable false
diff --git a/app/views/memos/_memo.json.jbuilder b/app/views/memos/_memo.json.jbuilder
index bc3744d1f..f0ac5cd3d 100644
--- a/app/views/memos/_memo.json.jbuilder
+++ b/app/views/memos/_memo.json.jbuilder
@@ -9,6 +9,6 @@ json.memo do
json.tag memo.tag_repertoires.map(&:name)
json.time memo.created_at
json.replies_count memo.all_replies_count
- json.user_praise memo.praise_treads.user_liker(@user.try(:id)) ? true : false
+ json.user_praise memo.praise_treads.user_liker(@user.try(:id)).count > 0 ? true : false
json.memo_praise_count memo.praise_treads.liker.count
end
diff --git a/app/views/memos/reply.json.jbuilder b/app/views/memos/reply.json.jbuilder
new file mode 100644
index 000000000..c117d2d24
--- /dev/null
+++ b/app/views/memos/reply.json.jbuilder
@@ -0,0 +1,2 @@
+json.(@reply, :id, :subject, :content, :hidden, :forum_id, :author_id, :all_replies_count, :is_md, :parent_id, :root_id,
+ :reward, :sticky, :updated_at, :created_at, :viewed_count)
\ No newline at end of file
diff --git a/app/views/tidings/_tiding.json.jbuilder b/app/views/tidings/_tiding.json.jbuilder
index 34b06320d..207d4b137 100644
--- a/app/views/tidings/_tiding.json.jbuilder
+++ b/app/views/tidings/_tiding.json.jbuilder
@@ -1,6 +1,19 @@
-json.extract! tiding, :id, :status, :viewed, :user_id, :tiding_type, :container_id, :container_type, :parent_container_id, :parent_container_type
+json.extract! tiding, :id, :status, :viewed, :user_id, :tiding_type, :container_id, :container_type,
+ :parent_container_id, :parent_container_type, :belong_container_id, :belong_container_type
json.content tiding.content
+
json.identifier tiding.identifier
+json.auth_type tiding.container_type == 'ApplyUserAuthentication' ? tiding.container.auth_type : nil
+
+homework_type = nil
+if tiding.container_type == 'HomeworkCommon'
+ homework_type = tiding.container.homework_type rescue nil
+end
+if homework_type.blank? && tiding.parent_container_type == 'HomeworkCommon'
+ homework_type = tiding.parent_container.homework_type rescue nil
+end
+json.homework_type homework_type
+
json.time tiding.how_long_time
json.new_tiding tiding.unread?(@onclick_time)
diff --git a/app/views/users/private_messages/create.json.jbuilder b/app/views/users/private_messages/create.json.jbuilder
index 888cfeff6..2d5b4e7bf 100644
--- a/app/views/users/private_messages/create.json.jbuilder
+++ b/app/views/users/private_messages/create.json.jbuilder
@@ -3,6 +3,7 @@ json.message 'success'
json.private_message do
json.extract! @message, :id, :user_id, :receiver_id, :sender_id, :content
+ json.send_day @message.send_time.strftime('%Y-%m-%d')
json.send_time @message.display_send_time
json.sender do
json.partial! 'users/user_simple', user: @message.sender
diff --git a/app/views/users/project_packages/index.json.jbuilder b/app/views/users/project_packages/index.json.jbuilder
index a2574d558..ad56be7d2 100644
--- a/app/views/users/project_packages/index.json.jbuilder
+++ b/app/views/users/project_packages/index.json.jbuilder
@@ -16,5 +16,11 @@ json.project_packages do
json.deadline_at package.display_deadline_at
json.published_at package.display_published_at
+
+ json.operation do
+ can_manage = current_user&.id == observed_user.id || current_user&.admin_or_business?
+ json.can_edit can_manage && package.editable?
+ json.can_delete can_manage && package.deletable?
+ end
end
end
\ No newline at end of file
diff --git a/config/locales/tidings/zh-CN.yml b/config/locales/tidings/zh-CN.yml
index 07e3c2f6d..1a8cc7061 100644
--- a/config/locales/tidings/zh-CN.yml
+++ b/config/locales/tidings/zh-CN.yml
@@ -6,9 +6,9 @@
"2_end": "申请职业认证:%s %s"
System:
"1_1_end": "你提交的实名认证申请,审核已通过"
- "1_2_end": "你提交的实名认证申请,审核未通过 原因:%{reason}"
+ "1_2_end": "你提交的实名认证申请,审核未通过原因:%{reason} "
"2_1_end": "你提交的职业认证申请,审核已通过"
- "2_2_end": "你提交的职业认证申请,审核未通过 原因:%{reason}"
+ "2_2_end": "你提交的职业认证申请,审核未通过原因:%{reason} "
CancelUserAuthentication_end: "取消了你的实名认证:%s %s"
CancelUserProCertification_end: "取消了你的实名认证:%s %s"
JoinCourse:
@@ -21,6 +21,9 @@
"7_2_end": "你提交的加入课堂申请:%s(助教), 审核未通过"
StudentJoinCourse_end: "加入了课堂:%s(学生)"
TeacherJoinCourse:
+ "2_end": "%s将你加入课堂:%s(教师)"
+ "3_end": "%s将你加入课堂:%s(助教)"
+ "4_end": "%s将你加入课堂:%s(学生)"
"9_end": "%s将你加入课堂:%s(教师)"
"7_end": "%s将你加入课堂:%s(助教)"
"10_end": "%s将你加入课堂:%s(学生)"
@@ -28,35 +31,37 @@
Apply_end: "申请添加二级单位:%s(%s)"
System:
"1_end": "你提交的添加二级单位申请:%s(%s),审核已通过"
- "2_false_end": "你提交的添加二级单位申请:%s(%s),审核未通过 原因:%{reason}"
+ "2_false_end": "你提交的添加二级单位申请:%s(%s),审核未通过原因:%{reason} "
"2_true_end": "你提交的添加二级单位申请:%s(%s),审核未通过"
"3_end": "你提交的添加二级单位申请:%s(%s),已被更改为%{reason}"
ApplyAddSchools:
Apply_end: "申请添加单位:%s"
System:
"1_end": "你提交的添加单位申请:%{name},审核已通过"
- "2_reason_end": "你提交的添加单位申请:%{name},审核未通过 原因:%{reason}"
- "2_no_reason_end": "你提交的添加单位申请:%{name},审核未通过"
+ "2_false_end": "你提交的添加单位申请:%{name},审核未通过原因:%{reason} "
+ "2_true_end": "你提交的添加单位申请:%{name},审核未通过"
"3_end": "你提交的添加单位申请:%{name},已被更改为:%{reason}"
ApplyAction:
ApplyShixun:
System:
"1_end": "你提交的实训发布申请:%{name},审核已通过"
- "2_end": "你提交的实训发布申请:%{name},审核未通过 原因:%{reason}"
+ "2_end": "你提交的实训发布申请:%{name},审核未通过原因:%{reason} "
Apply_end: "申请发布实训:%{name}"
ApplySubject:
System:
"1_end": "你提交的实训课程发布申请:%{name},审核已通过"
- "2_end": "你提交的实训课程发布申请:%{name},审核未通过 原因:%{reason}"
+ "2_end": "你提交的实训课程发布申请:%{name},审核未通过原因:%{reason} "
Apply_end: "申请发布实训课程:%{name}"
TrialAuthorization:
System:
"1_end": "你提交的试用授权申请,审核已通过"
- "2_end": "你提交的试用授权申请,审核未通过 原因:%{reason}"
+ "2_end": "你提交的试用授权申请,审核未通过原因:%{reason} "
Apply_end: "提交了试用授权申请"
- Course_end: "成功创建了课堂:%s"
- Shixun_end: "成功创建了实训:%s"
- Subject_end: "成功创建了实训课程:%s"
+ Course_end: "你创建了课堂:%s"
+ Course:
+ Delete_end: "你删除了课堂:%s"
+ Shixun_end: "你创建了实训:%s"
+ Subject_end: "你创建了实训课程:%s"
ArchiveCourse_end: "你的课堂已经归档:%s"
JournalsForMessage:
Mentioned_end: "@了你:%s"
@@ -159,7 +164,7 @@
NearlyEnd_end: "试卷的截止时间快到啦:%s"
CommitExercise_end: "提交了试卷答题:%s"
ExerciseScore_end: "评阅了你的试卷:%s"
- StudentGraduationTopic_end: "选择了毕设选题:%s"
+ StudentGraduationTopic_end: "申请选择毕设选题:%s"
DealStudentTopicSelect:
1_end: "你提交的选题申请:%s,审核已通过"
2_end: "你提交的选题申请:%s,审核未通过"
@@ -174,7 +179,7 @@
GraduationWorkScore_end: "评阅了你的作品:%s"
HomeworkCommon:
AnonymousComment_end: "开启了作业匿评:%{name}"
- AnonymousCommentFail_end: "开启作业匿评失败:%{name}, 原因:%{reason}"
+ AnonymousCommentFail_end: "开启作业匿评失败:%{name}原因:%{reason} "
AnonymousAppeal_end: "开启了匿评申诉:%{name}"
HomeworkPublish_end: "发布了作业:%{name}"
NearlyEnd_end: "作业的提交截止时间快到啦:%{name}"
@@ -190,11 +195,11 @@
ChallengeWorkScore_end: "调整了你的作品分数:%s"
StudentWorksScoresAppeal:
UserAppealResult:
- 1_end: "同意了你提交的匿评申诉申请:%s"
- 2_end: "拒绝了你提交的匿评申诉:%s"
+ 1_end: "你提交的匿评申诉申请:%s,审核已通过"
+ 2_end: "你提交的匿评申诉:%s,审核未通过"
AppealResult:
- 1_end: "同意了他人对你的匿评申诉申请:%s"
- 2_end: "拒绝了他人对你的匿评申诉:%s"
+ 1_end: "别人对你的匿评发起的申诉申请:%s,审核已通过"
+ 2_end: "别人对你的匿评发起的申诉申请:%s,审核未通过"
StudentWork:
Apply_end: "发起了匿评申诉申请:%s"
HomeworkCommon_end: "有人对你的匿评发起了申诉:%s"
@@ -203,12 +208,12 @@
Apply_end: "申请发布教学案例:%s"
System:
1_end: "你提交的发布教学案例申请:%s,审核已通过"
- 2_end: "你提交的发布教学案例申请:%s,审核未通过,原因:%{reason}"
+ 2_end: "你提交的发布教学案例申请:%s,审核未通过原因:%{reason} "
ProjectPackage:
Apply_end: "申请发布众包需求:%s"
System:
1_end: "你提交的众包需求申请:%s,审核已通过"
- 2_end: "你提交的众包需求申请:%s,审核未通过,原因:%{reason}"
+ 2_end: "你提交的众包需求申请:%s,审核未通过原因:%{reason} "
Created_end: "你创建了众包需求:%s"
Destroyed_end: "你删除了众包需求:%s"
Bidding_end: "应征了你发布的众包任务:%s"
diff --git a/config/routes.rb b/config/routes.rb
index 79542817f..b8db3afa6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -5,6 +5,7 @@ Rails.application.routes.draw do
mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new
get 'attachments/download/:id', to: 'attachments#show'
+ get 'attachments/download/:id/:filename', to: 'attachments#show'
resources :edu_settings
scope '/api' do
diff --git a/db/migrate/20190730024112_add_index_to_user.rb b/db/migrate/20190730024112_add_index_to_user.rb
deleted file mode 100644
index fa198cffa..000000000
--- a/db/migrate/20190730024112_add_index_to_user.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class AddIndexToUser < ActiveRecord::Migration[5.2]
- def change
- # add_index :users, :login, unique: true
- # add_index :users, :mail, unique: true
- # add_index :users, :phone, unique: true
- end
-end
diff --git a/db/migrate/20190801075337_add_praises_count_to_memos.rb b/db/migrate/20190801075337_add_praises_count_to_memos.rb
new file mode 100644
index 000000000..0cc2259e2
--- /dev/null
+++ b/db/migrate/20190801075337_add_praises_count_to_memos.rb
@@ -0,0 +1,12 @@
+class AddPraisesCountToMemos < ActiveRecord::Migration[5.2]
+ def change
+ add_column :memos, :praises_count, :integer, :default => 0
+
+ memos = Memo.includes(:praise_treads).all
+ memos.find_each do |m|
+ puts("####{m.id}")
+ praises_count = m.praise_treads.select{|pt| pt.praise_or_tread == 1}.count
+ m.update_column(:praises_count, praises_count)
+ end
+ end
+end
diff --git a/db/migrate/20190801084533_add_praises_count_to_libraries.rb b/db/migrate/20190801084533_add_praises_count_to_libraries.rb
new file mode 100644
index 000000000..b773cf918
--- /dev/null
+++ b/db/migrate/20190801084533_add_praises_count_to_libraries.rb
@@ -0,0 +1,10 @@
+class AddPraisesCountToLibraries < ActiveRecord::Migration[5.2]
+ def change
+ # add_column :libraries, :praises_count, :integer, :default => 0
+ #
+ # Library.find_each do |library|
+ # praises_count = library.praise_treads.count
+ # library.update_column(:praises_count, praises_count)
+ # end
+ end
+end
diff --git a/db/migrate/20190802105008_tranfer_tiding_data.rb b/db/migrate/20190802105008_tranfer_tiding_data.rb
new file mode 100644
index 000000000..ef7682530
--- /dev/null
+++ b/db/migrate/20190802105008_tranfer_tiding_data.rb
@@ -0,0 +1,5 @@
+class TranferTidingData < ActiveRecord::Migration[5.2]
+ def change
+ Tiding.where(container_type: 'ApplyAddSchool').update_all(container_type: 'ApplyAddSchools')
+ end
+end
diff --git a/db/migrate/20190805004505_sync_index_to_users.rb b/db/migrate/20190805004505_sync_index_to_users.rb
new file mode 100644
index 000000000..33adca30c
--- /dev/null
+++ b/db/migrate/20190805004505_sync_index_to_users.rb
@@ -0,0 +1,7 @@
+class SyncIndexToUsers < ActiveRecord::Migration[5.2]
+ def change
+ add_index :users, :login, unique: true
+ add_index :users, :mail, unique: true
+ add_index :users, :phone, unique: true
+ end
+end
diff --git a/dump.rdb b/dump.rdb
index a799840b1..63b8abb0a 100644
Binary files a/dump.rdb and b/dump.rdb differ
diff --git a/public/javascripts/media/clappr.js b/public/javascripts/media/clappr.js
new file mode 100644
index 000000000..d16774aa2
--- /dev/null
+++ b/public/javascripts/media/clappr.js
@@ -0,0 +1,38289 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["Clappr"] = factory();
+ else
+ root["Clappr"] = factory();
+})(window, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "dist/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "./src/main.js");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./node_modules/babel-runtime/core-js/array/from.js":
+/*!**********************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/array/from.js ***!
+ \**********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/array/from */ "./node_modules/core-js/library/fn/array/from.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/get-iterator.js":
+/*!************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/get-iterator.js ***!
+ \************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/get-iterator */ "./node_modules/core-js/library/fn/get-iterator.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/json/stringify.js":
+/*!**************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/json/stringify.js ***!
+ \**************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/json/stringify */ "./node_modules/core-js/library/fn/json/stringify.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/object/assign.js":
+/*!*************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/object/assign.js ***!
+ \*************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/object/assign */ "./node_modules/core-js/library/fn/object/assign.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/object/create.js":
+/*!*************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/object/create.js ***!
+ \*************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/object/create */ "./node_modules/core-js/library/fn/object/create.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/object/define-property.js":
+/*!**********************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/object/define-property.js ***!
+ \**********************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/object/define-property */ "./node_modules/core-js/library/fn/object/define-property.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/object/get-own-property-descriptor.js":
+/*!**********************************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/object/get-own-property-descriptor.js ***!
+ \**********************************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/object/get-own-property-descriptor */ "./node_modules/core-js/library/fn/object/get-own-property-descriptor.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/object/keys.js":
+/*!***********************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/object/keys.js ***!
+ \***********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/object/keys */ "./node_modules/core-js/library/fn/object/keys.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/object/set-prototype-of.js":
+/*!***********************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/object/set-prototype-of.js ***!
+ \***********************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/object/set-prototype-of */ "./node_modules/core-js/library/fn/object/set-prototype-of.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/symbol.js":
+/*!******************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/symbol.js ***!
+ \******************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/symbol */ "./node_modules/core-js/library/fn/symbol/index.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/core-js/symbol/iterator.js":
+/*!***************************************************************!*\
+ !*** ./node_modules/babel-runtime/core-js/symbol/iterator.js ***!
+ \***************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = { "default": __webpack_require__(/*! core-js/library/fn/symbol/iterator */ "./node_modules/core-js/library/fn/symbol/iterator.js"), __esModule: true };
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/helpers/classCallCheck.js":
+/*!**************************************************************!*\
+ !*** ./node_modules/babel-runtime/helpers/classCallCheck.js ***!
+ \**************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+exports.default = function (instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+};
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/helpers/createClass.js":
+/*!***********************************************************!*\
+ !*** ./node_modules/babel-runtime/helpers/createClass.js ***!
+ \***********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+var _defineProperty = __webpack_require__(/*! ../core-js/object/define-property */ "./node_modules/babel-runtime/core-js/object/define-property.js");
+
+var _defineProperty2 = _interopRequireDefault(_defineProperty);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ (0, _defineProperty2.default)(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+}();
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/helpers/extends.js":
+/*!*******************************************************!*\
+ !*** ./node_modules/babel-runtime/helpers/extends.js ***!
+ \*******************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+var _assign = __webpack_require__(/*! ../core-js/object/assign */ "./node_modules/babel-runtime/core-js/object/assign.js");
+
+var _assign2 = _interopRequireDefault(_assign);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _assign2.default || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+
+ for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+
+ return target;
+};
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/helpers/inherits.js":
+/*!********************************************************!*\
+ !*** ./node_modules/babel-runtime/helpers/inherits.js ***!
+ \********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+var _setPrototypeOf = __webpack_require__(/*! ../core-js/object/set-prototype-of */ "./node_modules/babel-runtime/core-js/object/set-prototype-of.js");
+
+var _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf);
+
+var _create = __webpack_require__(/*! ../core-js/object/create */ "./node_modules/babel-runtime/core-js/object/create.js");
+
+var _create2 = _interopRequireDefault(_create);
+
+var _typeof2 = __webpack_require__(/*! ../helpers/typeof */ "./node_modules/babel-runtime/helpers/typeof.js");
+
+var _typeof3 = _interopRequireDefault(_typeof2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = function (subClass, superClass) {
+ if (typeof superClass !== "function" && superClass !== null) {
+ throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : (0, _typeof3.default)(superClass)));
+ }
+
+ subClass.prototype = (0, _create2.default)(superClass && superClass.prototype, {
+ constructor: {
+ value: subClass,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ if (superClass) _setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass;
+};
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js":
+/*!*************************************************************************!*\
+ !*** ./node_modules/babel-runtime/helpers/possibleConstructorReturn.js ***!
+ \*************************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+var _typeof2 = __webpack_require__(/*! ../helpers/typeof */ "./node_modules/babel-runtime/helpers/typeof.js");
+
+var _typeof3 = _interopRequireDefault(_typeof2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = function (self, call) {
+ if (!self) {
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
+ }
+
+ return call && ((typeof call === "undefined" ? "undefined" : (0, _typeof3.default)(call)) === "object" || typeof call === "function") ? call : self;
+};
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/helpers/toConsumableArray.js":
+/*!*****************************************************************!*\
+ !*** ./node_modules/babel-runtime/helpers/toConsumableArray.js ***!
+ \*****************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+var _from = __webpack_require__(/*! ../core-js/array/from */ "./node_modules/babel-runtime/core-js/array/from.js");
+
+var _from2 = _interopRequireDefault(_from);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = function (arr) {
+ if (Array.isArray(arr)) {
+ for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
+ arr2[i] = arr[i];
+ }
+
+ return arr2;
+ } else {
+ return (0, _from2.default)(arr);
+ }
+};
+
+/***/ }),
+
+/***/ "./node_modules/babel-runtime/helpers/typeof.js":
+/*!******************************************************!*\
+ !*** ./node_modules/babel-runtime/helpers/typeof.js ***!
+ \******************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+exports.__esModule = true;
+
+var _iterator = __webpack_require__(/*! ../core-js/symbol/iterator */ "./node_modules/babel-runtime/core-js/symbol/iterator.js");
+
+var _iterator2 = _interopRequireDefault(_iterator);
+
+var _symbol = __webpack_require__(/*! ../core-js/symbol */ "./node_modules/babel-runtime/core-js/symbol.js");
+
+var _symbol2 = _interopRequireDefault(_symbol);
+
+var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj; };
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) {
+ return typeof obj === "undefined" ? "undefined" : _typeof(obj);
+} : function (obj) {
+ return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj);
+};
+
+/***/ }),
+
+/***/ "./node_modules/clappr-zepto/zepto.js":
+/*!********************************************!*\
+ !*** ./node_modules/clappr-zepto/zepto.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+/* Zepto v1.2.0 - zepto ajax callbacks deferred event ie selector - zeptojs.com/license */
+
+
+var Zepto = (function() {
+ var undefined, key, $, classList, emptyArray = [], concat = emptyArray.concat, filter = emptyArray.filter, slice = emptyArray.slice,
+ document = window.document,
+ elementDisplay = {}, classCache = {},
+ cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },
+ fragmentRE = /^\s*<(\w+|!)[^>]*>/,
+ singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+ tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+ rootNodeRE = /^(?:body|html)$/i,
+ capitalRE = /([A-Z])/g,
+
+ // special attributes that should be get/set via method calls
+ methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],
+
+ adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
+ table = document.createElement('table'),
+ tableRow = document.createElement('tr'),
+ containers = {
+ 'tr': document.createElement('tbody'),
+ 'tbody': table, 'thead': table, 'tfoot': table,
+ 'td': tableRow, 'th': tableRow,
+ '*': document.createElement('div')
+ },
+ readyRE = /complete|loaded|interactive/,
+ simpleSelectorRE = /^[\w-]*$/,
+ class2type = {},
+ toString = class2type.toString,
+ zepto = {},
+ camelize, uniq,
+ tempParent = document.createElement('div'),
+ propMap = {
+ 'tabindex': 'tabIndex',
+ 'readonly': 'readOnly',
+ 'for': 'htmlFor',
+ 'class': 'className',
+ 'maxlength': 'maxLength',
+ 'cellspacing': 'cellSpacing',
+ 'cellpadding': 'cellPadding',
+ 'rowspan': 'rowSpan',
+ 'colspan': 'colSpan',
+ 'usemap': 'useMap',
+ 'frameborder': 'frameBorder',
+ 'contenteditable': 'contentEditable'
+ },
+ isArray = Array.isArray ||
+ function(object){ return object instanceof Array }
+
+ zepto.matches = function(element, selector) {
+ if (!selector || !element || element.nodeType !== 1) return false
+ var matchesSelector = element.matches || element.webkitMatchesSelector ||
+ element.mozMatchesSelector || element.oMatchesSelector ||
+ element.matchesSelector
+ if (matchesSelector) return matchesSelector.call(element, selector)
+ // fall back to performing a selector:
+ var match, parent = element.parentNode, temp = !parent
+ if (temp) (parent = tempParent).appendChild(element)
+ match = ~zepto.qsa(parent, selector).indexOf(element)
+ temp && tempParent.removeChild(element)
+ return match
+ }
+
+ function type(obj) {
+ return obj == null ? String(obj) :
+ class2type[toString.call(obj)] || "object"
+ }
+
+ function isFunction(value) { return type(value) == "function" }
+ function isWindow(obj) { return obj != null && obj == obj.window }
+ function isDocument(obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }
+ function isObject(obj) { return type(obj) == "object" }
+ function isPlainObject(obj) {
+ return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype
+ }
+
+ function likeArray(obj) {
+ var length = !!obj && 'length' in obj && obj.length,
+ type = $.type(obj)
+
+ return 'function' != type && !isWindow(obj) && (
+ 'array' == type || length === 0 ||
+ (typeof length == 'number' && length > 0 && (length - 1) in obj)
+ )
+ }
+
+ function compact(array) { return filter.call(array, function(item){ return item != null }) }
+ function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }
+ camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }
+ function dasherize(str) {
+ return str.replace(/::/g, '/')
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
+ .replace(/([a-z\d])([A-Z])/g, '$1_$2')
+ .replace(/_/g, '-')
+ .toLowerCase()
+ }
+ uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }
+
+ function classRE(name) {
+ return name in classCache ?
+ classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'))
+ }
+
+ function maybeAddPx(name, value) {
+ return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value
+ }
+
+ function defaultDisplay(nodeName) {
+ var element, display
+ if (!elementDisplay[nodeName]) {
+ element = document.createElement(nodeName)
+ document.body.appendChild(element)
+ display = getComputedStyle(element, '').getPropertyValue("display")
+ element.parentNode.removeChild(element)
+ display == "none" && (display = "block")
+ elementDisplay[nodeName] = display
+ }
+ return elementDisplay[nodeName]
+ }
+
+ function children(element) {
+ return 'children' in element ?
+ slice.call(element.children) :
+ $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node })
+ }
+
+ function Z(dom, selector) {
+ var i, len = dom ? dom.length : 0
+ for (i = 0; i < len; i++) this[i] = dom[i]
+ this.length = len
+ this.selector = selector || ''
+ }
+
+ // `$.zepto.fragment` takes a html string and an optional tag name
+ // to generate DOM nodes from the given html string.
+ // The generated DOM nodes are returned as an array.
+ // This function can be overridden in plugins for example to make
+ // it compatible with browsers that don't support the DOM fully.
+ zepto.fragment = function(html, name, properties) {
+ var dom, nodes, container
+
+ // A special case optimization for a single tag
+ if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))
+
+ if (!dom) {
+ if (html.replace) html = html.replace(tagExpanderRE, "<$1>$2>")
+ if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
+ if (!(name in containers)) name = '*'
+
+ container = containers[name]
+ container.innerHTML = '' + html
+ dom = $.each(slice.call(container.childNodes), function(){
+ container.removeChild(this)
+ })
+ }
+
+ if (isPlainObject(properties)) {
+ nodes = $(dom)
+ $.each(properties, function(key, value) {
+ if (methodAttributes.indexOf(key) > -1) nodes[key](value)
+ else nodes.attr(key, value)
+ })
+ }
+
+ return dom
+ }
+
+ // `$.zepto.Z` swaps out the prototype of the given `dom` array
+ // of nodes with `$.fn` and thus supplying all the Zepto functions
+ // to the array. This method can be overridden in plugins.
+ zepto.Z = function(dom, selector) {
+ return new Z(dom, selector)
+ }
+
+ // `$.zepto.isZ` should return `true` if the given object is a Zepto
+ // collection. This method can be overridden in plugins.
+ zepto.isZ = function(object) {
+ return object instanceof zepto.Z
+ }
+
+ // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and
+ // takes a CSS selector and an optional context (and handles various
+ // special cases).
+ // This method can be overridden in plugins.
+ zepto.init = function(selector, context) {
+ var dom
+ // If nothing given, return an empty Zepto collection
+ if (!selector) return zepto.Z()
+ // Optimize for string selectors
+ else if (typeof selector == 'string') {
+ selector = selector.trim()
+ // If it's a html fragment, create nodes from it
+ // Note: In both Chrome 21 and Firefox 15, DOM error 12
+ // is thrown if the fragment doesn't begin with <
+ if (selector[0] == '<' && fragmentRE.test(selector))
+ dom = zepto.fragment(selector, RegExp.$1, context), selector = null
+ // If there's a context, create a collection on that context first, and select
+ // nodes from there
+ else if (context !== undefined) return $(context).find(selector)
+ // If it's a CSS selector, use it to select nodes.
+ else dom = zepto.qsa(document, selector)
+ }
+ // If a function is given, call it when the DOM is ready
+ else if (isFunction(selector)) return $(document).ready(selector)
+ // If a Zepto collection is given, just return it
+ else if (zepto.isZ(selector)) return selector
+ else {
+ // normalize array if an array of nodes is given
+ if (isArray(selector)) dom = compact(selector)
+ // Wrap DOM nodes.
+ else if (isObject(selector))
+ dom = [selector], selector = null
+ // If it's a html fragment, create nodes from it
+ else if (fragmentRE.test(selector))
+ dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
+ // If there's a context, create a collection on that context first, and select
+ // nodes from there
+ else if (context !== undefined) return $(context).find(selector)
+ // And last but no least, if it's a CSS selector, use it to select nodes.
+ else dom = zepto.qsa(document, selector)
+ }
+ // create a new Zepto collection from the nodes found
+ return zepto.Z(dom, selector)
+ }
+
+ // `$` will be the base `Zepto` object. When calling this
+ // function just call `$.zepto.init, which makes the implementation
+ // details of selecting nodes and creating Zepto collections
+ // patchable in plugins.
+ $ = function(selector, context){
+ return zepto.init(selector, context)
+ }
+
+ function extend(target, source, deep) {
+ for (key in source)
+ if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
+ if (isPlainObject(source[key]) && !isPlainObject(target[key]))
+ target[key] = {}
+ if (isArray(source[key]) && !isArray(target[key]))
+ target[key] = []
+ extend(target[key], source[key], deep)
+ }
+ else if (source[key] !== undefined) target[key] = source[key]
+ }
+
+ // Copy all but undefined properties from one or more
+ // objects to the `target` object.
+ $.extend = function(target){
+ var deep, args = slice.call(arguments, 1)
+ if (typeof target == 'boolean') {
+ deep = target
+ target = args.shift()
+ }
+ args.forEach(function(arg){ extend(target, arg, deep) })
+ return target
+ }
+
+ // `$.zepto.qsa` is Zepto's CSS selector implementation which
+ // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.
+ // This method can be overridden in plugins.
+ zepto.qsa = function(element, selector){
+ var found,
+ maybeID = selector[0] == '#',
+ maybeClass = !maybeID && selector[0] == '.',
+ nameOnly = maybeID || maybeClass ? selector.slice(1) : selector, // Ensure that a 1 char tag name still gets checked
+ isSimple = simpleSelectorRE.test(nameOnly)
+ return (element.getElementById && isSimple && maybeID) ? // Safari DocumentFragment doesn't have getElementById
+ ( (found = element.getElementById(nameOnly)) ? [found] : [] ) :
+ (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] :
+ slice.call(
+ isSimple && !maybeID && element.getElementsByClassName ? // DocumentFragment doesn't have getElementsByClassName/TagName
+ maybeClass ? element.getElementsByClassName(nameOnly) : // If it's simple, it could be a class
+ element.getElementsByTagName(selector) : // Or a tag
+ element.querySelectorAll(selector) // Or it's not simple, and we need to query all
+ )
+ }
+
+ function filtered(nodes, selector) {
+ return selector == null ? $(nodes) : $(nodes).filter(selector)
+ }
+
+ $.contains = document.documentElement.contains ?
+ function(parent, node) {
+ return parent !== node && parent.contains(node)
+ } :
+ function(parent, node) {
+ while (node && (node = node.parentNode))
+ if (node === parent) return true
+ return false
+ }
+
+ function funcArg(context, arg, idx, payload) {
+ return isFunction(arg) ? arg.call(context, idx, payload) : arg
+ }
+
+ function setAttribute(node, name, value) {
+ value == null ? node.removeAttribute(name) : node.setAttribute(name, value)
+ }
+
+ // access className property while respecting SVGAnimatedString
+ function className(node, value){
+ var klass = node.className || '',
+ svg = klass && klass.baseVal !== undefined
+
+ if (value === undefined) return svg ? klass.baseVal : klass
+ svg ? (klass.baseVal = value) : (node.className = value)
+ }
+
+ // "true" => true
+ // "false" => false
+ // "null" => null
+ // "42" => 42
+ // "42.5" => 42.5
+ // "08" => "08"
+ // JSON => parse if valid
+ // String => self
+ function deserializeValue(value) {
+ try {
+ return value ?
+ value == "true" ||
+ ( value == "false" ? false :
+ value == "null" ? null :
+ +value + "" == value ? +value :
+ /^[\[\{]/.test(value) ? $.parseJSON(value) :
+ value )
+ : value
+ } catch(e) {
+ return value
+ }
+ }
+
+ $.type = type
+ $.isFunction = isFunction
+ $.isWindow = isWindow
+ $.isArray = isArray
+ $.isPlainObject = isPlainObject
+
+ $.isEmptyObject = function(obj) {
+ var name
+ for (name in obj) return false
+ return true
+ }
+
+ $.isNumeric = function(val) {
+ var num = Number(val), type = typeof val
+ return val != null && type != 'boolean' &&
+ (type != 'string' || val.length) &&
+ !isNaN(num) && isFinite(num) || false
+ }
+
+ $.inArray = function(elem, array, i){
+ return emptyArray.indexOf.call(array, elem, i)
+ }
+
+ $.camelCase = camelize
+ $.trim = function(str) {
+ return str == null ? "" : String.prototype.trim.call(str)
+ }
+
+ // plugin compatibility
+ $.uuid = 0
+ $.support = { }
+ $.expr = { }
+ $.noop = function() {}
+
+ $.map = function(elements, callback){
+ var value, values = [], i, key
+ if (likeArray(elements))
+ for (i = 0; i < elements.length; i++) {
+ value = callback(elements[i], i)
+ if (value != null) values.push(value)
+ }
+ else
+ for (key in elements) {
+ value = callback(elements[key], key)
+ if (value != null) values.push(value)
+ }
+ return flatten(values)
+ }
+
+ $.each = function(elements, callback){
+ var i, key
+ if (likeArray(elements)) {
+ for (i = 0; i < elements.length; i++)
+ if (callback.call(elements[i], i, elements[i]) === false) return elements
+ } else {
+ for (key in elements)
+ if (callback.call(elements[key], key, elements[key]) === false) return elements
+ }
+
+ return elements
+ }
+
+ $.grep = function(elements, callback){
+ return filter.call(elements, callback)
+ }
+
+ if (window.JSON) $.parseJSON = JSON.parse
+
+ // Populate the class2type map
+ $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase()
+ })
+
+ // Define methods that will be available on all
+ // Zepto collections
+ $.fn = {
+ constructor: zepto.Z,
+ length: 0,
+
+ // Because a collection acts like an array
+ // copy over these useful array functions.
+ forEach: emptyArray.forEach,
+ reduce: emptyArray.reduce,
+ push: emptyArray.push,
+ sort: emptyArray.sort,
+ splice: emptyArray.splice,
+ indexOf: emptyArray.indexOf,
+ concat: function(){
+ var i, value, args = []
+ for (i = 0; i < arguments.length; i++) {
+ value = arguments[i]
+ args[i] = zepto.isZ(value) ? value.toArray() : value
+ }
+ return concat.apply(zepto.isZ(this) ? this.toArray() : this, args)
+ },
+
+ // `map` and `slice` in the jQuery API work differently
+ // from their array counterparts
+ map: function(fn){
+ return $($.map(this, function(el, i){ return fn.call(el, i, el) }))
+ },
+ slice: function(){
+ return $(slice.apply(this, arguments))
+ },
+
+ ready: function(callback){
+ // need to check if document.body exists for IE as that browser reports
+ // document ready when it hasn't yet created the body element
+ if (readyRE.test(document.readyState) && document.body) callback($)
+ else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false)
+ return this
+ },
+ get: function(idx){
+ return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
+ },
+ toArray: function(){ return this.get() },
+ size: function(){
+ return this.length
+ },
+ remove: function(){
+ return this.each(function(){
+ if (this.parentNode != null)
+ this.parentNode.removeChild(this)
+ })
+ },
+ each: function(callback){
+ emptyArray.every.call(this, function(el, idx){
+ return callback.call(el, idx, el) !== false
+ })
+ return this
+ },
+ filter: function(selector){
+ if (isFunction(selector)) return this.not(this.not(selector))
+ return $(filter.call(this, function(element){
+ return zepto.matches(element, selector)
+ }))
+ },
+ add: function(selector,context){
+ return $(uniq(this.concat($(selector,context))))
+ },
+ is: function(selector){
+ return this.length > 0 && zepto.matches(this[0], selector)
+ },
+ not: function(selector){
+ var nodes=[]
+ if (isFunction(selector) && selector.call !== undefined)
+ this.each(function(idx){
+ if (!selector.call(this,idx)) nodes.push(this)
+ })
+ else {
+ var excludes = typeof selector == 'string' ? this.filter(selector) :
+ (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
+ this.forEach(function(el){
+ if (excludes.indexOf(el) < 0) nodes.push(el)
+ })
+ }
+ return $(nodes)
+ },
+ has: function(selector){
+ return this.filter(function(){
+ return isObject(selector) ?
+ $.contains(this, selector) :
+ $(this).find(selector).size()
+ })
+ },
+ eq: function(idx){
+ return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)
+ },
+ first: function(){
+ var el = this[0]
+ return el && !isObject(el) ? el : $(el)
+ },
+ last: function(){
+ var el = this[this.length - 1]
+ return el && !isObject(el) ? el : $(el)
+ },
+ find: function(selector){
+ var result, $this = this
+ if (!selector) result = $()
+ else if (typeof selector == 'object')
+ result = $(selector).filter(function(){
+ var node = this
+ return emptyArray.some.call($this, function(parent){
+ return $.contains(parent, node)
+ })
+ })
+ else if (this.length == 1) result = $(zepto.qsa(this[0], selector))
+ else result = this.map(function(){ return zepto.qsa(this, selector) })
+ return result
+ },
+ closest: function(selector, context){
+ var nodes = [], collection = typeof selector == 'object' && $(selector)
+ this.each(function(_, node){
+ while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector)))
+ node = node !== context && !isDocument(node) && node.parentNode
+ if (node && nodes.indexOf(node) < 0) nodes.push(node)
+ })
+ return $(nodes)
+ },
+ parents: function(selector){
+ var ancestors = [], nodes = this
+ while (nodes.length > 0)
+ nodes = $.map(nodes, function(node){
+ if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {
+ ancestors.push(node)
+ return node
+ }
+ })
+ return filtered(ancestors, selector)
+ },
+ parent: function(selector){
+ return filtered(uniq(this.pluck('parentNode')), selector)
+ },
+ children: function(selector){
+ return filtered(this.map(function(){ return children(this) }), selector)
+ },
+ contents: function() {
+ return this.map(function() { return this.contentDocument || slice.call(this.childNodes) })
+ },
+ siblings: function(selector){
+ return filtered(this.map(function(i, el){
+ return filter.call(children(el.parentNode), function(child){ return child!==el })
+ }), selector)
+ },
+ empty: function(){
+ return this.each(function(){ this.innerHTML = '' })
+ },
+ // `pluck` is borrowed from Prototype.js
+ pluck: function(property){
+ return $.map(this, function(el){ return el[property] })
+ },
+ show: function(){
+ return this.each(function(){
+ this.style.display == "none" && (this.style.display = '')
+ if (getComputedStyle(this, '').getPropertyValue("display") == "none")
+ this.style.display = defaultDisplay(this.nodeName)
+ })
+ },
+ replaceWith: function(newContent){
+ return this.before(newContent).remove()
+ },
+ wrap: function(structure){
+ var func = isFunction(structure)
+ if (this[0] && !func)
+ var dom = $(structure).get(0),
+ clone = dom.parentNode || this.length > 1
+
+ return this.each(function(index){
+ $(this).wrapAll(
+ func ? structure.call(this, index) :
+ clone ? dom.cloneNode(true) : dom
+ )
+ })
+ },
+ wrapAll: function(structure){
+ if (this[0]) {
+ $(this[0]).before(structure = $(structure))
+ var children
+ // drill down to the inmost element
+ while ((children = structure.children()).length) structure = children.first()
+ $(structure).append(this)
+ }
+ return this
+ },
+ wrapInner: function(structure){
+ var func = isFunction(structure)
+ return this.each(function(index){
+ var self = $(this), contents = self.contents(),
+ dom = func ? structure.call(this, index) : structure
+ contents.length ? contents.wrapAll(dom) : self.append(dom)
+ })
+ },
+ unwrap: function(){
+ this.parent().each(function(){
+ $(this).replaceWith($(this).children())
+ })
+ return this
+ },
+ clone: function(){
+ return this.map(function(){ return this.cloneNode(true) })
+ },
+ hide: function(){
+ return this.css("display", "none")
+ },
+ toggle: function(setting){
+ return this.each(function(){
+ var el = $(this)
+ ;(setting === undefined ? el.css("display") == "none" : setting) ? el.show() : el.hide()
+ })
+ },
+ prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') },
+ next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },
+ html: function(html){
+ return 0 in arguments ?
+ this.each(function(idx){
+ var originHtml = this.innerHTML
+ $(this).empty().append( funcArg(this, html, idx, originHtml) )
+ }) :
+ (0 in this ? this[0].innerHTML : null)
+ },
+ text: function(text){
+ return 0 in arguments ?
+ this.each(function(idx){
+ var newText = funcArg(this, text, idx, this.textContent)
+ this.textContent = newText == null ? '' : ''+newText
+ }) :
+ (0 in this ? this.pluck('textContent').join("") : null)
+ },
+ attr: function(name, value){
+ var result
+ return (typeof name == 'string' && !(1 in arguments)) ?
+ (0 in this && this[0].nodeType == 1 && (result = this[0].getAttribute(name)) != null ? result : undefined) :
+ this.each(function(idx){
+ if (this.nodeType !== 1) return
+ if (isObject(name)) for (key in name) setAttribute(this, key, name[key])
+ else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))
+ })
+ },
+ removeAttr: function(name){
+ return this.each(function(){ this.nodeType === 1 && name.split(' ').forEach(function(attribute){
+ setAttribute(this, attribute)
+ }, this)})
+ },
+ prop: function(name, value){
+ name = propMap[name] || name
+ return (1 in arguments) ?
+ this.each(function(idx){
+ this[name] = funcArg(this, value, idx, this[name])
+ }) :
+ (this[0] && this[0][name])
+ },
+ removeProp: function(name){
+ name = propMap[name] || name
+ return this.each(function(){ delete this[name] })
+ },
+ data: function(name, value){
+ var attrName = 'data-' + name.replace(capitalRE, '-$1').toLowerCase()
+
+ var data = (1 in arguments) ?
+ this.attr(attrName, value) :
+ this.attr(attrName)
+
+ return data !== null ? deserializeValue(data) : undefined
+ },
+ val: function(value){
+ if (0 in arguments) {
+ if (value == null) value = ""
+ return this.each(function(idx){
+ this.value = funcArg(this, value, idx, this.value)
+ })
+ } else {
+ return this[0] && (this[0].multiple ?
+ $(this[0]).find('option').filter(function(){ return this.selected }).pluck('value') :
+ this[0].value)
+ }
+ },
+ offset: function(coordinates){
+ if (coordinates) return this.each(function(index){
+ var $this = $(this),
+ coords = funcArg(this, coordinates, index, $this.offset()),
+ parentOffset = $this.offsetParent().offset(),
+ props = {
+ top: coords.top - parentOffset.top,
+ left: coords.left - parentOffset.left
+ }
+
+ if ($this.css('position') == 'static') props['position'] = 'relative'
+ $this.css(props)
+ })
+ if (!this.length) return null
+ if (document.documentElement !== this[0] && !$.contains(document.documentElement, this[0]))
+ return {top: 0, left: 0}
+ var obj = this[0].getBoundingClientRect()
+ return {
+ left: obj.left + window.pageXOffset,
+ top: obj.top + window.pageYOffset,
+ width: Math.round(obj.width),
+ height: Math.round(obj.height)
+ }
+ },
+ css: function(property, value){
+ if (arguments.length < 2) {
+ var element = this[0]
+ if (typeof property == 'string') {
+ if (!element) return
+ return element.style[camelize(property)] || getComputedStyle(element, '').getPropertyValue(property)
+ } else if (isArray(property)) {
+ if (!element) return
+ var props = {}
+ var computedStyle = getComputedStyle(element, '')
+ $.each(property, function(_, prop){
+ props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop))
+ })
+ return props
+ }
+ }
+
+ var css = ''
+ if (type(property) == 'string') {
+ if (!value && value !== 0)
+ this.each(function(){ this.style.removeProperty(dasherize(property)) })
+ else
+ css = dasherize(property) + ":" + maybeAddPx(property, value)
+ } else {
+ for (key in property)
+ if (!property[key] && property[key] !== 0)
+ this.each(function(){ this.style.removeProperty(dasherize(key)) })
+ else
+ css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
+ }
+
+ return this.each(function(){ this.style.cssText += ';' + css })
+ },
+ index: function(element){
+ return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])
+ },
+ hasClass: function(name){
+ if (!name) return false
+ return emptyArray.some.call(this, function(el){
+ return this.test(className(el))
+ }, classRE(name))
+ },
+ addClass: function(name){
+ if (!name) return this
+ return this.each(function(idx){
+ if (!('className' in this)) return
+ classList = []
+ var cls = className(this), newName = funcArg(this, name, idx, cls)
+ newName.split(/\s+/g).forEach(function(klass){
+ if (!$(this).hasClass(klass)) classList.push(klass)
+ }, this)
+ classList.length && className(this, cls + (cls ? " " : "") + classList.join(" "))
+ })
+ },
+ removeClass: function(name){
+ return this.each(function(idx){
+ if (!('className' in this)) return
+ if (name === undefined) return className(this, '')
+ classList = className(this)
+ funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){
+ classList = classList.replace(classRE(klass), " ")
+ })
+ className(this, classList.trim())
+ })
+ },
+ toggleClass: function(name, when){
+ if (!name) return this
+ return this.each(function(idx){
+ var $this = $(this), names = funcArg(this, name, idx, className(this))
+ names.split(/\s+/g).forEach(function(klass){
+ (when === undefined ? !$this.hasClass(klass) : when) ?
+ $this.addClass(klass) : $this.removeClass(klass)
+ })
+ })
+ },
+ scrollTop: function(value){
+ if (!this.length) return
+ var hasScrollTop = 'scrollTop' in this[0]
+ if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset
+ return this.each(hasScrollTop ?
+ function(){ this.scrollTop = value } :
+ function(){ this.scrollTo(this.scrollX, value) })
+ },
+ scrollLeft: function(value){
+ if (!this.length) return
+ var hasScrollLeft = 'scrollLeft' in this[0]
+ if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset
+ return this.each(hasScrollLeft ?
+ function(){ this.scrollLeft = value } :
+ function(){ this.scrollTo(value, this.scrollY) })
+ },
+ position: function() {
+ if (!this.length) return
+
+ var elem = this[0],
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset()
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( $(elem).css('margin-top') ) || 0
+ offset.left -= parseFloat( $(elem).css('margin-left') ) || 0
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0
+ parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ }
+ },
+ offsetParent: function() {
+ return this.map(function(){
+ var parent = this.offsetParent || document.body
+ while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static")
+ parent = parent.offsetParent
+ return parent
+ })
+ }
+ }
+
+ // for now
+ $.fn.detach = $.fn.remove
+
+ // Generate the `width` and `height` functions
+ ;['width', 'height'].forEach(function(dimension){
+ var dimensionProperty =
+ dimension.replace(/./, function(m){ return m[0].toUpperCase() })
+
+ $.fn[dimension] = function(value){
+ var offset, el = this[0]
+ if (value === undefined) return isWindow(el) ? el['inner' + dimensionProperty] :
+ isDocument(el) ? el.documentElement['scroll' + dimensionProperty] :
+ (offset = this.offset()) && offset[dimension]
+ else return this.each(function(idx){
+ el = $(this)
+ el.css(dimension, funcArg(this, value, idx, el[dimension]()))
+ })
+ }
+ })
+
+ function traverseNode(node, fun) {
+ fun(node)
+ for (var i = 0, len = node.childNodes.length; i < len; i++)
+ traverseNode(node.childNodes[i], fun)
+ }
+
+ // Generate the `after`, `prepend`, `before`, `append`,
+ // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.
+ adjacencyOperators.forEach(function(operator, operatorIndex) {
+ var inside = operatorIndex % 2 //=> prepend, append
+
+ $.fn[operator] = function(){
+ // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
+ var argType, nodes = $.map(arguments, function(arg) {
+ var arr = []
+ argType = type(arg)
+ if (argType == "array") {
+ arg.forEach(function(el) {
+ if (el.nodeType !== undefined) return arr.push(el)
+ else if ($.zepto.isZ(el)) return arr = arr.concat(el.get())
+ arr = arr.concat(zepto.fragment(el))
+ })
+ return arr
+ }
+ return argType == "object" || arg == null ?
+ arg : zepto.fragment(arg)
+ }),
+ parent, copyByClone = this.length > 1
+ if (nodes.length < 1) return this
+
+ return this.each(function(_, target){
+ parent = inside ? target : target.parentNode
+
+ // convert all methods to a "before" operation
+ target = operatorIndex == 0 ? target.nextSibling :
+ operatorIndex == 1 ? target.firstChild :
+ operatorIndex == 2 ? target :
+ null
+
+ var parentInDocument = $.contains(document.documentElement, parent)
+
+ nodes.forEach(function(node){
+ if (copyByClone) node = node.cloneNode(true)
+ else if (!parent) return $(node).remove()
+
+ parent.insertBefore(node, target)
+ if (parentInDocument) traverseNode(node, function(el){
+ if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&
+ (!el.type || el.type === 'text/javascript') && !el.src){
+ var target = el.ownerDocument ? el.ownerDocument.defaultView : window
+ target['eval'].call(target, el.innerHTML)
+ }
+ })
+ })
+ })
+ }
+
+ // after => insertAfter
+ // prepend => prependTo
+ // before => insertBefore
+ // append => appendTo
+ $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){
+ $(html)[operator](this)
+ return this
+ }
+ })
+
+ zepto.Z.prototype = Z.prototype = $.fn
+
+ // Export internal API functions in the `$.zepto` namespace
+ zepto.uniq = uniq
+ zepto.deserializeValue = deserializeValue
+ $.zepto = zepto
+
+ return $
+})()
+
+window.Zepto = Zepto
+window.$ === undefined && (window.$ = Zepto)
+
+;(function($){
+ var jsonpID = +new Date(),
+ document = window.document,
+ key,
+ name,
+ rscript = /
+ *
+ * ```
+ * Now, create the player:
+ * ```html
+ *
+ *
+ *
+ *
+ * ```
+ */
+// Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var Player = function (_BaseObject) {
+ (0, _inherits3.default)(Player, _BaseObject);
+ (0, _createClass3.default)(Player, [{
+ key: 'loader',
+ set: function set(loader) {
+ this._loader = loader;
+ },
+ get: function get() {
+ if (!this._loader) this._loader = new _loader2.default(this.options.plugins || {}, this.options.playerId);
+
+ return this._loader;
+ }
+
+ /**
+ * Determine if the playback has ended.
+ * @property ended
+ * @type Boolean
+ */
+
+ }, {
+ key: 'ended',
+ get: function get() {
+ return this.core.activeContainer.ended;
+ }
+
+ /**
+ * Determine if the playback is having to buffer in order for
+ * playback to be smooth.
+ * (i.e if a live stream is playing smoothly, this will be false)
+ * @property buffering
+ * @type Boolean
+ */
+
+ }, {
+ key: 'buffering',
+ get: function get() {
+ return this.core.activeContainer.buffering;
+ }
+
+ /*
+ * determine if the player is ready.
+ * @property isReady
+ * @type {Boolean} `true` if the player is ready. ie PLAYER_READY event has fired
+ */
+
+ }, {
+ key: 'isReady',
+ get: function get() {
+ return !!this._ready;
+ }
+
+ /**
+ * An events map that allows the user to add custom callbacks in player's options.
+ * @property eventsMapping
+ * @type {Object}
+ */
+
+ }, {
+ key: 'eventsMapping',
+ get: function get() {
+ return {
+ onReady: _events2.default.PLAYER_READY,
+ onResize: _events2.default.PLAYER_RESIZE,
+ onPlay: _events2.default.PLAYER_PLAY,
+ onPause: _events2.default.PLAYER_PAUSE,
+ onStop: _events2.default.PLAYER_STOP,
+ onEnded: _events2.default.PLAYER_ENDED,
+ onSeek: _events2.default.PLAYER_SEEK,
+ onError: _events2.default.PLAYER_ERROR,
+ onTimeUpdate: _events2.default.PLAYER_TIMEUPDATE,
+ onVolumeUpdate: _events2.default.PLAYER_VOLUMEUPDATE,
+ onSubtitleAvailable: _events2.default.PLAYER_SUBTITLE_AVAILABLE
+ };
+ }
+
+ /**
+ * @typedef {Object} PlaybackConfig
+ * @prop {boolean} disableContextMenu
+ * disables the context menu (right click) on the video element if a HTML5Video playback is used.
+ * @prop {boolean} preload
+ * video will be preloaded according to `preload` attribute options **default**: `'metadata'`
+ * @prop {boolean} controls
+ * enabled/disables displaying controls
+ * @prop {boolean} crossOrigin
+ * enables cross-origin capability for media-resources
+ * @prop {boolean} playInline
+ * enables in-line video elements
+ * @prop {boolean} audioOnly
+ * enforce audio-only playback (when possible)
+ * @prop {Object} externalTracks
+ * pass externaly loaded track to playback
+ * @prop {Number} [maxBufferLength]
+ * The default behavior for the **HLS playback** is to keep buffering indefinitely, even on VoD.
+ * This replicates the behavior for progressive download, which continues buffering when pausing the video, thus making the video available for playback even on slow networks.
+ * To change this behavior use `maxBufferLength` where **value is in seconds**.
+ * @prop {Number} [maxBackBufferLength]
+ * After how much distance of the playhead data should be pruned from the buffer (influences memory consumption
+ * of adaptive media-engines like Hls.js or Shaka)
+ * @prop {Number} [minBufferLength]
+ * After how much data in the buffer at least we attempt to consume it (influences QoS-related behavior
+ * of adaptive media-engines like Hls.js or Shaka). If this is too low, and the available bandwidth is varying a lot
+ * and too close to the streamed bitrate, we may continuously hit under-runs.
+ * @prop {Number} [initialBandwidthEstimate]
+ * define an initial bandwidth "guess" (or previously stored/established value) for underlying adaptive-bitreate engines
+ * of adaptive playback implementations, like Hls.js or Shaka
+ * @prop {Number} [maxAdaptiveBitrate]
+ * Limits the streamed bitrate (for adaptive media-engines in underlying playback implementations)
+ * @prop {Object} [maxAdaptiveVideoDimensions]
+ * Limits the video dimensions in adaptive media-engines. Should be a literal object with `height` and `width`.
+ * @prop {Boolean}[enableAutomaticABR] **default**: `true`
+ * Allows to enable/disable automatic bitrate switching in adaptive media-engines
+ * @prop {String} [preferredTextLanguage] **default**: `'pt-BR'`
+ * Allows to set a preferred text language, that may be enabled by the media-engine if available.
+ * @prop {String} [preferredAudioLanguage] **default**: `'pt-BR'`
+ * Allows to set a preferred audio language, that may be enabled by the media-engine if available.
+ */
+
+ /**
+ * ## Player's constructor
+ *
+ * You might pass the options object to build the player.
+ * ```javascript
+ * var options = {source: "http://example.com/video.mp4", param1: "val1"};
+ * var player = new Clappr.Player(options);
+ * ```
+ *
+ * @method constructor
+ * @param {Object} options Data
+ * options to build a player instance
+ * @param {Number} [options.width]
+ * player's width **default**: `640`
+ * @param {Number} [options.height]
+ * player's height **default**: `360`
+ * @param {String} [options.parentId]
+ * the id of the element on the page that the player should be inserted into
+ * @param {Object} [options.parent]
+ * a reference to a dom element that the player should be inserted into
+ * @param {String} [options.source]
+ * The media source URL, or {source: <>, mimeType: <>}
+ * @param {Object} [options.sources]
+ * An array of media source URL's, or an array of {source: <>, mimeType: <>}
+ * @param {Boolean} [options.autoPlay]
+ * automatically play after page load **default**: `false`
+ * @param {Boolean} [options.loop]
+ * automatically replay after it ends **default**: `false`
+ * @param {Boolean} [options.chromeless]
+ * player acts in chromeless mode **default**: `false`
+ * @param {Boolean} [options.allowUserInteraction]
+ * whether or not the player should handle click events when in chromeless mode **default**: `false` on desktops browsers, `true` on mobile.
+ * @param {Boolean} [options.disableKeyboardShortcuts]
+ * disable keyboard shortcuts. **default**: `false`. `true` if `allowUserInteraction` is `false`.
+ * @param {Boolean} [options.mute]
+ * start the video muted **default**: `false`
+ * @param {String} [options.mimeType]
+ * add `mimeType: "application/vnd.apple.mpegurl"` if you need to use a url without extension.
+ * @param {Boolean} [options.actualLiveTime]
+ * show duration and seek time relative to actual time.
+ * @param {String} [options.actualLiveServerTime]
+ * specify server time as a string, format: "2015/11/26 06:01:03". This option is meant to be used with actualLiveTime.
+ * @param {Boolean} [options.persistConfig]
+ * persist player's settings (volume) through the same domain **default**: `true`
+ * @param {String} [options.preload] @deprecated
+ * video will be preloaded according to `preload` attribute options **default**: `'metadata'`
+ * @param {Number} [options.maxBufferLength] @deprecated
+ * the default behavior for the **HLS playback** is to keep buffering indefinitely, even on VoD.
+ * This replicates the behavior for progressive download, which continues buffering when pausing the video, thus making the video available for playback even on slow networks.
+ * To change this behavior use `maxBufferLength` where **value is in seconds**.
+ * @param {String} [options.gaAccount]
+ * enable Google Analytics events dispatch **(play/pause/stop/buffering/etc)** by adding your `gaAccount`
+ * @param {String} [options.gaTrackerName]
+ * besides `gaAccount` you can optionally, pass your favorite trackerName as `gaTrackerName`
+ * @param {Object} [options.mediacontrol]
+ * customize control bar colors, example: `mediacontrol: {seekbar: "#E113D3", buttons: "#66B2FF"}`
+ * @param {Boolean} [options.hideMediaControl]
+ * control media control auto hide **default**: `true`
+ * @param {Boolean} [options.hideVolumeBar]
+ * when embedded with width less than 320, volume bar will hide. You can force this behavior for all sizes by adding `true` **default**: `false`
+ * @param {String} [options.watermark]
+ * put `watermark: 'http://url/img.png'` on your embed parameters to automatically add watermark on your video.
+ * You can customize corner position by defining position parameter. Positions can be `bottom-left`, `bottom-right`, `top-left` and `top-right`.
+ * @param {String} [options.watermarkLink]
+ * `watermarkLink: 'http://example.net/'` - define URL to open when the watermark is clicked. If not provided watermark will not be clickable.
+ * @param {Boolean} [options.disableVideoTagContextMenu] @deprecated
+ * disables the context menu (right click) on the video element if a HTML5Video playback is used.
+ * @param {Boolean} [options.autoSeekFromUrl]
+ * Automatically seek to the seconds provided in the url (e.g example.com?t=100) **default**: `true`
+ * @param {Boolean} [options.exitFullscreenOnEnd]
+ * Automatically exit full screen when the media finishes. **default**: `true`
+ * @param {String} [options.poster]
+ * define a poster by adding its address `poster: 'http://url/img.png'`. It will appear after video embed, disappear on play and go back when user stops the video.
+ * @param {String} [options.playbackNotSupportedMessage]
+ * define a custom message to be displayed when a playback is not supported.
+ * @param {Object} [options.events]
+ * Specify listeners which will be registered with their corresponding player events.
+ * E.g. onReady -> "PLAYER_READY", onTimeUpdate -> "PLAYER_TIMEUPDATE"
+ * @param {PlaybackConfig} [options.playback]
+ * Generic `Playback` component related configuration
+ * @param {Boolean} [options.disableErrorScreen]
+ * disables the error screen plugin.
+ * @param {Number} [options.autoPlayTimeout]
+ * autoplay check timeout.
+ */
+
+ }]);
+
+ function Player(options) {
+ (0, _classCallCheck3.default)(this, Player);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _BaseObject.call(this, options));
+
+ var playbackDefaultOptions = { recycleVideo: true };
+ var defaultOptions = {
+ playerId: (0, _utils.uniqueId)(''),
+ persistConfig: true,
+ width: 640,
+ height: 360,
+ baseUrl: baseUrl,
+ allowUserInteraction: _browser2.default.isMobile,
+ playback: playbackDefaultOptions
+ };
+ _this._options = _clapprZepto2.default.extend(defaultOptions, options);
+ _this.options.sources = _this._normalizeSources(options);
+ if (!_this.options.chromeless) {
+ // "allowUserInteraction" cannot be false if not in chromeless mode.
+ _this.options.allowUserInteraction = true;
+ }
+ if (!_this.options.allowUserInteraction) {
+ // if user iteraction is not allowed ensure keyboard shortcuts are disabled
+ _this.options.disableKeyboardShortcuts = true;
+ }
+ _this._registerOptionEventListeners(_this.options.events);
+ _this._coreFactory = new _core_factory2.default(_this);
+ _this.playerInfo = _player_info2.default.getInstance(_this.options.playerId);
+ _this.playerInfo.currentSize = { width: options.width, height: options.height };
+ _this.playerInfo.options = _this.options;
+ if (_this.options.parentId) _this.setParentId(_this.options.parentId);else if (_this.options.parent) _this.attachTo(_this.options.parent);
+
+ return _this;
+ }
+
+ /**
+ * Specify a `parentId` to the player.
+ * @method setParentId
+ * @param {String} parentId the element parent id.
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.setParentId = function setParentId(parentId) {
+ var el = document.querySelector(parentId);
+ if (el) this.attachTo(el);
+
+ return this;
+ };
+
+ /**
+ * You can use this method to attach the player to a given element. You don't need to do this when you specify it during the player instantiation passing the `parentId` param.
+ * @method attachTo
+ * @param {Object} element a given element.
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.attachTo = function attachTo(element) {
+ this.options.parentElement = element;
+ this.core = this._coreFactory.create();
+ this._addEventListeners();
+ return this;
+ };
+
+ Player.prototype._addEventListeners = function _addEventListeners() {
+ if (!this.core.isReady) this.listenToOnce(this.core, _events2.default.CORE_READY, this._onReady);else this._onReady();
+
+ this.listenTo(this.core, _events2.default.CORE_ACTIVE_CONTAINER_CHANGED, this._containerChanged);
+ this.listenTo(this.core, _events2.default.CORE_FULLSCREEN, this._onFullscreenChange);
+ this.listenTo(this.core, _events2.default.CORE_RESIZE, this._onResize);
+ return this;
+ };
+
+ Player.prototype._addContainerEventListeners = function _addContainerEventListeners() {
+ var container = this.core.activeContainer;
+ if (container) {
+ this.listenTo(container, _events2.default.CONTAINER_PLAY, this._onPlay);
+ this.listenTo(container, _events2.default.CONTAINER_PAUSE, this._onPause);
+ this.listenTo(container, _events2.default.CONTAINER_STOP, this._onStop);
+ this.listenTo(container, _events2.default.CONTAINER_ENDED, this._onEnded);
+ this.listenTo(container, _events2.default.CONTAINER_SEEK, this._onSeek);
+ this.listenTo(container, _events2.default.CONTAINER_ERROR, this._onError);
+ this.listenTo(container, _events2.default.CONTAINER_TIMEUPDATE, this._onTimeUpdate);
+ this.listenTo(container, _events2.default.CONTAINER_VOLUME, this._onVolumeUpdate);
+ this.listenTo(container, _events2.default.CONTAINER_SUBTITLE_AVAILABLE, this._onSubtitleAvailable);
+ }
+ return this;
+ };
+
+ Player.prototype._registerOptionEventListeners = function _registerOptionEventListeners() {
+ var _this2 = this;
+
+ var newEvents = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+ var hasNewEvents = (0, _keys2.default)(newEvents).length > 0;
+ hasNewEvents && (0, _keys2.default)(events).forEach(function (userEvent) {
+ var eventType = _this2.eventsMapping[userEvent];
+ eventType && _this2.off(eventType, events[userEvent]);
+ });
+
+ (0, _keys2.default)(newEvents).forEach(function (userEvent) {
+ var eventType = _this2.eventsMapping[userEvent];
+ if (eventType) {
+ var eventFunction = newEvents[userEvent];
+ eventFunction = typeof eventFunction === 'function' && eventFunction;
+ eventFunction && _this2.on(eventType, eventFunction);
+ }
+ });
+ return this;
+ };
+
+ Player.prototype._containerChanged = function _containerChanged() {
+ this.stopListening();
+ this._addEventListeners();
+ };
+
+ Player.prototype._onReady = function _onReady() {
+ this._ready = true;
+ this._addContainerEventListeners();
+ this.trigger(_events2.default.PLAYER_READY);
+ };
+
+ Player.prototype._onFullscreenChange = function _onFullscreenChange(fullscreen) {
+ this.trigger(_events2.default.PLAYER_FULLSCREEN, fullscreen);
+ };
+
+ Player.prototype._onVolumeUpdate = function _onVolumeUpdate(volume) {
+ this.trigger(_events2.default.PLAYER_VOLUMEUPDATE, volume);
+ };
+
+ Player.prototype._onSubtitleAvailable = function _onSubtitleAvailable() {
+ this.trigger(_events2.default.PLAYER_SUBTITLE_AVAILABLE);
+ };
+
+ Player.prototype._onResize = function _onResize(size) {
+ this.trigger(_events2.default.PLAYER_RESIZE, size);
+ };
+
+ Player.prototype._onPlay = function _onPlay() {
+ this.trigger(_events2.default.PLAYER_PLAY);
+ };
+
+ Player.prototype._onPause = function _onPause() {
+ this.trigger(_events2.default.PLAYER_PAUSE);
+ };
+
+ Player.prototype._onStop = function _onStop() {
+ this.trigger(_events2.default.PLAYER_STOP, this.getCurrentTime());
+ };
+
+ Player.prototype._onEnded = function _onEnded() {
+ this.trigger(_events2.default.PLAYER_ENDED);
+ };
+
+ Player.prototype._onSeek = function _onSeek(time) {
+ this.trigger(_events2.default.PLAYER_SEEK, time);
+ };
+
+ Player.prototype._onTimeUpdate = function _onTimeUpdate(timeProgress) {
+ this.trigger(_events2.default.PLAYER_TIMEUPDATE, timeProgress);
+ };
+
+ Player.prototype._onError = function _onError(error) {
+ this.trigger(_events2.default.PLAYER_ERROR, error);
+ };
+
+ Player.prototype._normalizeSources = function _normalizeSources(options) {
+ var sources = options.sources || (options.source !== undefined ? [options.source] : []);
+ return sources.length === 0 ? [{ source: '', mimeType: '' }] : sources;
+ };
+
+ /**
+ * resizes the current player canvas.
+ * @method resize
+ * @param {Object} size should be a literal object with `height` and `width`.
+ * @return {Player} itself
+ * @example
+ * ```javascript
+ * player.resize({height: 360, width: 640})
+ * ```
+ */
+
+
+ Player.prototype.resize = function resize(size) {
+ this.core.resize(size);
+ return this;
+ };
+
+ /**
+ * loads a new source.
+ * @method load
+ * @param {Array|String} sources source or sources of video.
+ * An array item can be a string or {source: <>, mimeType: <>}
+ * @param {String} mimeType a mime type, example: `'application/vnd.apple.mpegurl'`
+ * @param {Boolean} [autoPlay=false] whether playing should be started immediately
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.load = function load(sources, mimeType, autoPlay) {
+ if (autoPlay !== undefined) this.configure({ autoPlay: !!autoPlay });
+
+ this.core.load(sources, mimeType);
+ return this;
+ };
+
+ /**
+ * destroys the current player and removes it from the DOM.
+ * @method destroy
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.destroy = function destroy() {
+ this.stopListening();
+ this.core.destroy();
+ return this;
+ };
+
+ /**
+ * Gives user consent to playback. Required by mobile device after a click event before Player.load().
+ * @method consent
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.consent = function consent() {
+ this.core.getCurrentPlayback().consent();
+ return this;
+ };
+
+ /**
+ * plays the current video (`source`).
+ * @method play
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.play = function play() {
+ this.core.activeContainer.play();
+ return this;
+ };
+
+ /**
+ * pauses the current video (`source`).
+ * @method pause
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.pause = function pause() {
+ this.core.activeContainer.pause();
+ return this;
+ };
+
+ /**
+ * stops the current video (`source`).
+ * @method stop
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.stop = function stop() {
+ this.core.activeContainer.stop();
+ return this;
+ };
+
+ /**
+ * seeks the current video (`source`). For example, `player.seek(120)` will seek to second 120 (2minutes) of the current video.
+ * @method seek
+ * @param {Number} time should be a number between 0 and the video duration.
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.seek = function seek(time) {
+ this.core.activeContainer.seek(time);
+ return this;
+ };
+
+ /**
+ * seeks the current video (`source`). For example, `player.seek(50)` will seek to the middle of the current video.
+ * @method seekPercentage
+ * @param {Number} time should be a number between 0 and 100.
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.seekPercentage = function seekPercentage(percentage) {
+ this.core.activeContainer.seekPercentage(percentage);
+ return this;
+ };
+
+ /**
+ * mutes the current video (`source`).
+ * @method mute
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.mute = function mute() {
+ this._mutedVolume = this.getVolume();
+ this.setVolume(0);
+ return this;
+ };
+
+ /**
+ * unmutes the current video (`source`).
+ * @method unmute
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.unmute = function unmute() {
+ this.setVolume(typeof this._mutedVolume === 'number' ? this._mutedVolume : 100);
+ this._mutedVolume = null;
+ return this;
+ };
+
+ /**
+ * checks if the player is playing.
+ * @method isPlaying
+ * @return {Boolean} `true` if the current source is playing, otherwise `false`
+ */
+
+
+ Player.prototype.isPlaying = function isPlaying() {
+ return this.core.activeContainer.isPlaying();
+ };
+
+ /**
+ * returns `true` if DVR is enable otherwise `false`.
+ * @method isDvrEnabled
+ * @return {Boolean}
+ */
+
+
+ Player.prototype.isDvrEnabled = function isDvrEnabled() {
+ return this.core.activeContainer.isDvrEnabled();
+ };
+
+ /**
+ * returns `true` if DVR is in use otherwise `false`.
+ * @method isDvrInUse
+ * @return {Boolean}
+ */
+
+
+ Player.prototype.isDvrInUse = function isDvrInUse() {
+ return this.core.activeContainer.isDvrInUse();
+ };
+
+ /**
+ * enables to configure a player after its creation
+ * @method configure
+ * @param {Object} options all the options to change in form of a javascript object
+ * @return {Player} itself
+ */
+
+
+ Player.prototype.configure = function configure() {
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ this._registerOptionEventListeners(options.events, this.options.events);
+ this.core.configure(options);
+ return this;
+ };
+
+ /**
+ * get a plugin by its name.
+ * @method getPlugin
+ * @param {String} name of the plugin.
+ * @return {Object} the plugin instance
+ * @example
+ * ```javascript
+ * var poster = player.getPlugin('poster');
+ * poster.hidePlayButton();
+ * ```
+ */
+
+
+ Player.prototype.getPlugin = function getPlugin(name) {
+ var plugins = this.core.plugins.concat(this.core.activeContainer.plugins);
+ return plugins.filter(function (plugin) {
+ return plugin.name === name;
+ })[0];
+ };
+
+ /**
+ * the current time in seconds.
+ * @method getCurrentTime
+ * @return {Number} current time (in seconds) of the current source
+ */
+
+
+ Player.prototype.getCurrentTime = function getCurrentTime() {
+ return this.core.activeContainer.getCurrentTime();
+ };
+
+ /**
+ * The time that "0" now represents relative to when playback started.
+ * For a stream with a sliding window this will increase as content is
+ * removed from the beginning.
+ * @method getStartTimeOffset
+ * @return {Number} time (in seconds) that time "0" represents.
+ */
+
+
+ Player.prototype.getStartTimeOffset = function getStartTimeOffset() {
+ return this.core.activeContainer.getStartTimeOffset();
+ };
+
+ /**
+ * the duration time in seconds.
+ * @method getDuration
+ * @return {Number} duration time (in seconds) of the current source
+ */
+
+
+ Player.prototype.getDuration = function getDuration() {
+ return this.core.activeContainer.getDuration();
+ };
+
+ return Player;
+}(_base_object2.default);
+
+exports.default = Player;
+
+
+(0, _assign2.default)(Player.prototype, _error_mixin2.default);
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/components/player_info.js":
+/*!***************************************!*\
+ !*** ./src/components/player_info.js ***!
+ \***************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var PlayerInfo = function PlayerInfo() {
+ (0, _classCallCheck3.default)(this, PlayerInfo);
+
+ this.options = {};
+ this.playbackPlugins = [];
+ this.currentSize = { width: 0, height: 0 };
+};
+
+PlayerInfo._players = {};
+
+PlayerInfo.getInstance = function (playerId) {
+ return PlayerInfo._players[playerId] || (PlayerInfo._players[playerId] = new PlayerInfo());
+};
+
+exports.default = PlayerInfo;
+module.exports = exports["default"];
+
+/***/ }),
+
+/***/ "./src/icons/01-play.svg":
+/*!*******************************!*\
+ !*** ./src/icons/01-play.svg ***!
+ \*******************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/02-pause.svg":
+/*!********************************!*\
+ !*** ./src/icons/02-pause.svg ***!
+ \********************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/03-stop.svg":
+/*!*******************************!*\
+ !*** ./src/icons/03-stop.svg ***!
+ \*******************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/04-volume.svg":
+/*!*********************************!*\
+ !*** ./src/icons/04-volume.svg ***!
+ \*********************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/05-mute.svg":
+/*!*******************************!*\
+ !*** ./src/icons/05-mute.svg ***!
+ \*******************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/06-expand.svg":
+/*!*********************************!*\
+ !*** ./src/icons/06-expand.svg ***!
+ \*********************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/07-shrink.svg":
+/*!*********************************!*\
+ !*** ./src/icons/07-shrink.svg ***!
+ \*********************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/08-hd.svg":
+/*!*****************************!*\
+ !*** ./src/icons/08-hd.svg ***!
+ \*****************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/09-cc.svg":
+/*!*****************************!*\
+ !*** ./src/icons/09-cc.svg ***!
+ \*****************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/icons/10-reload.svg":
+/*!*********************************!*\
+ !*** ./src/icons/10-reload.svg ***!
+ \*********************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " "
+
+/***/ }),
+
+/***/ "./src/main.js":
+/*!*********************!*\
+ !*** ./src/main.js ***!
+ \*********************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _player = __webpack_require__(/*! ./components/player */ "./src/components/player.js");
+
+var _player2 = _interopRequireDefault(_player);
+
+var _utils = __webpack_require__(/*! ./base/utils */ "./src/base/utils.js");
+
+var _utils2 = _interopRequireDefault(_utils);
+
+var _events = __webpack_require__(/*! ./base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _playback = __webpack_require__(/*! ./base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _container_plugin = __webpack_require__(/*! ./base/container_plugin */ "./src/base/container_plugin.js");
+
+var _container_plugin2 = _interopRequireDefault(_container_plugin);
+
+var _core_plugin = __webpack_require__(/*! ./base/core_plugin */ "./src/base/core_plugin.js");
+
+var _core_plugin2 = _interopRequireDefault(_core_plugin);
+
+var _ui_core_plugin = __webpack_require__(/*! ./base/ui_core_plugin */ "./src/base/ui_core_plugin.js");
+
+var _ui_core_plugin2 = _interopRequireDefault(_ui_core_plugin);
+
+var _ui_container_plugin = __webpack_require__(/*! ./base/ui_container_plugin */ "./src/base/ui_container_plugin.js");
+
+var _ui_container_plugin2 = _interopRequireDefault(_ui_container_plugin);
+
+var _base_object = __webpack_require__(/*! ./base/base_object */ "./src/base/base_object.js");
+
+var _base_object2 = _interopRequireDefault(_base_object);
+
+var _ui_object = __webpack_require__(/*! ./base/ui_object */ "./src/base/ui_object.js");
+
+var _ui_object2 = _interopRequireDefault(_ui_object);
+
+var _browser = __webpack_require__(/*! ./components/browser */ "./src/components/browser/index.js");
+
+var _browser2 = _interopRequireDefault(_browser);
+
+var _container = __webpack_require__(/*! ./components/container */ "./src/components/container/index.js");
+
+var _container2 = _interopRequireDefault(_container);
+
+var _core = __webpack_require__(/*! ./components/core */ "./src/components/core/index.js");
+
+var _core2 = _interopRequireDefault(_core);
+
+var _error = __webpack_require__(/*! ./components/error */ "./src/components/error/index.js");
+
+var _error2 = _interopRequireDefault(_error);
+
+var _loader = __webpack_require__(/*! ./components/loader */ "./src/components/loader/index.js");
+
+var _loader2 = _interopRequireDefault(_loader);
+
+var _mediator = __webpack_require__(/*! ./components/mediator */ "./src/components/mediator.js");
+
+var _mediator2 = _interopRequireDefault(_mediator);
+
+var _player_info = __webpack_require__(/*! ./components/player_info */ "./src/components/player_info.js");
+
+var _player_info2 = _interopRequireDefault(_player_info);
+
+var _base_flash_playback = __webpack_require__(/*! ./playbacks/base_flash_playback */ "./src/playbacks/base_flash_playback/index.js");
+
+var _base_flash_playback2 = _interopRequireDefault(_base_flash_playback);
+
+var _flash = __webpack_require__(/*! ./playbacks/flash */ "./src/playbacks/flash/index.js");
+
+var _flash2 = _interopRequireDefault(_flash);
+
+var _flashls = __webpack_require__(/*! ./playbacks/flashls */ "./src/playbacks/flashls/index.js");
+
+var _flashls2 = _interopRequireDefault(_flashls);
+
+var _hls = __webpack_require__(/*! ./playbacks/hls */ "./src/playbacks/hls/index.js");
+
+var _hls2 = _interopRequireDefault(_hls);
+
+var _html5_audio = __webpack_require__(/*! ./playbacks/html5_audio */ "./src/playbacks/html5_audio/index.js");
+
+var _html5_audio2 = _interopRequireDefault(_html5_audio);
+
+var _html5_video = __webpack_require__(/*! ./playbacks/html5_video */ "./src/playbacks/html5_video/index.js");
+
+var _html5_video2 = _interopRequireDefault(_html5_video);
+
+var _html_img = __webpack_require__(/*! ./playbacks/html_img */ "./src/playbacks/html_img/index.js");
+
+var _html_img2 = _interopRequireDefault(_html_img);
+
+var _no_op = __webpack_require__(/*! ./playbacks/no_op */ "./src/playbacks/no_op/index.js");
+
+var _no_op2 = _interopRequireDefault(_no_op);
+
+var _media_control = __webpack_require__(/*! ./plugins/media_control */ "./src/plugins/media_control/index.js");
+
+var _media_control2 = _interopRequireDefault(_media_control);
+
+var _click_to_pause = __webpack_require__(/*! ./plugins/click_to_pause */ "./src/plugins/click_to_pause/index.js");
+
+var _click_to_pause2 = _interopRequireDefault(_click_to_pause);
+
+var _dvr_controls = __webpack_require__(/*! ./plugins/dvr_controls */ "./src/plugins/dvr_controls/index.js");
+
+var _dvr_controls2 = _interopRequireDefault(_dvr_controls);
+
+var _favicon = __webpack_require__(/*! ./plugins/favicon */ "./src/plugins/favicon/index.js");
+
+var _favicon2 = _interopRequireDefault(_favicon);
+
+var _log = __webpack_require__(/*! ./plugins/log */ "./src/plugins/log/index.js");
+
+var _log2 = _interopRequireDefault(_log);
+
+var _poster = __webpack_require__(/*! ./plugins/poster */ "./src/plugins/poster/index.js");
+
+var _poster2 = _interopRequireDefault(_poster);
+
+var _spinner_three_bounce = __webpack_require__(/*! ./plugins/spinner_three_bounce */ "./src/plugins/spinner_three_bounce/index.js");
+
+var _spinner_three_bounce2 = _interopRequireDefault(_spinner_three_bounce);
+
+var _watermark = __webpack_require__(/*! ./plugins/watermark */ "./src/plugins/watermark/index.js");
+
+var _watermark2 = _interopRequireDefault(_watermark);
+
+var _styler = __webpack_require__(/*! ./base/styler */ "./src/base/styler.js");
+
+var _styler2 = _interopRequireDefault(_styler);
+
+var _vendor = __webpack_require__(/*! ./vendor */ "./src/vendor/index.js");
+
+var _vendor2 = _interopRequireDefault(_vendor);
+
+var _template = __webpack_require__(/*! ./base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var version = "0.3.7"; // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = {
+ Player: _player2.default,
+ Mediator: _mediator2.default,
+ Events: _events2.default,
+ Browser: _browser2.default,
+ PlayerInfo: _player_info2.default,
+ MediaControl: _media_control2.default,
+ ContainerPlugin: _container_plugin2.default,
+ UIContainerPlugin: _ui_container_plugin2.default,
+ CorePlugin: _core_plugin2.default,
+ UICorePlugin: _ui_core_plugin2.default,
+ Playback: _playback2.default,
+ Container: _container2.default,
+ Core: _core2.default,
+ PlayerError: _error2.default,
+ Loader: _loader2.default,
+ BaseObject: _base_object2.default,
+ UIObject: _ui_object2.default,
+ Utils: _utils2.default,
+ BaseFlashPlayback: _base_flash_playback2.default,
+ Flash: _flash2.default,
+ FlasHLS: _flashls2.default,
+ HLS: _hls2.default,
+ HTML5Audio: _html5_audio2.default,
+ HTML5Video: _html5_video2.default,
+ HTMLImg: _html_img2.default,
+ NoOp: _no_op2.default,
+ ClickToPausePlugin: _click_to_pause2.default,
+ DVRControls: _dvr_controls2.default,
+ Favicon: _favicon2.default,
+ Log: _log2.default,
+ Poster: _poster2.default,
+ SpinnerThreeBouncePlugin: _spinner_three_bounce2.default,
+ WaterMarkPlugin: _watermark2.default,
+ Styler: _styler2.default,
+ Vendor: _vendor2.default,
+ version: version,
+ template: _template2.default,
+ $: _clapprZepto2.default
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/base_flash_playback/base_flash_playback.js":
+/*!******************************************************************!*\
+ !*** ./src/playbacks/base_flash_playback/base_flash_playback.js ***!
+ \******************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _browser = __webpack_require__(/*! ../../components/browser */ "./src/components/browser/index.js");
+
+var _browser2 = _interopRequireDefault(_browser);
+
+var _flash = __webpack_require__(/*! ./public/flash.html */ "./src/playbacks/base_flash_playback/public/flash.html");
+
+var _flash2 = _interopRequireDefault(_flash);
+
+__webpack_require__(/*! ./public/flash.scss */ "./src/playbacks/base_flash_playback/public/flash.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var IE_CLASSID = 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000'; // Copyright 2015 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var BaseFlashPlayback = function (_Playback) {
+ (0, _inherits3.default)(BaseFlashPlayback, _Playback);
+
+ function BaseFlashPlayback() {
+ (0, _classCallCheck3.default)(this, BaseFlashPlayback);
+ return (0, _possibleConstructorReturn3.default)(this, _Playback.apply(this, arguments));
+ }
+
+ BaseFlashPlayback.prototype.setElement = function setElement(element) {
+ this.$el = element;
+ this.el = element[0];
+ };
+
+ BaseFlashPlayback.prototype.render = function render() {
+ this.$el.attr('data', this.swfPath);
+ this.$el.html(this.template({
+ cid: this.cid,
+ swfPath: this.swfPath,
+ baseUrl: this.baseUrl,
+ playbackId: this.uniqueId,
+ wmode: this.wmode,
+ callbackName: 'window.Clappr.flashlsCallbacks.' + this.cid }));
+
+ if (_browser2.default.isIE) {
+ this.$('embed').remove();
+
+ if (_browser2.default.isLegacyIE) this.$el.attr('classid', IE_CLASSID);
+ }
+
+ this.el.id = this.cid;
+
+ return this;
+ };
+
+ (0, _createClass3.default)(BaseFlashPlayback, [{
+ key: 'tagName',
+ get: function get() {
+ return 'object';
+ }
+ }, {
+ key: 'swfPath',
+ get: function get() {
+ return '';
+ }
+ }, {
+ key: 'wmode',
+ get: function get() {
+ return 'transparent';
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_flash2.default);
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ var type = 'application/x-shockwave-flash';
+
+ if (_browser2.default.isLegacyIE) type = '';
+
+ return {
+ class: 'clappr-flash-playback',
+ type: type,
+ width: '100%',
+ height: '100%',
+ data: this.swfPath,
+ 'data-flash-playback': this.name
+ };
+ }
+ }]);
+ return BaseFlashPlayback;
+}(_playback2.default);
+
+exports.default = BaseFlashPlayback;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/base_flash_playback/index.js":
+/*!****************************************************!*\
+ !*** ./src/playbacks/base_flash_playback/index.js ***!
+ \****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = __webpack_require__(/*! ./base_flash_playback */ "./src/playbacks/base_flash_playback/base_flash_playback.js");
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/base_flash_playback/public/flash.html":
+/*!*************************************************************!*\
+ !*** ./src/playbacks/base_flash_playback/public/flash.html ***!
+ \*************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " \">\n \n \n \n \n \n \">\n \n &callback=<%= callbackName %>\">\n\"\n type=\"application/x-shockwave-flash\"\n disabled=\"disabled\"\n tabindex=\"-1\"\n enablecontextmenu=\"false\"\n allowScriptAccess=\"always\"\n quality=\"autohigh\"\n pluginspage=\"http://www.macromedia.com/go/getflashplayer\"\n wmode=\"<%= wmode %>\"\n swliveconnect=\"true\"\n allowfullscreen=\"false\"\n bgcolor=\"#000000\"\n FlashVars=\"playbackId=<%= playbackId %>&callback=<%= callbackName %>\"\n data=\"<%= swfPath %>\"\n src=\"<%= swfPath %>\"\n width=\"100%\"\n height=\"100%\">\n \n";
+
+/***/ }),
+
+/***/ "./src/playbacks/base_flash_playback/public/flash.scss":
+/*!*************************************************************!*\
+ !*** ./src/playbacks/base_flash_playback/public/flash.scss ***!
+ \*************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./flash.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/playbacks/base_flash_playback/public/flash.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/playbacks/flash/flash.js":
+/*!**************************************!*\
+ !*** ./src/playbacks/flash/flash.js ***!
+ \**************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _utils = __webpack_require__(/*! ../../base/utils */ "./src/base/utils.js");
+
+var _base_flash_playback = __webpack_require__(/*! ../../playbacks/base_flash_playback */ "./src/playbacks/base_flash_playback/index.js");
+
+var _base_flash_playback2 = _interopRequireDefault(_base_flash_playback);
+
+var _browser = __webpack_require__(/*! ../../components/browser */ "./src/components/browser/index.js");
+
+var _browser2 = _interopRequireDefault(_browser);
+
+var _mediator = __webpack_require__(/*! ../../components/mediator */ "./src/components/mediator.js");
+
+var _mediator2 = _interopRequireDefault(_mediator);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _Player = __webpack_require__(/*! ./public/Player.swf */ "./src/playbacks/flash/public/Player.swf");
+
+var _Player2 = _interopRequireDefault(_Player);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var MAX_ATTEMPTS = 60; // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var Flash = function (_BaseFlashPlayback) {
+ (0, _inherits3.default)(Flash, _BaseFlashPlayback);
+ (0, _createClass3.default)(Flash, [{
+ key: 'name',
+ get: function get() {
+ return 'flash';
+ }
+ }, {
+ key: 'swfPath',
+ get: function get() {
+ return (0, _template2.default)(_Player2.default)({ baseUrl: this._baseUrl });
+ }
+
+ /**
+ * Determine if the playback has ended.
+ * @property ended
+ * @type Boolean
+ */
+
+ }, {
+ key: 'ended',
+ get: function get() {
+ return this._currentState === 'ENDED';
+ }
+
+ /**
+ * Determine if the playback is buffering.
+ * This is related to the PLAYBACK_BUFFERING and PLAYBACK_BUFFERFULL events
+ * @property buffering
+ * @type Boolean
+ */
+
+ }, {
+ key: 'buffering',
+ get: function get() {
+ return !!this._bufferingState && this._currentState !== 'ENDED';
+ }
+ }]);
+
+ function Flash() {
+ (0, _classCallCheck3.default)(this, Flash);
+
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _BaseFlashPlayback.call.apply(_BaseFlashPlayback, [this].concat(args)));
+
+ _this._src = _this.options.src;
+ _this._baseUrl = _this.options.baseUrl;
+ _this._autoPlay = _this.options.autoPlay;
+ _this.settings = { default: ['seekbar'] };
+ _this.settings.left = ['playpause', 'position', 'duration'];
+ _this.settings.right = ['fullscreen', 'volume'];
+ _this.settings.seekEnabled = true;
+ _this._isReadyState = false;
+ _this._addListeners();
+ return _this;
+ }
+
+ Flash.prototype._bootstrap = function _bootstrap() {
+ var _this2 = this;
+
+ if (this.el.playerPlay) {
+ this.el.width = '100%';
+ this.el.height = '100%';
+ if (this._currentState === 'PLAYING') {
+ this._firstPlay();
+ } else {
+ this._currentState = 'IDLE';
+ this._autoPlay && this.play();
+ }
+ (0, _clapprZepto2.default)('
').insertAfter(this.$el);
+ if (this.getDuration() > 0) this._metadataLoaded();else _mediator2.default.once(this.uniqueId + ':timeupdate', this._metadataLoaded, this);
+ } else {
+ this._attempts = this._attempts || 0;
+ if (++this._attempts <= MAX_ATTEMPTS) setTimeout(function () {
+ return _this2._bootstrap();
+ }, 50);else this.trigger(_events2.default.PLAYBACK_ERROR, { message: 'Max number of attempts reached' }, this.name);
+ }
+ };
+
+ Flash.prototype._metadataLoaded = function _metadataLoaded() {
+ this._isReadyState = true;
+ this.trigger(_events2.default.PLAYBACK_READY, this.name);
+ this.trigger(_events2.default.PLAYBACK_SETTINGSUPDATE, this.name);
+ };
+
+ Flash.prototype.getPlaybackType = function getPlaybackType() {
+ return _playback2.default.VOD;
+ };
+
+ Flash.prototype.isHighDefinitionInUse = function isHighDefinitionInUse() {
+ return false;
+ };
+
+ Flash.prototype._updateTime = function _updateTime() {
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: this.el.getPosition(), total: this.el.getDuration() }, this.name);
+ };
+
+ Flash.prototype._addListeners = function _addListeners() {
+ _mediator2.default.on(this.uniqueId + ':progress', this._progress, this);
+ _mediator2.default.on(this.uniqueId + ':timeupdate', this._updateTime, this);
+ _mediator2.default.on(this.uniqueId + ':statechanged', this._checkState, this);
+ _mediator2.default.on(this.uniqueId + ':flashready', this._bootstrap, this);
+ };
+
+ Flash.prototype.stopListening = function stopListening() {
+ _BaseFlashPlayback.prototype.stopListening.call(this);
+ _mediator2.default.off(this.uniqueId + ':progress');
+ _mediator2.default.off(this.uniqueId + ':timeupdate');
+ _mediator2.default.off(this.uniqueId + ':statechanged');
+ _mediator2.default.off(this.uniqueId + ':flashready');
+ };
+
+ Flash.prototype._checkState = function _checkState() {
+ if (this._isIdle || this._currentState === 'PAUSED') {
+ return;
+ } else if (this._currentState !== 'PLAYING_BUFFERING' && this.el.getState() === 'PLAYING_BUFFERING') {
+ this._bufferingState = true;
+ this.trigger(_events2.default.PLAYBACK_BUFFERING, this.name);
+ this._currentState = 'PLAYING_BUFFERING';
+ } else if (this.el.getState() === 'PLAYING') {
+ this._bufferingState = false;
+ this.trigger(_events2.default.PLAYBACK_BUFFERFULL, this.name);
+ this._currentState = 'PLAYING';
+ } else if (this.el.getState() === 'IDLE') {
+ this._currentState = 'IDLE';
+ } else if (this.el.getState() === 'ENDED') {
+ this.trigger(_events2.default.PLAYBACK_ENDED, this.name);
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: 0, total: this.el.getDuration() }, this.name);
+ this._currentState = 'ENDED';
+ this._isIdle = true;
+ }
+ };
+
+ Flash.prototype._progress = function _progress() {
+ if (this._currentState !== 'IDLE' && this._currentState !== 'ENDED') {
+ this.trigger(_events2.default.PLAYBACK_PROGRESS, {
+ start: 0,
+ current: this.el.getBytesLoaded(),
+ total: this.el.getBytesTotal()
+ });
+ }
+ };
+
+ Flash.prototype._firstPlay = function _firstPlay() {
+ var _this3 = this;
+
+ if (this.el.playerPlay) {
+ this._isIdle = false;
+ this.el.playerPlay(this._src);
+ this.listenToOnce(this, _events2.default.PLAYBACK_BUFFERFULL, function () {
+ return _this3._checkInitialSeek();
+ });
+ this._currentState = 'PLAYING';
+ } else {
+ this.listenToOnce(this, _events2.default.PLAYBACK_READY, this._firstPlay);
+ }
+ };
+
+ Flash.prototype._checkInitialSeek = function _checkInitialSeek() {
+ var seekTime = (0, _utils.seekStringToSeconds)(window.location.href);
+ if (seekTime !== 0) this.seekSeconds(seekTime);
+ };
+
+ Flash.prototype.play = function play() {
+ this.trigger(_events2.default.PLAYBACK_PLAY_INTENT);
+ if (this._currentState === 'PAUSED' || this._currentState === 'PLAYING_BUFFERING') {
+ this._currentState = 'PLAYING';
+ this.el.playerResume();
+ this.trigger(_events2.default.PLAYBACK_PLAY, this.name);
+ } else if (this._currentState !== 'PLAYING') {
+ this._firstPlay();
+ this.trigger(_events2.default.PLAYBACK_PLAY, this.name);
+ }
+ };
+
+ Flash.prototype.volume = function volume(value) {
+ var _this4 = this;
+
+ if (this.isReady) this.el.playerVolume(value);else this.listenToOnce(this, _events2.default.PLAYBACK_BUFFERFULL, function () {
+ return _this4.volume(value);
+ });
+ };
+
+ Flash.prototype.pause = function pause() {
+ this._currentState = 'PAUSED';
+ this.el.playerPause();
+ this.trigger(_events2.default.PLAYBACK_PAUSE, this.name);
+ };
+
+ Flash.prototype.stop = function stop() {
+ this.el.playerStop();
+ this.trigger(_events2.default.PLAYBACK_STOP);
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: 0, total: 0 }, this.name);
+ };
+
+ Flash.prototype.isPlaying = function isPlaying() {
+ return !!(this.isReady && this._currentState.indexOf('PLAYING') > -1);
+ };
+
+ Flash.prototype.getDuration = function getDuration() {
+ return this.el.getDuration();
+ };
+
+ Flash.prototype.seekPercentage = function seekPercentage(percentage) {
+ var _this5 = this;
+
+ if (this.el.getDuration() > 0) {
+ var seekSeconds = this.el.getDuration() * (percentage / 100);
+ this.seek(seekSeconds);
+ } else {
+ this.listenToOnce(this, _events2.default.PLAYBACK_BUFFERFULL, function () {
+ return _this5.seekPercentage(percentage);
+ });
+ }
+ };
+
+ Flash.prototype.seek = function seek(time) {
+ var _this6 = this;
+
+ if (this.isReady && this.el.playerSeek) {
+ this.el.playerSeek(time);
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: time, total: this.el.getDuration() }, this.name);
+ if (this._currentState === 'PAUSED') this.el.playerPause();
+ } else {
+ this.listenToOnce(this, _events2.default.PLAYBACK_BUFFERFULL, function () {
+ return _this6.seek(time);
+ });
+ }
+ };
+
+ Flash.prototype.destroy = function destroy() {
+ clearInterval(this.bootstrapId);
+ _BaseFlashPlayback.prototype.stopListening.call(this);
+ this.$el.remove();
+ };
+
+ (0, _createClass3.default)(Flash, [{
+ key: 'isReady',
+ get: function get() {
+ return this._isReadyState;
+ }
+ }]);
+ return Flash;
+}(_base_flash_playback2.default);
+
+exports.default = Flash;
+
+
+Flash.canPlay = function (resource) {
+ if (!_browser2.default.hasFlash || !resource || resource.constructor !== String) {
+ return false;
+ } else {
+ var resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
+ return resourceParts.length > 1 && !_browser2.default.isMobile && resourceParts[1].toLowerCase().match(/^(mp4|mov|f4v|3gpp|3gp)$/);
+ }
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/flash/index.js":
+/*!**************************************!*\
+ !*** ./src/playbacks/flash/index.js ***!
+ \**************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _flash = __webpack_require__(/*! ./flash */ "./src/playbacks/flash/flash.js");
+
+var _flash2 = _interopRequireDefault(_flash);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _flash2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/flash/public/Player.swf":
+/*!***********************************************!*\
+ !*** ./src/playbacks/flash/public/Player.swf ***!
+ \***********************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "<%=baseUrl%>/4b76590b32dab62bc95c1b7951efae78.swf";
+
+/***/ }),
+
+/***/ "./src/playbacks/flashls/flashls.js":
+/*!******************************************!*\
+ !*** ./src/playbacks/flashls/flashls.js ***!
+ \******************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _base_flash_playback = __webpack_require__(/*! ../../playbacks/base_flash_playback */ "./src/playbacks/base_flash_playback/index.js");
+
+var _base_flash_playback2 = _interopRequireDefault(_base_flash_playback);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _mediator = __webpack_require__(/*! ../../components/mediator */ "./src/components/mediator.js");
+
+var _mediator2 = _interopRequireDefault(_mediator);
+
+var _browser = __webpack_require__(/*! ../../components/browser */ "./src/components/browser/index.js");
+
+var _browser2 = _interopRequireDefault(_browser);
+
+var _error = __webpack_require__(/*! ../../components/error */ "./src/components/error/index.js");
+
+var _error2 = _interopRequireDefault(_error);
+
+var _flashls_events = __webpack_require__(/*! ./flashls_events */ "./src/playbacks/flashls/flashls_events.js");
+
+var _flashls_events2 = _interopRequireDefault(_flashls_events);
+
+var _HLSPlayer = __webpack_require__(/*! ./public/HLSPlayer.swf */ "./src/playbacks/flashls/public/HLSPlayer.swf");
+
+var _HLSPlayer2 = _interopRequireDefault(_HLSPlayer);
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var MAX_ATTEMPTS = 60;
+var AUTO = -1;
+
+var FlasHLS = function (_BaseFlashPlayback) {
+ (0, _inherits3.default)(FlasHLS, _BaseFlashPlayback);
+ (0, _createClass3.default)(FlasHLS, [{
+ key: 'name',
+ get: function get() {
+ return 'flashls';
+ }
+ }, {
+ key: 'swfPath',
+ get: function get() {
+ return (0, _template2.default)(_HLSPlayer2.default)({ baseUrl: this._baseUrl });
+ }
+ }, {
+ key: 'levels',
+ get: function get() {
+ return this._levels || [];
+ }
+ }, {
+ key: 'currentLevel',
+ get: function get() {
+ if (this._currentLevel === null || this._currentLevel === undefined) return AUTO;else return this._currentLevel; //0 is a valid level ID
+ },
+ set: function set(id) {
+ this._currentLevel = id;
+ this.trigger(_events2.default.PLAYBACK_LEVEL_SWITCH_START);
+ this.el.playerSetCurrentLevel(id);
+ }
+
+ /**
+ * Determine if the playback has ended.
+ * @property ended
+ * @type Boolean
+ */
+
+ }, {
+ key: 'ended',
+ get: function get() {
+ return this._hasEnded;
+ }
+
+ /**
+ * Determine if the playback is buffering.
+ * This is related to the PLAYBACK_BUFFERING and PLAYBACK_BUFFERFULL events
+ * @property buffering
+ * @type Boolean
+ */
+
+ }, {
+ key: 'buffering',
+ get: function get() {
+ return !!this._bufferingState && !this._hasEnded;
+ }
+ }]);
+
+ function FlasHLS() {
+ (0, _classCallCheck3.default)(this, FlasHLS);
+
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _BaseFlashPlayback.call.apply(_BaseFlashPlayback, [this].concat(args)));
+
+ _this._src = _this.options.src;
+ _this._baseUrl = _this.options.baseUrl;
+ _this._initHlsParameters(_this.options);
+ // TODO can this be private?
+ _this.highDefinition = false;
+ _this._autoPlay = _this.options.autoPlay;
+ _this._loop = _this.options.loop;
+ _this._defaultSettings = {
+ left: ['playstop'],
+ default: ['seekbar'],
+ right: ['fullscreen', 'volume', 'hd-indicator'],
+ seekEnabled: false
+ };
+ _this.settings = _clapprZepto2.default.extend({}, _this._defaultSettings);
+ _this._playbackType = _playback2.default.LIVE;
+ _this._hasEnded = false;
+ _this._addListeners();
+ return _this;
+ }
+
+ FlasHLS.prototype._initHlsParameters = function _initHlsParameters(options) {
+ this._autoStartLoad = options.autoStartLoad === undefined ? true : options.autoStartLoad;
+ this._capLevelToStage = options.capLevelToStage === undefined ? false : options.capLevelToStage;
+ this._maxLevelCappingMode = options.maxLevelCappingMode === undefined ? 'downscale' : options.maxLevelCappingMode;
+ this._minBufferLength = options.minBufferLength === undefined ? -1 : options.minBufferLength;
+ this._minBufferLengthCapping = options.minBufferLengthCapping === undefined ? -1 : options.minBufferLengthCapping;
+ this._maxBufferLength = options.maxBufferLength === undefined ? 120 : options.maxBufferLength;
+ this._maxBackBufferLength = options.maxBackBufferLength === undefined ? 30 : options.maxBackBufferLength;
+ this._lowBufferLength = options.lowBufferLength === undefined ? 3 : options.lowBufferLength;
+ this._mediaTimePeriod = options.mediaTimePeriod === undefined ? 100 : options.mediaTimePeriod;
+ this._fpsDroppedMonitoringPeriod = options.fpsDroppedMonitoringPeriod === undefined ? 5000 : options.fpsDroppedMonitoringPeriod;
+ this._fpsDroppedMonitoringThreshold = options.fpsDroppedMonitoringThreshold === undefined ? 0.2 : options.fpsDroppedMonitoringThreshold;
+ this._capLevelonFPSDrop = options.capLevelonFPSDrop === undefined ? false : options.capLevelonFPSDrop;
+ this._smoothAutoSwitchonFPSDrop = options.smoothAutoSwitchonFPSDrop === undefined ? this.capLevelonFPSDrop : options.smoothAutoSwitchonFPSDrop;
+ this._switchDownOnLevelError = options.switchDownOnLevelError === undefined ? true : options.switchDownOnLevelError;
+ this._seekMode = options.seekMode === undefined ? 'ACCURATE' : options.seekMode;
+ this._keyLoadMaxRetry = options.keyLoadMaxRetry === undefined ? 3 : options.keyLoadMaxRetry;
+ this._keyLoadMaxRetryTimeout = options.keyLoadMaxRetryTimeout === undefined ? 64000 : options.keyLoadMaxRetryTimeout;
+ this._fragmentLoadMaxRetry = options.fragmentLoadMaxRetry === undefined ? 3 : options.fragmentLoadMaxRetry;
+ this._fragmentLoadMaxRetryTimeout = options.fragmentLoadMaxRetryTimeout === undefined ? 4000 : options.fragmentLoadMaxRetryTimeout;
+ this._fragmentLoadSkipAfterMaxRetry = options.fragmentLoadSkipAfterMaxRetry === undefined ? true : options.fragmentLoadSkipAfterMaxRetry;
+ this._maxSkippedFragments = options.maxSkippedFragments === undefined ? 5 : options.maxSkippedFragments;
+ this._flushLiveURLCache = options.flushLiveURLCache === undefined ? false : options.flushLiveURLCache;
+ this._initialLiveManifestSize = options.initialLiveManifestSize === undefined ? 1 : options.initialLiveManifestSize;
+ this._manifestLoadMaxRetry = options.manifestLoadMaxRetry === undefined ? 3 : options.manifestLoadMaxRetry;
+ this._manifestLoadMaxRetryTimeout = options.manifestLoadMaxRetryTimeout === undefined ? 64000 : options.manifestLoadMaxRetryTimeout;
+ this._manifestRedundantLoadmaxRetry = options.manifestRedundantLoadmaxRetry === undefined ? 3 : options.manifestRedundantLoadmaxRetry;
+ this._startFromBitrate = options.startFromBitrate === undefined ? -1 : options.startFromBitrate;
+ this._startFromLevel = options.startFromLevel === undefined ? -1 : options.startFromLevel;
+ this._autoStartMaxDuration = options.autoStartMaxDuration === undefined ? -1 : options.autoStartMaxDuration;
+ this._seekFromLevel = options.seekFromLevel === undefined ? -1 : options.seekFromLevel;
+ this._useHardwareVideoDecoder = options.useHardwareVideoDecoder === undefined ? false : options.useHardwareVideoDecoder;
+ this._hlsLogEnabled = options.hlsLogEnabled === undefined ? true : options.hlsLogEnabled;
+ this._logDebug = options.logDebug === undefined ? false : options.logDebug;
+ this._logDebug2 = options.logDebug2 === undefined ? false : options.logDebug2;
+ this._logWarn = options.logWarn === undefined ? true : options.logWarn;
+ this._logError = options.logError === undefined ? true : options.logError;
+ this._hlsMinimumDvrSize = options.hlsMinimumDvrSize === undefined ? 60 : options.hlsMinimumDvrSize;
+ };
+
+ FlasHLS.prototype._addListeners = function _addListeners() {
+ var _this2 = this;
+
+ _mediator2.default.on(this.cid + ':flashready', function () {
+ return _this2._bootstrap();
+ });
+ _mediator2.default.on(this.cid + ':timeupdate', function (timeMetrics) {
+ return _this2._updateTime(timeMetrics);
+ });
+ _mediator2.default.on(this.cid + ':playbackstate', function (state) {
+ return _this2._setPlaybackState(state);
+ });
+ _mediator2.default.on(this.cid + ':levelchanged', function (level) {
+ return _this2._levelChanged(level);
+ });
+ _mediator2.default.on(this.cid + ':error', function (code, url, message) {
+ return _this2._flashPlaybackError(code, url, message);
+ });
+ _mediator2.default.on(this.cid + ':fragmentloaded', function (loadmetrics) {
+ return _this2._onFragmentLoaded(loadmetrics);
+ });
+ _mediator2.default.on(this.cid + ':levelendlist', function (level) {
+ return _this2._onLevelEndlist(level);
+ });
+ };
+
+ FlasHLS.prototype.stopListening = function stopListening() {
+ _BaseFlashPlayback.prototype.stopListening.call(this);
+ _mediator2.default.off(this.cid + ':flashready');
+ _mediator2.default.off(this.cid + ':timeupdate');
+ _mediator2.default.off(this.cid + ':playbackstate');
+ _mediator2.default.off(this.cid + ':levelchanged');
+ _mediator2.default.off(this.cid + ':playbackerror');
+ _mediator2.default.off(this.cid + ':fragmentloaded');
+ _mediator2.default.off(this.cid + ':manifestloaded');
+ _mediator2.default.off(this.cid + ':levelendlist');
+ };
+
+ FlasHLS.prototype._bootstrap = function _bootstrap() {
+ var _this3 = this;
+
+ if (this.el.playerLoad) {
+ this.el.width = '100%';
+ this.el.height = '100%';
+ this._isReadyState = true;
+ this._srcLoaded = false;
+ this._currentState = 'IDLE';
+ this._setFlashSettings();
+ this._updatePlaybackType();
+ if (this._autoPlay || this._shouldPlayOnManifestLoaded) this.play();
+
+ this.trigger(_events2.default.PLAYBACK_READY, this.name);
+ } else {
+ this._bootstrapAttempts = this._bootstrapAttempts || 0;
+ if (++this._bootstrapAttempts <= MAX_ATTEMPTS) {
+ setTimeout(function () {
+ return _this3._bootstrap();
+ }, 50);
+ } else {
+ var formattedError = this.createError({
+ code: 'playerLoadFail_maxNumberAttemptsReached',
+ description: this.name + ' error: Max number of attempts reached',
+ level: _error2.default.Levels.FATAL,
+ raw: {}
+ });
+ this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ }
+ }
+ };
+
+ FlasHLS.prototype._setFlashSettings = function _setFlashSettings() {
+ this.el.playerSetAutoStartLoad(this._autoStartLoad);
+ this.el.playerSetCapLevelToStage(this._capLevelToStage);
+ this.el.playerSetMaxLevelCappingMode(this._maxLevelCappingMode);
+ this.el.playerSetMinBufferLength(this._minBufferLength);
+ this.el.playerSetMinBufferLengthCapping(this._minBufferLengthCapping);
+ this.el.playerSetMaxBufferLength(this._maxBufferLength);
+ this.el.playerSetMaxBackBufferLength(this._maxBackBufferLength);
+ this.el.playerSetLowBufferLength(this._lowBufferLength);
+ this.el.playerSetMediaTimePeriod(this._mediaTimePeriod);
+ this.el.playerSetFpsDroppedMonitoringPeriod(this._fpsDroppedMonitoringPeriod);
+ this.el.playerSetFpsDroppedMonitoringThreshold(this._fpsDroppedMonitoringThreshold);
+ this.el.playerSetCapLevelonFPSDrop(this._capLevelonFPSDrop);
+ this.el.playerSetSmoothAutoSwitchonFPSDrop(this._smoothAutoSwitchonFPSDrop);
+ this.el.playerSetSwitchDownOnLevelError(this._switchDownOnLevelError);
+ this.el.playerSetSeekMode(this._seekMode);
+ this.el.playerSetKeyLoadMaxRetry(this._keyLoadMaxRetry);
+ this.el.playerSetKeyLoadMaxRetryTimeout(this._keyLoadMaxRetryTimeout);
+ this.el.playerSetFragmentLoadMaxRetry(this._fragmentLoadMaxRetry);
+ this.el.playerSetFragmentLoadMaxRetryTimeout(this._fragmentLoadMaxRetryTimeout);
+ this.el.playerSetFragmentLoadSkipAfterMaxRetry(this._fragmentLoadSkipAfterMaxRetry);
+ this.el.playerSetMaxSkippedFragments(this._maxSkippedFragments);
+ this.el.playerSetFlushLiveURLCache(this._flushLiveURLCache);
+ this.el.playerSetInitialLiveManifestSize(this._initialLiveManifestSize);
+ this.el.playerSetManifestLoadMaxRetry(this._manifestLoadMaxRetry);
+ this.el.playerSetManifestLoadMaxRetryTimeout(this._manifestLoadMaxRetryTimeout);
+ this.el.playerSetManifestRedundantLoadmaxRetry(this._manifestRedundantLoadmaxRetry);
+ this.el.playerSetStartFromBitrate(this._startFromBitrate);
+ this.el.playerSetStartFromLevel(this._startFromLevel);
+ this.el.playerSetAutoStartMaxDuration(this._autoStartMaxDuration);
+ this.el.playerSetSeekFromLevel(this._seekFromLevel);
+ this.el.playerSetUseHardwareVideoDecoder(this._useHardwareVideoDecoder);
+ this.el.playerSetLogInfo(this._hlsLogEnabled);
+ this.el.playerSetLogDebug(this._logDebug);
+ this.el.playerSetLogDebug2(this._logDebug2);
+ this.el.playerSetLogWarn(this._logWarn);
+ this.el.playerSetLogError(this._logError);
+ };
+
+ FlasHLS.prototype.setAutoStartLoad = function setAutoStartLoad(autoStartLoad) {
+ this._autoStartLoad = autoStartLoad;
+ this.el.playerSetAutoStartLoad(this._autoStartLoad);
+ };
+
+ FlasHLS.prototype.setCapLevelToStage = function setCapLevelToStage(capLevelToStage) {
+ this._capLevelToStage = capLevelToStage;
+ this.el.playerSetCapLevelToStage(this._capLevelToStage);
+ };
+
+ FlasHLS.prototype.setMaxLevelCappingMode = function setMaxLevelCappingMode(maxLevelCappingMode) {
+ this._maxLevelCappingMode = maxLevelCappingMode;
+ this.el.playerSetMaxLevelCappingMode(this._maxLevelCappingMode);
+ };
+
+ FlasHLS.prototype.setSetMinBufferLength = function setSetMinBufferLength(minBufferLength) {
+ this._minBufferLength = minBufferLength;
+ this.el.playerSetMinBufferLength(this._minBufferLength);
+ };
+
+ FlasHLS.prototype.setMinBufferLengthCapping = function setMinBufferLengthCapping(minBufferLengthCapping) {
+ this._minBufferLengthCapping = minBufferLengthCapping;
+ this.el.playerSetMinBufferLengthCapping(this._minBufferLengthCapping);
+ };
+
+ FlasHLS.prototype.setMaxBufferLength = function setMaxBufferLength(maxBufferLength) {
+ this._maxBufferLength = maxBufferLength;
+ this.el.playerSetMaxBufferLength(this._maxBufferLength);
+ };
+
+ FlasHLS.prototype.setMaxBackBufferLength = function setMaxBackBufferLength(maxBackBufferLength) {
+ this._maxBackBufferLength = maxBackBufferLength;
+ this.el.playerSetMaxBackBufferLength(this._maxBackBufferLength);
+ };
+
+ FlasHLS.prototype.setLowBufferLength = function setLowBufferLength(lowBufferLength) {
+ this._lowBufferLength = lowBufferLength;
+ this.el.playerSetLowBufferLength(this._lowBufferLength);
+ };
+
+ FlasHLS.prototype.setMediaTimePeriod = function setMediaTimePeriod(mediaTimePeriod) {
+ this._mediaTimePeriod = mediaTimePeriod;
+ this.el.playerSetMediaTimePeriod(this._mediaTimePeriod);
+ };
+
+ FlasHLS.prototype.setFpsDroppedMonitoringPeriod = function setFpsDroppedMonitoringPeriod(fpsDroppedMonitoringPeriod) {
+ this._fpsDroppedMonitoringPeriod = fpsDroppedMonitoringPeriod;
+ this.el.playerSetFpsDroppedMonitoringPeriod(this._fpsDroppedMonitoringPeriod);
+ };
+
+ FlasHLS.prototype.setFpsDroppedMonitoringThreshold = function setFpsDroppedMonitoringThreshold(fpsDroppedMonitoringThreshold) {
+ this._fpsDroppedMonitoringThreshold = fpsDroppedMonitoringThreshold;
+ this.el.playerSetFpsDroppedMonitoringThreshold(this._fpsDroppedMonitoringThreshold);
+ };
+
+ FlasHLS.prototype.setCapLevelonFPSDrop = function setCapLevelonFPSDrop(capLevelonFPSDrop) {
+ this._capLevelonFPSDrop = capLevelonFPSDrop;
+ this.el.playerSetCapLevelonFPSDrop(this._capLevelonFPSDrop);
+ };
+
+ FlasHLS.prototype.setSmoothAutoSwitchonFPSDrop = function setSmoothAutoSwitchonFPSDrop(smoothAutoSwitchonFPSDrop) {
+ this._smoothAutoSwitchonFPSDrop = smoothAutoSwitchonFPSDrop;
+ this.el.playerSetSmoothAutoSwitchonFPSDrop(this._smoothAutoSwitchonFPSDrop);
+ };
+
+ FlasHLS.prototype.setSwitchDownOnLevelError = function setSwitchDownOnLevelError(switchDownOnLevelError) {
+ this._switchDownOnLevelError = switchDownOnLevelError;
+ this.el.playerSetSwitchDownOnLevelError(this._switchDownOnLevelError);
+ };
+
+ FlasHLS.prototype.setSeekMode = function setSeekMode(seekMode) {
+ this._seekMode = seekMode;
+ this.el.playerSetSeekMode(this._seekMode);
+ };
+
+ FlasHLS.prototype.setKeyLoadMaxRetry = function setKeyLoadMaxRetry(keyLoadMaxRetry) {
+ this._keyLoadMaxRetry = keyLoadMaxRetry;
+ this.el.playerSetKeyLoadMaxRetry(this._keyLoadMaxRetry);
+ };
+
+ FlasHLS.prototype.setKeyLoadMaxRetryTimeout = function setKeyLoadMaxRetryTimeout(keyLoadMaxRetryTimeout) {
+ this._keyLoadMaxRetryTimeout = keyLoadMaxRetryTimeout;
+ this.el.playerSetKeyLoadMaxRetryTimeout(this._keyLoadMaxRetryTimeout);
+ };
+
+ FlasHLS.prototype.setFragmentLoadMaxRetry = function setFragmentLoadMaxRetry(fragmentLoadMaxRetry) {
+ this._fragmentLoadMaxRetry = fragmentLoadMaxRetry;
+ this.el.playerSetFragmentLoadMaxRetry(this._fragmentLoadMaxRetry);
+ };
+
+ FlasHLS.prototype.setFragmentLoadMaxRetryTimeout = function setFragmentLoadMaxRetryTimeout(fragmentLoadMaxRetryTimeout) {
+ this._fragmentLoadMaxRetryTimeout = fragmentLoadMaxRetryTimeout;
+ this.el.playerSetFragmentLoadMaxRetryTimeout(this._fragmentLoadMaxRetryTimeout);
+ };
+
+ FlasHLS.prototype.setFragmentLoadSkipAfterMaxRetry = function setFragmentLoadSkipAfterMaxRetry(fragmentLoadSkipAfterMaxRetry) {
+ this._fragmentLoadSkipAfterMaxRetry = fragmentLoadSkipAfterMaxRetry;
+ this.el.playerSetFragmentLoadSkipAfterMaxRetry(this._fragmentLoadSkipAfterMaxRetry);
+ };
+
+ FlasHLS.prototype.setMaxSkippedFragments = function setMaxSkippedFragments(maxSkippedFragments) {
+ this._maxSkippedFragments = maxSkippedFragments;
+ this.el.playerSetMaxSkippedFragments(this._maxSkippedFragments);
+ };
+
+ FlasHLS.prototype.setFlushLiveURLCache = function setFlushLiveURLCache(flushLiveURLCache) {
+ this._flushLiveURLCache = flushLiveURLCache;
+ this.el.playerSetFlushLiveURLCache(this._flushLiveURLCache);
+ };
+
+ FlasHLS.prototype.setInitialLiveManifestSize = function setInitialLiveManifestSize(initialLiveManifestSize) {
+ this._initialLiveManifestSize = initialLiveManifestSize;
+ this.el.playerSetInitialLiveManifestSize(this._initialLiveManifestSize);
+ };
+
+ FlasHLS.prototype.setManifestLoadMaxRetry = function setManifestLoadMaxRetry(manifestLoadMaxRetry) {
+ this._manifestLoadMaxRetry = manifestLoadMaxRetry;
+ this.el.playerSetManifestLoadMaxRetry(this._manifestLoadMaxRetry);
+ };
+
+ FlasHLS.prototype.setManifestLoadMaxRetryTimeout = function setManifestLoadMaxRetryTimeout(manifestLoadMaxRetryTimeout) {
+ this._manifestLoadMaxRetryTimeout = manifestLoadMaxRetryTimeout;
+ this.el.playerSetManifestLoadMaxRetryTimeout(this._manifestLoadMaxRetryTimeout);
+ };
+
+ FlasHLS.prototype.setManifestRedundantLoadmaxRetry = function setManifestRedundantLoadmaxRetry(manifestRedundantLoadmaxRetry) {
+ this._manifestRedundantLoadmaxRetry = manifestRedundantLoadmaxRetry;
+ this.el.playerSetManifestRedundantLoadmaxRetry(this._manifestRedundantLoadmaxRetry);
+ };
+
+ FlasHLS.prototype.setStartFromBitrate = function setStartFromBitrate(startFromBitrate) {
+ this._startFromBitrate = startFromBitrate;
+ this.el.playerSetStartFromBitrate(this._startFromBitrate);
+ };
+
+ FlasHLS.prototype.setStartFromLevel = function setStartFromLevel(startFromLevel) {
+ this._startFromLevel = startFromLevel;
+ this.el.playerSetStartFromLevel(this._startFromLevel);
+ };
+
+ FlasHLS.prototype.setAutoStartMaxDuration = function setAutoStartMaxDuration(autoStartMaxDuration) {
+ this._autoStartMaxDuration = autoStartMaxDuration;
+ this.el.playerSetAutoStartMaxDuration(this._autoStartMaxDuration);
+ };
+
+ FlasHLS.prototype.setSeekFromLevel = function setSeekFromLevel(seekFromLevel) {
+ this._seekFromLevel = seekFromLevel;
+ this.el.playerSetSeekFromLevel(this._seekFromLevel);
+ };
+
+ FlasHLS.prototype.setUseHardwareVideoDecoder = function setUseHardwareVideoDecoder(useHardwareVideoDecoder) {
+ this._useHardwareVideoDecoder = useHardwareVideoDecoder;
+ this.el.playerSetUseHardwareVideoDecoder(this._useHardwareVideoDecoder);
+ };
+
+ FlasHLS.prototype.setSetLogInfo = function setSetLogInfo(hlsLogEnabled) {
+ this._hlsLogEnabled = hlsLogEnabled;
+ this.el.playerSetLogInfo(this._hlsLogEnabled);
+ };
+
+ FlasHLS.prototype.setLogDebug = function setLogDebug(logDebug) {
+ this._logDebug = logDebug;
+ this.el.playerSetLogDebug(this._logDebug);
+ };
+
+ FlasHLS.prototype.setLogDebug2 = function setLogDebug2(logDebug2) {
+ this._logDebug2 = logDebug2;
+ this.el.playerSetLogDebug2(this._logDebug2);
+ };
+
+ FlasHLS.prototype.setLogWarn = function setLogWarn(logWarn) {
+ this._logWarn = logWarn;
+ this.el.playerSetLogWarn(this._logWarn);
+ };
+
+ FlasHLS.prototype.setLogError = function setLogError(logError) {
+ this._logError = logError;
+ this.el.playerSetLogError(this._logError);
+ };
+
+ FlasHLS.prototype._levelChanged = function _levelChanged(level) {
+ var currentLevel = this.el.getLevels()[level];
+ if (currentLevel) {
+ this.highDefinition = currentLevel.height >= 720 || currentLevel.bitrate / 1000 >= 2000;
+ this.trigger(_events2.default.PLAYBACK_HIGHDEFINITIONUPDATE, this.highDefinition);
+
+ if (!this._levels || this._levels.length === 0) this._fillLevels();
+
+ this.trigger(_events2.default.PLAYBACK_BITRATE, {
+ height: currentLevel.height,
+ width: currentLevel.width,
+ bandwidth: currentLevel.bitrate,
+ bitrate: currentLevel.bitrate,
+ level: level
+ });
+ this.trigger(_events2.default.PLAYBACK_LEVEL_SWITCH_END);
+ }
+ };
+
+ FlasHLS.prototype._updateTime = function _updateTime(timeMetrics) {
+ if (this._currentState === 'IDLE') return;
+
+ var duration = this._normalizeDuration(timeMetrics.duration);
+ var position = Math.min(Math.max(timeMetrics.position, 0), duration);
+ var previousDVRStatus = this._dvrEnabled;
+ var livePlayback = this._playbackType === _playback2.default.LIVE;
+ this._dvrEnabled = livePlayback && duration > this._hlsMinimumDvrSize;
+
+ if (duration === 100 || livePlayback === undefined) return;
+
+ if (this._dvrEnabled !== previousDVRStatus) {
+ this._updateSettings();
+ this.trigger(_events2.default.PLAYBACK_SETTINGSUPDATE, this.name);
+ }
+
+ if (livePlayback && !this._dvrEnabled) position = duration;
+
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: position, total: duration }, this.name);
+ };
+
+ FlasHLS.prototype.play = function play() {
+ this.trigger(_events2.default.PLAYBACK_PLAY_INTENT);
+ if (this._currentState === 'PAUSED') this.el.playerResume();else if (!this._srcLoaded && this._currentState !== 'PLAYING') this._firstPlay();else this.el.playerPlay();
+ };
+
+ FlasHLS.prototype.getPlaybackType = function getPlaybackType() {
+ return this._playbackType ? this._playbackType : null;
+ };
+
+ FlasHLS.prototype.getCurrentTime = function getCurrentTime() {
+ return this.el.getPosition();
+ };
+
+ FlasHLS.prototype.getCurrentLevelIndex = function getCurrentLevelIndex() {
+ return this._currentLevel;
+ };
+
+ FlasHLS.prototype.getCurrentLevel = function getCurrentLevel() {
+ return this.levels[this.currentLevel];
+ };
+
+ FlasHLS.prototype.getCurrentBitrate = function getCurrentBitrate() {
+ return this.levels[this.currentLevel].bitrate;
+ };
+
+ FlasHLS.prototype.setCurrentLevel = function setCurrentLevel(level) {
+ this.currentLevel = level;
+ };
+
+ FlasHLS.prototype.isHighDefinitionInUse = function isHighDefinitionInUse() {
+ return this.highDefinition;
+ };
+
+ FlasHLS.prototype.getLevels = function getLevels() {
+ return this.levels;
+ };
+
+ FlasHLS.prototype._setPlaybackState = function _setPlaybackState(state) {
+ if (['PLAYING_BUFFERING', 'PAUSED_BUFFERING'].indexOf(state) >= 0) {
+ this._bufferingState = true;
+ this.trigger(_events2.default.PLAYBACK_BUFFERING, this.name);
+ this._updateCurrentState(state);
+ } else if (['PLAYING', 'PAUSED'].indexOf(state) >= 0) {
+ if (['PLAYING_BUFFERING', 'PAUSED_BUFFERING', 'IDLE'].indexOf(this._currentState) >= 0) {
+ this._bufferingState = false;
+ this.trigger(_events2.default.PLAYBACK_BUFFERFULL, this.name);
+ }
+ this._updateCurrentState(state);
+ } else if (state === 'IDLE') {
+ this._srcLoaded = false;
+ if (this._loop && ['PLAYING_BUFFERING', 'PLAYING'].indexOf(this._currentState) >= 0) {
+ this.play();
+ this.seek(0);
+ } else {
+ this._updateCurrentState(state);
+ this._hasEnded = true;
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: 0, total: this.getDuration() }, this.name);
+ this.trigger(_events2.default.PLAYBACK_ENDED, this.name);
+ }
+ }
+ };
+
+ FlasHLS.prototype._updateCurrentState = function _updateCurrentState(state) {
+ this._currentState = state;
+ if (state !== 'IDLE') this._hasEnded = false;
+
+ this._updatePlaybackType();
+ if (state === 'PLAYING') this.trigger(_events2.default.PLAYBACK_PLAY, this.name);else if (state === 'PAUSED') this.trigger(_events2.default.PLAYBACK_PAUSE, this.name);
+ };
+
+ FlasHLS.prototype._updatePlaybackType = function _updatePlaybackType() {
+ this._playbackType = this.el.getType();
+ if (this._playbackType) {
+ this._playbackType = this._playbackType.toLowerCase();
+ if (this._playbackType === _playback2.default.VOD) this._startReportingProgress();else this._stopReportingProgress();
+ }
+ this.trigger(_events2.default.PLAYBACK_PLAYBACKSTATE, { type: this._playbackType });
+ };
+
+ FlasHLS.prototype._startReportingProgress = function _startReportingProgress() {
+ if (!this._reportingProgress) this._reportingProgress = true;
+ };
+
+ FlasHLS.prototype._stopReportingProgress = function _stopReportingProgress() {
+ this._reportingProgress = false;
+ };
+
+ FlasHLS.prototype._onFragmentLoaded = function _onFragmentLoaded(loadmetrics) {
+ this.trigger(_events2.default.PLAYBACK_FRAGMENT_LOADED, loadmetrics);
+ if (this._reportingProgress && this.getCurrentTime()) {
+ var buffered = this.getCurrentTime() + this.el.getbufferLength();
+ this.trigger(_events2.default.PLAYBACK_PROGRESS, {
+ start: this.getCurrentTime(),
+ current: buffered,
+ total: this.el.getDuration()
+ });
+ }
+ };
+
+ FlasHLS.prototype._onLevelEndlist = function _onLevelEndlist() {
+ this._updatePlaybackType();
+ };
+
+ FlasHLS.prototype._firstPlay = function _firstPlay() {
+ var _this4 = this;
+
+ this._shouldPlayOnManifestLoaded = true;
+ if (this.el.playerLoad) {
+ _mediator2.default.once(this.cid + ':manifestloaded', function (duration, loadmetrics) {
+ return _this4._manifestLoaded(duration, loadmetrics);
+ });
+ this._setFlashSettings(); //ensure flushLiveURLCache will work (#327)
+ this.el.playerLoad(this._src);
+ this._srcLoaded = true;
+ }
+ };
+
+ FlasHLS.prototype.volume = function volume(value) {
+ var _this5 = this;
+
+ if (this.isReady) this.el.playerVolume(value);else this.listenToOnce(this, _events2.default.PLAYBACK_BUFFERFULL, function () {
+ return _this5.volume(value);
+ });
+ };
+
+ FlasHLS.prototype.pause = function pause() {
+ if (this._playbackType !== _playback2.default.LIVE || this._dvrEnabled) {
+ this.el.playerPause();
+ if (this._playbackType === _playback2.default.LIVE && this._dvrEnabled) this._updateDvr(true);
+ }
+ };
+
+ FlasHLS.prototype.stop = function stop() {
+ this._srcLoaded = false;
+ this.el.playerStop();
+ this.trigger(_events2.default.PLAYBACK_STOP);
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: 0, total: 0 }, this.name);
+ };
+
+ FlasHLS.prototype.isPlaying = function isPlaying() {
+ if (this._currentState) return !!this._currentState.match(/playing/i);
+
+ return false;
+ };
+
+ FlasHLS.prototype.getDuration = function getDuration() {
+ return this._normalizeDuration(this.el.getDuration());
+ };
+
+ FlasHLS.prototype._normalizeDuration = function _normalizeDuration(duration) {
+ if (this._playbackType === _playback2.default.LIVE) {
+ // estimate 10 seconds of buffer time for live streams for seek positions
+ duration = Math.max(0, duration - 10);
+ }
+ return duration;
+ };
+
+ FlasHLS.prototype.seekPercentage = function seekPercentage(percentage) {
+ var duration = this.el.getDuration();
+ var time = 0;
+ if (percentage > 0) time = duration * percentage / 100;
+
+ this.seek(time);
+ };
+
+ FlasHLS.prototype.seek = function seek(time) {
+ var duration = this.getDuration();
+ if (this._playbackType === _playback2.default.LIVE) {
+ // seek operations to a time within 3 seconds from live stream will position playhead back to live
+ var dvrInUse = duration - time > 3;
+ this._updateDvr(dvrInUse);
+ }
+ this.el.playerSeek(time);
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: time, total: duration }, this.name);
+ };
+
+ FlasHLS.prototype._updateDvr = function _updateDvr(dvrInUse) {
+ var previousDvrInUse = !!this._dvrInUse;
+ this._dvrInUse = dvrInUse;
+ if (this._dvrInUse !== previousDvrInUse) {
+ this._updateSettings();
+ this.trigger(_events2.default.PLAYBACK_DVR, this._dvrInUse);
+ this.trigger(_events2.default.PLAYBACK_STATS_ADD, { 'dvr': this._dvrInUse });
+ }
+ };
+
+ FlasHLS.prototype._flashPlaybackError = function _flashPlaybackError(code, url, message) {
+ var error = {
+ code: code,
+ description: message,
+ level: _error2.default.Levels.FATAL,
+ raw: { code: code, url: url, message: message }
+ };
+ var formattedError = this.createError(error);
+ this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ this.trigger(_events2.default.PLAYBACK_STOP);
+ };
+
+ FlasHLS.prototype._manifestLoaded = function _manifestLoaded(duration, loadmetrics) {
+ if (this._shouldPlayOnManifestLoaded) {
+ this._shouldPlayOnManifestLoaded = false;
+ // this method initialises the player (and starts playback)
+ // this needs to happen before PLAYBACK_LOADEDMETADATA is fired
+ // as the user may call seek() in a LOADEDMETADATA listener.
+ /// when playerPlay() is called the player seeks to 0
+ this.el.playerPlay();
+ }
+
+ this._fillLevels();
+ this.trigger(_events2.default.PLAYBACK_LOADEDMETADATA, { duration: duration, data: loadmetrics });
+ };
+
+ FlasHLS.prototype._fillLevels = function _fillLevels() {
+ var levels = this.el.getLevels();
+ var levelsLength = levels.length;
+ this._levels = [];
+
+ for (var index = 0; index < levelsLength; index++) {
+ this._levels.push({ id: index, label: levels[index].height + 'p', level: levels[index] });
+ }this.trigger(_events2.default.PLAYBACK_LEVELS_AVAILABLE, this._levels);
+ };
+
+ FlasHLS.prototype.destroy = function destroy() {
+ this.stopListening();
+ this.$el.remove();
+ };
+
+ FlasHLS.prototype._updateSettings = function _updateSettings() {
+ this.settings = _clapprZepto2.default.extend({}, this._defaultSettings);
+ if (this._playbackType === _playback2.default.VOD || this._dvrInUse) {
+ this.settings.left = ['playpause', 'position', 'duration'];
+ this.settings.seekEnabled = true;
+ } else if (this._dvrEnabled) {
+ this.settings.left = ['playpause'];
+ this.settings.seekEnabled = true;
+ } else {
+ this.settings.seekEnabled = false;
+ }
+ };
+
+ FlasHLS.prototype._createCallbacks = function _createCallbacks() {
+ var _this6 = this;
+
+ if (!window.Clappr) window.Clappr = {};
+
+ if (!window.Clappr.flashlsCallbacks) window.Clappr.flashlsCallbacks = {};
+
+ this.flashlsEvents = new _flashls_events2.default(this.cid);
+ window.Clappr.flashlsCallbacks[this.cid] = function (eventName, args) {
+ _this6.flashlsEvents[eventName].apply(_this6.flashlsEvents, args);
+ };
+ };
+
+ FlasHLS.prototype.render = function render() {
+ _BaseFlashPlayback.prototype.render.call(this);
+ this._createCallbacks();
+ return this;
+ };
+
+ (0, _createClass3.default)(FlasHLS, [{
+ key: 'isReady',
+ get: function get() {
+ return this._isReadyState;
+ }
+ }, {
+ key: 'dvrEnabled',
+ get: function get() {
+ return !!this._dvrEnabled;
+ }
+ }]);
+ return FlasHLS;
+}(_base_flash_playback2.default);
+
+exports.default = FlasHLS;
+
+
+FlasHLS.canPlay = function (resource, mimeType) {
+ var resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
+ return _browser2.default.hasFlash && (resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'm3u8' || mimeType === 'application/x-mpegURL' || mimeType === 'application/vnd.apple.mpegurl');
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/flashls/flashls_events.js":
+/*!*************************************************!*\
+ !*** ./src/playbacks/flashls/flashls_events.js ***!
+ \*************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _mediator = __webpack_require__(/*! ../../components/mediator */ "./src/components/mediator.js");
+
+var _mediator2 = _interopRequireDefault(_mediator);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var HLSEvents = function () {
+ function HLSEvents(instanceId) {
+ (0, _classCallCheck3.default)(this, HLSEvents);
+
+ this.instanceId = instanceId;
+ }
+
+ HLSEvents.prototype.ready = function ready() {
+ _mediator2.default.trigger(this.instanceId + ':flashready');
+ };
+
+ HLSEvents.prototype.videoSize = function videoSize(width, height) {
+ _mediator2.default.trigger(this.instanceId + ':videosizechanged', width, height);
+ };
+
+ HLSEvents.prototype.complete = function complete() {
+ _mediator2.default.trigger(this.instanceId + ':complete');
+ };
+
+ HLSEvents.prototype.error = function error(code, url, message) {
+ _mediator2.default.trigger(this.instanceId + ':error', code, url, message);
+ };
+
+ HLSEvents.prototype.manifest = function manifest(duration, loadmetrics) {
+ _mediator2.default.trigger(this.instanceId + ':manifestloaded', duration, loadmetrics);
+ };
+
+ HLSEvents.prototype.audioLevelLoaded = function audioLevelLoaded(loadmetrics) {
+ _mediator2.default.trigger(this.instanceId + ':audiolevelloaded', loadmetrics);
+ };
+
+ HLSEvents.prototype.levelLoaded = function levelLoaded(loadmetrics) {
+ _mediator2.default.trigger(this.instanceId + ':levelloaded', loadmetrics);
+ };
+
+ HLSEvents.prototype.levelEndlist = function levelEndlist(level) {
+ _mediator2.default.trigger(this.instanceId + ':levelendlist', level);
+ };
+
+ HLSEvents.prototype.fragmentLoaded = function fragmentLoaded(loadmetrics) {
+ _mediator2.default.trigger(this.instanceId + ':fragmentloaded', loadmetrics);
+ };
+
+ HLSEvents.prototype.fragmentPlaying = function fragmentPlaying(playmetrics) {
+ _mediator2.default.trigger(this.instanceId + ':fragmentplaying', playmetrics);
+ };
+
+ HLSEvents.prototype.position = function position(timemetrics) {
+ _mediator2.default.trigger(this.instanceId + ':timeupdate', timemetrics);
+ };
+
+ HLSEvents.prototype.state = function state(newState) {
+ _mediator2.default.trigger(this.instanceId + ':playbackstate', newState);
+ };
+
+ HLSEvents.prototype.seekState = function seekState(newState) {
+ _mediator2.default.trigger(this.instanceId + ':seekstate', newState);
+ };
+
+ HLSEvents.prototype.switch = function _switch(newLevel) {
+ _mediator2.default.trigger(this.instanceId + ':levelchanged', newLevel);
+ };
+
+ HLSEvents.prototype.audioTracksListChange = function audioTracksListChange(trackList) {
+ _mediator2.default.trigger(this.instanceId + ':audiotracklistchanged', trackList);
+ };
+
+ HLSEvents.prototype.audioTrackChange = function audioTrackChange(trackId) {
+ _mediator2.default.trigger(this.instanceId + ':audiotrackchanged', trackId);
+ };
+
+ return HLSEvents;
+}();
+
+exports.default = HLSEvents;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/flashls/index.js":
+/*!****************************************!*\
+ !*** ./src/playbacks/flashls/index.js ***!
+ \****************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _flashls = __webpack_require__(/*! ./flashls */ "./src/playbacks/flashls/flashls.js");
+
+var _flashls2 = _interopRequireDefault(_flashls);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _flashls2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/flashls/public/HLSPlayer.swf":
+/*!****************************************************!*\
+ !*** ./src/playbacks/flashls/public/HLSPlayer.swf ***!
+ \****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "<%=baseUrl%>/8fa12a459188502b9f0d39b8a67d9e6c.swf";
+
+/***/ }),
+
+/***/ "./src/playbacks/hls/hls.js":
+/*!**********************************!*\
+ !*** ./src/playbacks/hls/hls.js ***!
+ \**********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _toConsumableArray2 = __webpack_require__(/*! babel-runtime/helpers/toConsumableArray */ "./node_modules/babel-runtime/helpers/toConsumableArray.js");
+
+var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
+
+var _stringify = __webpack_require__(/*! babel-runtime/core-js/json/stringify */ "./node_modules/babel-runtime/core-js/json/stringify.js");
+
+var _stringify2 = _interopRequireDefault(_stringify);
+
+var _extends2 = __webpack_require__(/*! babel-runtime/helpers/extends */ "./node_modules/babel-runtime/helpers/extends.js");
+
+var _extends3 = _interopRequireDefault(_extends2);
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _html5_video = __webpack_require__(/*! ../../playbacks/html5_video */ "./src/playbacks/html5_video/index.js");
+
+var _html5_video2 = _interopRequireDefault(_html5_video);
+
+var _hls = __webpack_require__(/*! hls.js */ "./node_modules/hls.js/dist/hls.js");
+
+var _hls2 = _interopRequireDefault(_hls);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _utils = __webpack_require__(/*! ../../base/utils */ "./src/base/utils.js");
+
+var _log = __webpack_require__(/*! ../../plugins/log */ "./src/plugins/log/index.js");
+
+var _log2 = _interopRequireDefault(_log);
+
+var _error = __webpack_require__(/*! ../../components/error */ "./src/components/error/index.js");
+
+var _error2 = _interopRequireDefault(_error);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var AUTO = -1; // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var HLS = function (_HTML5VideoPlayback) {
+ (0, _inherits3.default)(HLS, _HTML5VideoPlayback);
+ (0, _createClass3.default)(HLS, [{
+ key: 'name',
+ get: function get() {
+ return 'hls';
+ }
+ }, {
+ key: 'levels',
+ get: function get() {
+ return this._levels || [];
+ }
+ }, {
+ key: 'currentLevel',
+ get: function get() {
+ if (this._currentLevel === null || this._currentLevel === undefined) return AUTO;else return this._currentLevel; //0 is a valid level ID
+ },
+ set: function set(id) {
+ this._currentLevel = id;
+ this.trigger(_events2.default.PLAYBACK_LEVEL_SWITCH_START);
+ if (this.options.playback.hlsUseNextLevel) this._hls.nextLevel = this._currentLevel;else this._hls.currentLevel = this._currentLevel;
+ }
+ }, {
+ key: 'isReady',
+ get: function get() {
+ return this._isReadyState;
+ }
+ }, {
+ key: '_startTime',
+ get: function get() {
+ if (this._playbackType === _playback2.default.LIVE && this._playlistType !== 'EVENT') return this._extrapolatedStartTime;
+
+ return this._playableRegionStartTime;
+ }
+ }, {
+ key: '_now',
+ get: function get() {
+ return (0, _utils.now)();
+ }
+
+ // the time in the video element which should represent the start of the sliding window
+ // extrapolated to increase in real time (instead of jumping as the early segments are removed)
+
+ }, {
+ key: '_extrapolatedStartTime',
+ get: function get() {
+ if (!this._localStartTimeCorrelation) return this._playableRegionStartTime;
+
+ var corr = this._localStartTimeCorrelation;
+ var timePassed = this._now - corr.local;
+ var extrapolatedWindowStartTime = (corr.remote + timePassed) / 1000;
+ // cap at the end of the extrapolated window duration
+ return Math.min(extrapolatedWindowStartTime, this._playableRegionStartTime + this._extrapolatedWindowDuration);
+ }
+
+ // the time in the video element which should represent the end of the content
+ // extrapolated to increase in real time (instead of jumping as segments are added)
+
+ }, {
+ key: '_extrapolatedEndTime',
+ get: function get() {
+ var actualEndTime = this._playableRegionStartTime + this._playableRegionDuration;
+ if (!this._localEndTimeCorrelation) return actualEndTime;
+
+ var corr = this._localEndTimeCorrelation;
+ var timePassed = this._now - corr.local;
+ var extrapolatedEndTime = (corr.remote + timePassed) / 1000;
+ return Math.max(actualEndTime - this._extrapolatedWindowDuration, Math.min(extrapolatedEndTime, actualEndTime));
+ }
+ }, {
+ key: '_duration',
+ get: function get() {
+ return this._extrapolatedEndTime - this._startTime;
+ }
+
+ // Returns the duration (seconds) of the window that the extrapolated start time is allowed
+ // to move in before being capped.
+ // The extrapolated start time should never reach the cap at the end of the window as the
+ // window should slide as chunks are removed from the start.
+ // This also applies to the extrapolated end time in the same way.
+ //
+ // If chunks aren't being removed for some reason that the start time will reach and remain fixed at
+ // playableRegionStartTime + extrapolatedWindowDuration
+ //
+ // <-- window duration -->
+ // I.e playableRegionStartTime |-----------------------|
+ // | --> . . .
+ // . --> | --> . .
+ // . . --> | --> .
+ // . . . --> |
+ // . . . .
+ // extrapolatedStartTime
+
+ }, {
+ key: '_extrapolatedWindowDuration',
+ get: function get() {
+ if (this._segmentTargetDuration === null) return 0;
+
+ return this._extrapolatedWindowNumSegments * this._segmentTargetDuration;
+ }
+ }], [{
+ key: 'HLSJS',
+ get: function get() {
+ return _hls2.default;
+ }
+ }]);
+
+ function HLS() {
+ (0, _classCallCheck3.default)(this, HLS);
+
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ // backwards compatibility (TODO: remove on 0.3.0)
+ var _this = (0, _possibleConstructorReturn3.default)(this, _HTML5VideoPlayback.call.apply(_HTML5VideoPlayback, [this].concat(args)));
+
+ _this.options.playback = (0, _extends3.default)({}, _this.options, _this.options.playback);
+ _this._minDvrSize = typeof _this.options.hlsMinimumDvrSize === 'undefined' ? 60 : _this.options.hlsMinimumDvrSize;
+ // The size of the start time extrapolation window measured as a multiple of segments.
+ // Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
+ // removed from the start of the playlist at a time. E.g if the playlist is cached for 10 seconds and new chunks are
+ // added/removed every 5.
+ _this._extrapolatedWindowNumSegments = !_this.options.playback || typeof _this.options.playback.extrapolatedWindowNumSegments === 'undefined' ? 2 : _this.options.playback.extrapolatedWindowNumSegments;
+
+ _this._playbackType = _playback2.default.VOD;
+ _this._lastTimeUpdate = { current: 0, total: 0 };
+ _this._lastDuration = null;
+ // for hls streams which have dvr with a sliding window,
+ // the content at the start of the playlist is removed as new
+ // content is appended at the end.
+ // this means the actual playable start time will increase as the
+ // start content is deleted
+ // For streams with dvr where the entire recording is kept from the
+ // beginning this should stay as 0
+ _this._playableRegionStartTime = 0;
+ // {local, remote} remote is the time in the video element that should represent 0
+ // local is the system time when the 'remote' measurment took place
+ _this._localStartTimeCorrelation = null;
+ // {local, remote} remote is the time in the video element that should represents the end
+ // local is the system time when the 'remote' measurment took place
+ _this._localEndTimeCorrelation = null;
+ // if content is removed from the beginning then this empty area should
+ // be ignored. "playableRegionDuration" excludes the empty area
+ _this._playableRegionDuration = 0;
+ // #EXT-X-PROGRAM-DATE-TIME
+ _this._programDateTime = 0;
+ // true when the actual duration is longer than hlsjs's live sync point
+ // when this is false playableRegionDuration will be the actual duration
+ // when this is true playableRegionDuration will exclude the time after the sync point
+ _this._durationExcludesAfterLiveSyncPoint = false;
+ // #EXT-X-TARGETDURATION
+ _this._segmentTargetDuration = null;
+ // #EXT-X-PLAYLIST-TYPE
+ _this._playlistType = null;
+ _this._recoverAttemptsRemaining = _this.options.hlsRecoverAttempts || 16;
+ return _this;
+ }
+
+ HLS.prototype._setup = function _setup() {
+ var _this2 = this;
+
+ this._ccIsSetup = false;
+ this._ccTracksUpdated = false;
+ this._hls = new _hls2.default((0, _utils.assign)({}, this.options.playback.hlsjsConfig));
+ this._hls.on(_hls2.default.Events.MEDIA_ATTACHED, function () {
+ return _this2._hls.loadSource(_this2.options.src);
+ });
+ this._hls.on(_hls2.default.Events.LEVEL_LOADED, function (evt, data) {
+ return _this2._updatePlaybackType(evt, data);
+ });
+ this._hls.on(_hls2.default.Events.LEVEL_UPDATED, function (evt, data) {
+ return _this2._onLevelUpdated(evt, data);
+ });
+ this._hls.on(_hls2.default.Events.LEVEL_SWITCHING, function (evt, data) {
+ return _this2._onLevelSwitch(evt, data);
+ });
+ this._hls.on(_hls2.default.Events.FRAG_LOADED, function (evt, data) {
+ return _this2._onFragmentLoaded(evt, data);
+ });
+ this._hls.on(_hls2.default.Events.ERROR, function (evt, data) {
+ return _this2._onHLSJSError(evt, data);
+ });
+ this._hls.on(_hls2.default.Events.SUBTITLE_TRACK_LOADED, function (evt, data) {
+ return _this2._onSubtitleLoaded(evt, data);
+ });
+ this._hls.on(_hls2.default.Events.SUBTITLE_TRACKS_UPDATED, function () {
+ return _this2._ccTracksUpdated = true;
+ });
+ this._hls.attachMedia(this.el);
+ };
+
+ HLS.prototype.render = function render() {
+ this._ready();
+ return _HTML5VideoPlayback.prototype.render.call(this);
+ };
+
+ HLS.prototype._ready = function _ready() {
+ this._isReadyState = true;
+ this.trigger(_events2.default.PLAYBACK_READY, this.name);
+ };
+
+ HLS.prototype._recover = function _recover(evt, data, error) {
+ if (!this._recoveredDecodingError) {
+ this._recoveredDecodingError = true;
+ this._hls.recoverMediaError();
+ } else if (!this._recoveredAudioCodecError) {
+ this._recoveredAudioCodecError = true;
+ this._hls.swapAudioCodec();
+ this._hls.recoverMediaError();
+ } else {
+ _log2.default.error('hlsjs: failed to recover', { evt: evt, data: data });
+ error.level = _error2.default.Levels.FATAL;
+ var formattedError = this.createError(error);
+ this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ this.stop();
+ }
+ };
+
+ // override
+
+
+ HLS.prototype._setupSrc = function _setupSrc(srcUrl) {// eslint-disable-line no-unused-vars
+ // this playback manages the src on the video element itself
+ };
+
+ HLS.prototype._startTimeUpdateTimer = function _startTimeUpdateTimer() {
+ var _this3 = this;
+
+ if (this._timeUpdateTimer) return;
+
+ this._timeUpdateTimer = setInterval(function () {
+ _this3._onDurationChange();
+ _this3._onTimeUpdate();
+ }, 100);
+ };
+
+ HLS.prototype._stopTimeUpdateTimer = function _stopTimeUpdateTimer() {
+ if (!this._timeUpdateTimer) return;
+
+ clearInterval(this._timeUpdateTimer);
+ this._timeUpdateTimer = null;
+ };
+
+ HLS.prototype.getProgramDateTime = function getProgramDateTime() {
+ return this._programDateTime;
+ };
+ // the duration on the video element itself should not be used
+ // as this does not necesarily represent the duration of the stream
+ // https://github.com/clappr/clappr/issues/668#issuecomment-157036678
+
+
+ HLS.prototype.getDuration = function getDuration() {
+ return this._duration;
+ };
+
+ HLS.prototype.getCurrentTime = function getCurrentTime() {
+ // e.g. can be < 0 if user pauses near the start
+ // eventually they will then be kicked to the end by hlsjs if they run out of buffer
+ // before the official start time
+ return Math.max(0, this.el.currentTime - this._startTime);
+ };
+
+ // the time that "0" now represents relative to when playback started
+ // for a stream with a sliding window this will increase as content is
+ // removed from the beginning
+
+
+ HLS.prototype.getStartTimeOffset = function getStartTimeOffset() {
+ return this._startTime;
+ };
+
+ HLS.prototype.seekPercentage = function seekPercentage(percentage) {
+ var seekTo = this._duration;
+ if (percentage > 0) seekTo = this._duration * (percentage / 100);
+
+ this.seek(seekTo);
+ };
+
+ HLS.prototype.seek = function seek(time) {
+ if (time < 0) {
+ _log2.default.warn('Attempt to seek to a negative time. Resetting to live point. Use seekToLivePoint() to seek to the live point.');
+ time = this.getDuration();
+ }
+ // assume live if time within 3 seconds of end of stream
+ this.dvrEnabled && this._updateDvr(time < this.getDuration() - 3);
+ time += this._startTime;
+ _HTML5VideoPlayback.prototype.seek.call(this, time);
+ };
+
+ HLS.prototype.seekToLivePoint = function seekToLivePoint() {
+ this.seek(this.getDuration());
+ };
+
+ HLS.prototype._updateDvr = function _updateDvr(status) {
+ this.trigger(_events2.default.PLAYBACK_DVR, status);
+ this.trigger(_events2.default.PLAYBACK_STATS_ADD, { 'dvr': status });
+ };
+
+ HLS.prototype._updateSettings = function _updateSettings() {
+ if (this._playbackType === _playback2.default.VOD) this.settings.left = ['playpause', 'position', 'duration'];else if (this.dvrEnabled) this.settings.left = ['playpause'];else this.settings.left = ['playstop'];
+
+ this.settings.seekEnabled = this.isSeekEnabled();
+ this.trigger(_events2.default.PLAYBACK_SETTINGSUPDATE);
+ };
+
+ HLS.prototype._onHLSJSError = function _onHLSJSError(evt, data) {
+ var error = {
+ code: data.type + '_' + data.details,
+ description: this.name + ' error: type: ' + data.type + ', details: ' + data.details,
+ raw: data
+ };
+ var formattedError = void 0;
+ if (data.response) error.description += ', response: ' + (0, _stringify2.default)(data.response);
+ // only report/handle errors if they are fatal
+ // hlsjs should automatically handle non fatal errors
+ if (data.fatal) {
+ if (this._recoverAttemptsRemaining > 0) {
+ this._recoverAttemptsRemaining -= 1;
+ switch (data.type) {
+ case _hls2.default.ErrorTypes.NETWORK_ERROR:
+ switch (data.details) {
+ // The following network errors cannot be recovered with HLS.startLoad()
+ // For more details, see https://github.com/video-dev/hls.js/blob/master/doc/design.md#error-detection-and-handling
+ // For "level load" fatal errors, see https://github.com/video-dev/hls.js/issues/1138
+ case _hls2.default.ErrorDetails.MANIFEST_LOAD_ERROR:
+ case _hls2.default.ErrorDetails.MANIFEST_LOAD_TIMEOUT:
+ case _hls2.default.ErrorDetails.MANIFEST_PARSING_ERROR:
+ case _hls2.default.ErrorDetails.LEVEL_LOAD_ERROR:
+ case _hls2.default.ErrorDetails.LEVEL_LOAD_TIMEOUT:
+ _log2.default.error('hlsjs: unrecoverable network fatal error.', { evt: evt, data: data });
+ formattedError = this.createError(error);
+ this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ this.stop();
+ break;
+ default:
+ _log2.default.warn('hlsjs: trying to recover from network error.', { evt: evt, data: data });
+ error.level = _error2.default.Levels.WARN;
+ this.createError(error);
+ this._hls.startLoad();
+ break;
+ }
+ break;
+ case _hls2.default.ErrorTypes.MEDIA_ERROR:
+ _log2.default.warn('hlsjs: trying to recover from media error.', { evt: evt, data: data });
+ error.level = _error2.default.Levels.WARN;
+ this.createError(error);
+ this._recover(evt, data, error);
+ break;
+ default:
+ _log2.default.error('hlsjs: could not recover from error.', { evt: evt, data: data });
+ formattedError = this.createError(error);
+ this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ this.stop();
+ break;
+ }
+ } else {
+ _log2.default.error('hlsjs: could not recover from error after maximum number of attempts.', { evt: evt, data: data });
+ formattedError = this.createError(error);
+ this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ this.stop();
+ }
+ } else {
+ // Transforms HLSJS.ErrorDetails.KEY_LOAD_ERROR non-fatal error to
+ // playback fatal error if triggerFatalErrorOnResourceDenied playback
+ // option is set. HLSJS.ErrorTypes.KEY_SYSTEM_ERROR are fatal errors
+ // and therefore already handled.
+ if (this.options.playback.triggerFatalErrorOnResourceDenied && this._keyIsDenied(data)) {
+ _log2.default.error('hlsjs: could not load decrypt key.', { evt: evt, data: data });
+ formattedError = this.createError(error);
+ this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ this.stop();
+ return;
+ }
+
+ error.level = _error2.default.Levels.WARN;
+ this.createError(error);
+ _log2.default.warn('hlsjs: non-fatal error occurred', { evt: evt, data: data });
+ }
+ };
+
+ HLS.prototype._keyIsDenied = function _keyIsDenied(data) {
+ return data.type === _hls2.default.ErrorTypes.NETWORK_ERROR && data.details === _hls2.default.ErrorDetails.KEY_LOAD_ERROR && data.response && data.response.code >= 400;
+ };
+
+ HLS.prototype._onTimeUpdate = function _onTimeUpdate() {
+ var update = { current: this.getCurrentTime(), total: this.getDuration(), firstFragDateTime: this.getProgramDateTime() };
+ var isSame = this._lastTimeUpdate && update.current === this._lastTimeUpdate.current && update.total === this._lastTimeUpdate.total;
+ if (isSame) return;
+
+ this._lastTimeUpdate = update;
+ this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, update, this.name);
+ };
+
+ HLS.prototype._onDurationChange = function _onDurationChange() {
+ var duration = this.getDuration();
+ if (this._lastDuration === duration) return;
+
+ this._lastDuration = duration;
+ _HTML5VideoPlayback.prototype._onDurationChange.call(this);
+ };
+
+ HLS.prototype._onProgress = function _onProgress() {
+ if (!this.el.buffered.length) return;
+
+ var buffered = [];
+ var bufferedPos = 0;
+ for (var i = 0; i < this.el.buffered.length; i++) {
+ buffered = [].concat((0, _toConsumableArray3.default)(buffered), [{
+ // for a stream with sliding window dvr something that is buffered my slide off the start of the timeline
+ start: Math.max(0, this.el.buffered.start(i) - this._playableRegionStartTime),
+ end: Math.max(0, this.el.buffered.end(i) - this._playableRegionStartTime)
+ }]);
+ if (this.el.currentTime >= buffered[i].start && this.el.currentTime <= buffered[i].end) bufferedPos = i;
+ }
+ var progress = {
+ start: buffered[bufferedPos].start,
+ current: buffered[bufferedPos].end,
+ total: this.getDuration()
+ };
+ this.trigger(_events2.default.PLAYBACK_PROGRESS, progress, buffered);
+ };
+
+ HLS.prototype.play = function play() {
+ if (!this._hls) this._setup();
+
+ _HTML5VideoPlayback.prototype.play.call(this);
+ this._startTimeUpdateTimer();
+ };
+
+ HLS.prototype.pause = function pause() {
+ if (!this._hls) return;
+
+ _HTML5VideoPlayback.prototype.pause.call(this);
+ if (this.dvrEnabled) this._updateDvr(true);
+ };
+
+ HLS.prototype.stop = function stop() {
+ this._stopTimeUpdateTimer();
+ if (this._hls) {
+ _HTML5VideoPlayback.prototype.stop.call(this);
+ this._hls.destroy();
+ delete this._hls;
+ }
+ };
+
+ HLS.prototype.destroy = function destroy() {
+ this._stopTimeUpdateTimer();
+ if (this._hls) {
+ this._hls.destroy();
+ delete this._hls;
+ }
+ _HTML5VideoPlayback.prototype.destroy.call(this);
+ };
+
+ HLS.prototype._updatePlaybackType = function _updatePlaybackType(evt, data) {
+ this._playbackType = data.details.live ? _playback2.default.LIVE : _playback2.default.VOD;
+ this._onLevelUpdated(evt, data);
+
+ // Live stream subtitle tracks detection hack (may not immediately available)
+ if (this._ccTracksUpdated && this._playbackType === _playback2.default.LIVE && this.hasClosedCaptionsTracks) this._onSubtitleLoaded();
+ };
+
+ HLS.prototype._fillLevels = function _fillLevels() {
+ this._levels = this._hls.levels.map(function (level, index) {
+ return { id: index, level: level, label: level.bitrate / 1000 + 'Kbps' };
+ });
+ this.trigger(_events2.default.PLAYBACK_LEVELS_AVAILABLE, this._levels);
+ };
+
+ HLS.prototype._onLevelUpdated = function _onLevelUpdated(evt, data) {
+ this._segmentTargetDuration = data.details.targetduration;
+ this._playlistType = data.details.type || null;
+
+ var startTimeChanged = false;
+ var durationChanged = false;
+ var fragments = data.details.fragments;
+ var previousPlayableRegionStartTime = this._playableRegionStartTime;
+ var previousPlayableRegionDuration = this._playableRegionDuration;
+
+ if (fragments.length === 0) return;
+
+ // #EXT-X-PROGRAM-DATE-TIME
+ if (fragments[0].rawProgramDateTime) this._programDateTime = fragments[0].rawProgramDateTime;
+
+ if (this._playableRegionStartTime !== fragments[0].start) {
+ startTimeChanged = true;
+ this._playableRegionStartTime = fragments[0].start;
+ }
+
+ if (startTimeChanged) {
+ if (!this._localStartTimeCorrelation) {
+ // set the correlation to map to middle of the extrapolation window
+ this._localStartTimeCorrelation = {
+ local: this._now,
+ remote: (fragments[0].start + this._extrapolatedWindowDuration / 2) * 1000
+ };
+ } else {
+ // check if the correlation still works
+ var corr = this._localStartTimeCorrelation;
+ var timePassed = this._now - corr.local;
+ // this should point to a time within the extrapolation window
+ var startTime = (corr.remote + timePassed) / 1000;
+ if (startTime < fragments[0].start) {
+ // our start time is now earlier than the first chunk
+ // (maybe the chunk was removed early)
+ // reset correlation so that it sits at the beginning of the first available chunk
+ this._localStartTimeCorrelation = {
+ local: this._now,
+ remote: fragments[0].start * 1000
+ };
+ } else if (startTime > previousPlayableRegionStartTime + this._extrapolatedWindowDuration) {
+ // start time was past the end of the old extrapolation window (so would have been capped)
+ // see if now that time would be inside the window, and if it would be set the correlation
+ // so that it resumes from the time it was at at the end of the old window
+ // update the correlation so that the time starts counting again from the value it's on now
+ this._localStartTimeCorrelation = {
+ local: this._now,
+ remote: Math.max(fragments[0].start, previousPlayableRegionStartTime + this._extrapolatedWindowDuration) * 1000
+ };
+ }
+ }
+ }
+
+ var newDuration = data.details.totalduration;
+ // if it's a live stream then shorten the duration to remove access
+ // to the area after hlsjs's live sync point
+ // seeks to areas after this point sometimes have issues
+ if (this._playbackType === _playback2.default.LIVE) {
+ var fragmentTargetDuration = data.details.targetduration;
+ var hlsjsConfig = this.options.playback.hlsjsConfig || {};
+ var liveSyncDurationCount = hlsjsConfig.liveSyncDurationCount || _hls2.default.DefaultConfig.liveSyncDurationCount;
+ var hiddenAreaDuration = fragmentTargetDuration * liveSyncDurationCount;
+ if (hiddenAreaDuration <= newDuration) {
+ newDuration -= hiddenAreaDuration;
+ this._durationExcludesAfterLiveSyncPoint = true;
+ } else {
+ this._durationExcludesAfterLiveSyncPoint = false;
+ }
+ }
+
+ if (newDuration !== this._playableRegionDuration) {
+ durationChanged = true;
+ this._playableRegionDuration = newDuration;
+ }
+
+ // Note the end time is not the playableRegionDuration
+ // The end time will always increase even if content is removed from the beginning
+ var endTime = fragments[0].start + newDuration;
+ var previousEndTime = previousPlayableRegionStartTime + previousPlayableRegionDuration;
+ var endTimeChanged = endTime !== previousEndTime;
+ if (endTimeChanged) {
+ if (!this._localEndTimeCorrelation) {
+ // set the correlation to map to the end
+ this._localEndTimeCorrelation = {
+ local: this._now,
+ remote: endTime * 1000
+ };
+ } else {
+ // check if the correlation still works
+ var _corr = this._localEndTimeCorrelation;
+ var _timePassed = this._now - _corr.local;
+ // this should point to a time within the extrapolation window from the end
+ var extrapolatedEndTime = (_corr.remote + _timePassed) / 1000;
+ if (extrapolatedEndTime > endTime) {
+ this._localEndTimeCorrelation = {
+ local: this._now,
+ remote: endTime * 1000
+ };
+ } else if (extrapolatedEndTime < endTime - this._extrapolatedWindowDuration) {
+ // our extrapolated end time is now earlier than the extrapolation window from the actual end time
+ // (maybe a chunk became available early)
+ // reset correlation so that it sits at the beginning of the extrapolation window from the end time
+ this._localEndTimeCorrelation = {
+ local: this._now,
+ remote: (endTime - this._extrapolatedWindowDuration) * 1000
+ };
+ } else if (extrapolatedEndTime > previousEndTime) {
+ // end time was past the old end time (so would have been capped)
+ // set the correlation so that it resumes from the time it was at at the end of the old window
+ this._localEndTimeCorrelation = {
+ local: this._now,
+ remote: previousEndTime * 1000
+ };
+ }
+ }
+ }
+
+ // now that the values have been updated call any methods that use on them so they get the updated values
+ // immediately
+ durationChanged && this._onDurationChange();
+ startTimeChanged && this._onProgress();
+ };
+
+ HLS.prototype._onFragmentLoaded = function _onFragmentLoaded(evt, data) {
+ this.trigger(_events2.default.PLAYBACK_FRAGMENT_LOADED, data);
+ };
+
+ HLS.prototype._onSubtitleLoaded = function _onSubtitleLoaded() {
+ // This event may be triggered multiple times
+ // Setup CC only once (disable CC by default)
+ if (!this._ccIsSetup) {
+ this.trigger(_events2.default.PLAYBACK_SUBTITLE_AVAILABLE);
+ var trackId = this._playbackType === _playback2.default.LIVE ? -1 : this.closedCaptionsTrackId;
+ this.closedCaptionsTrackId = trackId;
+ this._ccIsSetup = true;
+ }
+ };
+
+ HLS.prototype._onLevelSwitch = function _onLevelSwitch(evt, data) {
+ if (!this.levels.length) this._fillLevels();
+
+ this.trigger(_events2.default.PLAYBACK_LEVEL_SWITCH_END);
+ this.trigger(_events2.default.PLAYBACK_LEVEL_SWITCH, data);
+ var currentLevel = this._hls.levels[data.level];
+ if (currentLevel) {
+ // TODO should highDefinition be private and maybe have a read only accessor if it's used somewhere
+ this.highDefinition = currentLevel.height >= 720 || currentLevel.bitrate / 1000 >= 2000;
+ this.trigger(_events2.default.PLAYBACK_HIGHDEFINITIONUPDATE, this.highDefinition);
+ this.trigger(_events2.default.PLAYBACK_BITRATE, {
+ height: currentLevel.height,
+ width: currentLevel.width,
+ bandwidth: currentLevel.bitrate,
+ bitrate: currentLevel.bitrate,
+ level: data.level
+ });
+ }
+ };
+
+ HLS.prototype.getPlaybackType = function getPlaybackType() {
+ return this._playbackType;
+ };
+
+ HLS.prototype.isSeekEnabled = function isSeekEnabled() {
+ return this._playbackType === _playback2.default.VOD || this.dvrEnabled;
+ };
+
+ (0, _createClass3.default)(HLS, [{
+ key: 'dvrEnabled',
+ get: function get() {
+ // enabled when:
+ // - the duration does not include content after hlsjs's live sync point
+ // - the playable region duration is longer than the configured duration to enable dvr after
+ // - the playback type is LIVE.
+ return this._durationExcludesAfterLiveSyncPoint && this._duration >= this._minDvrSize && this.getPlaybackType() === _playback2.default.LIVE;
+ }
+ }]);
+ return HLS;
+}(_html5_video2.default);
+
+exports.default = HLS;
+
+
+HLS.canPlay = function (resource, mimeType) {
+ var resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
+ var isHls = resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'm3u8' || (0, _utils.listContainsIgnoreCase)(mimeType, ['application/vnd.apple.mpegurl', 'application/x-mpegURL']);
+
+ return !!(_hls2.default.isSupported() && isHls);
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/hls/index.js":
+/*!************************************!*\
+ !*** ./src/playbacks/hls/index.js ***!
+ \************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _hls = __webpack_require__(/*! ./hls */ "./src/playbacks/hls/hls.js");
+
+var _hls2 = _interopRequireDefault(_hls);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _hls2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/html5_audio/html5_audio.js":
+/*!**************************************************!*\
+ !*** ./src/playbacks/html5_audio/html5_audio.js ***!
+ \**************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _html5_video = __webpack_require__(/*! ../../playbacks/html5_video */ "./src/playbacks/html5_video/index.js");
+
+var _html5_video2 = _interopRequireDefault(_html5_video);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// TODO: remove this playback and change HTML5Video to HTML5Playback (breaking change, only after 0.3.0)
+var HTML5Audio = function (_HTML5Video) {
+ (0, _inherits3.default)(HTML5Audio, _HTML5Video);
+
+ function HTML5Audio() {
+ (0, _classCallCheck3.default)(this, HTML5Audio);
+ return (0, _possibleConstructorReturn3.default)(this, _HTML5Video.apply(this, arguments));
+ }
+
+ HTML5Audio.prototype.updateSettings = function updateSettings() {
+ this.settings.left = ['playpause', 'position', 'duration'];
+ this.settings.seekEnabled = this.isSeekEnabled();
+ this.trigger(_events2.default.PLAYBACK_SETTINGSUPDATE);
+ };
+
+ HTML5Audio.prototype.getPlaybackType = function getPlaybackType() {
+ return _playback2.default.AOD;
+ };
+
+ (0, _createClass3.default)(HTML5Audio, [{
+ key: 'name',
+ get: function get() {
+ return 'html5_audio';
+ }
+ }, {
+ key: 'tagName',
+ get: function get() {
+ return 'audio';
+ }
+ }, {
+ key: 'isAudioOnly',
+ get: function get() {
+ return true;
+ }
+ }]);
+ return HTML5Audio;
+}(_html5_video2.default); // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = HTML5Audio;
+
+
+HTML5Audio.canPlay = function (resourceUrl, mimeType) {
+ var mimetypes = {
+ 'wav': ['audio/wav'],
+ 'mp3': ['audio/mp3', 'audio/mpeg;codecs="mp3"'],
+ 'aac': ['audio/mp4;codecs="mp4a.40.5"'],
+ 'oga': ['audio/ogg']
+ };
+ return _html5_video2.default._canPlay('audio', mimetypes, resourceUrl, mimeType);
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/html5_audio/index.js":
+/*!********************************************!*\
+ !*** ./src/playbacks/html5_audio/index.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _html5_audio = __webpack_require__(/*! ./html5_audio */ "./src/playbacks/html5_audio/html5_audio.js");
+
+var _html5_audio2 = _interopRequireDefault(_html5_audio);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _html5_audio2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/html5_video/html5_video.js":
+/*!**************************************************!*\
+ !*** ./src/playbacks/html5_video/html5_video.js ***!
+ \**************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(process) {
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _from = __webpack_require__(/*! babel-runtime/core-js/array/from */ "./node_modules/babel-runtime/core-js/array/from.js");
+
+var _from2 = _interopRequireDefault(_from);
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _toConsumableArray2 = __webpack_require__(/*! babel-runtime/helpers/toConsumableArray */ "./node_modules/babel-runtime/helpers/toConsumableArray.js");
+
+var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
+
+var _keys = __webpack_require__(/*! babel-runtime/core-js/object/keys */ "./node_modules/babel-runtime/core-js/object/keys.js");
+
+var _keys2 = _interopRequireDefault(_keys);
+
+var _utils = __webpack_require__(/*! ../../base/utils */ "./src/base/utils.js");
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _browser = __webpack_require__(/*! ../../components/browser */ "./src/components/browser/index.js");
+
+var _browser2 = _interopRequireDefault(_browser);
+
+var _error = __webpack_require__(/*! ../../components/error */ "./src/components/error/index.js");
+
+var _error2 = _interopRequireDefault(_error);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _log = __webpack_require__(/*! ../../plugins/log */ "./src/plugins/log/index.js");
+
+var _log2 = _interopRequireDefault(_log);
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _tracks = __webpack_require__(/*! ./public/tracks.html */ "./src/playbacks/html5_video/public/tracks.html");
+
+var _tracks2 = _interopRequireDefault(_tracks);
+
+__webpack_require__(/*! ./public/style.scss */ "./src/playbacks/html5_video/public/style.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var MIMETYPES = {
+ 'mp4': ['avc1.42E01E', 'avc1.58A01E', 'avc1.4D401E', 'avc1.64001E', 'mp4v.20.8', 'mp4v.20.240', 'mp4a.40.2'].map(function (codec) {
+ return 'video/mp4; codecs="' + codec + ', mp4a.40.2"';
+ }),
+ 'ogg': ['video/ogg; codecs="theora, vorbis"', 'video/ogg; codecs="dirac"', 'video/ogg; codecs="theora, speex"'],
+ '3gpp': ['video/3gpp; codecs="mp4v.20.8, samr"'],
+ 'webm': ['video/webm; codecs="vp8, vorbis"'],
+ 'mkv': ['video/x-matroska; codecs="theora, vorbis"'],
+ 'm3u8': ['application/x-mpegurl']
+};
+MIMETYPES['ogv'] = MIMETYPES['ogg'];
+MIMETYPES['3gp'] = MIMETYPES['3gpp'];
+
+var AUDIO_MIMETYPES = {
+ 'wav': ['audio/wav'],
+ 'mp3': ['audio/mp3', 'audio/mpeg;codecs="mp3"'],
+ 'aac': ['audio/mp4;codecs="mp4a.40.5"'],
+ 'oga': ['audio/ogg']
+};
+
+var KNOWN_AUDIO_MIMETYPES = (0, _keys2.default)(AUDIO_MIMETYPES).reduce(function (acc, k) {
+ return [].concat((0, _toConsumableArray3.default)(acc), (0, _toConsumableArray3.default)(AUDIO_MIMETYPES[k]));
+}, []);
+
+var UNKNOWN_ERROR = { code: 'unknown', message: 'unknown'
+
+ // TODO: rename this Playback to HTML5Playback (breaking change, only after 0.3.0)
+};
+var HTML5Video = function (_Playback) {
+ (0, _inherits3.default)(HTML5Video, _Playback);
+ (0, _createClass3.default)(HTML5Video, [{
+ key: 'name',
+ get: function get() {
+ return 'html5_video';
+ }
+ }, {
+ key: 'tagName',
+ get: function get() {
+ return this.isAudioOnly ? 'audio' : 'video';
+ }
+ }, {
+ key: 'isAudioOnly',
+ get: function get() {
+ var resourceUrl = this.options.src;
+ var mimeTypes = HTML5Video._mimeTypesForUrl(resourceUrl, AUDIO_MIMETYPES, this.options.mimeType);
+ return this.options.playback && this.options.playback.audioOnly || this.options.audioOnly || KNOWN_AUDIO_MIMETYPES.indexOf(mimeTypes[0]) >= 0;
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'data-html5-video': ''
+ };
+ }
+ }, {
+ key: 'events',
+ get: function get() {
+ return {
+ 'canplay': '_onCanPlay',
+ 'canplaythrough': '_handleBufferingEvents',
+ 'durationchange': '_onDurationChange',
+ 'ended': '_onEnded',
+ 'error': '_onError',
+ 'loadeddata': '_onLoadedData',
+ 'loadedmetadata': '_onLoadedMetadata',
+ 'pause': '_onPause',
+ 'playing': '_onPlaying',
+ 'progress': '_onProgress',
+ 'seeking': '_onSeeking',
+ 'seeked': '_onSeeked',
+ 'stalled': '_handleBufferingEvents',
+ 'timeupdate': '_onTimeUpdate',
+ 'waiting': '_onWaiting'
+ };
+ }
+
+ /**
+ * Determine if the playback has ended.
+ * @property ended
+ * @type Boolean
+ */
+
+ }, {
+ key: 'ended',
+ get: function get() {
+ return this.el.ended;
+ }
+
+ /**
+ * Determine if the playback is having to buffer in order for
+ * playback to be smooth.
+ * This is related to the PLAYBACK_BUFFERING and PLAYBACK_BUFFERFULL events
+ * @property buffering
+ * @type Boolean
+ */
+
+ }, {
+ key: 'buffering',
+ get: function get() {
+ return this._isBuffering;
+ }
+ }]);
+
+ function HTML5Video() {
+ (0, _classCallCheck3.default)(this, HTML5Video);
+
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _Playback.call.apply(_Playback, [this].concat(args)));
+
+ _this._destroyed = false;
+ _this._loadStarted = false;
+ _this._isBuffering = false;
+ _this._playheadMoving = false;
+ _this._playheadMovingTimer = null;
+ _this._stopped = false;
+ _this._ccTrackId = -1;
+ _this._setupSrc(_this.options.src);
+ // backwards compatibility (TODO: remove on 0.3.0)
+ _this.options.playback || (_this.options.playback = _this.options || {});
+ _this.options.playback.disableContextMenu = _this.options.playback.disableContextMenu || _this.options.disableVideoTagContextMenu;
+
+ var playbackConfig = _this.options.playback;
+ var preload = playbackConfig.preload || (_browser2.default.isSafari ? 'auto' : _this.options.preload);
+
+ var posterUrl = void 0; // FIXME: poster plugin should always convert poster to object with expected properties ?
+ if (_this.options.poster) {
+ if (typeof _this.options.poster === 'string') posterUrl = _this.options.poster;else if (typeof _this.options.poster.url === 'string') posterUrl = _this.options.poster.url;
+ }
+
+ _clapprZepto2.default.extend(_this.el, {
+ muted: _this.options.mute,
+ defaultMuted: _this.options.mute,
+ loop: _this.options.loop,
+ poster: posterUrl,
+ preload: preload || 'metadata',
+ controls: (playbackConfig.controls || _this.options.useVideoTagDefaultControls) && 'controls',
+ crossOrigin: playbackConfig.crossOrigin,
+ 'x-webkit-playsinline': playbackConfig.playInline
+ });
+
+ playbackConfig.playInline && _this.$el.attr({ playsinline: 'playsinline' });
+ playbackConfig.crossOrigin && _this.$el.attr({ crossorigin: playbackConfig.crossOrigin });
+
+ // TODO should settings be private?
+ _this.settings = { default: ['seekbar'] };
+ _this.settings.left = ['playpause', 'position', 'duration'];
+ _this.settings.right = ['fullscreen', 'volume', 'hd-indicator'];
+
+ playbackConfig.externalTracks && _this._setupExternalTracks(playbackConfig.externalTracks);
+
+ _this.options.autoPlay && _this.attemptAutoPlay();
+ return _this;
+ }
+
+ // See Playback.attemptAutoPlay()
+
+
+ HTML5Video.prototype.attemptAutoPlay = function attemptAutoPlay() {
+ var _this2 = this;
+
+ this.canAutoPlay(function (result, error) {
+ error && _log2.default.warn(_this2.name, 'autoplay error.', { result: result, error: error });
+
+ // https://github.com/clappr/clappr/issues/1076
+ result && process.nextTick(function () {
+ return !_this2._destroyed && _this2.play();
+ });
+ });
+ };
+
+ // See Playback.canAutoPlay()
+
+
+ HTML5Video.prototype.canAutoPlay = function canAutoPlay(cb) {
+ if (this.options.disableCanAutoPlay) cb(true, null);
+
+ var opts = {
+ timeout: this.options.autoPlayTimeout || 500,
+ inline: this.options.playback.playInline || false,
+ muted: this.options.mute || false // Known issue: mediacontrols may asynchronously mute video
+
+
+ // Use current video element if recycling feature enabled with mobile devices
+ };if (_browser2.default.isMobile && _utils.DomRecycler.options.recycleVideo) opts.element = this.el;
+
+ // Desktop browser autoplay policy may require user action
+ // Mobile browser autoplay require user consent and video recycling feature enabled
+ // It may returns a false positive with source-less player consent
+ (0, _utils.canAutoPlayMedia)(cb, opts);
+ };
+
+ HTML5Video.prototype._setupExternalTracks = function _setupExternalTracks(tracks) {
+ this._externalTracks = tracks.map(function (track) {
+ return {
+ kind: track.kind || 'subtitles', // Default is 'subtitles'
+ label: track.label,
+ lang: track.lang,
+ src: track.src
+ };
+ });
+ };
+
+ /**
+ * Sets the source url on the element, and also the 'src' property.
+ * @method setupSrc
+ * @private
+ * @param {String} srcUrl The source URL.
+ */
+
+
+ HTML5Video.prototype._setupSrc = function _setupSrc(srcUrl) {
+ if (this.el.src === srcUrl) return;
+
+ this._ccIsSetup = false;
+ this.el.src = srcUrl;
+ this._src = this.el.src;
+ };
+
+ HTML5Video.prototype._onLoadedMetadata = function _onLoadedMetadata(e) {
+ this._handleBufferingEvents();
+ this.trigger(_events2.default.PLAYBACK_LOADEDMETADATA, { duration: e.target.duration, data: e });
+ this._updateSettings();
+ var autoSeekFromUrl = typeof this._options.autoSeekFromUrl === 'undefined' || this._options.autoSeekFromUrl;
+ if (this.getPlaybackType() !== _playback2.default.LIVE && autoSeekFromUrl) this._checkInitialSeek();
+ };
+
+ HTML5Video.prototype._onDurationChange = function _onDurationChange() {
+ this._updateSettings();
+ this._onTimeUpdate();
+ // onProgress uses the duration
+ this._onProgress();
+ };
+
+ HTML5Video.prototype._updateSettings = function _updateSettings() {
+ // we can't figure out if hls resource is VoD or not until it is being loaded or duration has changed.
+ // that's why we check it again and update media control accordingly.
+ if (this.getPlaybackType() === _playback2.default.VOD || this.getPlaybackType() === _playback2.default.AOD) this.settings.left = ['playpause', 'position', 'duration'];else this.settings.left = ['playstop'];
+
+ this.settings.seekEnabled = this.isSeekEnabled();
+ this.trigger(_events2.default.PLAYBACK_SETTINGSUPDATE);
+ };
+
+ HTML5Video.prototype.isSeekEnabled = function isSeekEnabled() {
+ return isFinite(this.getDuration());
+ };
+
+ HTML5Video.prototype.getPlaybackType = function getPlaybackType() {
+ var onDemandType = this.tagName === 'audio' ? _playback2.default.AOD : _playback2.default.VOD;
+ return [0, undefined, Infinity].indexOf(this.el.duration) >= 0 ? _playback2.default.LIVE : onDemandType;
+ };
+
+ HTML5Video.prototype.isHighDefinitionInUse = function isHighDefinitionInUse() {
+ return false;
+ };
+
+ // On mobile device, HTML5 video element "retains" user action consent if
+ // load() method is called. See Player.consent().
+
+
+ HTML5Video.prototype.consent = function consent() {
+ if (!this.isPlaying()) {
+ _Playback.prototype.consent.call(this);
+ this.el.load();
+ }
+ };
+
+ HTML5Video.prototype.play = function play() {
+ this.trigger(_events2.default.PLAYBACK_PLAY_INTENT);
+ this._stopped = false;
+ this._setupSrc(this._src);
+ this._handleBufferingEvents();
+ var promise = this.el.play();
+ // For more details, see https://developers.google.com/web/updates/2016/03/play-returns-promise
+ if (promise && promise.catch) promise.catch(function () {});
+ };
+
+ HTML5Video.prototype.pause = function pause() {
+ this.el.pause();
+ };
+
+ HTML5Video.prototype.stop = function stop() {
+ this.pause();
+ this._stopped = true;
+ // src will be added again in play()
+ this.el.removeAttribute('src');
+ this.el.load(); // load with no src to stop loading of the previous source and avoid leaks
+ this._stopPlayheadMovingChecks();
+ this._handleBufferingEvents();
+ this.trigger(_events2.default.PLAYBACK_STOP);
+ };
+
+ HTML5Video.prototype.volume = function volume(value) {
+ if (value === 0) {
+ this.$el.attr({ muted: 'true' });
+ this.el.muted = true;
+ } else {
+ this.$el.attr({ muted: null });
+ this.el.muted = false;
+ this.el.volume = value / 100;
+ }
+ };
+
+ /**
+ * @deprecated
+ * @private
+ */
+
+
+ HTML5Video.prototype.mute = function mute() {
+ this.el.muted = true;
+ };
+
+ /**
+ * @deprecated
+ * @private
+ */
+
+
+ HTML5Video.prototype.unmute = function unmute() {
+ this.el.muted = false;
+ };
+
+ HTML5Video.prototype.isMuted = function isMuted() {
+ return this.el.muted === true || this.el.volume === 0;
+ };
+
+ HTML5Video.prototype.isPlaying = function isPlaying() {
+ return !this.el.paused && !this.el.ended;
+ };
+
+ HTML5Video.prototype._startPlayheadMovingChecks = function _startPlayheadMovingChecks() {
+ if (this._playheadMovingTimer !== null) return;
+
+ this._playheadMovingTimeOnCheck = null;
+ this._determineIfPlayheadMoving();
+ this._playheadMovingTimer = setInterval(this._determineIfPlayheadMoving.bind(this), 500);
+ };
+
+ HTML5Video.prototype._stopPlayheadMovingChecks = function _stopPlayheadMovingChecks() {
+ if (this._playheadMovingTimer === null) return;
+
+ clearInterval(this._playheadMovingTimer);
+ this._playheadMovingTimer = null;
+ this._playheadMoving = false;
+ };
+
+ HTML5Video.prototype._determineIfPlayheadMoving = function _determineIfPlayheadMoving() {
+ var before = this._playheadMovingTimeOnCheck;
+ var now = this.el.currentTime;
+ this._playheadMoving = before !== now;
+ this._playheadMovingTimeOnCheck = now;
+ this._handleBufferingEvents();
+ };
+
+ // this seems to happen when the user is having to wait
+ // for something to happen AFTER A USER INTERACTION
+ // e.g the player might be buffering, but when `play()` is called
+ // only at this point will this be called.
+ // Or the user may seek somewhere but the new area requires buffering,
+ // so it will fire then as well.
+ // On devices where playing is blocked until requested with a user action,
+ // buffering may start, but never finish until the user initiates a play,
+ // but this only happens when play is actually requested
+
+
+ HTML5Video.prototype._onWaiting = function _onWaiting() {
+ this._loadStarted = true;
+ this._handleBufferingEvents();
+ };
+
+ // called after the first frame has loaded
+ // note this doesn't fire on ios before the user has requested play
+ // ideally the "loadstart" event would be used instead, but this fires
+ // before a user has requested play on iOS, and also this is always fired
+ // even if the preload setting is "none". In both these cases this causes
+ // infinite buffering until the user does something which isn't great.
+
+
+ HTML5Video.prototype._onLoadedData = function _onLoadedData() {
+ this._loadStarted = true;
+ this._handleBufferingEvents();
+ };
+
+ // note this doesn't fire on ios before user has requested play
+
+
+ HTML5Video.prototype._onCanPlay = function _onCanPlay() {
+ this._handleBufferingEvents();
+ };
+
+ HTML5Video.prototype._onPlaying = function _onPlaying() {
+ this._checkForClosedCaptions();
+ this._startPlayheadMovingChecks();
+ this._handleBufferingEvents();
+ this.trigger(_events2.default.PLAYBACK_PLAY);
+ };
+
+ HTML5Video.prototype._onPause = function _onPause() {
+ this._stopPlayheadMovingChecks();
+ this._handleBufferingEvents();
+ this.trigger(_events2.default.PLAYBACK_PAUSE);
+ };
+
+ HTML5Video.prototype._onSeeking = function _onSeeking() {
+ this._handleBufferingEvents();
+ this.trigger(_events2.default.PLAYBACK_SEEK);
+ };
+
+ HTML5Video.prototype._onSeeked = function _onSeeked() {
+ this._handleBufferingEvents();
+ this.trigger(_events2.default.PLAYBACK_SEEKED);
+ };
+
+ HTML5Video.prototype._onEnded = function _onEnded() {
+ this._handleBufferingEvents();
+ this.trigger(_events2.default.PLAYBACK_ENDED, this.name);
+ };
+
+ // The playback should be classed as buffering if the following are true:
+ // - the ready state is less then HAVE_FUTURE_DATA or the playhead isn't moving and it should be
+ // - the media hasn't "ended",
+ // - the media hasn't been stopped
+ // - loading has started
+
+
+ HTML5Video.prototype._handleBufferingEvents = function _handleBufferingEvents() {
+ var playheadShouldBeMoving = !this.el.ended && !this.el.paused;
+ var buffering = this._loadStarted && !this.el.ended && !this._stopped && (playheadShouldBeMoving && !this._playheadMoving || this.el.readyState < this.el.HAVE_FUTURE_DATA);
+ if (this._isBuffering !== buffering) {
+ this._isBuffering = buffering;
+ if (buffering) this.trigger(_events2.default.PLAYBACK_BUFFERING, this.name);else this.trigger(_events2.default.PLAYBACK_BUFFERFULL, this.name);
+ }
+ };
+
+ HTML5Video.prototype._onError = function _onError() {
+ var _ref = this.el.error || UNKNOWN_ERROR,
+ code = _ref.code,
+ message = _ref.message;
+
+ var isUnknownError = code === UNKNOWN_ERROR.code;
+
+ var formattedError = this.createError({
+ code: code,
+ description: message,
+ raw: this.el.error,
+ level: isUnknownError ? _error2.default.Levels.WARN : _error2.default.Levels.FATAL
+ });
+
+ if (isUnknownError) _log2.default.warn(this.name, 'HTML5 unknown error: ', formattedError);else this.trigger(_events2.default.PLAYBACK_ERROR, formattedError);
+ };
+
+ HTML5Video.prototype.destroy = function destroy() {
+ this._destroyed = true;
+ this.handleTextTrackChange && this.el.textTracks.removeEventListener('change', this.handleTextTrackChange);
+ _Playback.prototype.destroy.call(this);
+ this.el.removeAttribute('src');
+ this.el.load(); // load with no src to stop loading of the previous source and avoid leaks
+ this._src = null;
+ _utils.DomRecycler.garbage(this.$el);
+ };
+
+ HTML5Video.prototype.seek = function seek(time) {
+ this.el.currentTime = time;
+ };
+
+ HTML5Video.prototype.seekPercentage = function seekPercentage(percentage) {
+ var time = this.el.duration * (percentage / 100);
+ this.seek(time);
+ };
+
+ HTML5Video.prototype._checkInitialSeek = function _checkInitialSeek() {
+ var seekTime = (0, _utils.seekStringToSeconds)();
+ if (seekTime !== 0) this.seek(seekTime);
+ };
+
+ HTML5Video.prototype.getCurrentTime = function getCurrentTime() {
+ return this.el.currentTime;
+ };
+
+ HTML5Video.prototype.getDuration = function getDuration() {
+ return this.el.duration;
+ };
+
+ HTML5Video.prototype._onTimeUpdate = function _onTimeUpdate() {
+ if (this.getPlaybackType() === _playback2.default.LIVE) this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: 1, total: 1 }, this.name);else this.trigger(_events2.default.PLAYBACK_TIMEUPDATE, { current: this.el.currentTime, total: this.el.duration }, this.name);
+ };
+
+ HTML5Video.prototype._onProgress = function _onProgress() {
+ if (!this.el.buffered.length) return;
+
+ var buffered = [];
+ var bufferedPos = 0;
+ for (var i = 0; i < this.el.buffered.length; i++) {
+ buffered = [].concat((0, _toConsumableArray3.default)(buffered), [{ start: this.el.buffered.start(i), end: this.el.buffered.end(i) }]);
+ if (this.el.currentTime >= buffered[i].start && this.el.currentTime <= buffered[i].end) bufferedPos = i;
+ }
+ var progress = {
+ start: buffered[bufferedPos].start,
+ current: buffered[bufferedPos].end,
+ total: this.el.duration
+ };
+ this.trigger(_events2.default.PLAYBACK_PROGRESS, progress, buffered);
+ };
+
+ HTML5Video.prototype._typeFor = function _typeFor(src) {
+ var mimeTypes = HTML5Video._mimeTypesForUrl(src, MIMETYPES, this.options.mimeType);
+ if (mimeTypes.length === 0) mimeTypes = HTML5Video._mimeTypesForUrl(src, AUDIO_MIMETYPES, this.options.mimeType);
+
+ var mimeType = mimeTypes[0] || '';
+ return mimeType.split(';')[0];
+ };
+
+ HTML5Video.prototype._ready = function _ready() {
+ if (this._isReadyState) return;
+
+ this._isReadyState = true;
+ this.trigger(_events2.default.PLAYBACK_READY, this.name);
+ };
+
+ HTML5Video.prototype._checkForClosedCaptions = function _checkForClosedCaptions() {
+ // Check if CC available only if current playback is HTML5Video
+ if (this.isHTML5Video && !this._ccIsSetup) {
+ if (this.hasClosedCaptionsTracks) {
+ this.trigger(_events2.default.PLAYBACK_SUBTITLE_AVAILABLE);
+ var trackId = this.closedCaptionsTrackId;
+ this.closedCaptionsTrackId = trackId;
+ this.handleTextTrackChange = this._handleTextTrackChange.bind(this);
+ this.el.textTracks.addEventListener('change', this.handleTextTrackChange);
+ }
+ this._ccIsSetup = true;
+ }
+ };
+
+ HTML5Video.prototype._handleTextTrackChange = function _handleTextTrackChange() {
+ var tracks = this.closedCaptionsTracks;
+ var track = tracks.find(function (track) {
+ return track.track.mode === 'showing';
+ }) || { id: -1 };
+
+ if (this._ccTrackId !== track.id) {
+ this._ccTrackId = track.id;
+ this.trigger(_events2.default.PLAYBACK_SUBTITLE_CHANGED, {
+ id: track.id
+ });
+ }
+ };
+
+ HTML5Video.prototype.render = function render() {
+ if (this.options.playback.disableContextMenu) {
+ this.$el.on('contextmenu', function () {
+ return false;
+ });
+ }
+
+ if (this._externalTracks && this._externalTracks.length > 0) {
+ this.$el.html(this.template({
+ tracks: this._externalTracks
+ }));
+ }
+
+ this._ready();
+ return this;
+ };
+
+ (0, _createClass3.default)(HTML5Video, [{
+ key: 'isReady',
+ get: function get() {
+ return this._isReadyState;
+ }
+ }, {
+ key: 'isHTML5Video',
+ get: function get() {
+ return this.name === HTML5Video.prototype.name;
+ }
+ }, {
+ key: 'closedCaptionsTracks',
+ get: function get() {
+ var id = 0;
+ var trackId = function trackId() {
+ return id++;
+ };
+ var textTracks = this.el.textTracks ? (0, _from2.default)(this.el.textTracks) : [];
+
+ return textTracks.filter(function (track) {
+ return track.kind === 'subtitles' || track.kind === 'captions';
+ }).map(function (track) {
+ return { id: trackId(), name: track.label, track: track };
+ });
+ }
+ }, {
+ key: 'closedCaptionsTrackId',
+ get: function get() {
+ return this._ccTrackId;
+ },
+ set: function set(trackId) {
+ if (!(0, _utils.isNumber)(trackId)) return;
+
+ var tracks = this.closedCaptionsTracks;
+ var showingTrack = void 0;
+
+ // Note: -1 is for hide all tracks
+ if (trackId !== -1) {
+ showingTrack = tracks.find(function (track) {
+ return track.id === trackId;
+ });
+ if (!showingTrack) return; // Track id not found
+
+ if (showingTrack.track.mode === 'showing') return; // Track already showing
+ }
+
+ // Since it is possible to display multiple tracks,
+ // ensure that all tracks are hidden.
+ tracks.filter(function (track) {
+ return track.track.mode !== 'hidden';
+ }).forEach(function (track) {
+ return track.track.mode = 'hidden';
+ });
+
+ showingTrack && (showingTrack.track.mode = 'showing');
+
+ this._ccTrackId = trackId;
+ this.trigger(_events2.default.PLAYBACK_SUBTITLE_CHANGED, {
+ id: trackId
+ });
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_tracks2.default);
+ }
+ }]);
+ return HTML5Video;
+}(_playback2.default);
+
+exports.default = HTML5Video;
+
+
+HTML5Video._mimeTypesForUrl = function (resourceUrl, mimeTypesByExtension, mimeType) {
+ var extension = (resourceUrl.split('?')[0].match(/.*\.(.*)$/) || [])[1];
+ var mimeTypes = mimeType || extension && mimeTypesByExtension[extension.toLowerCase()] || [];
+ return mimeTypes.constructor === Array ? mimeTypes : [mimeTypes];
+};
+
+HTML5Video._canPlay = function (type, mimeTypesByExtension, resourceUrl, mimeType) {
+ var mimeTypes = HTML5Video._mimeTypesForUrl(resourceUrl, mimeTypesByExtension, mimeType);
+ var media = document.createElement(type);
+ return !!mimeTypes.filter(function (mediaType) {
+ return !!media.canPlayType(mediaType).replace(/no/, '');
+ })[0];
+};
+
+HTML5Video.canPlay = function (resourceUrl, mimeType) {
+ return HTML5Video._canPlay('audio', AUDIO_MIMETYPES, resourceUrl, mimeType) || HTML5Video._canPlay('video', MIMETYPES, resourceUrl, mimeType);
+};
+module.exports = exports['default'];
+/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../../node_modules/node-libs-browser/node_modules/process/browser.js */ "./node_modules/node-libs-browser/node_modules/process/browser.js")))
+
+/***/ }),
+
+/***/ "./src/playbacks/html5_video/index.js":
+/*!********************************************!*\
+ !*** ./src/playbacks/html5_video/index.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _html5_video = __webpack_require__(/*! ./html5_video */ "./src/playbacks/html5_video/html5_video.js");
+
+var _html5_video2 = _interopRequireDefault(_html5_video);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _html5_video2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/html5_video/public/style.scss":
+/*!*****************************************************!*\
+ !*** ./src/playbacks/html5_video/public/style.scss ***!
+ \*****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./style.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/playbacks/html5_video/public/style.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/playbacks/html5_video/public/tracks.html":
+/*!******************************************************!*\
+ !*** ./src/playbacks/html5_video/public/tracks.html ***!
+ \******************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "<% for (var i = 0; i < tracks.length; i++) { %>\n \" kind=\"<%= tracks[i].kind %>\" label=\"<%= tracks[i].label %>\" srclang=\"<%= tracks[i].lang %>\" src=\"<%= tracks[i].src %>\" />\n<% }; %>\n";
+
+/***/ }),
+
+/***/ "./src/playbacks/html_img/html_img.js":
+/*!********************************************!*\
+ !*** ./src/playbacks/html_img/html_img.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+__webpack_require__(/*! ./public/style.scss */ "./src/playbacks/html_img/public/style.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var HTMLImg = function (_Playback) {
+ (0, _inherits3.default)(HTMLImg, _Playback);
+
+ HTMLImg.prototype.getPlaybackType = function getPlaybackType() {
+ return _playback2.default.NO_OP;
+ };
+
+ (0, _createClass3.default)(HTMLImg, [{
+ key: 'name',
+ get: function get() {
+ return 'html_img';
+ }
+ }, {
+ key: 'tagName',
+ get: function get() {
+ return 'img';
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'data-html-img': ''
+ };
+ }
+ }, {
+ key: 'events',
+ get: function get() {
+ return {
+ 'load': '_onLoad',
+ 'abort': '_onError',
+ 'error': '_onError'
+ };
+ }
+ }]);
+
+ function HTMLImg(params) {
+ (0, _classCallCheck3.default)(this, HTMLImg);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _Playback.call(this, params));
+
+ _this.el.src = params.src;
+ return _this;
+ }
+
+ HTMLImg.prototype.render = function render() {
+ this.trigger(_events2.default.PLAYBACK_READY, this.name);
+ return this;
+ };
+
+ HTMLImg.prototype._onLoad = function _onLoad() {
+ this.trigger(_events2.default.PLAYBACK_ENDED, this.name);
+ };
+
+ HTMLImg.prototype._onError = function _onError(evt) {
+ var m = evt.type === 'error' ? 'load error' : 'loading aborted';
+ this.trigger(_events2.default.PLAYBACK_ERROR, { message: m }, this.name);
+ };
+
+ return HTMLImg;
+}(_playback2.default); // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = HTMLImg;
+
+
+HTMLImg.canPlay = function (resource) {
+ return (/\.(png|jpg|jpeg|gif|bmp|tiff|pgm|pnm|webp)(|\?.*)$/i.test(resource)
+ );
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/html_img/index.js":
+/*!*****************************************!*\
+ !*** ./src/playbacks/html_img/index.js ***!
+ \*****************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _html_img = __webpack_require__(/*! ./html_img */ "./src/playbacks/html_img/html_img.js");
+
+var _html_img2 = _interopRequireDefault(_html_img);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _html_img2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/html_img/public/style.scss":
+/*!**************************************************!*\
+ !*** ./src/playbacks/html_img/public/style.scss ***!
+ \**************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./style.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/playbacks/html_img/public/style.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/playbacks/no_op/index.js":
+/*!**************************************!*\
+ !*** ./src/playbacks/no_op/index.js ***!
+ \**************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _no_op = __webpack_require__(/*! ./no_op */ "./src/playbacks/no_op/no_op.js");
+
+var _no_op2 = _interopRequireDefault(_no_op);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _no_op2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/no_op/no_op.js":
+/*!**************************************!*\
+ !*** ./src/playbacks/no_op/no_op.js ***!
+ \**************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _utils = __webpack_require__(/*! ../../base/utils */ "./src/base/utils.js");
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _error = __webpack_require__(/*! ./public/error.html */ "./src/playbacks/no_op/public/error.html");
+
+var _error2 = _interopRequireDefault(_error);
+
+__webpack_require__(/*! ./public/style.scss */ "./src/playbacks/no_op/public/style.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var NoOp = function (_Playback) {
+ (0, _inherits3.default)(NoOp, _Playback);
+ (0, _createClass3.default)(NoOp, [{
+ key: 'name',
+ get: function get() {
+ return 'no_op';
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_error2.default);
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return { 'data-no-op': '' };
+ }
+ }]);
+
+ function NoOp() {
+ (0, _classCallCheck3.default)(this, NoOp);
+
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _Playback.call.apply(_Playback, [this].concat(args)));
+
+ _this._noiseFrameNum = -1;
+ return _this;
+ }
+
+ NoOp.prototype.render = function render() {
+ var playbackNotSupported = this.options.playbackNotSupportedMessage || this.i18n.t('playback_not_supported');
+ this.$el.html(this.template({ message: playbackNotSupported }));
+ this.trigger(_events2.default.PLAYBACK_READY, this.name);
+ var showForNoOp = !!(this.options.poster && this.options.poster.showForNoOp);
+ if (this.options.autoPlay || !showForNoOp) this._animate();
+
+ return this;
+ };
+
+ NoOp.prototype._noise = function _noise() {
+ this._noiseFrameNum = (this._noiseFrameNum + 1) % 5;
+ if (this._noiseFrameNum) {
+ // only update noise every 5 frames to save cpu
+ return;
+ }
+
+ var idata = this.context.createImageData(this.context.canvas.width, this.context.canvas.height);
+ var buffer32 = void 0;
+ try {
+ buffer32 = new Uint32Array(idata.data.buffer);
+ } catch (err) {
+ buffer32 = new Uint32Array(this.context.canvas.width * this.context.canvas.height * 4);
+ var data = idata.data;
+ for (var i = 0; i < data.length; i++) {
+ buffer32[i] = data[i];
+ }
+ }
+
+ var len = buffer32.length,
+ m = Math.random() * 6 + 4;
+ var run = 0,
+ color = 0;
+ for (var _i = 0; _i < len;) {
+ if (run < 0) {
+ run = m * Math.random();
+ var p = Math.pow(Math.random(), 0.4);
+ color = 255 * p << 24;
+ }
+ run -= 1;
+ buffer32[_i++] = color;
+ }
+ this.context.putImageData(idata, 0, 0);
+ };
+
+ NoOp.prototype._loop = function _loop() {
+ var _this2 = this;
+
+ if (this._stop) return;
+
+ this._noise();
+ this._animationHandle = (0, _utils.requestAnimationFrame)(function () {
+ return _this2._loop();
+ });
+ };
+
+ NoOp.prototype.destroy = function destroy() {
+ if (this._animationHandle) {
+ (0, _utils.cancelAnimationFrame)(this._animationHandle);
+ this._stop = true;
+ }
+ };
+
+ NoOp.prototype._animate = function _animate() {
+ this.canvas = this.$el.find('canvas[data-no-op-canvas]')[0];
+ this.context = this.canvas.getContext('2d');
+ this._loop();
+ };
+
+ return NoOp;
+}(_playback2.default);
+
+exports.default = NoOp;
+
+
+NoOp.canPlay = function (source) {
+ // eslint-disable-line no-unused-vars
+ return true;
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/playbacks/no_op/public/error.html":
+/*!***********************************************!*\
+ !*** ./src/playbacks/no_op/public/error.html ***!
+ \***********************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " \n<%=message%>
\n";
+
+/***/ }),
+
+/***/ "./src/playbacks/no_op/public/style.scss":
+/*!***********************************************!*\
+ !*** ./src/playbacks/no_op/public/style.scss ***!
+ \***********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./style.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/playbacks/no_op/public/style.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/click_to_pause/click_to_pause.js":
+/*!******************************************************!*\
+ !*** ./src/plugins/click_to_pause/click_to_pause.js ***!
+ \******************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _container_plugin = __webpack_require__(/*! ../../base/container_plugin */ "./src/base/container_plugin.js");
+
+var _container_plugin2 = _interopRequireDefault(_container_plugin);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var ClickToPausePlugin = function (_ContainerPlugin) {
+ (0, _inherits3.default)(ClickToPausePlugin, _ContainerPlugin);
+ (0, _createClass3.default)(ClickToPausePlugin, [{
+ key: 'name',
+ get: function get() {
+ return 'click_to_pause';
+ }
+ }]);
+
+ function ClickToPausePlugin(container) {
+ (0, _classCallCheck3.default)(this, ClickToPausePlugin);
+ return (0, _possibleConstructorReturn3.default)(this, _ContainerPlugin.call(this, container));
+ }
+
+ ClickToPausePlugin.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.container, _events2.default.CONTAINER_CLICK, this.click);
+ this.listenTo(this.container, _events2.default.CONTAINER_SETTINGSUPDATE, this.settingsUpdate);
+ };
+
+ ClickToPausePlugin.prototype.click = function click() {
+ if (this.container.getPlaybackType() !== _playback2.default.LIVE || this.container.isDvrEnabled()) {
+ if (this.container.isPlaying()) this.container.pause();else this.container.play();
+ }
+ };
+
+ ClickToPausePlugin.prototype.settingsUpdate = function settingsUpdate() {
+ var pointerEnabled = this.container.getPlaybackType() !== _playback2.default.LIVE || this.container.isDvrEnabled();
+ if (pointerEnabled === this.pointerEnabled) return;
+
+ var method = pointerEnabled ? 'addClass' : 'removeClass';
+ this.container.$el[method]('pointer-enabled');
+ this.pointerEnabled = pointerEnabled;
+ };
+
+ return ClickToPausePlugin;
+}(_container_plugin2.default); //Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = ClickToPausePlugin;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/click_to_pause/index.js":
+/*!*********************************************!*\
+ !*** ./src/plugins/click_to_pause/index.js ***!
+ \*********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _click_to_pause = __webpack_require__(/*! ./click_to_pause */ "./src/plugins/click_to_pause/click_to_pause.js");
+
+var _click_to_pause2 = _interopRequireDefault(_click_to_pause);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _click_to_pause2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/closed_captions/closed_captions.js":
+/*!********************************************************!*\
+ !*** ./src/plugins/closed_captions/closed_captions.js ***!
+ \********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _ui_core_plugin = __webpack_require__(/*! ../../base/ui_core_plugin */ "./src/base/ui_core_plugin.js");
+
+var _ui_core_plugin2 = _interopRequireDefault(_ui_core_plugin);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _cc = __webpack_require__(/*! ../../icons/09-cc.svg */ "./src/icons/09-cc.svg");
+
+var _cc2 = _interopRequireDefault(_cc);
+
+var _closed_captions = __webpack_require__(/*! ./public/closed_captions.html */ "./src/plugins/closed_captions/public/closed_captions.html");
+
+var _closed_captions2 = _interopRequireDefault(_closed_captions);
+
+__webpack_require__(/*! ./public/closed_captions.scss */ "./src/plugins/closed_captions/public/closed_captions.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var ClosedCaptions = function (_UICorePlugin) {
+ (0, _inherits3.default)(ClosedCaptions, _UICorePlugin);
+ (0, _createClass3.default)(ClosedCaptions, [{
+ key: 'name',
+ get: function get() {
+ return 'closed_captions';
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_closed_captions2.default);
+ }
+ }, {
+ key: 'events',
+ get: function get() {
+ return {
+ 'click [data-cc-button]': 'toggleContextMenu',
+ 'click [data-cc-select]': 'onTrackSelect'
+ };
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'class': 'cc-controls',
+ 'data-cc-controls': ''
+ };
+ }
+ }]);
+
+ function ClosedCaptions(core) {
+ (0, _classCallCheck3.default)(this, ClosedCaptions);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UICorePlugin.call(this, core));
+
+ var config = core.options.closedCaptionsConfig;
+ _this._title = config && config.title ? config.title : null;
+ _this._ariaLabel = config && config.ariaLabel ? config.ariaLabel : 'cc-button';
+ _this._labelCb = config && config.labelCallback && typeof config.labelCallback === 'function' ? config.labelCallback : function (track) {
+ return track.name;
+ };
+ return _this;
+ }
+
+ ClosedCaptions.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.core, _events2.default.CORE_ACTIVE_CONTAINER_CHANGED, this.containerChanged);
+ this.listenTo(this.core.mediaControl, _events2.default.MEDIACONTROL_RENDERED, this.render);
+ this.listenTo(this.core.mediaControl, _events2.default.MEDIACONTROL_HIDE, this.hideContextMenu);
+ this.container = this.core.getCurrentContainer();
+ if (this.container) {
+ this.listenTo(this.container, _events2.default.CONTAINER_SUBTITLE_AVAILABLE, this.onSubtitleAvailable);
+ this.listenTo(this.container, _events2.default.CONTAINER_SUBTITLE_CHANGED, this.onSubtitleChanged);
+ this.listenTo(this.container, _events2.default.CONTAINER_STOP, this.onContainerStop);
+ }
+ };
+
+ ClosedCaptions.prototype.onContainerStop = function onContainerStop() {
+ this.ccAvailable(false);
+ };
+
+ ClosedCaptions.prototype.containerChanged = function containerChanged() {
+ this.ccAvailable(false);
+ this.stopListening();
+ this.bindEvents();
+ };
+
+ ClosedCaptions.prototype.onSubtitleAvailable = function onSubtitleAvailable() {
+ this.renderCcButton();
+ this.ccAvailable(true);
+ };
+
+ ClosedCaptions.prototype.onSubtitleChanged = function onSubtitleChanged(track) {
+ this.setCurrentContextMenuElement(track.id);
+ };
+
+ ClosedCaptions.prototype.onTrackSelect = function onTrackSelect(event) {
+ var trackId = parseInt(event.target.dataset.ccSelect, 10);
+ this.container.closedCaptionsTrackId = trackId;
+ this.hideContextMenu();
+ event.stopPropagation();
+ return false;
+ };
+
+ ClosedCaptions.prototype.ccAvailable = function ccAvailable(hasCC) {
+ var method = hasCC ? 'addClass' : 'removeClass';
+ this.$el[method]('available');
+ };
+
+ ClosedCaptions.prototype.toggleContextMenu = function toggleContextMenu() {
+ this.$el.find('ul').toggle();
+ };
+
+ ClosedCaptions.prototype.hideContextMenu = function hideContextMenu() {
+ this.$el.find('ul').hide();
+ };
+
+ ClosedCaptions.prototype.contextMenuElement = function contextMenuElement(id) {
+ return this.$el.find('ul a' + (!isNaN(id) ? '[data-cc-select="' + id + '"]' : '')).parent();
+ };
+
+ ClosedCaptions.prototype.setCurrentContextMenuElement = function setCurrentContextMenuElement(trackId) {
+ if (this._trackId !== trackId) {
+ this.contextMenuElement().removeClass('current');
+ this.contextMenuElement(trackId).addClass('current');
+ var method = trackId > -1 ? 'addClass' : 'removeClass';
+ this.$ccButton[method]('enabled');
+ this._trackId = trackId;
+ }
+ };
+
+ ClosedCaptions.prototype.renderCcButton = function renderCcButton() {
+ var tracks = this.container ? this.container.closedCaptionsTracks : [];
+ for (var i = 0; i < tracks.length; i++) {
+ tracks[i].label = this._labelCb(tracks[i]);
+ }this.$el.html(this.template({
+ ariaLabel: this._ariaLabel,
+ disabledLabel: this.core.i18n.t('disabled'),
+ title: this._title,
+ tracks: tracks
+ }));
+
+ this.$ccButton = this.$el.find('button.cc-button[data-cc-button]');
+ this.$ccButton.append(_cc2.default);
+ this.$el.append(this.style);
+ };
+
+ ClosedCaptions.prototype.render = function render() {
+ this.renderCcButton();
+
+ var $fullscreen = this.core.mediaControl.$el.find('button[data-fullscreen]');
+ if ($fullscreen[0]) this.$el.insertAfter($fullscreen);else this.core.mediaControl.$el.find('.media-control-right-panel[data-media-control]').prepend(this.$el);
+
+ return this;
+ };
+
+ return ClosedCaptions;
+}(_ui_core_plugin2.default);
+
+exports.default = ClosedCaptions;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/closed_captions/index.js":
+/*!**********************************************!*\
+ !*** ./src/plugins/closed_captions/index.js ***!
+ \**********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _closed_captions = __webpack_require__(/*! ./closed_captions */ "./src/plugins/closed_captions/closed_captions.js");
+
+var _closed_captions2 = _interopRequireDefault(_closed_captions);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _closed_captions2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/closed_captions/public/closed_captions.html":
+/*!*****************************************************************!*\
+ !*** ./src/plugins/closed_captions/public/closed_captions.html ***!
+ \*****************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "\"> \n
\n";
+
+/***/ }),
+
+/***/ "./src/plugins/closed_captions/public/closed_captions.scss":
+/*!*****************************************************************!*\
+ !*** ./src/plugins/closed_captions/public/closed_captions.scss ***!
+ \*****************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./closed_captions.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/closed_captions/public/closed_captions.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/dvr_controls/dvr_controls.js":
+/*!**************************************************!*\
+ !*** ./src/plugins/dvr_controls/dvr_controls.js ***!
+ \**************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _ui_core_plugin = __webpack_require__(/*! ../../base/ui_core_plugin */ "./src/base/ui_core_plugin.js");
+
+var _ui_core_plugin2 = _interopRequireDefault(_ui_core_plugin);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _index = __webpack_require__(/*! ./public/index.html */ "./src/plugins/dvr_controls/public/index.html");
+
+var _index2 = _interopRequireDefault(_index);
+
+__webpack_require__(/*! ./public/dvr_controls.scss */ "./src/plugins/dvr_controls/public/dvr_controls.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var DVRControls = function (_UICorePlugin) {
+ (0, _inherits3.default)(DVRControls, _UICorePlugin);
+ (0, _createClass3.default)(DVRControls, [{
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_index2.default);
+ }
+ }, {
+ key: 'name',
+ get: function get() {
+ return 'dvr_controls';
+ }
+ }, {
+ key: 'events',
+ get: function get() {
+ return {
+ 'click .live-button': 'click'
+ };
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'class': 'dvr-controls',
+ 'data-dvr-controls': ''
+ };
+ }
+ }]);
+
+ function DVRControls(core) {
+ (0, _classCallCheck3.default)(this, DVRControls);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UICorePlugin.call(this, core));
+
+ _this.settingsUpdate();
+ return _this;
+ }
+
+ DVRControls.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.core.mediaControl, _events2.default.MEDIACONTROL_CONTAINERCHANGED, this.containerChanged);
+ this.listenTo(this.core.mediaControl, _events2.default.MEDIACONTROL_RENDERED, this.settingsUpdate);
+ this.listenTo(this.core, _events2.default.CORE_OPTIONS_CHANGE, this.render);
+ if (this.core.getCurrentContainer()) {
+ this.listenToOnce(this.core.getCurrentContainer(), _events2.default.CONTAINER_TIMEUPDATE, this.render);
+ this.listenTo(this.core.getCurrentContainer(), _events2.default.CONTAINER_PLAYBACKDVRSTATECHANGED, this.dvrChanged);
+ }
+ };
+
+ DVRControls.prototype.containerChanged = function containerChanged() {
+ this.stopListening();
+ this.bindEvents();
+ };
+
+ DVRControls.prototype.dvrChanged = function dvrChanged(dvrEnabled) {
+ if (this.core.getPlaybackType() !== _playback2.default.LIVE) return;
+ this.settingsUpdate();
+ this.core.mediaControl.$el.addClass('live');
+ if (dvrEnabled) {
+ this.core.mediaControl.$el.addClass('dvr');
+ this.core.mediaControl.$el.find('.media-control-indicator[data-position], .media-control-indicator[data-duration]').hide();
+ } else {
+ this.core.mediaControl.$el.removeClass('dvr');
+ }
+ };
+
+ DVRControls.prototype.click = function click() {
+ var mediaControl = this.core.mediaControl;
+ var container = mediaControl.container;
+ if (!container.isPlaying()) container.play();
+
+ if (mediaControl.$el.hasClass('dvr')) container.seek(container.getDuration());
+ };
+
+ DVRControls.prototype.settingsUpdate = function settingsUpdate() {
+ var _this2 = this;
+
+ this.stopListening();
+ this.core.mediaControl.$el.removeClass('live');
+ if (this.shouldRender()) {
+ this.render();
+ this.$el.click(function () {
+ return _this2.click();
+ });
+ }
+ this.bindEvents();
+ };
+
+ DVRControls.prototype.shouldRender = function shouldRender() {
+ var useDvrControls = this.core.options.useDvrControls === undefined || !!this.core.options.useDvrControls;
+ return useDvrControls && this.core.getPlaybackType() === _playback2.default.LIVE;
+ };
+
+ DVRControls.prototype.render = function render() {
+ this.$el.html(this.template({
+ live: this.core.i18n.t('live'),
+ backToLive: this.core.i18n.t('back_to_live')
+ }));
+ if (this.shouldRender()) {
+ this.core.mediaControl.$el.addClass('live');
+ this.core.mediaControl.$('.media-control-left-panel[data-media-control]').append(this.$el);
+ }
+ return this;
+ };
+
+ return DVRControls;
+}(_ui_core_plugin2.default);
+
+exports.default = DVRControls;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/dvr_controls/index.js":
+/*!*******************************************!*\
+ !*** ./src/plugins/dvr_controls/index.js ***!
+ \*******************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _dvr_controls = __webpack_require__(/*! ./dvr_controls */ "./src/plugins/dvr_controls/dvr_controls.js");
+
+var _dvr_controls2 = _interopRequireDefault(_dvr_controls);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _dvr_controls2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/dvr_controls/public/dvr_controls.scss":
+/*!***********************************************************!*\
+ !*** ./src/plugins/dvr_controls/public/dvr_controls.scss ***!
+ \***********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./dvr_controls.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/dvr_controls/public/dvr_controls.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/dvr_controls/public/index.html":
+/*!****************************************************!*\
+ !*** ./src/plugins/dvr_controls/public/index.html ***!
+ \****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "<%= live %>
\n\"><%= backToLive %> \n";
+
+/***/ }),
+
+/***/ "./src/plugins/end_video.js":
+/*!**********************************!*\
+ !*** ./src/plugins/end_video.js ***!
+ \**********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _events = __webpack_require__(/*! ../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _core_plugin = __webpack_require__(/*! ../base/core_plugin */ "./src/base/core_plugin.js");
+
+var _core_plugin2 = _interopRequireDefault(_core_plugin);
+
+var _utils = __webpack_require__(/*! ../base/utils */ "./src/base/utils.js");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var EndVideo = function (_CorePlugin) {
+ (0, _inherits3.default)(EndVideo, _CorePlugin);
+
+ function EndVideo() {
+ (0, _classCallCheck3.default)(this, EndVideo);
+ return (0, _possibleConstructorReturn3.default)(this, _CorePlugin.apply(this, arguments));
+ }
+
+ EndVideo.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.core, _events2.default.CORE_ACTIVE_CONTAINER_CHANGED, this.containerChanged);
+ var container = this.core.activeContainer;
+ if (container) {
+ this.listenTo(container, _events2.default.CONTAINER_ENDED, this.ended);
+ this.listenTo(container, _events2.default.CONTAINER_STOP, this.ended);
+ }
+ };
+
+ EndVideo.prototype.containerChanged = function containerChanged() {
+ this.stopListening();
+ this.bindEvents();
+ };
+
+ EndVideo.prototype.ended = function ended() {
+ var exitOnEnd = typeof this.core.options.exitFullscreenOnEnd === 'undefined' || this.core.options.exitFullscreenOnEnd;
+ if (exitOnEnd && _utils.Fullscreen.isFullscreen()) this.core.toggleFullscreen();
+ };
+
+ (0, _createClass3.default)(EndVideo, [{
+ key: 'name',
+ get: function get() {
+ return 'end_video';
+ }
+ }]);
+ return EndVideo;
+}(_core_plugin2.default);
+
+exports.default = EndVideo;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/error_screen/error_screen.js":
+/*!**************************************************!*\
+ !*** ./src/plugins/error_screen/error_screen.js ***!
+ \**************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _ui_core_plugin = __webpack_require__(/*! ../../base/ui_core_plugin */ "./src/base/ui_core_plugin.js");
+
+var _ui_core_plugin2 = _interopRequireDefault(_ui_core_plugin);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _error = __webpack_require__(/*! ../../components/error/ */ "./src/components/error/index.js");
+
+var _error2 = _interopRequireDefault(_error);
+
+var _reload = __webpack_require__(/*! ../../icons/10-reload.svg */ "./src/icons/10-reload.svg");
+
+var _reload2 = _interopRequireDefault(_reload);
+
+var _error_screen = __webpack_require__(/*! ./public/error_screen.html */ "./src/plugins/error_screen/public/error_screen.html");
+
+var _error_screen2 = _interopRequireDefault(_error_screen);
+
+__webpack_require__(/*! ./public/error_screen.scss */ "./src/plugins/error_screen/public/error_screen.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var ErrorScreen = function (_UICorePlugin) {
+ (0, _inherits3.default)(ErrorScreen, _UICorePlugin);
+ (0, _createClass3.default)(ErrorScreen, [{
+ key: 'name',
+ get: function get() {
+ return 'error_screen';
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_error_screen2.default);
+ }
+ }, {
+ key: 'container',
+ get: function get() {
+ return this.core.getCurrentContainer();
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'class': 'player-error-screen',
+ 'data-error-screen': ''
+ };
+ }
+ }]);
+
+ function ErrorScreen(core) {
+ var _ret;
+
+ (0, _classCallCheck3.default)(this, ErrorScreen);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UICorePlugin.call(this, core));
+
+ if (_this.options.disableErrorScreen) return _ret = _this.disable(), (0, _possibleConstructorReturn3.default)(_this, _ret);
+ return _this;
+ }
+
+ ErrorScreen.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.core, _events2.default.ERROR, this.onError);
+ this.listenTo(this.core, _events2.default.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged);
+ };
+
+ ErrorScreen.prototype.bindReload = function bindReload() {
+ this.reloadButton = this.$el.find('.player-error-screen__reload');
+ this.reloadButton && this.reloadButton.on('click', this.reload.bind(this));
+ };
+
+ ErrorScreen.prototype.reload = function reload() {
+ var _this2 = this;
+
+ this.listenToOnce(this.core, _events2.default.CORE_READY, function () {
+ return _this2.container.play();
+ });
+ this.core.load(this.options.sources, this.options.mimeType);
+ this.unbindReload();
+ };
+
+ ErrorScreen.prototype.unbindReload = function unbindReload() {
+ this.reloadButton && this.reloadButton.off('click');
+ };
+
+ ErrorScreen.prototype.onContainerChanged = function onContainerChanged() {
+ this.err = null;
+ this.unbindReload();
+ this.hide();
+ };
+
+ ErrorScreen.prototype.onError = function onError() {
+ var err = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ if (err.level === _error2.default.Levels.FATAL) {
+ this.err = err;
+ this.container.disableMediaControl();
+ this.container.stop();
+ this.show();
+ }
+ };
+
+ ErrorScreen.prototype.show = function show() {
+ this.render();
+ this.$el.show();
+ };
+
+ ErrorScreen.prototype.hide = function hide() {
+ this.$el.hide();
+ };
+
+ ErrorScreen.prototype.render = function render() {
+ if (!this.err) return;
+
+ this.$el.html(this.template({
+ title: this.err.UI.title,
+ message: this.err.UI.message,
+ code: this.err.code,
+ icon: this.err.UI.icon || '',
+ reloadIcon: _reload2.default
+ }));
+
+ this.core.$el.append(this.el);
+
+ this.bindReload();
+
+ return this;
+ };
+
+ return ErrorScreen;
+}(_ui_core_plugin2.default);
+
+exports.default = ErrorScreen;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/error_screen/index.js":
+/*!*******************************************!*\
+ !*** ./src/plugins/error_screen/index.js ***!
+ \*******************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _error_screen = __webpack_require__(/*! ./error_screen */ "./src/plugins/error_screen/error_screen.js");
+
+var _error_screen2 = _interopRequireDefault(_error_screen);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _error_screen2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/error_screen/public/error_screen.html":
+/*!***********************************************************!*\
+ !*** ./src/plugins/error_screen/public/error_screen.html ***!
+ \***********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "\n <% if (icon) { %>\n
<%= icon %>
\n <% } %>\n
<%= title %>
\n
<%= message %>
\n
Error code: <%= code %>
\n
<%= reloadIcon %>
\n
\n";
+
+/***/ }),
+
+/***/ "./src/plugins/error_screen/public/error_screen.scss":
+/*!***********************************************************!*\
+ !*** ./src/plugins/error_screen/public/error_screen.scss ***!
+ \***********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./error_screen.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/error_screen/public/error_screen.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/favicon/favicon.js":
+/*!****************************************!*\
+ !*** ./src/plugins/favicon/favicon.js ***!
+ \****************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _core_plugin = __webpack_require__(/*! ../../base/core_plugin */ "./src/base/core_plugin.js");
+
+var _core_plugin2 = _interopRequireDefault(_core_plugin);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+var _play = __webpack_require__(/*! ../../icons/01-play.svg */ "./src/icons/01-play.svg");
+
+var _play2 = _interopRequireDefault(_play);
+
+var _pause = __webpack_require__(/*! ../../icons/02-pause.svg */ "./src/icons/02-pause.svg");
+
+var _pause2 = _interopRequireDefault(_pause);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var oldIcon = (0, _clapprZepto2.default)('link[rel="shortcut icon"]');
+
+var Favicon = function (_CorePlugin) {
+ (0, _inherits3.default)(Favicon, _CorePlugin);
+ (0, _createClass3.default)(Favicon, [{
+ key: 'name',
+ get: function get() {
+ return 'favicon';
+ }
+ }, {
+ key: 'oldIcon',
+ get: function get() {
+ return oldIcon;
+ }
+ }]);
+
+ function Favicon(core) {
+ (0, _classCallCheck3.default)(this, Favicon);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _CorePlugin.call(this, core));
+
+ _this._container = null;
+ _this.configure();
+ return _this;
+ }
+
+ Favicon.prototype.configure = function configure() {
+ if (this.core.options.changeFavicon) {
+ if (!this.enabled) {
+ this.stopListening(this.core, _events2.default.CORE_OPTIONS_CHANGE);
+ this.enable();
+ }
+ } else if (this.enabled) {
+ this.disable();
+ this.listenTo(this.core, _events2.default.CORE_OPTIONS_CHANGE, this.configure);
+ }
+ };
+
+ Favicon.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.core, _events2.default.CORE_OPTIONS_CHANGE, this.configure);
+ this.listenTo(this.core, _events2.default.CORE_ACTIVE_CONTAINER_CHANGED, this.containerChanged);
+ this.core.activeContainer && this.containerChanged();
+ };
+
+ Favicon.prototype.containerChanged = function containerChanged() {
+ this._container && this.stopListening(this._container);
+ this._container = this.core.activeContainer;
+ this.listenTo(this._container, _events2.default.CONTAINER_PLAY, this.setPlayIcon);
+ this.listenTo(this._container, _events2.default.CONTAINER_PAUSE, this.setPauseIcon);
+ this.listenTo(this._container, _events2.default.CONTAINER_STOP, this.resetIcon);
+ this.listenTo(this._container, _events2.default.CONTAINER_ENDED, this.resetIcon);
+ this.listenTo(this._container, _events2.default.CONTAINER_ERROR, this.resetIcon);
+ this.resetIcon();
+ };
+
+ Favicon.prototype.disable = function disable() {
+ _CorePlugin.prototype.disable.call(this);
+ this.resetIcon();
+ };
+
+ Favicon.prototype.destroy = function destroy() {
+ _CorePlugin.prototype.destroy.call(this);
+ this.resetIcon();
+ };
+
+ Favicon.prototype.createIcon = function createIcon(svg) {
+ var canvas = (0, _clapprZepto2.default)(' ');
+ canvas[0].width = 16;
+ canvas[0].height = 16;
+ var ctx = canvas[0].getContext('2d');
+ ctx.fillStyle = '#000';
+ var d = (0, _clapprZepto2.default)(svg).find('path').attr('d');
+ var path = new Path2D(d);
+ ctx.fill(path);
+ var icon = (0, _clapprZepto2.default)(' ');
+ icon.attr('href', canvas[0].toDataURL('image/png'));
+ return icon;
+ };
+
+ Favicon.prototype.setPlayIcon = function setPlayIcon() {
+ if (!this.playIcon) this.playIcon = this.createIcon(_play2.default);
+
+ this.changeIcon(this.playIcon);
+ };
+
+ Favicon.prototype.setPauseIcon = function setPauseIcon() {
+ if (!this.pauseIcon) this.pauseIcon = this.createIcon(_pause2.default);
+
+ this.changeIcon(this.pauseIcon);
+ };
+
+ Favicon.prototype.resetIcon = function resetIcon() {
+ (0, _clapprZepto2.default)('link[rel="shortcut icon"]').remove();
+ (0, _clapprZepto2.default)('head').append(this.oldIcon);
+ };
+
+ Favicon.prototype.changeIcon = function changeIcon(icon) {
+ if (icon) {
+ (0, _clapprZepto2.default)('link[rel="shortcut icon"]').remove();
+ (0, _clapprZepto2.default)('head').append(icon);
+ }
+ };
+
+ return Favicon;
+}(_core_plugin2.default);
+
+exports.default = Favicon;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/favicon/index.js":
+/*!**************************************!*\
+ !*** ./src/plugins/favicon/index.js ***!
+ \**************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _favicon = __webpack_require__(/*! ./favicon.js */ "./src/plugins/favicon/favicon.js");
+
+var _favicon2 = _interopRequireDefault(_favicon);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _favicon2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/google_analytics/google_analytics.js":
+/*!**********************************************************!*\
+ !*** ./src/plugins/google_analytics/google_analytics.js ***!
+ \**********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _container_plugin = __webpack_require__(/*! ../../base/container_plugin */ "./src/base/container_plugin.js");
+
+var _container_plugin2 = _interopRequireDefault(_container_plugin);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var GoogleAnalytics = function (_ContainerPlugin) {
+ (0, _inherits3.default)(GoogleAnalytics, _ContainerPlugin);
+ (0, _createClass3.default)(GoogleAnalytics, [{
+ key: 'name',
+ get: function get() {
+ return 'google_analytics';
+ }
+ }]);
+
+ function GoogleAnalytics(container) {
+ (0, _classCallCheck3.default)(this, GoogleAnalytics);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _ContainerPlugin.call(this, container));
+
+ if (_this.container.options.gaAccount) {
+ _this.account = _this.container.options.gaAccount;
+ _this.trackerName = _this.container.options.gaTrackerName ? _this.container.options.gaTrackerName + '.' : 'Clappr.';
+ _this.domainName = _this.container.options.gaDomainName;
+ _this.currentHDState = undefined;
+ _this.embedScript();
+ }
+ return _this;
+ }
+
+ GoogleAnalytics.prototype.embedScript = function embedScript() {
+ var _this2 = this;
+
+ if (!window._gat) {
+ var script = document.createElement('script');
+ script.setAttribute('type', 'text/javascript');
+ script.setAttribute('async', 'async');
+ script.setAttribute('src', '//www.google-analytics.com/ga.js');
+ script.onload = function () {
+ return _this2.addEventListeners();
+ };
+ document.body.appendChild(script);
+ } else {
+ this.addEventListeners();
+ }
+ };
+
+ GoogleAnalytics.prototype.addEventListeners = function addEventListeners() {
+ var _this3 = this;
+
+ if (this.container) {
+ this.listenTo(this.container, _events2.default.CONTAINER_READY, this.onReady);
+ this.listenTo(this.container, _events2.default.CONTAINER_PLAY, this.onPlay);
+ this.listenTo(this.container, _events2.default.CONTAINER_STOP, this.onStop);
+ this.listenTo(this.container, _events2.default.CONTAINER_PAUSE, this.onPause);
+ this.listenTo(this.container, _events2.default.CONTAINER_ENDED, this.onEnded);
+ this.listenTo(this.container, _events2.default.CONTAINER_STATE_BUFFERING, this.onBuffering);
+ this.listenTo(this.container, _events2.default.CONTAINER_STATE_BUFFERFULL, this.onBufferFull);
+ this.listenTo(this.container, _events2.default.CONTAINER_ERROR, this.onError);
+ this.listenTo(this.container, _events2.default.CONTAINER_PLAYBACKSTATE, this.onPlaybackChanged);
+ this.listenTo(this.container, _events2.default.CONTAINER_VOLUME, function (event) {
+ return _this3.onVolumeChanged(event);
+ });
+ this.listenTo(this.container, _events2.default.CONTAINER_SEEK, function (event) {
+ return _this3.onSeek(event);
+ });
+ this.listenTo(this.container, _events2.default.CONTAINER_FULL_SCREEN, this.onFullscreen);
+ this.listenTo(this.container, _events2.default.CONTAINER_HIGHDEFINITIONUPDATE, this.onHD);
+ this.listenTo(this.container, _events2.default.CONTAINER_PLAYBACKDVRSTATECHANGED, this.onDVR);
+ }
+ _gaq.push([this.trackerName + '_setAccount', this.account]);
+ if (this.domainName) _gaq.push([this.trackerName + '_setDomainName', this.domainName]);
+ };
+
+ GoogleAnalytics.prototype.onReady = function onReady() {
+ this.push(['Video', 'Playback', this.container.playback.name]);
+ };
+
+ GoogleAnalytics.prototype.onPlay = function onPlay() {
+ this.push(['Video', 'Play', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onStop = function onStop() {
+ this.push(['Video', 'Stop', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onEnded = function onEnded() {
+ this.push(['Video', 'Ended', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onBuffering = function onBuffering() {
+ this.push(['Video', 'Buffering', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onBufferFull = function onBufferFull() {
+ this.push(['Video', 'Bufferfull', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onError = function onError() {
+ this.push(['Video', 'Error', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onHD = function onHD(isHD) {
+ var status = isHD ? 'ON' : 'OFF';
+ if (status !== this.currentHDState) {
+ this.currentHDState = status;
+ this.push(['Video', 'HD - ' + status, this.container.playback.src]);
+ }
+ };
+
+ GoogleAnalytics.prototype.onPlaybackChanged = function onPlaybackChanged(playbackState) {
+ if (playbackState.type !== null) this.push(['Video', 'Playback Type - ' + playbackState.type, this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onDVR = function onDVR(dvrInUse) {
+ var status = dvrInUse ? 'ON' : 'OFF';
+ this.push(['Interaction', 'DVR - ' + status, this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onPause = function onPause() {
+ this.push(['Video', 'Pause', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onSeek = function onSeek() {
+ this.push(['Video', 'Seek', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onVolumeChanged = function onVolumeChanged() {
+ this.push(['Interaction', 'Volume', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.onFullscreen = function onFullscreen() {
+ this.push(['Interaction', 'Fullscreen', this.container.playback.src]);
+ };
+
+ GoogleAnalytics.prototype.push = function push(array) {
+ var res = [this.trackerName + '_trackEvent'].concat(array);
+ _gaq.push(res);
+ };
+
+ return GoogleAnalytics;
+}(_container_plugin2.default);
+
+exports.default = GoogleAnalytics;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/google_analytics/index.js":
+/*!***********************************************!*\
+ !*** ./src/plugins/google_analytics/index.js ***!
+ \***********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _google_analytics = __webpack_require__(/*! ./google_analytics */ "./src/plugins/google_analytics/google_analytics.js");
+
+var _google_analytics2 = _interopRequireDefault(_google_analytics);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _google_analytics2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/log/index.js":
+/*!**********************************!*\
+ !*** ./src/plugins/log/index.js ***!
+ \**********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _log = __webpack_require__(/*! ./log */ "./src/plugins/log/log.js");
+
+var _log2 = _interopRequireDefault(_log);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _log2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/log/log.js":
+/*!********************************!*\
+ !*** ./src/plugins/log/log.js ***!
+ \********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _vendor = __webpack_require__(/*! ../../vendor */ "./src/vendor/index.js");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var BOLD = 'font-weight: bold; font-size: 13px;';
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var INFO = 'color: #006600;' + BOLD;
+var DEBUG = 'color: #0000ff;' + BOLD;
+var WARN = 'color: #ff8000;' + BOLD;
+var ERROR = 'color: #ff0000;' + BOLD;
+
+var LEVEL_DEBUG = 0;
+var LEVEL_INFO = 1;
+var LEVEL_WARN = 2;
+var LEVEL_ERROR = 3;
+var LEVEL_DISABLED = LEVEL_ERROR;
+
+var COLORS = [DEBUG, INFO, WARN, ERROR, ERROR];
+var DESCRIPTIONS = ['debug', 'info', 'warn', 'error', 'disabled'];
+
+var Log = function () {
+ function Log() {
+ var _this = this;
+
+ var level = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : LEVEL_INFO;
+ var offLevel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : LEVEL_DISABLED;
+ (0, _classCallCheck3.default)(this, Log);
+
+ this.kibo = new _vendor.Kibo();
+ this.kibo.down(['ctrl shift d'], function () {
+ return _this.onOff();
+ });
+ this.BLACKLIST = ['timeupdate', 'playback:timeupdate', 'playback:progress', 'container:hover', 'container:timeupdate', 'container:progress'];
+ this.level = level;
+ this.offLevel = offLevel;
+ }
+
+ Log.prototype.debug = function debug(klass) {
+ this.log(klass, LEVEL_DEBUG, Array.prototype.slice.call(arguments, 1));
+ };
+
+ Log.prototype.info = function info(klass) {
+ this.log(klass, LEVEL_INFO, Array.prototype.slice.call(arguments, 1));
+ };
+
+ Log.prototype.warn = function warn(klass) {
+ this.log(klass, LEVEL_WARN, Array.prototype.slice.call(arguments, 1));
+ };
+
+ Log.prototype.error = function error(klass) {
+ this.log(klass, LEVEL_ERROR, Array.prototype.slice.call(arguments, 1));
+ };
+
+ Log.prototype.onOff = function onOff() {
+ if (this.level === this.offLevel) {
+ this.level = this.previousLevel;
+ } else {
+ this.previousLevel = this.level;
+ this.level = this.offLevel;
+ }
+ // handle instances where console.log is unavailable
+ if (window.console && window.console.log) window.console.log('%c[Clappr.Log] set log level to ' + DESCRIPTIONS[this.level], WARN);
+ };
+
+ Log.prototype.level = function level(newLevel) {
+ this.level = newLevel;
+ };
+
+ Log.prototype.log = function log(klass, level, message) {
+ if (this.BLACKLIST.indexOf(message[0]) >= 0) return;
+ if (level < this.level) return;
+
+ if (!message) {
+ message = klass;
+ klass = null;
+ }
+ var color = COLORS[level];
+ var klassDescription = '';
+ if (klass) klassDescription = '[' + klass + ']';
+
+ if (window.console && window.console.log) window.console.log.apply(console, ['%c[' + DESCRIPTIONS[level] + ']' + klassDescription, color].concat(message));
+ };
+
+ return Log;
+}();
+
+exports.default = Log;
+
+
+Log.LEVEL_DEBUG = LEVEL_DEBUG;
+Log.LEVEL_INFO = LEVEL_INFO;
+Log.LEVEL_WARN = LEVEL_WARN;
+Log.LEVEL_ERROR = LEVEL_ERROR;
+
+Log.getInstance = function () {
+ if (this._instance === undefined) {
+ this._instance = new this();
+ this._instance.previousLevel = this._instance.level;
+ this._instance.level = this._instance.offLevel;
+ }
+ return this._instance;
+};
+
+Log.setLevel = function (level) {
+ this.getInstance().level = level;
+};
+
+Log.debug = function () {
+ this.getInstance().debug.apply(this.getInstance(), arguments);
+};
+Log.info = function () {
+ this.getInstance().info.apply(this.getInstance(), arguments);
+};
+Log.warn = function () {
+ this.getInstance().warn.apply(this.getInstance(), arguments);
+};
+Log.error = function () {
+ this.getInstance().error.apply(this.getInstance(), arguments);
+};
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/media_control/index.js":
+/*!********************************************!*\
+ !*** ./src/plugins/media_control/index.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _media_control = __webpack_require__(/*! ./media_control */ "./src/plugins/media_control/media_control.js");
+
+var _media_control2 = _interopRequireDefault(_media_control);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _media_control2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/media_control/media_control.js":
+/*!****************************************************!*\
+ !*** ./src/plugins/media_control/media_control.js ***!
+ \****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(process) {
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _stringify = __webpack_require__(/*! babel-runtime/core-js/json/stringify */ "./node_modules/babel-runtime/core-js/json/stringify.js");
+
+var _stringify2 = _interopRequireDefault(_stringify);
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _utils = __webpack_require__(/*! ../../base/utils */ "./src/base/utils.js");
+
+var _vendor = __webpack_require__(/*! ../../vendor */ "./src/vendor/index.js");
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _ui_core_plugin = __webpack_require__(/*! ../../base/ui_core_plugin */ "./src/base/ui_core_plugin.js");
+
+var _ui_core_plugin2 = _interopRequireDefault(_ui_core_plugin);
+
+var _browser = __webpack_require__(/*! ../../components/browser */ "./src/components/browser/index.js");
+
+var _browser2 = _interopRequireDefault(_browser);
+
+var _mediator = __webpack_require__(/*! ../../components/mediator */ "./src/components/mediator.js");
+
+var _mediator2 = _interopRequireDefault(_mediator);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+__webpack_require__(/*! ./public/media-control.scss */ "./src/plugins/media_control/public/media-control.scss");
+
+var _mediaControl = __webpack_require__(/*! ./public/media-control.html */ "./src/plugins/media_control/public/media-control.html");
+
+var _mediaControl2 = _interopRequireDefault(_mediaControl);
+
+var _play = __webpack_require__(/*! ../../icons/01-play.svg */ "./src/icons/01-play.svg");
+
+var _play2 = _interopRequireDefault(_play);
+
+var _pause = __webpack_require__(/*! ../../icons/02-pause.svg */ "./src/icons/02-pause.svg");
+
+var _pause2 = _interopRequireDefault(_pause);
+
+var _stop = __webpack_require__(/*! ../../icons/03-stop.svg */ "./src/icons/03-stop.svg");
+
+var _stop2 = _interopRequireDefault(_stop);
+
+var _volume = __webpack_require__(/*! ../../icons/04-volume.svg */ "./src/icons/04-volume.svg");
+
+var _volume2 = _interopRequireDefault(_volume);
+
+var _mute = __webpack_require__(/*! ../../icons/05-mute.svg */ "./src/icons/05-mute.svg");
+
+var _mute2 = _interopRequireDefault(_mute);
+
+var _expand = __webpack_require__(/*! ../../icons/06-expand.svg */ "./src/icons/06-expand.svg");
+
+var _expand2 = _interopRequireDefault(_expand);
+
+var _shrink = __webpack_require__(/*! ../../icons/07-shrink.svg */ "./src/icons/07-shrink.svg");
+
+var _shrink2 = _interopRequireDefault(_shrink);
+
+var _hd = __webpack_require__(/*! ../../icons/08-hd.svg */ "./src/icons/08-hd.svg");
+
+var _hd2 = _interopRequireDefault(_hd);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var MediaControl = function (_UICorePlugin) {
+ (0, _inherits3.default)(MediaControl, _UICorePlugin);
+ (0, _createClass3.default)(MediaControl, [{
+ key: 'name',
+ get: function get() {
+ return 'media_control';
+ }
+ }, {
+ key: 'disabled',
+ get: function get() {
+ var playbackIsNOOP = this.container && this.container.getPlaybackType() === _playback2.default.NO_OP;
+ return this.userDisabled || playbackIsNOOP;
+ }
+ }, {
+ key: 'container',
+ get: function get() {
+ return this.core && this.core.activeContainer;
+ }
+ }, {
+ key: 'playback',
+ get: function get() {
+ return this.core && this.core.activePlayback;
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'class': 'media-control',
+ 'data-media-control': ''
+ };
+ }
+ }, {
+ key: 'events',
+ get: function get() {
+ return {
+ 'click [data-play]': 'play',
+ 'click [data-pause]': 'pause',
+ 'click [data-playpause]': 'togglePlayPause',
+ 'click [data-stop]': 'stop',
+ 'click [data-playstop]': 'togglePlayStop',
+ 'click [data-fullscreen]': 'toggleFullscreen',
+ 'click .bar-container[data-seekbar]': 'seek',
+ 'click .bar-container[data-volume]': 'onVolumeClick',
+ 'click .drawer-icon[data-volume]': 'toggleMute',
+ 'mouseenter .drawer-container[data-volume]': 'showVolumeBar',
+ 'mouseleave .drawer-container[data-volume]': 'hideVolumeBar',
+ 'mousedown .bar-container[data-volume]': 'startVolumeDrag',
+ 'mousemove .bar-container[data-volume]': 'mousemoveOnVolumeBar',
+ 'mousedown .bar-scrubber[data-seekbar]': 'startSeekDrag',
+ 'mousemove .bar-container[data-seekbar]': 'mousemoveOnSeekBar',
+ 'mouseleave .bar-container[data-seekbar]': 'mouseleaveOnSeekBar',
+ 'mouseenter .media-control-layer[data-controls]': 'setUserKeepVisible',
+ 'mouseleave .media-control-layer[data-controls]': 'resetUserKeepVisible'
+ };
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_mediaControl2.default);
+ }
+ }, {
+ key: 'volume',
+ get: function get() {
+ return this.container && this.container.isReady ? this.container.volume : this.intendedVolume;
+ }
+ }, {
+ key: 'muted',
+ get: function get() {
+ return this.volume === 0;
+ }
+ }]);
+
+ function MediaControl(core) {
+ (0, _classCallCheck3.default)(this, MediaControl);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UICorePlugin.call(this, core));
+
+ _this.persistConfig = _this.options.persistConfig;
+ _this.currentPositionValue = null;
+ _this.currentDurationValue = null;
+ _this.keepVisible = false;
+ _this.fullScreenOnVideoTagSupported = null; // unknown
+ _this.setInitialVolume();
+ _this.settings = {
+ left: ['play', 'stop', 'pause'],
+ right: ['volume'],
+ default: ['position', 'seekbar', 'duration']
+ };
+ _this.kibo = new _vendor.Kibo(_this.options.focusElement);
+ _this.bindKeyEvents();
+
+ if (_this.container) {
+ if (!_clapprZepto2.default.isEmptyObject(_this.container.settings)) _this.settings = _clapprZepto2.default.extend({}, _this.container.settings);
+ } else {
+ _this.settings = {};
+ }
+
+ _this.userDisabled = false;
+ if (_this.container && _this.container.mediaControlDisabled || _this.options.chromeless) _this.disable();
+
+ _this.stopDragHandler = function (event) {
+ return _this.stopDrag(event);
+ };
+ _this.updateDragHandler = function (event) {
+ return _this.updateDrag(event);
+ };
+ (0, _clapprZepto2.default)(document).bind('mouseup', _this.stopDragHandler);
+ (0, _clapprZepto2.default)(document).bind('mousemove', _this.updateDragHandler);
+ return _this;
+ }
+
+ MediaControl.prototype.getExternalInterface = function getExternalInterface() {
+ var _this2 = this;
+
+ return {
+ setVolume: this.setVolume,
+ getVolume: function getVolume() {
+ return _this2.volume;
+ }
+ };
+ };
+
+ MediaControl.prototype.bindEvents = function bindEvents() {
+ var _this3 = this;
+
+ this.stopListening();
+ this.listenTo(this.core, _events2.default.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
+ this.listenTo(this.core, _events2.default.CORE_MOUSE_MOVE, this.show);
+ this.listenTo(this.core, _events2.default.CORE_MOUSE_LEAVE, function () {
+ return _this3.hide(_this3.options.hideMediaControlDelay);
+ });
+ this.listenTo(this.core, _events2.default.CORE_FULLSCREEN, this.show);
+ this.listenTo(this.core, _events2.default.CORE_OPTIONS_CHANGE, this.configure);
+ _mediator2.default.on(this.options.playerId + ':' + _events2.default.PLAYER_RESIZE, this.playerResize, this);
+ this.bindContainerEvents();
+ };
+
+ MediaControl.prototype.bindContainerEvents = function bindContainerEvents() {
+ if (!this.container) return;
+ this.listenTo(this.container, _events2.default.CONTAINER_PLAY, this.changeTogglePlay);
+ this.listenTo(this.container, _events2.default.CONTAINER_PAUSE, this.changeTogglePlay);
+ this.listenTo(this.container, _events2.default.CONTAINER_STOP, this.changeTogglePlay);
+ this.listenTo(this.container, _events2.default.CONTAINER_DBLCLICK, this.toggleFullscreen);
+ this.listenTo(this.container, _events2.default.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
+ this.listenTo(this.container, _events2.default.CONTAINER_PROGRESS, this.updateProgressBar);
+ this.listenTo(this.container, _events2.default.CONTAINER_SETTINGSUPDATE, this.settingsUpdate);
+ this.listenTo(this.container, _events2.default.CONTAINER_PLAYBACKDVRSTATECHANGED, this.settingsUpdate);
+ this.listenTo(this.container, _events2.default.CONTAINER_HIGHDEFINITIONUPDATE, this.highDefinitionUpdate);
+ this.listenTo(this.container, _events2.default.CONTAINER_MEDIACONTROL_DISABLE, this.disable);
+ this.listenTo(this.container, _events2.default.CONTAINER_MEDIACONTROL_ENABLE, this.enable);
+ this.listenTo(this.container, _events2.default.CONTAINER_ENDED, this.ended);
+ this.listenTo(this.container, _events2.default.CONTAINER_VOLUME, this.onVolumeChanged);
+ this.listenTo(this.container, _events2.default.CONTAINER_OPTIONS_CHANGE, this.setInitialVolume);
+ if (this.container.playback.el.nodeName.toLowerCase() === 'video') {
+ // wait until the metadata has loaded and then check if fullscreen on video tag is supported
+ this.listenToOnce(this.container, _events2.default.CONTAINER_LOADEDMETADATA, this.onLoadedMetadataOnVideoTag);
+ }
+ };
+
+ MediaControl.prototype.disable = function disable() {
+ this.userDisabled = true;
+ this.hide();
+ this.unbindKeyEvents();
+ this.$el.hide();
+ };
+
+ MediaControl.prototype.enable = function enable() {
+ if (this.options.chromeless) return;
+ this.userDisabled = false;
+ this.bindKeyEvents();
+ this.show();
+ };
+
+ MediaControl.prototype.play = function play() {
+ this.container && this.container.play();
+ };
+
+ MediaControl.prototype.pause = function pause() {
+ this.container && this.container.pause();
+ };
+
+ MediaControl.prototype.stop = function stop() {
+ this.container && this.container.stop();
+ };
+
+ MediaControl.prototype.setInitialVolume = function setInitialVolume() {
+ var initialVolume = this.persistConfig ? _utils.Config.restore('volume') : 100;
+ var options = this.container && this.container.options || this.options;
+ this.setVolume(options.mute ? 0 : initialVolume, true);
+ };
+
+ MediaControl.prototype.onVolumeChanged = function onVolumeChanged() {
+ this.updateVolumeUI();
+ };
+
+ MediaControl.prototype.onLoadedMetadataOnVideoTag = function onLoadedMetadataOnVideoTag() {
+ var video = this.playback && this.playback.el;
+ // video.webkitSupportsFullscreen is deprecated but iOS appears to only use this
+ // see https://github.com/clappr/clappr/issues/1127
+ if (!_utils.Fullscreen.fullscreenEnabled() && video.webkitSupportsFullscreen) {
+ this.fullScreenOnVideoTagSupported = true;
+ this.settingsUpdate();
+ }
+ };
+
+ MediaControl.prototype.updateVolumeUI = function updateVolumeUI() {
+ // this will be called after a render
+ if (!this.rendered) return;
+
+ // update volume bar scrubber/fill on bar mode
+ this.$volumeBarContainer.find('.bar-fill-2').css({});
+ var containerWidth = this.$volumeBarContainer.width();
+ var barWidth = this.$volumeBarBackground.width();
+ var offset = (containerWidth - barWidth) / 2.0;
+ var pos = barWidth * this.volume / 100.0 + offset;
+ this.$volumeBarFill.css({ width: this.volume + '%' });
+ this.$volumeBarScrubber.css({ left: pos });
+
+ // update volume bar segments on segmented bar mode
+ this.$volumeBarContainer.find('.segmented-bar-element').removeClass('fill');
+ var item = Math.ceil(this.volume / 10.0);
+ this.$volumeBarContainer.find('.segmented-bar-element').slice(0, item).addClass('fill');
+ this.$volumeIcon.html('');
+ this.$volumeIcon.removeClass('muted');
+ if (!this.muted) {
+ this.$volumeIcon.append(_volume2.default);
+ } else {
+ this.$volumeIcon.append(_mute2.default);
+ this.$volumeIcon.addClass('muted');
+ }
+ this.applyButtonStyle(this.$volumeIcon);
+ };
+
+ MediaControl.prototype.changeTogglePlay = function changeTogglePlay() {
+ this.$playPauseToggle.html('');
+ this.$playStopToggle.html('');
+ if (this.container && this.container.isPlaying()) {
+ this.$playPauseToggle.append(_pause2.default);
+ this.$playStopToggle.append(_stop2.default);
+ this.trigger(_events2.default.MEDIACONTROL_PLAYING);
+ } else {
+ this.$playPauseToggle.append(_play2.default);
+ this.$playStopToggle.append(_play2.default);
+ this.trigger(_events2.default.MEDIACONTROL_NOTPLAYING);
+ _browser2.default.isMobile && this.show();
+ }
+ this.applyButtonStyle(this.$playPauseToggle);
+ this.applyButtonStyle(this.$playStopToggle);
+ };
+
+ MediaControl.prototype.mousemoveOnSeekBar = function mousemoveOnSeekBar(event) {
+ if (this.settings.seekEnabled) {
+ var offsetX = event.pageX - this.$seekBarContainer.offset().left - this.$seekBarHover.width() / 2;
+ this.$seekBarHover.css({ left: offsetX });
+ }
+ this.trigger(_events2.default.MEDIACONTROL_MOUSEMOVE_SEEKBAR, event);
+ };
+
+ MediaControl.prototype.mouseleaveOnSeekBar = function mouseleaveOnSeekBar(event) {
+ this.trigger(_events2.default.MEDIACONTROL_MOUSELEAVE_SEEKBAR, event);
+ };
+
+ MediaControl.prototype.onVolumeClick = function onVolumeClick(event) {
+ this.setVolume(this.getVolumeFromUIEvent(event));
+ };
+
+ MediaControl.prototype.mousemoveOnVolumeBar = function mousemoveOnVolumeBar(event) {
+ this.draggingVolumeBar && this.setVolume(this.getVolumeFromUIEvent(event));
+ };
+
+ MediaControl.prototype.playerResize = function playerResize(size) {
+ this.$fullscreenToggle.html('');
+ var icon = _utils.Fullscreen.isFullscreen() ? _shrink2.default : _expand2.default;
+ this.$fullscreenToggle.append(icon);
+ this.applyButtonStyle(this.$fullscreenToggle);
+ this.$el.find('.media-control').length !== 0 && this.$el.removeClass('w320');
+ if (size.width <= 320 || this.options.hideVolumeBar) this.$el.addClass('w320');
+ };
+
+ MediaControl.prototype.togglePlayPause = function togglePlayPause() {
+ this.container.isPlaying() ? this.container.pause() : this.container.play();
+ return false;
+ };
+
+ MediaControl.prototype.togglePlayStop = function togglePlayStop() {
+ this.container.isPlaying() ? this.container.stop() : this.container.play();
+ };
+
+ MediaControl.prototype.startSeekDrag = function startSeekDrag(event) {
+ if (!this.settings.seekEnabled) return;
+ this.draggingSeekBar = true;
+ this.$el.addClass('dragging');
+ this.$seekBarLoaded.addClass('media-control-notransition');
+ this.$seekBarPosition.addClass('media-control-notransition');
+ this.$seekBarScrubber.addClass('media-control-notransition');
+ event && event.preventDefault();
+ };
+
+ MediaControl.prototype.startVolumeDrag = function startVolumeDrag(event) {
+ this.draggingVolumeBar = true;
+ this.$el.addClass('dragging');
+ event && event.preventDefault();
+ };
+
+ MediaControl.prototype.stopDrag = function stopDrag(event) {
+ this.draggingSeekBar && this.seek(event);
+ this.$el.removeClass('dragging');
+ this.$seekBarLoaded.removeClass('media-control-notransition');
+ this.$seekBarPosition.removeClass('media-control-notransition');
+ this.$seekBarScrubber.removeClass('media-control-notransition dragging');
+ this.draggingSeekBar = false;
+ this.draggingVolumeBar = false;
+ };
+
+ MediaControl.prototype.updateDrag = function updateDrag(event) {
+ if (this.draggingSeekBar) {
+ event.preventDefault();
+ var offsetX = event.pageX - this.$seekBarContainer.offset().left;
+ var pos = offsetX / this.$seekBarContainer.width() * 100;
+ pos = Math.min(100, Math.max(pos, 0));
+ this.setSeekPercentage(pos);
+ } else if (this.draggingVolumeBar) {
+ event.preventDefault();
+ this.setVolume(this.getVolumeFromUIEvent(event));
+ }
+ };
+
+ MediaControl.prototype.getVolumeFromUIEvent = function getVolumeFromUIEvent(event) {
+ var offsetY = event.pageX - this.$volumeBarContainer.offset().left;
+ var volumeFromUI = offsetY / this.$volumeBarContainer.width() * 100;
+ return volumeFromUI;
+ };
+
+ MediaControl.prototype.toggleMute = function toggleMute() {
+ this.setVolume(this.muted ? 100 : 0);
+ };
+
+ MediaControl.prototype.setVolume = function setVolume(value) {
+ var _this4 = this;
+
+ var isInitialVolume = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
+ value = Math.min(100, Math.max(value, 0));
+ // this will hold the intended volume
+ // it may not actually get set to this straight away
+ // if the container is not ready etc
+ this.intendedVolume = value;
+ this.persistConfig && !isInitialVolume && _utils.Config.persist('volume', value);
+ var setWhenContainerReady = function setWhenContainerReady() {
+ if (_this4.container && _this4.container.isReady) {
+ _this4.container.setVolume(value);
+ } else {
+ _this4.listenToOnce(_this4.container, _events2.default.CONTAINER_READY, function () {
+ _this4.container.setVolume(value);
+ });
+ }
+ };
+
+ if (!this.container) this.listenToOnce(this, _events2.default.MEDIACONTROL_CONTAINERCHANGED, function () {
+ return setWhenContainerReady();
+ });else setWhenContainerReady();
+ };
+
+ MediaControl.prototype.toggleFullscreen = function toggleFullscreen() {
+ this.trigger(_events2.default.MEDIACONTROL_FULLSCREEN, this.name);
+ this.container.fullscreen();
+ this.core.toggleFullscreen();
+ this.resetUserKeepVisible();
+ };
+
+ MediaControl.prototype.onActiveContainerChanged = function onActiveContainerChanged() {
+ this.fullScreenOnVideoTagSupported = null;
+ this.bindEvents();
+ _mediator2.default.off(this.options.playerId + ':' + _events2.default.PLAYER_RESIZE, this.playerResize, this);
+ // set the new container to match the volume of the last one
+ this.setInitialVolume();
+ this.changeTogglePlay();
+ this.bindContainerEvents();
+ this.settingsUpdate();
+ this.container && this.container.trigger(_events2.default.CONTAINER_PLAYBACKDVRSTATECHANGED, this.container.isDvrInUse());
+ this.container && this.container.mediaControlDisabled && this.disable();
+ this.trigger(_events2.default.MEDIACONTROL_CONTAINERCHANGED);
+ };
+
+ MediaControl.prototype.showVolumeBar = function showVolumeBar() {
+ this.hideVolumeId && clearTimeout(this.hideVolumeId);
+ this.$volumeBarContainer.removeClass('volume-bar-hide');
+ };
+
+ MediaControl.prototype.hideVolumeBar = function hideVolumeBar() {
+ var _this5 = this;
+
+ var timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 400;
+
+ if (!this.$volumeBarContainer) return;
+ if (this.draggingVolumeBar) {
+ this.hideVolumeId = setTimeout(function () {
+ return _this5.hideVolumeBar();
+ }, timeout);
+ } else {
+ this.hideVolumeId && clearTimeout(this.hideVolumeId);
+ this.hideVolumeId = setTimeout(function () {
+ return _this5.$volumeBarContainer.addClass('volume-bar-hide');
+ }, timeout);
+ }
+ };
+
+ MediaControl.prototype.ended = function ended() {
+ this.changeTogglePlay();
+ };
+
+ MediaControl.prototype.updateProgressBar = function updateProgressBar(progress) {
+ var loadedStart = progress.start / progress.total * 100;
+ var loadedEnd = progress.current / progress.total * 100;
+ this.$seekBarLoaded.css({ left: loadedStart + '%', width: loadedEnd - loadedStart + '%' });
+ };
+
+ MediaControl.prototype.onTimeUpdate = function onTimeUpdate(timeProgress) {
+ if (this.draggingSeekBar) return;
+ // TODO why should current time ever be negative?
+ var position = timeProgress.current < 0 ? timeProgress.total : timeProgress.current;
+
+ this.currentPositionValue = position;
+ this.currentDurationValue = timeProgress.total;
+ this.renderSeekBar();
+ };
+
+ MediaControl.prototype.renderSeekBar = function renderSeekBar() {
+ // this will be triggered as soon as these become available
+ if (this.currentPositionValue === null || this.currentDurationValue === null) return;
+
+ // default to 100%
+ this.currentSeekBarPercentage = 100;
+ if (this.container && (this.container.getPlaybackType() !== _playback2.default.LIVE || this.container.isDvrInUse())) this.currentSeekBarPercentage = this.currentPositionValue / this.currentDurationValue * 100;
+
+ this.setSeekPercentage(this.currentSeekBarPercentage);
+
+ var newPosition = (0, _utils.formatTime)(this.currentPositionValue);
+ var newDuration = (0, _utils.formatTime)(this.currentDurationValue);
+ if (newPosition !== this.displayedPosition) {
+ this.$position.text(newPosition);
+ this.displayedPosition = newPosition;
+ }
+ if (newDuration !== this.displayedDuration) {
+ this.$duration.text(newDuration);
+ this.displayedDuration = newDuration;
+ }
+ };
+
+ MediaControl.prototype.seek = function seek(event) {
+ if (!this.settings.seekEnabled) return;
+ var offsetX = event.pageX - this.$seekBarContainer.offset().left;
+ var pos = offsetX / this.$seekBarContainer.width() * 100;
+ pos = Math.min(100, Math.max(pos, 0));
+ this.container && this.container.seekPercentage(pos);
+ this.setSeekPercentage(pos);
+ return false;
+ };
+
+ MediaControl.prototype.setKeepVisible = function setKeepVisible() {
+ this.keepVisible = true;
+ };
+
+ MediaControl.prototype.resetKeepVisible = function resetKeepVisible() {
+ this.keepVisible = false;
+ };
+
+ MediaControl.prototype.setUserKeepVisible = function setUserKeepVisible() {
+ this.userKeepVisible = true;
+ };
+
+ MediaControl.prototype.resetUserKeepVisible = function resetUserKeepVisible() {
+ this.userKeepVisible = false;
+ };
+
+ MediaControl.prototype.isVisible = function isVisible() {
+ return !this.$el.hasClass('media-control-hide');
+ };
+
+ MediaControl.prototype.show = function show(event) {
+ var _this6 = this;
+
+ if (this.disabled) return;
+
+ var timeout = 2000;
+ var mousePointerMoved = event && event.clientX !== this.lastMouseX && event.clientY !== this.lastMouseY;
+ if (!event || mousePointerMoved || navigator.userAgent.match(/firefox/i)) {
+ clearTimeout(this.hideId);
+ this.$el.show();
+ this.trigger(_events2.default.MEDIACONTROL_SHOW, this.name);
+ this.container && this.container.trigger(_events2.default.CONTAINER_MEDIACONTROL_SHOW, this.name);
+ this.$el.removeClass('media-control-hide');
+ this.hideId = setTimeout(function () {
+ return _this6.hide();
+ }, timeout);
+ if (event) {
+ this.lastMouseX = event.clientX;
+ this.lastMouseY = event.clientY;
+ }
+ }
+ var showing = true;
+ this.updateCursorStyle(showing);
+ };
+
+ MediaControl.prototype.hide = function hide() {
+ var _this7 = this;
+
+ var delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+
+ if (!this.isVisible()) return;
+
+ var timeout = delay || 2000;
+ clearTimeout(this.hideId);
+ if (!this.disabled && this.options.hideMediaControl === false) return;
+
+ var hasKeepVisibleRequested = this.userKeepVisible || this.keepVisible;
+ var hasDraggingAction = this.draggingSeekBar || this.draggingVolumeBar;
+
+ if (!this.disabled && (delay || hasKeepVisibleRequested || hasDraggingAction)) {
+ this.hideId = setTimeout(function () {
+ return _this7.hide();
+ }, timeout);
+ } else {
+ this.trigger(_events2.default.MEDIACONTROL_HIDE, this.name);
+ this.container && this.container.trigger(_events2.default.CONTAINER_MEDIACONTROL_HIDE, this.name);
+ this.$el.addClass('media-control-hide');
+ this.hideVolumeBar(0);
+ var showing = false;
+ this.updateCursorStyle(showing);
+ }
+ };
+
+ MediaControl.prototype.updateCursorStyle = function updateCursorStyle(showing) {
+ if (showing) this.core.$el.removeClass('nocursor');else if (_utils.Fullscreen.isFullscreen()) this.core.$el.addClass('nocursor');
+ };
+
+ MediaControl.prototype.settingsUpdate = function settingsUpdate() {
+ var newSettings = this.getSettings();
+ if (newSettings && !this.fullScreenOnVideoTagSupported && !_utils.Fullscreen.fullscreenEnabled()) {
+ // remove fullscreen from settings if it is present
+ newSettings.default && (0, _utils.removeArrayItem)(newSettings.default, 'fullscreen');
+ newSettings.left && (0, _utils.removeArrayItem)(newSettings.left, 'fullscreen');
+ newSettings.right && (0, _utils.removeArrayItem)(newSettings.right, 'fullscreen');
+ }
+ var settingsChanged = (0, _stringify2.default)(this.settings) !== (0, _stringify2.default)(newSettings);
+ if (settingsChanged) {
+ this.settings = newSettings;
+ this.render();
+ }
+ };
+
+ MediaControl.prototype.getSettings = function getSettings() {
+ return _clapprZepto2.default.extend(true, {}, this.container && this.container.settings);
+ };
+
+ MediaControl.prototype.highDefinitionUpdate = function highDefinitionUpdate(isHD) {
+ this.isHD = isHD;
+ var method = isHD ? 'addClass' : 'removeClass';
+ this.$hdIndicator[method]('enabled');
+ };
+
+ MediaControl.prototype.createCachedElements = function createCachedElements() {
+ var $layer = this.$el.find('.media-control-layer');
+ this.$duration = $layer.find('.media-control-indicator[data-duration]');
+ this.$fullscreenToggle = $layer.find('button.media-control-button[data-fullscreen]');
+ this.$playPauseToggle = $layer.find('button.media-control-button[data-playpause]');
+ this.$playStopToggle = $layer.find('button.media-control-button[data-playstop]');
+ this.$position = $layer.find('.media-control-indicator[data-position]');
+ this.$seekBarContainer = $layer.find('.bar-container[data-seekbar]');
+ this.$seekBarHover = $layer.find('.bar-hover[data-seekbar]');
+ this.$seekBarLoaded = $layer.find('.bar-fill-1[data-seekbar]');
+ this.$seekBarPosition = $layer.find('.bar-fill-2[data-seekbar]');
+ this.$seekBarScrubber = $layer.find('.bar-scrubber[data-seekbar]');
+ this.$volumeBarContainer = $layer.find('.bar-container[data-volume]');
+ this.$volumeContainer = $layer.find('.drawer-container[data-volume]');
+ this.$volumeIcon = $layer.find('.drawer-icon[data-volume]');
+ this.$volumeBarBackground = this.$el.find('.bar-background[data-volume]');
+ this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]');
+ this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]');
+ this.$hdIndicator = this.$el.find('button.media-control-button[data-hd-indicator]');
+ this.resetIndicators();
+ this.initializeIcons();
+ };
+
+ MediaControl.prototype.resetIndicators = function resetIndicators() {
+ this.displayedPosition = this.$position.text();
+ this.displayedDuration = this.$duration.text();
+ };
+
+ MediaControl.prototype.initializeIcons = function initializeIcons() {
+ var $layer = this.$el.find('.media-control-layer');
+ $layer.find('button.media-control-button[data-play]').append(_play2.default);
+ $layer.find('button.media-control-button[data-pause]').append(_pause2.default);
+ $layer.find('button.media-control-button[data-stop]').append(_stop2.default);
+ this.$playPauseToggle.append(_play2.default);
+ this.$playStopToggle.append(_play2.default);
+ this.$volumeIcon.append(_volume2.default);
+ this.$fullscreenToggle.append(_expand2.default);
+ this.$hdIndicator.append(_hd2.default);
+ };
+
+ MediaControl.prototype.setSeekPercentage = function setSeekPercentage(value) {
+ value = Math.max(Math.min(value, 100.0), 0);
+ // not changed since last update
+ if (this.displayedSeekBarPercentage === value) return;
+
+ this.displayedSeekBarPercentage = value;
+ this.$seekBarPosition.removeClass('media-control-notransition');
+ this.$seekBarScrubber.removeClass('media-control-notransition');
+ this.$seekBarPosition.css({ width: value + '%' });
+ this.$seekBarScrubber.css({ left: value + '%' });
+ };
+
+ MediaControl.prototype.seekRelative = function seekRelative(delta) {
+ if (!this.settings.seekEnabled) return;
+
+ var currentTime = this.container.getCurrentTime();
+ var duration = this.container.getDuration();
+ var position = Math.min(Math.max(currentTime + delta, 0), duration);
+ position = Math.min(position * 100 / duration, 100);
+ this.container.seekPercentage(position);
+ };
+
+ MediaControl.prototype.bindKeyAndShow = function bindKeyAndShow(key, callback) {
+ var _this8 = this;
+
+ this.kibo.down(key, function () {
+ _this8.show();
+ return callback();
+ });
+ };
+
+ MediaControl.prototype.bindKeyEvents = function bindKeyEvents() {
+ var _this9 = this;
+
+ if (_browser2.default.isMobile || this.options.disableKeyboardShortcuts) return;
+
+ this.unbindKeyEvents();
+ this.kibo = new _vendor.Kibo(this.options.focusElement || this.options.parentElement);
+ this.bindKeyAndShow('space', function () {
+ return _this9.togglePlayPause();
+ });
+ this.bindKeyAndShow('left', function () {
+ return _this9.seekRelative(-5);
+ });
+ this.bindKeyAndShow('right', function () {
+ return _this9.seekRelative(5);
+ });
+ this.bindKeyAndShow('shift left', function () {
+ return _this9.seekRelative(-10);
+ });
+ this.bindKeyAndShow('shift right', function () {
+ return _this9.seekRelative(10);
+ });
+ this.bindKeyAndShow('shift ctrl left', function () {
+ return _this9.seekRelative(-15);
+ });
+ this.bindKeyAndShow('shift ctrl right', function () {
+ return _this9.seekRelative(15);
+ });
+ var keys = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
+ keys.forEach(function (i) {
+ _this9.bindKeyAndShow(i, function () {
+ _this9.settings.seekEnabled && _this9.container && _this9.container.seekPercentage(i * 10);
+ });
+ });
+ };
+
+ MediaControl.prototype.unbindKeyEvents = function unbindKeyEvents() {
+ if (this.kibo) {
+ this.kibo.off('space');
+ this.kibo.off('left');
+ this.kibo.off('right');
+ this.kibo.off('shift left');
+ this.kibo.off('shift right');
+ this.kibo.off('shift ctrl left');
+ this.kibo.off('shift ctrl right');
+ this.kibo.off(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']);
+ }
+ };
+
+ MediaControl.prototype.parseColors = function parseColors() {
+ if (this.options.mediacontrol) {
+ this.buttonsColor = this.options.mediacontrol.buttons;
+ var seekbarColor = this.options.mediacontrol.seekbar;
+ this.$el.find('.bar-fill-2[data-seekbar]').css('background-color', seekbarColor);
+ this.$el.find('.media-control-icon svg path').css('fill', this.buttonsColor);
+ this.$el.find('.segmented-bar-element[data-volume]').css('boxShadow', 'inset 2px 0 0 ' + this.buttonsColor);
+ }
+ };
+
+ MediaControl.prototype.applyButtonStyle = function applyButtonStyle(element) {
+ this.buttonsColor && element && (0, _clapprZepto2.default)(element).find('svg path').css('fill', this.buttonsColor);
+ };
+
+ MediaControl.prototype.destroy = function destroy() {
+ (0, _clapprZepto2.default)(document).unbind('mouseup', this.stopDragHandler);
+ (0, _clapprZepto2.default)(document).unbind('mousemove', this.updateDragHandler);
+ this.unbindKeyEvents();
+ this.stopListening();
+ _UICorePlugin.prototype.destroy.call(this);
+ };
+
+ /**
+ * enables to configure the media control after its creation
+ * @method configure
+ * @param {Object} options all the options to change in form of a javascript object
+ */
+
+
+ MediaControl.prototype.configure = function configure() {
+ this.options.chromeless ? this.disable() : this.enable();
+ this.trigger(_events2.default.MEDIACONTROL_OPTIONS_CHANGE);
+ };
+
+ MediaControl.prototype.render = function render() {
+ var _this10 = this;
+
+ var timeout = this.options.hideMediaControlDelay || 2000;
+ this.settings && this.$el.html(this.template({ settings: this.settings }));
+ this.createCachedElements();
+ this.$playPauseToggle.addClass('paused');
+ this.$playStopToggle.addClass('stopped');
+
+ this.changeTogglePlay();
+
+ if (this.container) {
+ this.hideId = setTimeout(function () {
+ return _this10.hide();
+ }, timeout);
+ this.disabled && this.hide();
+ }
+
+ // Video volume cannot be changed with Safari on mobile devices
+ // Display mute/unmute icon only if Safari version >= 10
+ if (_browser2.default.isSafari && _browser2.default.isMobile) {
+ if (_browser2.default.version < 10) this.$volumeContainer.css('display', 'none');else this.$volumeBarContainer.css('display', 'none');
+ }
+
+ this.$seekBarPosition.addClass('media-control-notransition');
+ this.$seekBarScrubber.addClass('media-control-notransition');
+
+ var previousSeekPercentage = 0;
+ if (this.displayedSeekBarPercentage) previousSeekPercentage = this.displayedSeekBarPercentage;
+
+ this.displayedSeekBarPercentage = null;
+ this.setSeekPercentage(previousSeekPercentage);
+
+ process.nextTick(function () {
+ !_this10.settings.seekEnabled && _this10.$seekBarContainer.addClass('seek-disabled');
+ !_browser2.default.isMobile && !_this10.options.disableKeyboardShortcuts && _this10.bindKeyEvents();
+ _this10.playerResize({ width: _this10.options.width, height: _this10.options.height });
+ _this10.hideVolumeBar(0);
+ });
+
+ this.parseColors();
+ this.highDefinitionUpdate(this.isHD);
+
+ this.core.$el.append(this.el);
+
+ this.rendered = true;
+ this.updateVolumeUI();
+ this.trigger(_events2.default.MEDIACONTROL_RENDERED);
+ return this;
+ };
+
+ return MediaControl;
+}(_ui_core_plugin2.default); // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/**
+ * The MediaControl is responsible for displaying the Player controls.
+ */
+
+exports.default = MediaControl;
+
+
+MediaControl.extend = function (properties) {
+ return (0, _utils.extend)(MediaControl, properties);
+};
+module.exports = exports['default'];
+/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../../node_modules/node-libs-browser/node_modules/process/browser.js */ "./node_modules/node-libs-browser/node_modules/process/browser.js")))
+
+/***/ }),
+
+/***/ "./src/plugins/media_control/public/closed-hand.cur":
+/*!**********************************************************!*\
+ !*** ./src/plugins/media_control/public/closed-hand.cur ***!
+ \**********************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "<%=baseUrl%>/a8c874b93b3d848f39a71260c57e3863.cur";
+
+/***/ }),
+
+/***/ "./src/plugins/media_control/public/media-control.html":
+/*!*************************************************************!*\
+ !*** ./src/plugins/media_control/public/media-control.html ***!
+ \*************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "
\n\n";
+
+/***/ }),
+
+/***/ "./src/plugins/media_control/public/media-control.scss":
+/*!*************************************************************!*\
+ !*** ./src/plugins/media_control/public/media-control.scss ***!
+ \*************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./media-control.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/media_control/public/media-control.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/poster/index.js":
+/*!*************************************!*\
+ !*** ./src/plugins/poster/index.js ***!
+ \*************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _poster = __webpack_require__(/*! ./poster */ "./src/plugins/poster/poster.js");
+
+var _poster2 = _interopRequireDefault(_poster);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _poster2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/poster/poster.js":
+/*!**************************************!*\
+ !*** ./src/plugins/poster/poster.js ***!
+ \**************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(process) {
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _ui_container_plugin = __webpack_require__(/*! ../../base/ui_container_plugin */ "./src/base/ui_container_plugin.js");
+
+var _ui_container_plugin2 = _interopRequireDefault(_ui_container_plugin);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _error = __webpack_require__(/*! ../../components/error/error */ "./src/components/error/error.js");
+
+var _error2 = _interopRequireDefault(_error);
+
+var _poster = __webpack_require__(/*! ./public/poster.html */ "./src/plugins/poster/public/poster.html");
+
+var _poster2 = _interopRequireDefault(_poster);
+
+var _play = __webpack_require__(/*! ../../icons/01-play.svg */ "./src/icons/01-play.svg");
+
+var _play2 = _interopRequireDefault(_play);
+
+__webpack_require__(/*! ./public/poster.scss */ "./src/plugins/poster/public/poster.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+//Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+var PosterPlugin = function (_UIContainerPlugin) {
+ (0, _inherits3.default)(PosterPlugin, _UIContainerPlugin);
+ (0, _createClass3.default)(PosterPlugin, [{
+ key: 'name',
+ get: function get() {
+ return 'poster';
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_poster2.default);
+ }
+ }, {
+ key: 'shouldRender',
+ get: function get() {
+ var showForNoOp = !!(this.options.poster && this.options.poster.showForNoOp);
+ return this.container.playback.name !== 'html_img' && (this.container.playback.getPlaybackType() !== _playback2.default.NO_OP || showForNoOp);
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'class': 'player-poster',
+ 'data-poster': ''
+ };
+ }
+ }, {
+ key: 'events',
+ get: function get() {
+ return {
+ 'click': 'clicked'
+ };
+ }
+ }, {
+ key: 'showOnVideoEnd',
+ get: function get() {
+ return !this.options.poster || this.options.poster.showOnVideoEnd || this.options.poster.showOnVideoEnd === undefined;
+ }
+ }]);
+
+ function PosterPlugin(container) {
+ (0, _classCallCheck3.default)(this, PosterPlugin);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UIContainerPlugin.call(this, container));
+
+ _this.hasStartedPlaying = false;
+ _this.playRequested = false;
+ _this.render();
+ process.nextTick(function () {
+ return _this.update();
+ });
+ return _this;
+ }
+
+ PosterPlugin.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.container, _events2.default.CONTAINER_STOP, this.onStop);
+ this.listenTo(this.container, _events2.default.CONTAINER_PLAY, this.onPlay);
+ this.listenTo(this.container, _events2.default.CONTAINER_STATE_BUFFERING, this.update);
+ this.listenTo(this.container, _events2.default.CONTAINER_STATE_BUFFERFULL, this.update);
+ this.listenTo(this.container, _events2.default.CONTAINER_OPTIONS_CHANGE, this.render);
+ this.listenTo(this.container, _events2.default.CONTAINER_ERROR, this.onError);
+ this.showOnVideoEnd && this.listenTo(this.container, _events2.default.CONTAINER_ENDED, this.onStop);
+ };
+
+ PosterPlugin.prototype.onError = function onError(error) {
+ this.hasFatalError = error.level === _error2.default.Levels.FATAL;
+
+ if (this.hasFatalError) {
+ this.hasStartedPlaying = false;
+ this.playRequested = false;
+ this.showPlayButton();
+ }
+ };
+
+ PosterPlugin.prototype.onPlay = function onPlay() {
+ this.hasStartedPlaying = true;
+ this.update();
+ };
+
+ PosterPlugin.prototype.onStop = function onStop() {
+ this.hasStartedPlaying = false;
+ this.playRequested = false;
+ this.update();
+ };
+
+ PosterPlugin.prototype.updatePlayButton = function updatePlayButton(show) {
+ if (show && (!this.options.chromeless || this.options.allowUserInteraction)) this.showPlayButton();else this.hidePlayButton();
+ };
+
+ PosterPlugin.prototype.showPlayButton = function showPlayButton() {
+ if (this.hasFatalError && !this.options.disableErrorScreen) return;
+
+ this.$playButton.show();
+ this.$el.addClass('clickable');
+ };
+
+ PosterPlugin.prototype.hidePlayButton = function hidePlayButton() {
+ this.$playButton.hide();
+ this.$el.removeClass('clickable');
+ };
+
+ PosterPlugin.prototype.clicked = function clicked() {
+ // Let "click_to_pause" plugin handle click event if media has started playing
+ if (!this.hasStartedPlaying) {
+ if (!this.options.chromeless || this.options.allowUserInteraction) {
+ this.playRequested = true;
+ this.update();
+ this.container.play();
+ }
+ return false;
+ }
+ };
+
+ PosterPlugin.prototype.shouldHideOnPlay = function shouldHideOnPlay() {
+ // Audio broadcasts should keep the poster up; video should hide poster while playing.
+ return !this.container.playback.isAudioOnly;
+ };
+
+ PosterPlugin.prototype.update = function update() {
+ if (!this.shouldRender) return;
+
+ var showPlayButton = !this.playRequested && !this.hasStartedPlaying && !this.container.buffering;
+ this.updatePlayButton(showPlayButton);
+ this.updatePoster();
+ };
+
+ PosterPlugin.prototype.updatePoster = function updatePoster() {
+ if (!this.hasStartedPlaying) this.showPoster();else this.hidePoster();
+ };
+
+ PosterPlugin.prototype.showPoster = function showPoster() {
+ this.container.disableMediaControl();
+ this.$el.show();
+ };
+
+ PosterPlugin.prototype.hidePoster = function hidePoster() {
+ this.container.enableMediaControl();
+ if (this.shouldHideOnPlay()) this.$el.hide();
+ };
+
+ PosterPlugin.prototype.render = function render() {
+ if (!this.shouldRender) return;
+
+ this.$el.html(this.template());
+
+ var isRegularPoster = this.options.poster && this.options.poster.custom === undefined;
+
+ if (isRegularPoster) {
+ var posterUrl = this.options.poster.url || this.options.poster;
+ this.$el.css({ 'background-image': 'url(' + posterUrl + ')' });
+ } else if (this.options.poster) {
+ this.$el.css({ 'background': this.options.poster.custom });
+ }
+
+ this.container.$el.append(this.el);
+ this.$playWrapper = this.$el.find('.play-wrapper');
+ this.$playWrapper.append(_play2.default);
+ this.$playButton = this.$playWrapper.find('svg');
+ this.$playButton.addClass('poster-icon');
+ this.$playButton.attr('data-poster', '');
+
+ var buttonsColor = this.options.mediacontrol && this.options.mediacontrol.buttons;
+ if (buttonsColor) this.$el.find('svg path').css('fill', buttonsColor);
+
+ if (this.options.mediacontrol && this.options.mediacontrol.buttons) {
+ buttonsColor = this.options.mediacontrol.buttons;
+ this.$playButton.css('color', buttonsColor);
+ }
+ this.update();
+ return this;
+ };
+
+ return PosterPlugin;
+}(_ui_container_plugin2.default);
+
+exports.default = PosterPlugin;
+module.exports = exports['default'];
+/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../../node_modules/node-libs-browser/node_modules/process/browser.js */ "./node_modules/node-libs-browser/node_modules/process/browser.js")))
+
+/***/ }),
+
+/***/ "./src/plugins/poster/public/poster.html":
+/*!***********************************************!*\
+ !*** ./src/plugins/poster/public/poster.html ***!
+ \***********************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "
\n";
+
+/***/ }),
+
+/***/ "./src/plugins/poster/public/poster.scss":
+/*!***********************************************!*\
+ !*** ./src/plugins/poster/public/poster.scss ***!
+ \***********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./poster.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/poster/public/poster.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/seek_time/index.js":
+/*!****************************************!*\
+ !*** ./src/plugins/seek_time/index.js ***!
+ \****************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _seek_time = __webpack_require__(/*! ./seek_time */ "./src/plugins/seek_time/seek_time.js");
+
+var _seek_time2 = _interopRequireDefault(_seek_time);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _seek_time2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/seek_time/public/seek_time.html":
+/*!*****************************************************!*\
+ !*** ./src/plugins/seek_time/public/seek_time.html ***!
+ \*****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = " \n \n";
+
+/***/ }),
+
+/***/ "./src/plugins/seek_time/public/seek_time.scss":
+/*!*****************************************************!*\
+ !*** ./src/plugins/seek_time/public/seek_time.scss ***!
+ \*****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./seek_time.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/seek_time/public/seek_time.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/seek_time/seek_time.js":
+/*!********************************************!*\
+ !*** ./src/plugins/seek_time/seek_time.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _utils = __webpack_require__(/*! ../../base/utils */ "./src/base/utils.js");
+
+var _ui_core_plugin = __webpack_require__(/*! ../../base/ui_core_plugin */ "./src/base/ui_core_plugin.js");
+
+var _ui_core_plugin2 = _interopRequireDefault(_ui_core_plugin);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _playback = __webpack_require__(/*! ../../base/playback */ "./src/base/playback.js");
+
+var _playback2 = _interopRequireDefault(_playback);
+
+var _seek_time = __webpack_require__(/*! ./public/seek_time.html */ "./src/plugins/seek_time/public/seek_time.html");
+
+var _seek_time2 = _interopRequireDefault(_seek_time);
+
+__webpack_require__(/*! ./public/seek_time.scss */ "./src/plugins/seek_time/public/seek_time.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var SeekTime = function (_UICorePlugin) {
+ (0, _inherits3.default)(SeekTime, _UICorePlugin);
+ (0, _createClass3.default)(SeekTime, [{
+ key: 'name',
+ get: function get() {
+ return 'seek_time';
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_seek_time2.default);
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'class': 'seek-time',
+ 'data-seek-time': ''
+ };
+ }
+ }, {
+ key: 'mediaControl',
+ get: function get() {
+ return this.core.mediaControl;
+ }
+ }, {
+ key: 'mediaControlContainer',
+ get: function get() {
+ return this.mediaControl.container;
+ }
+ }, {
+ key: 'isLiveStreamWithDvr',
+ get: function get() {
+ return this.mediaControlContainer && this.mediaControlContainer.getPlaybackType() === _playback2.default.LIVE && this.mediaControlContainer.isDvrEnabled();
+ }
+ }, {
+ key: 'durationShown',
+ get: function get() {
+ return this.isLiveStreamWithDvr && !this.actualLiveTime;
+ }
+ }, {
+ key: 'useActualLiveTime',
+ get: function get() {
+ return this.actualLiveTime && this.isLiveStreamWithDvr;
+ }
+ }]);
+
+ function SeekTime(core) {
+ (0, _classCallCheck3.default)(this, SeekTime);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UICorePlugin.call(this, core));
+
+ _this.hoveringOverSeekBar = false;
+ _this.hoverPosition = null;
+ _this.duration = null;
+ _this.firstFragDateTime = null;
+ _this.actualLiveTime = !!_this.mediaControl.options.actualLiveTime;
+ if (_this.actualLiveTime) {
+ if (_this.mediaControl.options.actualLiveServerTime) _this.actualLiveServerTimeDiff = new Date().getTime() - new Date(_this.mediaControl.options.actualLiveServerTime).getTime();else _this.actualLiveServerTimeDiff = 0;
+ }
+ return _this;
+ }
+
+ SeekTime.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.mediaControl, _events2.default.MEDIACONTROL_RENDERED, this.render);
+ this.listenTo(this.mediaControl, _events2.default.MEDIACONTROL_MOUSEMOVE_SEEKBAR, this.showTime);
+ this.listenTo(this.mediaControl, _events2.default.MEDIACONTROL_MOUSELEAVE_SEEKBAR, this.hideTime);
+ this.listenTo(this.mediaControl, _events2.default.MEDIACONTROL_CONTAINERCHANGED, this.onContainerChanged);
+ if (this.mediaControlContainer) {
+ this.listenTo(this.mediaControlContainer, _events2.default.CONTAINER_PLAYBACKDVRSTATECHANGED, this.update);
+ this.listenTo(this.mediaControlContainer, _events2.default.CONTAINER_TIMEUPDATE, this.updateDuration);
+ }
+ };
+
+ SeekTime.prototype.onContainerChanged = function onContainerChanged() {
+ this.stopListening();
+ this.bindEvents();
+ };
+
+ SeekTime.prototype.updateDuration = function updateDuration(timeProgress) {
+ this.duration = timeProgress.total;
+ this.firstFragDateTime = timeProgress.firstFragDateTime;
+ this.update();
+ };
+
+ SeekTime.prototype.showTime = function showTime(event) {
+ this.hoveringOverSeekBar = true;
+ this.calculateHoverPosition(event);
+ this.update();
+ };
+
+ SeekTime.prototype.hideTime = function hideTime() {
+ this.hoveringOverSeekBar = false;
+ this.update();
+ };
+
+ SeekTime.prototype.calculateHoverPosition = function calculateHoverPosition(event) {
+ var offset = event.pageX - this.mediaControl.$seekBarContainer.offset().left;
+ // proportion into the seek bar that the mouse is hovered over 0-1
+ this.hoverPosition = Math.min(1, Math.max(offset / this.mediaControl.$seekBarContainer.width(), 0));
+ };
+
+ SeekTime.prototype.getSeekTime = function getSeekTime() {
+ var seekTime = void 0,
+ secondsSinceMidnight = void 0,
+ d = void 0,
+ e = void 0;
+ if (this.useActualLiveTime) {
+ if (this.firstFragDateTime) {
+ e = new Date(this.firstFragDateTime);
+ d = new Date(this.firstFragDateTime);
+ d.setHours(0, 0, 0, 0);
+ secondsSinceMidnight = (e.getTime() - d.getTime()) / 1000 + this.duration;
+ } else {
+ d = new Date(new Date().getTime() - this.actualLiveServerTimeDiff);
+ e = new Date(d);
+ secondsSinceMidnight = (e - d.setHours(0, 0, 0, 0)) / 1000;
+ }
+ seekTime = secondsSinceMidnight - this.duration + this.hoverPosition * this.duration;
+ if (seekTime < 0) seekTime += 86400;
+ } else {
+ seekTime = this.hoverPosition * this.duration;
+ }
+
+ return { seekTime: seekTime, secondsSinceMidnight: secondsSinceMidnight };
+ };
+
+ SeekTime.prototype.update = function update() {
+ if (!this.rendered) {
+ // update() is always called after a render
+ return;
+ }
+ if (!this.shouldBeVisible()) {
+ this.$el.hide();
+ this.$el.css('left', '-100%');
+ } else {
+ var seekTime = this.getSeekTime();
+ var currentSeekTime = (0, _utils.formatTime)(seekTime.seekTime, this.useActualLiveTime);
+ // only update dom if necessary, ie time actually changed
+ if (currentSeekTime !== this.displayedSeekTime) {
+ this.$seekTimeEl.text(currentSeekTime);
+ this.displayedSeekTime = currentSeekTime;
+ }
+
+ if (this.durationShown) {
+ this.$durationEl.show();
+ var currentDuration = (0, _utils.formatTime)(this.actualLiveTime ? seekTime.secondsSinceMidnight : this.duration, this.actualLiveTime);
+ if (currentDuration !== this.displayedDuration) {
+ this.$durationEl.text(currentDuration);
+ this.displayedDuration = currentDuration;
+ }
+ } else {
+ this.$durationEl.hide();
+ }
+
+ // the element must be unhidden before its width is requested, otherwise it's width will be reported as 0
+ this.$el.show();
+ var containerWidth = this.mediaControl.$seekBarContainer.width();
+ var elWidth = this.$el.width();
+ var elLeftPos = this.hoverPosition * containerWidth;
+ elLeftPos -= elWidth / 2;
+ elLeftPos = Math.max(0, Math.min(elLeftPos, containerWidth - elWidth));
+ this.$el.css('left', elLeftPos);
+ }
+ };
+
+ SeekTime.prototype.shouldBeVisible = function shouldBeVisible() {
+ return this.mediaControlContainer && this.mediaControlContainer.settings.seekEnabled && this.hoveringOverSeekBar && this.hoverPosition !== null && this.duration !== null;
+ };
+
+ SeekTime.prototype.render = function render() {
+ this.rendered = true;
+ this.displayedDuration = null;
+ this.displayedSeekTime = null;
+ this.$el.html(this.template());
+ this.$el.hide();
+ this.mediaControl.$el.append(this.el);
+ this.$seekTimeEl = this.$el.find('[data-seek-time]');
+ this.$durationEl = this.$el.find('[data-duration]');
+ this.$durationEl.hide();
+ this.update();
+ };
+
+ return SeekTime;
+}(_ui_core_plugin2.default); // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = SeekTime;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/sources.js":
+/*!********************************!*\
+ !*** ./src/plugins/sources.js ***!
+ \********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _core_plugin = __webpack_require__(/*! ../base/core_plugin */ "./src/base/core_plugin.js");
+
+var _core_plugin2 = _interopRequireDefault(_core_plugin);
+
+var _events = __webpack_require__(/*! ../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var SourcesPlugin = function (_CorePlugin) {
+ (0, _inherits3.default)(SourcesPlugin, _CorePlugin);
+
+ function SourcesPlugin() {
+ (0, _classCallCheck3.default)(this, SourcesPlugin);
+ return (0, _possibleConstructorReturn3.default)(this, _CorePlugin.apply(this, arguments));
+ }
+
+ SourcesPlugin.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.core, _events2.default.CORE_CONTAINERS_CREATED, this.onContainersCreated);
+ };
+
+ SourcesPlugin.prototype.onContainersCreated = function onContainersCreated() {
+ var firstValidSource = this.core.containers.filter(function (container) {
+ return container.playback.name !== 'no_op';
+ })[0] || this.core.containers[0];
+ if (firstValidSource) {
+ this.core.containers.forEach(function (container) {
+ if (container !== firstValidSource) container.destroy();
+ });
+ }
+ };
+
+ (0, _createClass3.default)(SourcesPlugin, [{
+ key: 'name',
+ get: function get() {
+ return 'sources';
+ }
+ }]);
+ return SourcesPlugin;
+}(_core_plugin2.default);
+
+exports.default = SourcesPlugin;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/spinner_three_bounce/index.js":
+/*!***************************************************!*\
+ !*** ./src/plugins/spinner_three_bounce/index.js ***!
+ \***************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _spinner_three_bounce = __webpack_require__(/*! ./spinner_three_bounce */ "./src/plugins/spinner_three_bounce/spinner_three_bounce.js");
+
+var _spinner_three_bounce2 = _interopRequireDefault(_spinner_three_bounce);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _spinner_three_bounce2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/spinner_three_bounce/public/spinner.html":
+/*!**************************************************************!*\
+ !*** ./src/plugins/spinner_three_bounce/public/spinner.html ***!
+ \**************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "
\n";
+
+/***/ }),
+
+/***/ "./src/plugins/spinner_three_bounce/public/spinner.scss":
+/*!**************************************************************!*\
+ !*** ./src/plugins/spinner_three_bounce/public/spinner.scss ***!
+ \**************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./spinner.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/spinner_three_bounce/public/spinner.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/spinner_three_bounce/spinner_three_bounce.js":
+/*!******************************************************************!*\
+ !*** ./src/plugins/spinner_three_bounce/spinner_three_bounce.js ***!
+ \******************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _ui_container_plugin = __webpack_require__(/*! ../../base/ui_container_plugin */ "./src/base/ui_container_plugin.js");
+
+var _ui_container_plugin2 = _interopRequireDefault(_ui_container_plugin);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _spinner = __webpack_require__(/*! ./public/spinner.html */ "./src/plugins/spinner_three_bounce/public/spinner.html");
+
+var _spinner2 = _interopRequireDefault(_spinner);
+
+__webpack_require__(/*! ./public/spinner.scss */ "./src/plugins/spinner_three_bounce/public/spinner.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var SpinnerThreeBouncePlugin = function (_UIContainerPlugin) {
+ (0, _inherits3.default)(SpinnerThreeBouncePlugin, _UIContainerPlugin);
+ (0, _createClass3.default)(SpinnerThreeBouncePlugin, [{
+ key: 'name',
+ get: function get() {
+ return 'spinner';
+ }
+ }, {
+ key: 'attributes',
+ get: function get() {
+ return {
+ 'data-spinner': '',
+ 'class': 'spinner-three-bounce'
+ };
+ }
+ }]);
+
+ function SpinnerThreeBouncePlugin(container) {
+ (0, _classCallCheck3.default)(this, SpinnerThreeBouncePlugin);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UIContainerPlugin.call(this, container));
+
+ _this.template = (0, _template2.default)(_spinner2.default);
+ _this.showTimeout = null;
+ _this.listenTo(_this.container, _events2.default.CONTAINER_STATE_BUFFERING, _this.onBuffering);
+ _this.listenTo(_this.container, _events2.default.CONTAINER_STATE_BUFFERFULL, _this.onBufferFull);
+ _this.listenTo(_this.container, _events2.default.CONTAINER_STOP, _this.onStop);
+ _this.listenTo(_this.container, _events2.default.CONTAINER_ENDED, _this.onStop);
+ _this.listenTo(_this.container, _events2.default.CONTAINER_ERROR, _this.onStop);
+ _this.render();
+ return _this;
+ }
+
+ SpinnerThreeBouncePlugin.prototype.onBuffering = function onBuffering() {
+ this.show();
+ };
+
+ SpinnerThreeBouncePlugin.prototype.onBufferFull = function onBufferFull() {
+ this.hide();
+ };
+
+ SpinnerThreeBouncePlugin.prototype.onStop = function onStop() {
+ this.hide();
+ };
+
+ SpinnerThreeBouncePlugin.prototype.show = function show() {
+ var _this2 = this;
+
+ if (this.showTimeout === null) this.showTimeout = setTimeout(function () {
+ return _this2.$el.show();
+ }, 300);
+ };
+
+ SpinnerThreeBouncePlugin.prototype.hide = function hide() {
+ if (this.showTimeout !== null) {
+ clearTimeout(this.showTimeout);
+ this.showTimeout = null;
+ }
+ this.$el.hide();
+ };
+
+ SpinnerThreeBouncePlugin.prototype.render = function render() {
+ this.$el.html(this.template());
+ this.container.$el.append(this.$el);
+ this.$el.hide();
+ if (this.container.buffering) this.onBuffering();
+
+ return this;
+ };
+
+ return SpinnerThreeBouncePlugin;
+}(_ui_container_plugin2.default); // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = SpinnerThreeBouncePlugin;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/stats/index.js":
+/*!************************************!*\
+ !*** ./src/plugins/stats/index.js ***!
+ \************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _stats = __webpack_require__(/*! ./stats */ "./src/plugins/stats/stats.js");
+
+var _stats2 = _interopRequireDefault(_stats);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _stats2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/stats/stats.js":
+/*!************************************!*\
+ !*** ./src/plugins/stats/stats.js ***!
+ \************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _container_plugin = __webpack_require__(/*! ../../base/container_plugin */ "./src/base/container_plugin.js");
+
+var _container_plugin2 = _interopRequireDefault(_container_plugin);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var StatsPlugin = function (_ContainerPlugin) {
+ (0, _inherits3.default)(StatsPlugin, _ContainerPlugin);
+ (0, _createClass3.default)(StatsPlugin, [{
+ key: 'name',
+ get: function get() {
+ return 'stats';
+ }
+ }]);
+
+ function StatsPlugin(container) {
+ (0, _classCallCheck3.default)(this, StatsPlugin);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _ContainerPlugin.call(this, container));
+
+ _this.setInitialAttrs();
+ _this.reportInterval = _this.options.reportInterval || 5000;
+ _this.state = 'IDLE';
+ return _this;
+ }
+
+ StatsPlugin.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.container.playback, _events2.default.PLAYBACK_PLAY, this.onPlay);
+ this.listenTo(this.container, _events2.default.CONTAINER_STOP, this.onStop);
+ this.listenTo(this.container, _events2.default.CONTAINER_ENDED, this.onStop);
+ this.listenTo(this.container, _events2.default.CONTAINER_DESTROYED, this.onStop);
+ this.listenTo(this.container, _events2.default.CONTAINER_STATE_BUFFERING, this.onBuffering);
+ this.listenTo(this.container, _events2.default.CONTAINER_STATE_BUFFERFULL, this.onBufferFull);
+ this.listenTo(this.container, _events2.default.CONTAINER_STATS_ADD, this.onStatsAdd);
+ this.listenTo(this.container, _events2.default.CONTAINER_BITRATE, this.onStatsAdd);
+ this.listenTo(this.container.playback, _events2.default.PLAYBACK_STATS_ADD, this.onStatsAdd);
+ };
+
+ StatsPlugin.prototype.setInitialAttrs = function setInitialAttrs() {
+ this.firstPlay = true;
+ this.startupTime = 0;
+ this.rebufferingTime = 0;
+ this.watchingTime = 0;
+ this.rebuffers = 0;
+ this.externalMetrics = {};
+ };
+
+ StatsPlugin.prototype.onPlay = function onPlay() {
+ this.state = 'PLAYING';
+ this.watchingTimeInit = Date.now();
+ if (!this.intervalId) this.intervalId = setInterval(this.report.bind(this), this.reportInterval);
+ };
+
+ StatsPlugin.prototype.onStop = function onStop() {
+ clearInterval(this.intervalId);
+ this.report();
+ this.intervalId = undefined;
+ this.state = 'STOPPED';
+ };
+
+ StatsPlugin.prototype.onBuffering = function onBuffering() {
+ if (this.firstPlay) this.startupTimeInit = Date.now();else this.rebufferingTimeInit = Date.now();
+
+ this.state = 'BUFFERING';
+ this.rebuffers++;
+ };
+
+ StatsPlugin.prototype.onBufferFull = function onBufferFull() {
+ if (this.firstPlay && this.startupTimeInit) {
+ this.firstPlay = false;
+ this.startupTime = Date.now() - this.startupTimeInit;
+ this.watchingTimeInit = Date.now();
+ } else if (this.rebufferingTimeInit) {
+ this.rebufferingTime += this.getRebufferingTime();
+ }
+
+ this.rebufferingTimeInit = undefined;
+ this.state = 'PLAYING';
+ };
+
+ StatsPlugin.prototype.getRebufferingTime = function getRebufferingTime() {
+ return Date.now() - this.rebufferingTimeInit;
+ };
+
+ StatsPlugin.prototype.getWatchingTime = function getWatchingTime() {
+ var totalTime = Date.now() - this.watchingTimeInit;
+ return totalTime - this.rebufferingTime;
+ };
+
+ StatsPlugin.prototype.isRebuffering = function isRebuffering() {
+ return !!this.rebufferingTimeInit;
+ };
+
+ StatsPlugin.prototype.onStatsAdd = function onStatsAdd(metric) {
+ _clapprZepto2.default.extend(this.externalMetrics, metric);
+ };
+
+ StatsPlugin.prototype.getStats = function getStats() {
+ var metrics = {
+ startupTime: this.startupTime,
+ rebuffers: this.rebuffers,
+ rebufferingTime: this.isRebuffering() ? this.rebufferingTime + this.getRebufferingTime() : this.rebufferingTime,
+ watchingTime: this.isRebuffering() ? this.getWatchingTime() - this.getRebufferingTime() : this.getWatchingTime()
+ };
+ _clapprZepto2.default.extend(metrics, this.externalMetrics);
+ return metrics;
+ };
+
+ StatsPlugin.prototype.report = function report() {
+ this.container.statsReport(this.getStats());
+ };
+
+ return StatsPlugin;
+}(_container_plugin2.default); // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = StatsPlugin;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/strings.js":
+/*!********************************!*\
+ !*** ./src/plugins/strings.js ***!
+ \********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _utils = __webpack_require__(/*! ../base/utils */ "./src/base/utils.js");
+
+var _clapprZepto = __webpack_require__(/*! clappr-zepto */ "./node_modules/clappr-zepto/zepto.js");
+
+var _clapprZepto2 = _interopRequireDefault(_clapprZepto);
+
+var _core_plugin = __webpack_require__(/*! ../base/core_plugin */ "./src/base/core_plugin.js");
+
+var _core_plugin2 = _interopRequireDefault(_core_plugin);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The internationalization (i18n) plugin
+ * @class Strings
+ * @constructor
+ * @extends CorePlugin
+ * @module plugins
+ */
+var Strings = function (_CorePlugin) {
+ (0, _inherits3.default)(Strings, _CorePlugin);
+ (0, _createClass3.default)(Strings, [{
+ key: 'name',
+ get: function get() {
+ return 'strings';
+ }
+ }]);
+
+ function Strings(core) {
+ (0, _classCallCheck3.default)(this, Strings);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _CorePlugin.call(this, core));
+
+ _this._initializeMessages();
+ return _this;
+ }
+ /**
+ * Gets a translated string for the given key.
+ * @method t
+ * @param {String} key the key to all messages
+ * @return {String} translated label
+ */
+
+
+ Strings.prototype.t = function t(key) {
+ var lang = this._language();
+ var fallbackLang = this._messages['en'];
+ var i18n = lang && this._messages[lang] || fallbackLang;
+ return i18n[key] || fallbackLang[key] || key;
+ };
+
+ Strings.prototype._language = function _language() {
+ return this.core.options.language || (0, _utils.getBrowserLanguage)();
+ };
+
+ Strings.prototype._initializeMessages = function _initializeMessages() {
+ var defaultMessages = {
+ 'en': {
+ 'live': 'live',
+ 'back_to_live': 'back to live',
+ 'disabled': 'Disabled',
+ 'playback_not_supported': 'Your browser does not support the playback of this video. Please try using a different browser.',
+ 'default_error_title': 'Could not play video.',
+ 'default_error_message': 'There was a problem trying to load the video.'
+ },
+ 'pt': {
+ 'live': 'ao vivo',
+ 'back_to_live': 'voltar para o ao vivo',
+ 'disabled': 'Desativado',
+ 'playback_not_supported': 'Seu navegador não supporta a reprodução deste video. Por favor, tente usar um navegador diferente.',
+ 'default_error_title': 'Não foi possível reproduzir o vídeo.',
+ 'default_error_message': 'Ocorreu um problema ao tentar carregar o vídeo.'
+ },
+ 'es': {
+ 'live': 'vivo',
+ 'back_to_live': 'volver en vivo',
+ 'disabled': 'Discapacitado',
+ 'playback_not_supported': 'Su navegador no soporta la reproducción de un video. Por favor, trate de usar un navegador diferente.'
+ },
+ 'ru': {
+ 'live': 'прямой эфир',
+ 'back_to_live': 'к прямому эфиру',
+ 'disabled': 'Отключено',
+ 'playback_not_supported': 'Ваш браузер не поддерживает воспроизведение этого видео. Пожалуйста, попробуйте другой браузер.'
+ },
+ 'fr': {
+ 'live': 'en direct',
+ 'back_to_live': 'retour au direct',
+ 'disabled': 'Désactivé',
+ 'playback_not_supported': 'Votre navigateur ne supporte pas la lecture de cette vidéo. Merci de tenter sur un autre navigateur.',
+ 'default_error_title': 'Impossible de lire la vidéo.',
+ 'default_error_message': 'Un problème est survenu lors du chargement de la vidéo.'
+ },
+ 'tr': {
+ 'live': 'canlı',
+ 'back_to_live': 'canlı yayına dön',
+ 'disabled': 'Engelli',
+ 'playback_not_supported': 'Tarayıcınız bu videoyu oynatma desteğine sahip değil. Lütfen farklı bir tarayıcı ile deneyin.'
+ },
+ 'et': {
+ 'live': 'Otseülekanne',
+ 'back_to_live': 'Tagasi otseülekande juurde',
+ 'disabled': 'Keelatud',
+ 'playback_not_supported': 'Teie brauser ei toeta selle video taasesitust. Proovige kasutada muud brauserit.'
+ },
+ 'ar': {
+ 'live': 'مباشر',
+ 'back_to_live': 'الرجوع إلى المباشر',
+ 'disabled': 'معطّل',
+ 'playback_not_supported': 'المتصفح الذي تستخدمه لا يدعم تشغيل هذا الفيديو. الرجاء إستخدام متصفح آخر.',
+ 'default_error_title': 'غير قادر الى التشغيل.',
+ 'default_error_message': 'حدثت مشكلة أثناء تحميل الفيديو.'
+ }
+ };
+
+ this._messages = _clapprZepto2.default.extend(true, defaultMessages, this.core.options.strings || {});
+ this._messages['pt-BR'] = this._messages['pt'];
+ this._messages['en-US'] = this._messages['en'];
+ this._messages['es-419'] = this._messages['es'];
+ this._messages['fr-FR'] = this._messages['fr'];
+ this._messages['tr-TR'] = this._messages['tr'];
+ this._messages['et-EE'] = this._messages['et'];
+ this._messages['ar-IQ'] = this._messages['ar'];
+ };
+
+ return Strings;
+}(_core_plugin2.default);
+
+exports.default = Strings;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/watermark/index.js":
+/*!****************************************!*\
+ !*** ./src/plugins/watermark/index.js ***!
+ \****************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _watermark = __webpack_require__(/*! ./watermark */ "./src/plugins/watermark/watermark.js");
+
+var _watermark2 = _interopRequireDefault(_watermark);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = _watermark2.default;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/plugins/watermark/public/watermark.html":
+/*!*****************************************************!*\
+ !*** ./src/plugins/watermark/public/watermark.html ***!
+ \*****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+module.exports = "\n";
+
+/***/ }),
+
+/***/ "./src/plugins/watermark/public/watermark.scss":
+/*!*****************************************************!*\
+ !*** ./src/plugins/watermark/public/watermark.scss ***!
+ \*****************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+
+var content = __webpack_require__(/*! !../../../../node_modules/css-loader!../../../../node_modules/postcss-loader/lib!../../../../node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./watermark.scss */ "./node_modules/css-loader/index.js!./node_modules/postcss-loader/lib/index.js!./node_modules/sass-loader/lib/loader.js?includePaths[]=/Users/bruno/workspace/clappr/clappr/src/base/scss!./src/plugins/watermark/public/watermark.scss");
+
+if(typeof content === 'string') content = [[module.i, content, '']];
+
+var transform;
+var insertInto;
+
+
+
+var options = {"singleton":true,"hmr":true}
+
+options.transform = transform
+options.insertInto = undefined;
+
+var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options);
+
+if(content.locals) module.exports = content.locals;
+
+if(false) {}
+
+/***/ }),
+
+/***/ "./src/plugins/watermark/watermark.js":
+/*!********************************************!*\
+ !*** ./src/plugins/watermark/watermark.js ***!
+ \********************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _classCallCheck2 = __webpack_require__(/*! babel-runtime/helpers/classCallCheck */ "./node_modules/babel-runtime/helpers/classCallCheck.js");
+
+var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
+
+var _possibleConstructorReturn2 = __webpack_require__(/*! babel-runtime/helpers/possibleConstructorReturn */ "./node_modules/babel-runtime/helpers/possibleConstructorReturn.js");
+
+var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
+
+var _createClass2 = __webpack_require__(/*! babel-runtime/helpers/createClass */ "./node_modules/babel-runtime/helpers/createClass.js");
+
+var _createClass3 = _interopRequireDefault(_createClass2);
+
+var _inherits2 = __webpack_require__(/*! babel-runtime/helpers/inherits */ "./node_modules/babel-runtime/helpers/inherits.js");
+
+var _inherits3 = _interopRequireDefault(_inherits2);
+
+var _ui_container_plugin = __webpack_require__(/*! ../../base/ui_container_plugin */ "./src/base/ui_container_plugin.js");
+
+var _ui_container_plugin2 = _interopRequireDefault(_ui_container_plugin);
+
+var _events = __webpack_require__(/*! ../../base/events */ "./src/base/events.js");
+
+var _events2 = _interopRequireDefault(_events);
+
+var _template = __webpack_require__(/*! ../../base/template */ "./src/base/template.js");
+
+var _template2 = _interopRequireDefault(_template);
+
+var _watermark = __webpack_require__(/*! ./public/watermark.html */ "./src/plugins/watermark/public/watermark.html");
+
+var _watermark2 = _interopRequireDefault(_watermark);
+
+__webpack_require__(/*! ./public/watermark.scss */ "./src/plugins/watermark/public/watermark.scss");
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var WaterMarkPlugin = function (_UIContainerPlugin) {
+ (0, _inherits3.default)(WaterMarkPlugin, _UIContainerPlugin);
+ (0, _createClass3.default)(WaterMarkPlugin, [{
+ key: 'name',
+ get: function get() {
+ return 'watermark';
+ }
+ }, {
+ key: 'template',
+ get: function get() {
+ return (0, _template2.default)(_watermark2.default);
+ }
+ }]);
+
+ function WaterMarkPlugin(container) {
+ (0, _classCallCheck3.default)(this, WaterMarkPlugin);
+
+ var _this = (0, _possibleConstructorReturn3.default)(this, _UIContainerPlugin.call(this, container));
+
+ _this.configure();
+ return _this;
+ }
+
+ WaterMarkPlugin.prototype.bindEvents = function bindEvents() {
+ this.listenTo(this.container, _events2.default.CONTAINER_PLAY, this.onPlay);
+ this.listenTo(this.container, _events2.default.CONTAINER_STOP, this.onStop);
+ this.listenTo(this.container, _events2.default.CONTAINER_OPTIONS_CHANGE, this.configure);
+ };
+
+ WaterMarkPlugin.prototype.configure = function configure() {
+ this.position = this.options.position || 'bottom-right';
+ if (this.options.watermark) {
+ this.imageUrl = this.options.watermark;
+ this.imageLink = this.options.watermarkLink;
+ this.render();
+ } else {
+ this.$el.remove();
+ }
+ };
+
+ WaterMarkPlugin.prototype.onPlay = function onPlay() {
+ if (!this.hidden) this.$el.show();
+ };
+
+ WaterMarkPlugin.prototype.onStop = function onStop() {
+ this.$el.hide();
+ };
+
+ WaterMarkPlugin.prototype.render = function render() {
+ this.$el.hide();
+ var templateOptions = { position: this.position, imageUrl: this.imageUrl, imageLink: this.imageLink };
+ this.$el.html(this.template(templateOptions));
+ this.container.$el.append(this.$el);
+ return this;
+ };
+
+ return WaterMarkPlugin;
+}(_ui_container_plugin2.default); // Copyright 2014 Globo.com Player authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+exports.default = WaterMarkPlugin;
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/vendor/index.js":
+/*!*****************************!*\
+ !*** ./src/vendor/index.js ***!
+ \*****************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _kibo = __webpack_require__(/*! ./kibo */ "./src/vendor/kibo.js");
+
+var _kibo2 = _interopRequireDefault(_kibo);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = { Kibo: _kibo2.default };
+module.exports = exports['default'];
+
+/***/ }),
+
+/***/ "./src/vendor/kibo.js":
+/*!****************************!*\
+ !*** ./src/vendor/kibo.js ***!
+ \****************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+/* eslint-disable */
+// Kibo is released under the MIT License. Copyright (c) 2013 marquete.
+// see https://github.com/marquete/kibo
+
+var Kibo = function Kibo(element) {
+ this.element = element || window.document;
+ this.initialize();
+};
+
+Kibo.KEY_NAMES_BY_CODE = {
+ 8: 'backspace', 9: 'tab', 13: 'enter',
+ 16: 'shift', 17: 'ctrl', 18: 'alt',
+ 20: 'caps_lock',
+ 27: 'esc',
+ 32: 'space',
+ 37: 'left', 38: 'up', 39: 'right', 40: 'down',
+ 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7', 56: '8', 57: '9',
+ 65: 'a', 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', 73: 'i', 74: 'j',
+ 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't',
+ 85: 'u', 86: 'v', 87: 'w', 88: 'x', 89: 'y', 90: 'z', 112: 'f1', 113: 'f2', 114: 'f3',
+ 115: 'f4', 116: 'f5', 117: 'f6', 118: 'f7', 119: 'f8', 120: 'f9', 121: 'f10', 122: 'f11', 123: 'f12'
+};
+
+Kibo.KEY_CODES_BY_NAME = {};
+(function () {
+ for (var key in Kibo.KEY_NAMES_BY_CODE) {
+ if (Object.prototype.hasOwnProperty.call(Kibo.KEY_NAMES_BY_CODE, key)) {
+ Kibo.KEY_CODES_BY_NAME[Kibo.KEY_NAMES_BY_CODE[key]] = +key;
+ }
+ }
+})();
+
+Kibo.MODIFIERS = ['shift', 'ctrl', 'alt'];
+
+Kibo.registerEvent = function () {
+ if (document.addEventListener) {
+ return function (element, eventName, func) {
+ element.addEventListener(eventName, func, false);
+ };
+ } else if (document.attachEvent) {
+ return function (element, eventName, func) {
+ element.attachEvent('on' + eventName, func);
+ };
+ }
+}();
+
+Kibo.unregisterEvent = function () {
+ if (document.removeEventListener) {
+ return function (element, eventName, func) {
+ element.removeEventListener(eventName, func, false);
+ };
+ } else if (document.detachEvent) {
+ return function (element, eventName, func) {
+ element.detachEvent('on' + eventName, func);
+ };
+ }
+}();
+
+Kibo.stringContains = function (string, substring) {
+ return string.indexOf(substring) !== -1;
+};
+
+Kibo.neatString = function (string) {
+ return string.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ');
+};
+
+Kibo.capitalize = function (string) {
+ return string.toLowerCase().replace(/^./, function (match) {
+ return match.toUpperCase();
+ });
+};
+
+Kibo.isString = function (what) {
+ return Kibo.stringContains(Object.prototype.toString.call(what), 'String');
+};
+
+Kibo.arrayIncludes = function () {
+ if (Array.prototype.indexOf) {
+ return function (haystack, needle) {
+ return haystack.indexOf(needle) !== -1;
+ };
+ } else {
+ return function (haystack, needle) {
+ for (var i = 0; i < haystack.length; i++) {
+ if (haystack[i] === needle) {
+ return true;
+ }
+ }
+ return false;
+ };
+ }
+}();
+
+Kibo.extractModifiers = function (keyCombination) {
+ var modifiers, i;
+ modifiers = [];
+ for (i = 0; i < Kibo.MODIFIERS.length; i++) {
+ if (Kibo.stringContains(keyCombination, Kibo.MODIFIERS[i])) {
+ modifiers.push(Kibo.MODIFIERS[i]);
+ }
+ }
+ return modifiers;
+};
+
+Kibo.extractKey = function (keyCombination) {
+ var keys, i;
+ keys = Kibo.neatString(keyCombination).split(' ');
+ for (i = 0; i < keys.length; i++) {
+ if (!Kibo.arrayIncludes(Kibo.MODIFIERS, keys[i])) {
+ return keys[i];
+ }
+ }
+};
+
+Kibo.modifiersAndKey = function (keyCombination) {
+ var result, key;
+
+ if (Kibo.stringContains(keyCombination, 'any')) {
+ return Kibo.neatString(keyCombination).split(' ').slice(0, 2).join(' ');
+ }
+
+ result = Kibo.extractModifiers(keyCombination);
+
+ key = Kibo.extractKey(keyCombination);
+ if (key && !Kibo.arrayIncludes(Kibo.MODIFIERS, key)) {
+ result.push(key);
+ }
+
+ return result.join(' ');
+};
+
+Kibo.keyName = function (keyCode) {
+ return Kibo.KEY_NAMES_BY_CODE[keyCode + ''];
+};
+
+Kibo.keyCode = function (keyName) {
+ return +Kibo.KEY_CODES_BY_NAME[keyName];
+};
+
+Kibo.prototype.initialize = function () {
+ var i,
+ that = this;
+
+ this.lastKeyCode = -1;
+ this.lastModifiers = {};
+ for (i = 0; i < Kibo.MODIFIERS.length; i++) {
+ this.lastModifiers[Kibo.MODIFIERS[i]] = false;
+ }
+
+ this.keysDown = { any: [] };
+ this.keysUp = { any: [] };
+ this.downHandler = this.handler('down');
+ this.upHandler = this.handler('up');
+
+ Kibo.registerEvent(this.element, 'keydown', this.downHandler);
+ Kibo.registerEvent(this.element, 'keyup', this.upHandler);
+ Kibo.registerEvent(window, 'unload', function unloader() {
+ Kibo.unregisterEvent(that.element, 'keydown', that.downHandler);
+ Kibo.unregisterEvent(that.element, 'keyup', that.upHandler);
+ Kibo.unregisterEvent(window, 'unload', unloader);
+ });
+};
+
+Kibo.prototype.handler = function (upOrDown) {
+ var that = this;
+ return function (e) {
+ var i, registeredKeys, lastModifiersAndKey;
+
+ e = e || window.event;
+
+ that.lastKeyCode = e.keyCode;
+ for (i = 0; i < Kibo.MODIFIERS.length; i++) {
+ that.lastModifiers[Kibo.MODIFIERS[i]] = e[Kibo.MODIFIERS[i] + 'Key'];
+ }
+ if (Kibo.arrayIncludes(Kibo.MODIFIERS, Kibo.keyName(that.lastKeyCode))) {
+ that.lastModifiers[Kibo.keyName(that.lastKeyCode)] = true;
+ }
+
+ registeredKeys = that['keys' + Kibo.capitalize(upOrDown)];
+
+ for (i = 0; i < registeredKeys.any.length; i++) {
+ if (registeredKeys.any[i](e) === false && e.preventDefault) {
+ e.preventDefault();
+ }
+ }
+
+ lastModifiersAndKey = that.lastModifiersAndKey();
+ if (registeredKeys[lastModifiersAndKey]) {
+ for (i = 0; i < registeredKeys[lastModifiersAndKey].length; i++) {
+ if (registeredKeys[lastModifiersAndKey][i](e) === false && e.preventDefault) {
+ e.preventDefault();
+ }
+ }
+ }
+ };
+};
+
+Kibo.prototype.registerKeys = function (upOrDown, newKeys, func) {
+ var i,
+ keys,
+ registeredKeys = this['keys' + Kibo.capitalize(upOrDown)];
+
+ if (Kibo.isString(newKeys)) {
+ newKeys = [newKeys];
+ }
+
+ for (i = 0; i < newKeys.length; i++) {
+ keys = newKeys[i];
+ keys = Kibo.modifiersAndKey(keys + '');
+
+ if (registeredKeys[keys]) {
+ registeredKeys[keys].push(func);
+ } else {
+ registeredKeys[keys] = [func];
+ }
+ }
+
+ return this;
+};
+
+// jshint maxdepth:5
+Kibo.prototype.unregisterKeys = function (upOrDown, newKeys, func) {
+ var i,
+ j,
+ keys,
+ registeredKeys = this['keys' + Kibo.capitalize(upOrDown)];
+
+ if (Kibo.isString(newKeys)) {
+ newKeys = [newKeys];
+ }
+
+ for (i = 0; i < newKeys.length; i++) {
+ keys = newKeys[i];
+ keys = Kibo.modifiersAndKey(keys + '');
+
+ if (func === null) {
+ delete registeredKeys[keys];
+ } else {
+ if (registeredKeys[keys]) {
+ for (j = 0; j < registeredKeys[keys].length; j++) {
+ if (String(registeredKeys[keys][j]) === String(func)) {
+ registeredKeys[keys].splice(j, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return this;
+};
+
+Kibo.prototype.off = function (keys) {
+ return this.unregisterKeys('down', keys, null);
+};
+
+Kibo.prototype.delegate = function (upOrDown, keys, func) {
+ return func !== null || func !== undefined ? this.registerKeys(upOrDown, keys, func) : this.unregisterKeys(upOrDown, keys, func);
+};
+
+Kibo.prototype.down = function (keys, func) {
+ return this.delegate('down', keys, func);
+};
+
+Kibo.prototype.up = function (keys, func) {
+ return this.delegate('up', keys, func);
+};
+
+Kibo.prototype.lastKey = function (modifier) {
+ if (!modifier) {
+ return Kibo.keyName(this.lastKeyCode);
+ }
+
+ return this.lastModifiers[modifier];
+};
+
+Kibo.prototype.lastModifiersAndKey = function () {
+ var result, i;
+
+ result = [];
+ for (i = 0; i < Kibo.MODIFIERS.length; i++) {
+ if (this.lastKey(Kibo.MODIFIERS[i])) {
+ result.push(Kibo.MODIFIERS[i]);
+ }
+ }
+
+ if (!Kibo.arrayIncludes(result, this.lastKey())) {
+ result.push(this.lastKey());
+ }
+
+ return result.join(' ');
+};
+
+exports.default = Kibo;
+module.exports = exports['default'];
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=clappr.js.map
\ No newline at end of file
diff --git a/public/react/package.json b/public/react/package.json
index a0417c6ba..df60a3707 100644
--- a/public/react/package.json
+++ b/public/react/package.json
@@ -72,6 +72,7 @@
"react-infinite-scroller": "^1.2.4",
"react-loadable": "^5.3.1",
"react-monaco-editor": "^0.25.1",
+ "react-player": "^1.11.1",
"react-redux": "5.0.7",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
diff --git a/public/react/public/css/edu-all.css b/public/react/public/css/edu-all.css
index 9f129eabc..48b102ce3 100644
--- a/public/react/public/css/edu-all.css
+++ b/public/react/public/css/edu-all.css
@@ -577,7 +577,7 @@ p .activity-item:first-child{border-top: 1px solid #eee;}
.recently_name{float: left;line-height: 48px;display: block}
.recently_item:hover{background-color: #F9F9F9;}
/*私信对话框*/
-.private-list{min-height: 660px;max-height: 810px;overflow-y: auto}
+.private-list{min-height: 660px;max-height: 831px;overflow-y: auto;overflow-x: hidden;}
.private-list .private-part{padding-left:20px;cursor: pointer}
.private-part:hover{background-color: #F5F5F5;}
.private-part.active{background-color: #F5F5F5;}
diff --git a/public/react/public/js/js_min_all.js b/public/react/public/js/js_min_all.js
index dfead438a..63c1207af 100755
--- a/public/react/public/js/js_min_all.js
+++ b/public/react/public/js/js_min_all.js
@@ -209,6 +209,7 @@ $(function(){
// window resize
$(window).on('resize', function() {
+ window._tpiWidthResize && window._tpiWidthResize()
$('#games_repository_contents .CodeMirror.cm-s-railscasts').css("height", $("#games_repository_contents").height() - repositoryTabHeight);
})
@@ -1221,6 +1222,7 @@ $(function(){ // 这里重新加一次事件监听,不在原有事件的基
);
doc.live("mousemove", function(e) {
if (dragging === true && lab == dragDom) {
+ window._tpiWidthResize && window._tpiWidthResize()
// React 组件中需要resize,搜索该引用可以找到初始化的位置
window._currentChildcommentMDEditor && window._currentChildcommentMDEditor.resize()
}
diff --git a/public/react/src/App.css b/public/react/src/App.css
index 6f63551c6..932132832 100644
--- a/public/react/src/App.css
+++ b/public/react/src/App.css
@@ -1,57 +1,58 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- animation: App-logo-spin infinite 20s linear;
- height: 80px;
-}
-
-.App-header {
- background-color: #222;
- height: 150px;
- padding: 20px;
- color: white;
-}
-
-.App-title {
- font-size: 1.5em;
-}
-
-.App-intro {
- font-size: large;
-}
-
-@keyframes App-logo-spin {
- from { transform: rotate(0deg); }
- to { transform: rotate(360deg); }
-}
-
-
-
-/* 控制md编辑器列行的宽度
- 见 codermirror maybeUpdateLineNumberWidth方法
-*/
-.editormd .CodeMirror-linenumbers {
- padding: 0;
-}
-.editormd-html-preview hr, .editormd-preview-container hr {
- /* 颜色加深 */
- border-top: 1px solid #ccc;
-}
-
-/* 重置掉antd的一些样式 */
-html, body {
- -webkit-font-smoothing: auto !important;
-}
-
-.ant-progress-textyes {
- color: #52c41a;
-}
-.ant-progress-textno{
- color: #f5222d;
-}
-/* md多空格 */
-.markdown-body p {
- white-space: pre-wrap;
+.App {
+ text-align: center;
+}
+
+.App-logo {
+ animation: App-logo-spin infinite 20s linear;
+ height: 80px;
+}
+
+.App-header {
+ background-color: #222;
+ height: 150px;
+ padding: 20px;
+ color: white;
+}
+
+.App-title {
+ font-size: 1.5em;
+}
+
+.App-intro {
+ font-size: large;
+}
+
+@keyframes App-logo-spin {
+ from { transform: rotate(0deg); }
+ to { transform: rotate(360deg); }
+}
+
+
+
+/* 控制md编辑器列行的宽度
+ 见 codermirror maybeUpdateLineNumberWidth方法
+*/
+.editormd .CodeMirror-linenumbers {
+ padding: 0;
+}
+.editormd-html-preview hr, .editormd-preview-container hr {
+ /* 颜色加深 */
+ border-top: 1px solid #ccc;
+}
+
+/* 重置掉antd的一些样式 */
+html, body {
+ -webkit-font-smoothing: auto !important;
+}
+
+.ant-progress-textyes {
+ color: #52c41a;
+}
+.ant-progress-textno{
+ color: #f5222d;
+}
+/* md多空格 */
+.markdown-body p {
+ white-space: pre-wrap;
+ margin-bottom: 0px !important;
}
\ No newline at end of file
diff --git a/public/react/src/App.js b/public/react/src/App.js
index 8b900497f..1f1690432 100644
--- a/public/react/src/App.js
+++ b/public/react/src/App.js
@@ -18,9 +18,7 @@ import Notcompletedysl from './modules/user/Notcompletedysl';
import Trialapplicationysl from './modules/login/Trialapplicationysl';
import Trialapplicationreview from './modules/user/Trialapplicationreview';
import Addcourses from "./modules/courses/coursesPublic/Addcourses";
-import AccountProfile from"./modules/user/AccountProfile";
-
-
+import AccountProfile from "./modules/user/AccountProfile";
import Trialapplication from './modules/login/Trialapplication'
import NotFoundPage from './NotFoundPage'
@@ -238,6 +236,10 @@ const ProjectPackages=Loadable({
loading: Loading,
})
+const Messagerouting= Loadable({
+ loader: () => import('./modules/message/js/Messagerouting'),
+ loading: Loading,
+})
class App extends Component {
constructor(props) {
super(props)
@@ -355,22 +357,37 @@ class App extends Component {
{/*课堂*/}
+<<<<<<< HEAD
{/*
*/}
{/* 教学案例 */}
( )
}/>
+=======
+
+ ( )
+ }
+ >
+
+
+>>>>>>> dev_aliyun
-
+ ( )
+ }
+ >
-
+
diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js
index 363ff495d..97cfa8eeb 100644
--- a/public/react/src/AppConfig.js
+++ b/public/react/src/AppConfig.js
@@ -43,7 +43,6 @@ export function initAxiosInterceptors(props) {
// proxy = "https://testeduplus2.educoder.net"
proxy="http://47.96.87.25:48080"
-
// 在这里使用requestMap控制,避免用户通过双击等操作发出重复的请求;
// 如果需要支持重复的请求,考虑config里面自定义一个allowRepeat参考来控制
const requestMap = {};
diff --git a/public/react/src/common/UrlTool.js b/public/react/src/common/UrlTool.js
index 3953f1f34..f224526e6 100644
--- a/public/react/src/common/UrlTool.js
+++ b/public/react/src/common/UrlTool.js
@@ -59,4 +59,6 @@ export function toPath(path) {
}
-// export default queryString
\ No newline at end of file
+export function getTaskUrlById(id) {
+ return `/tasks/${id}`
+}
diff --git a/public/react/src/common/components/media/Clappr.js b/public/react/src/common/components/media/Clappr.js
index 7814c391a..312ea9007 100644
--- a/public/react/src/common/components/media/Clappr.js
+++ b/public/react/src/common/components/media/Clappr.js
@@ -1,5 +1,6 @@
import React,{ Component } from "react";
import { getUrl2 } from "educoder";
+import ReactPlayer from 'react-player'
const $ = window.$
let _url_origin = getUrl2()
@@ -10,33 +11,54 @@ class Clappr extends Component{
this.state={
}
}
+ componentWillUnmount() {
+ this['player'+this.props.id] && this['player'+this.props.id].destroy()
+ }
+
componentDidMount() {
+ return;
+
const source = this.props.source || "http://your.video/here.mp4"
- const { id } = this.props
+ const { id, type } = this.props
const _id = `#_player${id}`
- if (window['Clappr']) {
- const player = new window.Clappr.Player({
+
+ if (!window['Clappr'] && window['ClapprLoading'] == true) {
+ setTimeout(() => {
+ this.componentDidMount()
+ }, 300)
+ return;
+ }
+ // && window['clappr-playback-rate-plugin']
+ if (window['Clappr'] ) {
+ // https://github.com/clappr/clappr/issues/1839
+ // http://clappr.github.io/classes/Player.html#method_mute
+ this['player'+id] = new window.Clappr.Player({
source: source, parentId: _id,
- plugins: {
- 'core': [window.Clappr.MediaControl, window.Clappr.Playback]
- }
+ height: type == 'mp3' ? 60 : 360,
+ hideMediaControl: type == 'mp3' ? false : true,
+ // plugins: {
+ // 'core': [window.Clappr.MediaControl, window['clappr-playback-rate-plugin'].default]
+ // }
});
} else {
+ window['ClapprLoading'] = true;
$.getScript(
`${_url_origin}/javascripts/media/clappr.min.js`,
(data, textStatus, jqxhr) => {
window.clappr = window.Clappr
- $.getScript(
- `${_url_origin}/javascripts/media/clappr-playback-rate-plugin.min.js`,
- (data, textStatus, jqxhr) => {
- const player = new window.Clappr.Player({
+ // $.getScript(
+ // `${_url_origin}/javascripts/media/clappr-playback-rate-plugin.min.js`,
+ // (data, textStatus, jqxhr) => {
+ this['player'+id] = new window.Clappr.Player({
source: source, parentId: _id,
- plugins: {
- 'core': [window.Clappr.MediaControl, window['clappr-playback-rate-plugin'].default]
- }
+ height: type == 'mp3' ? 60 : 360,
+ hideMediaControl: type == 'mp3' ? false : true,
+ // plugins: {
+ // 'core': [window.Clappr.MediaControl, window['clappr-playback-rate-plugin'].default]
+ // }
});
- })
+ // })
});
@@ -62,16 +84,25 @@ class Clappr extends Component{
render(){
- let { source, id, className } = this.props;
+ let { source, id, className, type } = this.props;
const _id = `_player${id}`
return(
-
-
+
*/}
+
+ {/* 原生 */}
+ {/* { type == 'mp3' ?
+ :
+ 您的浏览器不支持 video 标签。
+ } */}
)
}
diff --git a/public/react/src/common/educoder.js b/public/react/src/common/educoder.js
index 791b2c6d6..2afbca8d1 100644
--- a/public/react/src/common/educoder.js
+++ b/public/react/src/common/educoder.js
@@ -3,7 +3,8 @@ import { from } from '_array-flatten@2.1.2@array-flatten';
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
export { getImageUrl as getImageUrl, getUrl as getUrl, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
- , getUploadActionUrl as getUploadActionUrl, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth } from './UrlTool';
+ , getUploadActionUrl as getUploadActionUrl, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
+ , getTaskUrlById as getTaskUrlById } from './UrlTool';
export { default as queryString } from './UrlTool2';
export { SnackbarHOC as SnackbarHOC } from './SnackbarHOC';
diff --git a/public/react/src/context/EffectDisplayContent.js b/public/react/src/context/EffectDisplayContent.js
index 60e2f5ad4..d4301506a 100644
--- a/public/react/src/context/EffectDisplayContent.js
+++ b/public/react/src/context/EffectDisplayContent.js
@@ -18,7 +18,7 @@ class EffectDisplayContent extends Component {
.effectDisplay .content>div {
flex: 1
}
- .effectDisplay .clappr {
+ .effectDisplay .clappr, .effectDisplay .contentWrap {
display: flex;
justify-content: center;
}
@@ -32,13 +32,13 @@ class EffectDisplayContent extends Component {
{content3 && 预期输出{typeName}
}
- {content1 &&
+ {content1 &&
{content1}
}
- {content2 &&
+ {content2 &&
{content2}
}
- {content3 &&
+ {content3 &&
{content3}
}
diff --git a/public/react/src/context/EvaluateSuccessEffectDisplay.js b/public/react/src/context/EvaluateSuccessEffectDisplay.js
index 2697079d1..ec34db31f 100644
--- a/public/react/src/context/EvaluateSuccessEffectDisplay.js
+++ b/public/react/src/context/EvaluateSuccessEffectDisplay.js
@@ -1,4 +1,6 @@
import React, { Component } from 'react';
+import ReactDOM from 'react-dom';
+
import { Redirect } from 'react-router';
import PropTypes from 'prop-types';
@@ -29,7 +31,11 @@ class EvaluateSuccessEffectDisplay extends Component {
}
}
hidepicture = () => {
- window.$('#picture_display').hide();
+ const dom = document.getElementById('picture_display');
+ ReactDOM.unmountComponentAtNode(dom)
+ // window.$('#picture_display').hide();
+
+ window.$('.data-tip-right').hide()
}
renderContent = () => {
// qrcode
@@ -107,11 +113,11 @@ class EvaluateSuccessEffectDisplay extends Component {
: null }
+ ? : null }
content2={ user_file[0] && user_file[0].file_url
- ? : null }
+ ? : null }
content3={ answer_file[0] && answer_file[0].file_url
- ? : null }
+ ? : null }
>
)
} else if (type == 'mp4') {
@@ -119,11 +125,11 @@ class EvaluateSuccessEffectDisplay extends Component {
: null }
+ ? : null }
content2={ user_file[0] && user_file[0].file_url
- ? : null }
+ ? : null }
content3={ answer_file[0] && answer_file[0].file_url
- ? : null }
+ ? : null }
>
)
}
diff --git a/public/react/src/modules/courses/Resource/index.js b/public/react/src/modules/courses/Resource/index.js
index f83b525ee..d93c30d75 100644
--- a/public/react/src/modules/courses/Resource/index.js
+++ b/public/react/src/modules/courses/Resource/index.js
@@ -950,7 +950,7 @@ class Fileslists extends Component{
diff --git a/public/react/src/modules/courses/boards/BoardsNew.js b/public/react/src/modules/courses/boards/BoardsNew.js
index 7c48d372b..cea4f47aa 100644
--- a/public/react/src/modules/courses/boards/BoardsNew.js
+++ b/public/react/src/modules/courses/boards/BoardsNew.js
@@ -1,449 +1,449 @@
-import React,{ Component } from "react";
-
-import {
- Form, Input, InputNumber, Switch, Radio,
- Slider, Button, Upload, Icon, Rate, Checkbox, message,
- Row, Col, Select, Modal, Divider
-} from 'antd';
-import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
-import axios from 'axios'
-import './board.css'
-import "../common/formCommon.css"
-import AddDirModal from './AddDirModal'
-import { RouteHOC } from './common.js'
-import CBreadcrumb from '../common/CBreadcrumb'
-import {getUploadActionUrl, bytesToSize, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll} from 'educoder';
-
-const confirm = Modal.confirm;
-const $ = window.$
-const { Option } = Select;
-// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652
-class BoardsNew extends Component{
- constructor(props){
- super(props);
-
- this.mdRef = React.createRef();
-
- this.state = {
- fileList: [],
- boards: [],
- title_num: 60
- }
- }
- addSuccess = () => {
- this.fetchBoards()
- }
- fetchBoards = () => {
- const isEdit = this.isEdit
- const boardId = this.props.match.params.boardId
-
- const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
- axios.get(boardsUrl, { })
- .then((response) => {
- if (response.data.status == 0) {
- this.setState({
- boards: response.data.data.boards || [],
- course_id: response.data.data.course_id
- })
- if (!isEdit) {
- response.data.data.boards.forEach( board => {
- if (board.id == boardId) {
- this.setState({ board_name: board.name })
- }
- })
- // board_name
- }
- }
- })
- .catch(function (error) {
- console.log(error);
- });
- }
- componentDidMount = () => {
-
- const topicId = this.props.match.params.topicId
- const isEdit = !!topicId
- this.isEdit = isEdit
-
- const boardId = this.props.match.params.boardId
-
- this.fetchBoards()
-
- if (isEdit) {
- const url = `/messages/${topicId}.json`
- axios.get(url, {
- })
- .then((response) => {
- if (response.data.status == 0) {
- const { id, data } = response.data;
- if (data) {
- this.editTopic = data;
- this.props.form.setFieldsValue({
- sticky: !!data.sticky,
- content: data.content,
- subject: data.subject,
- select_board_id: data.board_id // TODO 没返回给前端
- });
- this.mdRef.current.setValue(data.content)
- const _fileList = data.attachments.map(item => {
- return {
- id: item.id,
- uid: item.id,
- name: appendFileSizeToUploadFile(item),
- url: item.url,
- status: 'done'
- }
- })
-
- this.setState({ fileList: _fileList, board_name: data.board_name, title_num: 60 - parseInt(data.subject.length) })
- }
- }
- })
- .catch(function (error) {
- console.log(error);
- });
- } else {
- const boardId = this.props.match.params.boardId
-
- this.props.form.setFieldsValue({
- select_board_id: parseInt(boardId)
- });
- }
- }
- handleSubmit = (e) => {
- e.preventDefault();
- const cid = this.state.course_id
- const boardId = this.props.match.params.boardId
-
- this.props.form.validateFieldsAndScroll((err, values) => {
- if (!err) {
- console.log('Received values of form: ', values);
- if (this.isEdit == true) {
- const editTopic = this.editTopic
- const editUrl = `/messages/${editTopic.id}.json`
-
- let attachment_ids = undefined
- if (this.state.fileList) {
- attachment_ids = this.state.fileList.map(item => {
- return item.response ? item.response.id : item.id
- })
- }
- axios.put(editUrl, {
- subject: values.subject,
- select_board_id: values.select_board_id,
- content: values.content,
- sticky: values.sticky,
- attachment_ids,
- })
- .then((response) => {
- if (response.data.status == 0) {
- const { id } = response.data;
- console.log('--- success')
-
- this.props.toDetailPage(cid, values.select_board_id, editTopic.id)
- }
- })
- .catch(function (error) {
- console.log(error);
- });
- } else {
- const url = `/boards/${boardId}/messages.json`
- let attachment_ids = undefined
- if (this.state.fileList) {
- attachment_ids = this.state.fileList.map(item => {
- return item.response.id
- })
- }
-
- axios.post(url, {
- ...values,
- course_id: cid,
- attachment_ids,
- })
- .then((response) => {
- if (response.data.data && response.data.status == 0) {
- const { id } = response.data.data;
- if (id) {
- console.log('--- success')
- this.props.toDetailPage(cid, values.select_board_id, id)
- }
- }
- })
- .catch(function (error) {
- console.log(error);
- });
- }
- } else {
- $("html").animate({ scrollTop: $('html').scrollTop() - 100 })
- }
- });
- }
- // 附件相关 START
- handleChange = (info) => {
- let fileList = info.fileList;
- this.setState({ fileList: appendFileSizeToUploadFileAll(fileList)
- });
- }
- onAttachmentRemove = (file) => {
- confirm({
- // title: '确定要删除这个附件吗?',
- title: '是否确认删除?',
-
- okText: '确定',
- cancelText: '取消',
- // content: 'Some descriptions',
- onOk: () => {
- this.deleteAttachment(file)
- },
- onCancel() {
- console.log('Cancel');
- },
- });
-
-
- return false;
- }
- deleteAttachment = (file) => {
- // 初次上传不能直接取uid
- const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
- axios.delete(url, {
- })
- .then((response) => {
- if (response.data) {
- const { status } = response.data;
- if (status == 0) {
- console.log('--- success')
-
- this.setState((state) => {
- const index = state.fileList.indexOf(file);
- const newFileList = state.fileList.slice();
- newFileList.splice(index, 1);
- return {
- fileList: newFileList,
- };
- });
- }
- }
- })
- .catch(function (error) {
- console.log(error);
- });
- }
- // 附件相关 ------------ END
- changeTitle=(e)=>{
- console.log(e.target.value.length);
- this.setState({
- title_num: 60 - parseInt(e.target.value.length)
- })
- }
- render() {
- let { addGroup, fileList, course_id, title_num } = this.state;
- const { getFieldDecorator } = this.props.form;
- const { current_user } = this.props
-
- const formItemLayout = {
- labelCol: {
- xs: { span: 24 },
- // sm: { span: 8 },
- sm: { span: 24 },
- },
- wrapperCol: {
- xs: { span: 24 },
- // sm: { span: 16 },
- sm: { span: 24 },
- },
- };
-
- const uploadProps = {
- width: 600,
- fileList,
- multiple: true,
- // https://github.com/ant-design/ant-design/issues/15505
- // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
- // showUploadList: false,
- action: `${getUploadActionUrl()}`,
- onChange: this.handleChange,
- onRemove: this.onAttachmentRemove,
- beforeUpload: (file) => {
- console.log('beforeUpload', file.name);
- const isLt150M = file.size / 1024 / 1024 < 150;
- if (!isLt150M) {
- message.error('文件大小必须小于150MB!');
- }
- return isLt150M;
- },
- };
- const isAdmin = this.props.isAdmin()
- const courseId=this.props.match.params.coursesId;
- const boardId = this.props.match.params.boardId
-
- return(
-
- )
- }
-}
-
-const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew);
+import React,{ Component } from "react";
+
+import {
+ Form, Input, InputNumber, Switch, Radio,
+ Slider, Button, Upload, Icon, Rate, Checkbox, message,
+ Row, Col, Select, Modal, Divider
+} from 'antd';
+import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
+import axios from 'axios'
+import './board.css'
+import "../common/formCommon.css"
+import AddDirModal from './AddDirModal'
+import { RouteHOC } from './common.js'
+import CBreadcrumb from '../common/CBreadcrumb'
+import {getUploadActionUrl, bytesToSize, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll} from 'educoder';
+
+const confirm = Modal.confirm;
+const $ = window.$
+const { Option } = Select;
+// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652
+class BoardsNew extends Component{
+ constructor(props){
+ super(props);
+
+ this.mdRef = React.createRef();
+
+ this.state = {
+ fileList: [],
+ boards: [],
+ title_num: 60
+ }
+ }
+ addSuccess = () => {
+ this.fetchBoards()
+ }
+ fetchBoards = () => {
+ const isEdit = this.isEdit
+ const boardId = this.props.match.params.boardId
+
+ const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
+ axios.get(boardsUrl, { })
+ .then((response) => {
+ if (response.data.status == 0) {
+ this.setState({
+ boards: response.data.data.boards || [],
+ course_id: response.data.data.course_id
+ })
+ if (!isEdit) {
+ response.data.data.boards.forEach( board => {
+ if (board.id == boardId) {
+ this.setState({ board_name: board.name })
+ }
+ })
+ // board_name
+ }
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ componentDidMount = () => {
+
+ const topicId = this.props.match.params.topicId
+ const isEdit = !!topicId
+ this.isEdit = isEdit
+
+ const boardId = this.props.match.params.boardId
+
+ this.fetchBoards()
+
+ if (isEdit) {
+ const url = `/messages/${topicId}.json`
+ axios.get(url, {
+ })
+ .then((response) => {
+ if (response.data.status == 0) {
+ const { id, data } = response.data;
+ if (data) {
+ this.editTopic = data;
+ this.props.form.setFieldsValue({
+ sticky: !!data.sticky,
+ content: data.content,
+ subject: data.subject,
+ select_board_id: data.board_id // TODO 没返回给前端
+ });
+ this.mdRef.current.setValue(data.content)
+ const _fileList = data.attachments.map(item => {
+ return {
+ id: item.id,
+ uid: item.id,
+ name: appendFileSizeToUploadFile(item),
+ url: item.url,
+ status: 'done'
+ }
+ })
+
+ this.setState({ fileList: _fileList, board_name: data.board_name, title_num: 60 - parseInt(data.subject.length) })
+ }
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ } else {
+ const boardId = this.props.match.params.boardId
+
+ this.props.form.setFieldsValue({
+ select_board_id: parseInt(boardId)
+ });
+ }
+ }
+ handleSubmit = (e) => {
+ e.preventDefault();
+ const cid = this.state.course_id
+ const boardId = this.props.match.params.boardId
+
+ this.props.form.validateFieldsAndScroll((err, values) => {
+ if (!err) {
+ console.log('Received values of form: ', values);
+ if (this.isEdit == true) {
+ const editTopic = this.editTopic
+ const editUrl = `/messages/${editTopic.id}.json`
+
+ let attachment_ids = undefined
+ if (this.state.fileList) {
+ attachment_ids = this.state.fileList.map(item => {
+ return item.response ? item.response.id : item.id
+ })
+ }
+ axios.put(editUrl, {
+ subject: values.subject,
+ select_board_id: values.select_board_id,
+ content: values.content,
+ sticky: values.sticky,
+ attachment_ids,
+ })
+ .then((response) => {
+ if (response.data.status == 0) {
+ const { id } = response.data;
+ console.log('--- success')
+
+ this.props.toDetailPage(cid, values.select_board_id, editTopic.id)
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ } else {
+ const url = `/boards/${boardId}/messages.json`
+ let attachment_ids = undefined
+ if (this.state.fileList) {
+ attachment_ids = this.state.fileList.map(item => {
+ return item.response.id
+ })
+ }
+
+ axios.post(url, {
+ ...values,
+ course_id: cid,
+ attachment_ids,
+ })
+ .then((response) => {
+ if (response.data.data && response.data.status == 0) {
+ const { id } = response.data.data;
+ if (id) {
+ console.log('--- success')
+ this.props.toDetailPage(cid, values.select_board_id, id)
+ }
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ } else {
+ $("html").animate({ scrollTop: $('html').scrollTop() - 100 })
+ }
+ });
+ }
+ // 附件相关 START
+ handleChange = (info) => {
+ let fileList = info.fileList;
+ this.setState({ fileList: appendFileSizeToUploadFileAll(fileList)
+ });
+ }
+ onAttachmentRemove = (file) => {
+ confirm({
+ // title: '确定要删除这个附件吗?',
+ title: '是否确认删除?',
+
+ okText: '确定',
+ cancelText: '取消',
+ // content: 'Some descriptions',
+ onOk: () => {
+ this.deleteAttachment(file)
+ },
+ onCancel() {
+ console.log('Cancel');
+ },
+ });
+
+
+ return false;
+ }
+ deleteAttachment = (file) => {
+ // 初次上传不能直接取uid
+ const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
+ axios.delete(url, {
+ })
+ .then((response) => {
+ if (response.data) {
+ const { status } = response.data;
+ if (status == 0) {
+ console.log('--- success')
+
+ this.setState((state) => {
+ const index = state.fileList.indexOf(file);
+ const newFileList = state.fileList.slice();
+ newFileList.splice(index, 1);
+ return {
+ fileList: newFileList,
+ };
+ });
+ }
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ // 附件相关 ------------ END
+ changeTitle=(e)=>{
+ console.log(e.target.value.length);
+ this.setState({
+ title_num: 60 - parseInt(e.target.value.length)
+ })
+ }
+ render() {
+ let { addGroup, fileList, course_id, title_num } = this.state;
+ const { getFieldDecorator } = this.props.form;
+ const { current_user } = this.props
+
+ const formItemLayout = {
+ labelCol: {
+ xs: { span: 24 },
+ // sm: { span: 8 },
+ sm: { span: 24 },
+ },
+ wrapperCol: {
+ xs: { span: 24 },
+ // sm: { span: 16 },
+ sm: { span: 24 },
+ },
+ };
+
+ const uploadProps = {
+ width: 600,
+ fileList,
+ multiple: true,
+ // https://github.com/ant-design/ant-design/issues/15505
+ // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
+ // showUploadList: false,
+ action: `${getUploadActionUrl()}`,
+ onChange: this.handleChange,
+ onRemove: this.onAttachmentRemove,
+ beforeUpload: (file) => {
+ console.log('beforeUpload', file.name);
+ const isLt150M = file.size / 1024 / 1024 < 150;
+ if (!isLt150M) {
+ message.error('文件大小必须小于150MB!');
+ }
+ return isLt150M;
+ },
+ };
+ const isAdmin = this.props.isAdmin()
+ const courseId=this.props.match.params.coursesId;
+ const boardId = this.props.match.params.boardId
+
+ return(
+
+ )
+ }
+}
+
+const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew);
export default RouteHOC()(WrappedBoardsNew);
\ No newline at end of file
diff --git a/public/react/src/modules/courses/boards/TopicDetail.js b/public/react/src/modules/courses/boards/TopicDetail.js
index 7aaecdd16..970cf798a 100644
--- a/public/react/src/modules/courses/boards/TopicDetail.js
+++ b/public/react/src/modules/courses/boards/TopicDetail.js
@@ -1,726 +1,726 @@
-import React, { Component } from 'react';
-import { Redirect } from 'react-router';
-
-import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
-
-import PropTypes from 'prop-types';
-
-import classNames from 'classnames'
-
-import axios from 'axios'
-
-import moment from 'moment'
-
-import Comments from '../../comment/Comments'
-
-import update from 'immutability-helper'
-import RewardDialog from '../../common/RewardDialog';
-import {ImageLayerOfCommentHOC} from '../../page/layers/ImageLayerOfCommentHOC'
-
-import MemoDetailMDEditor from '../../forums/MemoDetailMDEditor'
-import { RouteHOC } from './common.js'
-import '../../forums/Post.css'
-import '../../forums/RightSection.css'
-import './TopicDetail.css'
-import '../common/courseMessage.css'
-import { Pagination, Tooltip } from 'antd'
-import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml } from 'educoder'
-import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal'
-import CBreadcrumb from '../common/CBreadcrumb'
-import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment
- , addSecondLevelComment, NEED_TO_WRITE_CONTENT, handleContentBeforeCreateSecondLevelComment
- , handleDeleteComment, handleCommentPraise, handleHiddenComment } from '../common/CommentsHelper'
-
-const $ = window.$
-const REPLY_PAGE_COUNT = 10
-function urlStringify(params) {
- let noParams = true;
- let paramsUrl = '';
- for (let key in params) {
- noParams = false;
- paramsUrl += `${key}=${params[key]}&`
- }
- if (noParams) {
- return '';
- }
- paramsUrl = paramsUrl.substring(0, paramsUrl.length - 1);
- return paramsUrl;
-}
-class TopicDetail extends Component {
- constructor(props) {
- super(props)
-
- this.state = {
- memo: {},
- memoLoading: true,
- hasMoreComments: false,
- pageCount: 1,
- comments: [],
- goldRewardDialogOpen: false,
- }
- }
- componentDidMount() {
- window.$("html,body").animate({"scrollTop":0})
-
- const topicId = this.props.match.params.topicId
- const bid = this.props.match.params.boardId
-
- const memoUrl = `/messages/${topicId}.json`;
- this.setState({
- memoLoading: true
- })
- axios.get(memoUrl,{
- })
- .then((response) => {
-
- if (response.data.status === -1) {
- setTimeout(() => {
- this.props.showNotification('帖子不存在!')
- }, 300)
- // this.props.toListPage(response.data.data.course_id, bid)
- return;
- } else {
-
- this.setState({
- memo: Object.assign({}, {
- ...response.data.data,
- replies_count: response.data.data.total_replies_count
- }, {...this.state.memo})
- }, () => {
- })
-
- // const { memo_replies, memo } = response.data;
- // let hasMoreComments = false;
- // if (memo_replies && memo_replies.length === 10 && memo.total_replies_count > 10) {
- // // 遍历一遍,计算下是否还有评论未加载
- // let totalCount = 10;
- // memo_replies.forEach(item=>{
- // totalCount += item.children.length
- // })
- // if (totalCount < memo.total_replies_count) {
- // hasMoreComments = true;
- // }
- // }
- // this.setState({
- // hasMoreComments,
- // pageCount: 1,
- // comments: memo_replies
- // })
- // delete response.data.memo_replies;
- // this.setState(response.data)
- // const user = response.data.current_user;
- // user.tidding_count = response.data.tidding_count;
- // this.props.initCommonState(user)
- }
- this.setState({
- memoLoading: false
- })
-
- }).catch((error) => {
- console.log(error)
- })
-
- this.fetchReplies()
-
- $('body>#root').on('onMemoDelete', (event) => {
- // const val = $('body>#root').data('onMemoDelete')
- const val = window.onMemoDelete ;
- this.onMemoDelete( JSON.parse(decodeURIComponent(val)) )
- })
-
-
- }
-
- onPaginationChange = (pageCount) => {
- this.setState({ pageCount }, () => {
- this.fetchReplies()
- })
- }
-
- componentWillUnmount() {
- $('body>#root').off('onMemoDelete')
- }
- onMemoDelete(memo) {
- const deleteUrl = `/commons/delete.json`;
- // 获取memo list
- axios.delete(deleteUrl, { data: {
- object_id: memo.id,
- object_type: 'message'
- }
- })
- .then((response) => {
- const status = response.data.status
- if (status === 0) {
-
- this.props.showNotification('删除成功');
- const props = Object.assign({}, this.props, {})
- this.props.toListPage( Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id} ) )
-
- } else if (status === -1) {
- this.props.showNotification('帖子已被删除');
- this.props.history.push(`/forums`)
- }
- }).catch((error) => {
- console.log(error)
- })
- }
-
- componentDidUpdate(prevProps, prevState, snapshot) {
- // if (this.state.memo && this.state.memo.content
- // && (!prevProps.memo || prevProps.memo.content != this.state.memo.content) ) {
- if (this.state.memo && this.state.memo.content && prevState.memoLoading === true && this.state.memoLoading === false) {
- // md渲染content,等xhr执行完(即memoLoading变化),memo.content更新后初始化md
-
- setTimeout(()=>{
- // var shixunDescr = window.editormd.markdownToHTML("memo_content_editorMd", {
- // htmlDecode: "style,script,iframe", // you can filter tags decode
- // taskList: true,
- // tex: true, // 默认不解析
- // flowChart: true, // 默认不解析
- // sequenceDiagram: true // 默认不解析
- // });
- }, 200)
- }
-
- }
-
- clickPraise(){
- const { memo } = this.state;
- // const url = `/api/v1/discusses/${memo.id}/plus`;
- const url = memo.user_praise ? '/praise_tread/unlike.json' : `/praise_tread/like.json`;
- const _method = memo.user_praise ? axios.delete : axios.post
- let _data = {
- object_id: memo.id,
- object_type: 'message', //Discuss
- }
- if (memo.user_praise) {
- _data = {
- data: _data
- }
- }
- _method(url, {
- ..._data
- },
- {
-
- }
- ).then((response) => {
-
- const newMemo = Object.assign({}, this.state.memo)
- newMemo.praises_count = newMemo.user_praise ? newMemo.praises_count - 1 : newMemo.praises_count + 1
- newMemo.total_praises_count = newMemo.user_praise ? newMemo.total_praises_count - 1 : newMemo.total_praises_count + 1
- newMemo.user_praise = !newMemo.user_praise
- this.setState({memo : newMemo })
- }).catch((error) => {
- console.log(error)
- })
- }
- renderAttachment() {
- const { memo } = this.state;
- const attachments = []
- memo.attachments.forEach((item, index) => {
- const ar = item.url.split('/')
- const fileName = item.title || ar[ar.length - 1]
- let filesize = 0
- if (item.filesize) {
- filesize = item.filesize
- // filesize = bytesToSize(item.filesize)
- }
- attachments.push(
- //
- //
- //
- // {fileName && 30 }>
- // {fileName}
- // }
- // {filesize? ` ${filesize.replace(' ', '')}` : ''}
- //
- //
-
-
- )
- })
- return attachments;
- }
- // ------------------------------------------------------------------------------------------- comments START
- // ------------------------------------------------------------------------------------------- comments START
- transformReply = (reply, children = []) => {
- const isAdmin = this.props.isAdmin()
- const isSuperAdmin = this.props.isSuperAdmin()
- return {
- isSuperAdmin: isSuperAdmin,
- admin: isAdmin, //
- permission: true, //
- children: children,
- child_message_count: reply.total_count,
- hidden: reply.is_hidden,
- id: reply.id,
- image_url: reply.author.image_url,
- reward: null, //
- time: moment(reply.created_on).fromNow(),
- user_id: reply.author.id,
- user_login: reply.author.login,
- user_praise: reply.liked,
- username: reply.author.name,
- content: reply.content,
- praise_count: reply.praises_count
- }
- }
-
- fetchReplies = () => {
- const topicId = this.props.match.params.topicId
- const url = `/messages/${topicId}/reply_list.json?page=${this.state.pageCount}&page_size=${REPLY_PAGE_COUNT}`
- axios.get(url,{
- })
- .then((response) => {
- const { replies, liked, total_replies_count, total_count } = response.data.data
-
- const memo = Object.assign({}, this.state.memo)
- memo.user_praise = liked
- memo.total_replies_count = total_replies_count;
- this.setState({
- memo,
- comments: generateComments(replies, this.transformReply, 'replies'),
- // : this.state.comments.concat(comments),
- total_count: total_count
- })
- }).catch((error) => {
- console.log(error)
- })
- }
-
- _getUser() {
- const { current_user } = this.props;
- current_user.user_url = `/users/${current_user.login}`;
- return current_user;
- }
- _findById = _findById
- replyComment = (commentContent, id, editor) => {
- const { showNotification } = this.props;
- // if (!commentContent || commentContent.length === 0) {
- // showNotification(NEED_TO_WRITE_CONTENT)
- // return;
- // }
-
- if (this.state.memo.id === id ) { // 回复帖子
- this.createNewComment(commentContent, id, editor);
- return;
- }
- const url = `/messages/${id}/reply.json`;
-
- const { comments } = this.state;
- const user = this._getUser();
- /*
- 移除末尾的空行
- .replace(/(\n
\n\t \n<\/p>)*$/g,'');
-
- */
-
- commentContent = handleContentBeforeCreateSecondLevelComment(commentContent)
- if (!commentContent) {
- this.props.showNotification('不能为空')
- return;
- }
- axios.post(url, {
- content: commentContent
- },
- {
- }
- ).then((response) => {
- if (response.data.data.id) {
- let newId = response.data.data.id;
- const commentIndex = this._findById(id, comments);
- const parentComment = comments[commentIndex]
-
- this.setState({
- // runTesting: false,
- comments: addSecondLevelComment(comments, parentComment, commentIndex, newId, commentContent, user, editor)
- }, ()=>{
- // keditor代码美化
- editor.html && window.prettyPrint()
- })
-
- const newMemo2 = Object.assign({}, this.state.memo);
- newMemo2.total_replies_count = newMemo2.total_replies_count + 1;
- this.setState({
- memo: newMemo2
- })
- }
-
- }).catch((error) => {
- console.log(error)
- })
- }
- // 公共接口 --- 删除回复
- deleteComment = (parrentComment, childCommentId) => {
- handleDeleteComment(this, parrentComment, childCommentId, 'message')
-
- }
- // 公共接口 --- 回复点赞
- commentPraise = (discussId) => {
- handleCommentPraise(this, discussId, 'message', (old_user_praise) => {
- const newMemo2 = Object.assign({}, this.state.memo);
-
- newMemo2.total_praises_count = old_user_praise
- ? newMemo2.total_praises_count - 1 : newMemo2.total_praises_count + 1;
- this.setState({
- memo: newMemo2
- })
- })
- }
- // 公共接口 --- 隐藏回复
- hiddenComment = (item, childCommentId) => {
- handleHiddenComment(this, item, childCommentId, 'message')
- }
- createNewComment = (commentContent, id, editor) => {
- let content = handleContentBeforeCreateNew(commentContent);
- const { memo } = this.props;
-
- const url = `/messages/${id}/reply.json`;
-
- // const url = `/api/v1/memos/${memo.id}/reply`;
- let { comments } = this.state;
- axios.post(url, {
- content: content
- },
- {
- }
- ).then((response) => {
- if (response.data.status === -1) {
- console.error('服务端异常')
- return;
- }
- // this.props.showNotification('帖子发表成功')
-
- if (response.data) {
- const _id = response.data.data.id;
- // ke
- editor.html && editor.html('');
- editor.afterBlur && editor.afterBlur()
- // md
- editor.setValue && editor.setValue('')
-
-
- const user = this._getUser();
- this.setState({
- comments: addNewComment(comments, _id, content, user, this.props.isSuperAdmin(), this)
- })
- const newMemo2 = Object.assign({}, this.state.memo);
- newMemo2.total_replies_count = newMemo2.total_replies_count + 1;
- this.setState({
- memo: newMemo2
- })
- this.refs.editor.showEditor();
- this.refs.editor.close();
-
-
- }
- }).catch((error) => {
- console.log(error)
- })
- }
-
- /**
- * parent.isAllChildrenLoaded 为 true的时候,表示已经没有更多子回复了
- */
- loadMoreChildComments = (parent) => {
- const url = `/messages/${parent.id}/reply_list.json?page=1&page_size=500`
- axios.get(url,{
- })
- .then((response) => {
- const { replies, liked, total_replies_count } = response.data.data
-
- // const memo = Object.assign({}, this.state.memo)
- // memo.total_replies_count = total_replies_count;
- this.setState({
- // memo,
- comments: generateChildComments(replies, this.state.comments, parent, this.transformReply)
- })
- }).catch((error) => {
- console.log(error)
- })
- }
- // ------------------------------------------------------------------------------------------- comments END
- // ------------------------------------------------------------------------------------------- comments END
- // 置顶
- setTop(memo) {
- // const params = {
- // sticky: memo.sticky ? 0 : 1,
- // }
- // if (this.state.p_s_order) {
- // params.order = this.state.p_s_order;
- // }
- // if (this.state.p_forum_id) {
- // params.forum_id = this.state.p_forum_id;
- // }
- // let paramsUrl = urlStringify(params)
- const set_top_or_down_Url = `/messages/${memo.id}/sticky_top.json`;
- // 获取memo list
- axios.put(set_top_or_down_Url, {
-
- })
- .then((response) => {
- const status = response.data.status
- if (status === 0) {
- this.props.showNotification( memo.sticky ? '取消置顶成功' : '置顶成功');
- memo.sticky = memo.sticky ? false : true
- this.setState({
- memo: Object.assign({}, memo)
- })
- }
- }).catch((error) => {
- console.log(error)
- })
- }
-
- setRewardDialogVisible = (visible) => {
- this.setState({
- goldRewardDialogOpen: visible
- })
- }
- showRewardDialog = () => {
- this.setState({
- goldRewardDialogOpen: true
- })
- }
- // --------------------------------------------------------------------------------------------帖子獎勵 END
- showCommentInput = () => {
- if (window.__useKindEditor === true) {
- this.refs.editor.showEditor();
- } else {
- this.refs.editor.showEditor();
- }
- }
- initReply = (parent) => {
- if (!parent.isAllChildrenLoaded) {
- this.loadMoreChildComments(parent)
- }
- }
-
-
- render() {
- const { match, history } = this.props
- const { recommend_shixun, current_user,author_info } = this.props;
- const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count } = this.state;
- const messageId = match.params.topicId
- if (this.state.memoLoading || !current_user) {
- return
- }
- current_user.user_url = `/users/${current_user.login}`;
- const isCurrentUserTheAuthor = current_user.login == memo.author.login
- const isAdmin = this.props.isAdmin()
- // TODO 图片上传地址
- const courseId=this.props.match.params.coursesId;
- const boardId = this.props.match.params.boardId
- return (
-
{/* fl with100 */}
-
-
-
-
-
-
-
-
-
{memo.subject}
- { !!memo.sticky &&
置顶 }
- { !!memo.reward &&
- {memo.reward}
- }
- {/* || current_user.user_id === author_info.user_id */}
- { current_user && (isAdmin || isCurrentUserTheAuthor) &&
-
- }
-
-
-
-
{moment(memo.created_on).fromNow()} 发布
-
-
-
-
-
-
-
- {/* { current_user.admin &&
-
-
-
- } */}
-
-
-
- {memo.visits || '1'}
-
-
- { !!memo.total_replies_count &&
-
-
-
- { memo.total_replies_count }
-
-
- }
- {!!memo.total_praises_count &&
-
-
-
- { memo.total_praises_count }
-
-
- }
-
-
-
-
-
-
-
- {memo.is_md == true ?
:
-
- }
-
-
-
- {/* ${memo.user_praise ? '' : ''} */}
-
- {this.clickPraise()}} >
-
- {memo.praises_count}
-
-
-
-
- { memo.attachments && !!memo.attachments.length &&
-
- {this.renderAttachment()}
-
- }
-
-
-
-
- {/* onClick={ this.createNewComment }
- enableReplyTo={true}
- */}
-
-
- 全部回复
- ({memo.total_replies_count})
-
-
-
-
-
- {/* { true ? :
-
} */}
-
-
-
-
- { total_count > REPLY_PAGE_COUNT &&
-
- }
- 写评论
-
-
-
-
-
-
- );
- }
-}
-
-export default ImageLayerOfCommentHOC() ( RouteHOC()(TopicDetail) );
+import React, { Component } from 'react';
+import { Redirect } from 'react-router';
+
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+
+import PropTypes from 'prop-types';
+
+import classNames from 'classnames'
+
+import axios from 'axios'
+
+import moment from 'moment'
+
+import Comments from '../../comment/Comments'
+
+import update from 'immutability-helper'
+import RewardDialog from '../../common/RewardDialog';
+import {ImageLayerOfCommentHOC} from '../../page/layers/ImageLayerOfCommentHOC'
+
+import MemoDetailMDEditor from '../../forums/MemoDetailMDEditor'
+import { RouteHOC } from './common.js'
+import '../../forums/Post.css'
+import '../../forums/RightSection.css'
+import './TopicDetail.css'
+import '../common/courseMessage.css'
+import { Pagination, Tooltip } from 'antd'
+import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml } from 'educoder'
+import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal'
+import CBreadcrumb from '../common/CBreadcrumb'
+import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment
+ , addSecondLevelComment, NEED_TO_WRITE_CONTENT, handleContentBeforeCreateSecondLevelComment
+ , handleDeleteComment, handleCommentPraise, handleHiddenComment } from '../common/CommentsHelper'
+
+const $ = window.$
+const REPLY_PAGE_COUNT = 10
+function urlStringify(params) {
+ let noParams = true;
+ let paramsUrl = '';
+ for (let key in params) {
+ noParams = false;
+ paramsUrl += `${key}=${params[key]}&`
+ }
+ if (noParams) {
+ return '';
+ }
+ paramsUrl = paramsUrl.substring(0, paramsUrl.length - 1);
+ return paramsUrl;
+}
+class TopicDetail extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+ memo: {},
+ memoLoading: true,
+ hasMoreComments: false,
+ pageCount: 1,
+ comments: [],
+ goldRewardDialogOpen: false,
+ }
+ }
+ componentDidMount() {
+ window.$("html,body").animate({"scrollTop":0})
+
+ const topicId = this.props.match.params.topicId
+ const bid = this.props.match.params.boardId
+
+ const memoUrl = `/messages/${topicId}.json`;
+ this.setState({
+ memoLoading: true
+ })
+ axios.get(memoUrl,{
+ })
+ .then((response) => {
+
+ if (response.data.status === -1) {
+ setTimeout(() => {
+ this.props.showNotification('帖子不存在!')
+ }, 300)
+ // this.props.toListPage(response.data.data.course_id, bid)
+ return;
+ } else {
+
+ this.setState({
+ memo: Object.assign({}, {
+ ...response.data.data,
+ replies_count: response.data.data.total_replies_count
+ }, {...this.state.memo})
+ }, () => {
+ })
+
+ // const { memo_replies, memo } = response.data;
+ // let hasMoreComments = false;
+ // if (memo_replies && memo_replies.length === 10 && memo.total_replies_count > 10) {
+ // // 遍历一遍,计算下是否还有评论未加载
+ // let totalCount = 10;
+ // memo_replies.forEach(item=>{
+ // totalCount += item.children.length
+ // })
+ // if (totalCount < memo.total_replies_count) {
+ // hasMoreComments = true;
+ // }
+ // }
+ // this.setState({
+ // hasMoreComments,
+ // pageCount: 1,
+ // comments: memo_replies
+ // })
+ // delete response.data.memo_replies;
+ // this.setState(response.data)
+ // const user = response.data.current_user;
+ // user.tidding_count = response.data.tidding_count;
+ // this.props.initCommonState(user)
+ }
+ this.setState({
+ memoLoading: false
+ })
+
+ }).catch((error) => {
+ console.log(error)
+ })
+
+ this.fetchReplies()
+
+ $('body>#root').on('onMemoDelete', (event) => {
+ // const val = $('body>#root').data('onMemoDelete')
+ const val = window.onMemoDelete ;
+ this.onMemoDelete( JSON.parse(decodeURIComponent(val)) )
+ })
+
+
+ }
+
+ onPaginationChange = (pageCount) => {
+ this.setState({ pageCount }, () => {
+ this.fetchReplies()
+ })
+ }
+
+ componentWillUnmount() {
+ $('body>#root').off('onMemoDelete')
+ }
+ onMemoDelete(memo) {
+ const deleteUrl = `/commons/delete.json`;
+ // 获取memo list
+ axios.delete(deleteUrl, { data: {
+ object_id: memo.id,
+ object_type: 'message'
+ }
+ })
+ .then((response) => {
+ const status = response.data.status
+ if (status === 0) {
+
+ this.props.showNotification('删除成功');
+ const props = Object.assign({}, this.props, {})
+ this.props.toListPage( Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id} ) )
+
+ } else if (status === -1) {
+ this.props.showNotification('帖子已被删除');
+ this.props.history.push(`/forums`)
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+
+ componentDidUpdate(prevProps, prevState, snapshot) {
+ // if (this.state.memo && this.state.memo.content
+ // && (!prevProps.memo || prevProps.memo.content != this.state.memo.content) ) {
+ if (this.state.memo && this.state.memo.content && prevState.memoLoading === true && this.state.memoLoading === false) {
+ // md渲染content,等xhr执行完(即memoLoading变化),memo.content更新后初始化md
+
+ setTimeout(()=>{
+ // var shixunDescr = window.editormd.markdownToHTML("memo_content_editorMd", {
+ // htmlDecode: "style,script,iframe", // you can filter tags decode
+ // taskList: true,
+ // tex: true, // 默认不解析
+ // flowChart: true, // 默认不解析
+ // sequenceDiagram: true // 默认不解析
+ // });
+ }, 200)
+ }
+
+ }
+
+ clickPraise(){
+ const { memo } = this.state;
+ // const url = `/api/v1/discusses/${memo.id}/plus`;
+ const url = memo.user_praise ? '/praise_tread/unlike.json' : `/praise_tread/like.json`;
+ const _method = memo.user_praise ? axios.delete : axios.post
+ let _data = {
+ object_id: memo.id,
+ object_type: 'message', //Discuss
+ }
+ if (memo.user_praise) {
+ _data = {
+ data: _data
+ }
+ }
+ _method(url, {
+ ..._data
+ },
+ {
+
+ }
+ ).then((response) => {
+
+ const newMemo = Object.assign({}, this.state.memo)
+ newMemo.praises_count = newMemo.user_praise ? newMemo.praises_count - 1 : newMemo.praises_count + 1
+ newMemo.total_praises_count = newMemo.user_praise ? newMemo.total_praises_count - 1 : newMemo.total_praises_count + 1
+ newMemo.user_praise = !newMemo.user_praise
+ this.setState({memo : newMemo })
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+ renderAttachment() {
+ const { memo } = this.state;
+ const attachments = []
+ memo.attachments.forEach((item, index) => {
+ const ar = item.url.split('/')
+ const fileName = item.title || ar[ar.length - 1]
+ let filesize = 0
+ if (item.filesize) {
+ filesize = item.filesize
+ // filesize = bytesToSize(item.filesize)
+ }
+ attachments.push(
+ //
+ //
+ //
+ // {fileName && 30 }>
+ // {fileName}
+ // }
+ // {filesize? ` ${filesize.replace(' ', '')}` : ''}
+ //
+ //
+
+
+ )
+ })
+ return attachments;
+ }
+ // ------------------------------------------------------------------------------------------- comments START
+ // ------------------------------------------------------------------------------------------- comments START
+ transformReply = (reply, children = []) => {
+ const isAdmin = this.props.isAdmin()
+ const isSuperAdmin = this.props.isSuperAdmin()
+ return {
+ isSuperAdmin: isSuperAdmin,
+ admin: isAdmin, //
+ permission: true, //
+ children: children,
+ child_message_count: reply.total_count,
+ hidden: reply.is_hidden,
+ id: reply.id,
+ image_url: reply.author.image_url,
+ reward: null, //
+ time: moment(reply.created_on).fromNow(),
+ user_id: reply.author.id,
+ user_login: reply.author.login,
+ user_praise: reply.liked,
+ username: reply.author.name,
+ content: reply.content,
+ praise_count: reply.praises_count
+ }
+ }
+
+ fetchReplies = () => {
+ const topicId = this.props.match.params.topicId
+ const url = `/messages/${topicId}/reply_list.json?page=${this.state.pageCount}&page_size=${REPLY_PAGE_COUNT}`
+ axios.get(url,{
+ })
+ .then((response) => {
+ const { replies, liked, total_replies_count, total_count } = response.data.data
+
+ const memo = Object.assign({}, this.state.memo)
+ memo.user_praise = liked
+ memo.total_replies_count = total_replies_count;
+ this.setState({
+ memo,
+ comments: generateComments(replies, this.transformReply, 'replies'),
+ // : this.state.comments.concat(comments),
+ total_count: total_count
+ })
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+
+ _getUser() {
+ const { current_user } = this.props;
+ current_user.user_url = `/users/${current_user.login}`;
+ return current_user;
+ }
+ _findById = _findById
+ replyComment = (commentContent, id, editor) => {
+ const { showNotification } = this.props;
+ // if (!commentContent || commentContent.length === 0) {
+ // showNotification(NEED_TO_WRITE_CONTENT)
+ // return;
+ // }
+
+ if (this.state.memo.id === id ) { // 回复帖子
+ this.createNewComment(commentContent, id, editor);
+ return;
+ }
+ const url = `/messages/${id}/reply.json`;
+
+ const { comments } = this.state;
+ const user = this._getUser();
+ /*
+ 移除末尾的空行
+ .replace(/(\n
\n\t \n<\/p>)*$/g,'');
+
+ */
+
+ commentContent = handleContentBeforeCreateSecondLevelComment(commentContent)
+ if (!commentContent) {
+ this.props.showNotification('不能为空')
+ return;
+ }
+ axios.post(url, {
+ content: commentContent
+ },
+ {
+ }
+ ).then((response) => {
+ if (response.data.data.id) {
+ let newId = response.data.data.id;
+ const commentIndex = this._findById(id, comments);
+ const parentComment = comments[commentIndex]
+
+ this.setState({
+ // runTesting: false,
+ comments: addSecondLevelComment(comments, parentComment, commentIndex, newId, commentContent, user, editor)
+ }, ()=>{
+ // keditor代码美化
+ editor.html && window.prettyPrint()
+ })
+
+ const newMemo2 = Object.assign({}, this.state.memo);
+ newMemo2.total_replies_count = newMemo2.total_replies_count + 1;
+ this.setState({
+ memo: newMemo2
+ })
+ }
+
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+ // 公共接口 --- 删除回复
+ deleteComment = (parrentComment, childCommentId) => {
+ handleDeleteComment(this, parrentComment, childCommentId, 'message')
+
+ }
+ // 公共接口 --- 回复点赞
+ commentPraise = (discussId) => {
+ handleCommentPraise(this, discussId, 'message', (old_user_praise) => {
+ const newMemo2 = Object.assign({}, this.state.memo);
+
+ newMemo2.total_praises_count = old_user_praise
+ ? newMemo2.total_praises_count - 1 : newMemo2.total_praises_count + 1;
+ this.setState({
+ memo: newMemo2
+ })
+ })
+ }
+ // 公共接口 --- 隐藏回复
+ hiddenComment = (item, childCommentId) => {
+ handleHiddenComment(this, item, childCommentId, 'message')
+ }
+ createNewComment = (commentContent, id, editor) => {
+ let content = handleContentBeforeCreateNew(commentContent);
+ const { memo } = this.props;
+
+ const url = `/messages/${id}/reply.json`;
+
+ // const url = `/api/v1/memos/${memo.id}/reply`;
+ let { comments } = this.state;
+ axios.post(url, {
+ content: content
+ },
+ {
+ }
+ ).then((response) => {
+ if (response.data.status === -1) {
+ console.error('服务端异常')
+ return;
+ }
+ // this.props.showNotification('帖子发表成功')
+
+ if (response.data) {
+ const _id = response.data.data.id;
+ // ke
+ editor.html && editor.html('');
+ editor.afterBlur && editor.afterBlur()
+ // md
+ editor.setValue && editor.setValue('')
+
+
+ const user = this._getUser();
+ this.setState({
+ comments: addNewComment(comments, _id, content, user, this.props.isSuperAdmin(), this)
+ })
+ const newMemo2 = Object.assign({}, this.state.memo);
+ newMemo2.total_replies_count = newMemo2.total_replies_count + 1;
+ this.setState({
+ memo: newMemo2
+ })
+ this.refs.editor.showEditor();
+ this.refs.editor.close();
+
+
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+
+ /**
+ * parent.isAllChildrenLoaded 为 true的时候,表示已经没有更多子回复了
+ */
+ loadMoreChildComments = (parent) => {
+ const url = `/messages/${parent.id}/reply_list.json?page=1&page_size=500`
+ axios.get(url,{
+ })
+ .then((response) => {
+ const { replies, liked, total_replies_count } = response.data.data
+
+ // const memo = Object.assign({}, this.state.memo)
+ // memo.total_replies_count = total_replies_count;
+ this.setState({
+ // memo,
+ comments: generateChildComments(replies, this.state.comments, parent, this.transformReply)
+ })
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+ // ------------------------------------------------------------------------------------------- comments END
+ // ------------------------------------------------------------------------------------------- comments END
+ // 置顶
+ setTop(memo) {
+ // const params = {
+ // sticky: memo.sticky ? 0 : 1,
+ // }
+ // if (this.state.p_s_order) {
+ // params.order = this.state.p_s_order;
+ // }
+ // if (this.state.p_forum_id) {
+ // params.forum_id = this.state.p_forum_id;
+ // }
+ // let paramsUrl = urlStringify(params)
+ const set_top_or_down_Url = `/messages/${memo.id}/sticky_top.json`;
+ // 获取memo list
+ axios.put(set_top_or_down_Url, {
+
+ })
+ .then((response) => {
+ const status = response.data.status
+ if (status === 0) {
+ this.props.showNotification( memo.sticky ? '取消置顶成功' : '置顶成功');
+ memo.sticky = memo.sticky ? false : true
+ this.setState({
+ memo: Object.assign({}, memo)
+ })
+ }
+ }).catch((error) => {
+ console.log(error)
+ })
+ }
+
+ setRewardDialogVisible = (visible) => {
+ this.setState({
+ goldRewardDialogOpen: visible
+ })
+ }
+ showRewardDialog = () => {
+ this.setState({
+ goldRewardDialogOpen: true
+ })
+ }
+ // --------------------------------------------------------------------------------------------帖子獎勵 END
+ showCommentInput = () => {
+ if (window.__useKindEditor === true) {
+ this.refs.editor.showEditor();
+ } else {
+ this.refs.editor.showEditor();
+ }
+ }
+ initReply = (parent) => {
+ if (!parent.isAllChildrenLoaded) {
+ this.loadMoreChildComments(parent)
+ }
+ }
+
+
+ render() {
+ const { match, history } = this.props
+ const { recommend_shixun, current_user,author_info } = this.props;
+ const { memo, comments, hasMoreComments, goldRewardDialogOpen, pageCount, total_count } = this.state;
+ const messageId = match.params.topicId
+ if (this.state.memoLoading || !current_user) {
+ return
+ }
+ current_user.user_url = `/users/${current_user.login}`;
+ const isCurrentUserTheAuthor = current_user.login == memo.author.login
+ const isAdmin = this.props.isAdmin()
+ // TODO 图片上传地址
+ const courseId=this.props.match.params.coursesId;
+ const boardId = this.props.match.params.boardId
+ return (
+
{/* fl with100 */}
+
+
+
+
+
+
+
+
+
{memo.subject}
+ { !!memo.sticky &&
置顶 }
+ { !!memo.reward &&
+ {memo.reward}
+ }
+ {/* || current_user.user_id === author_info.user_id */}
+ { current_user && (isAdmin || isCurrentUserTheAuthor) &&
+
+ }
+
+
+
+
{moment(memo.created_on).fromNow()} 发布
+
+
+
+
+
+
+
+ {/* { current_user.admin &&
+
+
+
+ } */}
+
+
+
+ {memo.visits || '1'}
+
+
+ { !!memo.total_replies_count &&
+
+
+
+ { memo.total_replies_count }
+
+
+ }
+ {!!memo.total_praises_count &&
+
+
+
+ { memo.total_praises_count }
+
+
+ }
+
+
+
+
+
+
+
+ {memo.is_md == true ?
:
+
+ }
+
+
+
+ {/* ${memo.user_praise ? '' : ''} */}
+
+ {this.clickPraise()}} >
+
+ {memo.praises_count}
+
+
+
+
+ { memo.attachments && !!memo.attachments.length &&
+
+ {this.renderAttachment()}
+
+ }
+
+
+
+
+ {/* onClick={ this.createNewComment }
+ enableReplyTo={true}
+ */}
+
+
+ 全部回复
+ ({memo.total_replies_count})
+
+
+
+
+
+ {/* { true ? :
+
} */}
+
+
+
+
+ { total_count > REPLY_PAGE_COUNT &&
+
+ }
+ 写评论
+
+
+
+
+
+
+ );
+ }
+}
+
+export default ImageLayerOfCommentHOC() ( RouteHOC()(TopicDetail) );
diff --git a/public/react/src/modules/courses/boards/index.js b/public/react/src/modules/courses/boards/index.js
index 94c8c4c00..db3232b23 100644
--- a/public/react/src/modules/courses/boards/index.js
+++ b/public/react/src/modules/courses/boards/index.js
@@ -440,7 +440,7 @@ class Boards extends Component{
{
- ( !messages || messages.length == 0 ) &&
+ ( !this.state.isSpin && (!messages || messages.length == 0) ) &&
}
{/* { haveMore &&
diff --git a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js
index eb53fa373..4d82f4182 100644
--- a/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js
+++ b/public/react/src/modules/courses/busyWork/CommonWorkDetailIndex.js
@@ -223,7 +223,7 @@ class CommonWorkDetailIndex extends Component{
}
`}
{current_user &&
+ className="courseMessageMD" initValue={this.state.description}>
)}
}
@@ -508,7 +508,7 @@ class NewWork extends Component{
required: false
}],
})(
-
)}
diff --git a/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js b/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js
index eef99bfcd..56460a44a 100644
--- a/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js
+++ b/public/react/src/modules/courses/busyWork/common/WorkDetailPageHeader.js
@@ -90,7 +90,7 @@ class WorkDetailPageHeader extends Component{
}
`}
请先上传资源
:""}
+ {newfileListtype===true&&this.state.fileListtype===false?
请先上传资源
:""}
-
- { current_user &&
}
-
-
- {this.isEdit ? "编辑" : "新建"}试卷
- this.props.history.length == 1 ? this.props.history.push(`/courses/${courseId}/exercises/${left_banner_id}`): this.props.history.goBack()}>
- 返回
-
-
-
- {!this.state.editMode &&
}
- {this.state.editMode &&
}
-
-
-
-
- { !!q_singles && 单选题{q_singles}题,共{q_singles_scores}分 }
- { !!q_doubles && 多选题{q_doubles}题,共{q_doubles_scores}分 }
- { !!q_judges && 判断题{q_judges}题,共{q_judges_scores}分 }
- { !!q_nulls && 填空题{q_nulls}题,共{q_nulls_scores}分 }
- { !!q_mains && 简答题{q_mains}题,共{q_mains_scores}分 }
- { !!q_shixuns && 实训题{q_shixuns}题,共{q_shixuns_scores}分 }
-
-
- { !!q_counts &&
-
- 合计 {q_counts} 题,
- 共 100 ? 'color-red font-bd' : 'color-orange'}`}>{q_scores} 分
-
- }
-
-
-
- { exercise_questions.map((item, index) => {
- if (item.question_type == 0 || item.question_type == 1) {
- if (item.isNew) {
- return
- } else {
- return
- }
- } else if (item.question_type == 2) {
- if (item.isNew) {
- return
- } else {
- return
- }
- } else if (item.question_type == 3) {
- if (item.isNew) {
- return
- } else {
- return
- }
- } else if (item.question_type == 4) {
- if (item.isNew) {
- return
- } else {
- return
- }
- } else if (item.question_type == 5) {
- if (item.isNew) {
- return
- } else {
- return
- }
- }
- return
- })}
-
- {!commonHandler.exerciseIsPublish &&
-
this.addQuestion(null, Q_TYPE_SINGLE)}>
- 选择题
-
-
this.addQuestion(null, Q_TYPE_JUDGE)}>
- 判断题
-
-
this.addQuestion(null, Q_TYPE_NULL)}>
- 填空题
-
-
this.addQuestion(null, Q_TYPE_MAIN)}>
- 简答题
-
-
this.addShixun(null)}>
- 实训题
-
-
- {exercise_id &&
this.goToPreview()}>
- {/* */}
- 试卷预览
- }
-
}
-
-
-
-
- )
- }
-}
-// RouteHOC()
+import React,{ Component } from "react";
+
+import {
+ Form, Input, InputNumber, Switch, Radio,
+ Slider, Button, Upload, Icon, Rate, Checkbox, message,
+ Row, Col, Select, Modal, Tooltip
+} from 'antd';
+import { Q_TYPE_SINGLE, Q_TYPE_MULTI, Q_TYPE_JUDGE, Q_TYPE_NULL, Q_TYPE_MAIN, Q_TYPE_SHIXUN } from './new/common'
+import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
+import axios from 'axios'
+// import './board.css'
+import "../common/formCommon.css"
+
+// import { RouteHOC } from './common.js'
+import CBreadcrumb from '../common/CBreadcrumb'
+import {getUrl, ActionBtn} from 'educoder';
+
+import SingleEditor from './new/SingleEditor'
+import SingleDisplay from './new/SingleDisplay'
+import JudgeEditor from './new/JudgeEditor'
+import JudgeDisplay from './new/JudgeDisplay'
+import NullEditor from './new/NullEditor'
+import NullDisplay from './new/NullDisplay'
+import MainEditor from './new/MainEditor'
+import MainDisplay from './new/MainDisplay'
+import ShixunEditor from './new/ShixunEditor'
+import ShixunDisplay from './new/ShixunDisplay'
+
+import ShixunChooseModal from '../coursesPublic/ShixunChooseModal'
+import update from 'immutability-helper'
+import './new/common.css'
+import '../css/Courses.css'
+const { TextArea } = Input;
+const confirm = Modal.confirm;
+const $ = window.$
+const { Option } = Select;
+
+class ExerciceNew extends Component{
+ constructor(props){
+ super(props);
+
+
+ this.state = {
+ exercise_questions: [],
+ exercise_name: '',
+ exercise_description: '',
+ exercise_types: {},
+ editMode: !this.props.match.params.Id,
+ }
+ }
+ fetchExercise = () => {
+ const Id = this.props.match.params.Id
+ this.isEdit = !!Id
+ if (Id) {
+ const url = `/exercises/${Id}/edit.json`
+ axios.get(url)
+ .then((response) => {
+ if (response.data.status == 0) {
+ const { exercise, ...others } = response.data
+ this.setState({
+ ...exercise,
+ ...others,
+ editMode: false
+ })
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ } else {
+ const courseId=this.props.match.params.coursesId;
+
+ const newUrl = `/courses/${courseId}/exercises/new.json`
+ axios.get(newUrl)
+ .then((response) => {
+ if (response.data.status == 0) {
+ this.setState({
+ ...response.data
+ })
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ }
+ componentDidMount = () => {
+ this.fetchExercise()
+ }
+ handleSubmit = (e) => {
+
+ }
+ onSaveExercise = () => {
+ const { exercise_name, exercise_description } = this.state;
+ const exercise_id = this.props.match.params.Id
+ const courseId = this.props.match.params.coursesId
+ if (this.isEdit) {
+ const editUrl = `/exercises/${exercise_id}.json`
+ axios.put(editUrl, {
+ exercise_name,
+ exercise_description
+ })
+ .then((response) => {
+ if (response.data.status == 0) {
+ this.setState({editMode: false})
+ this.props.showNotification('试卷编辑成功')
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ } else {
+ const url = `/courses/${courseId}/exercises.json`
+ axios.post(url, {
+ exercise_name,
+ exercise_description
+ })
+ .then((response) => {
+ if (response.data.status == 0) {
+ this.setState({editMode: false})
+
+ this.props.showNotification('试卷新建成功')
+ const exercise_id = response.data.data.exercise_id;
+ this.isEdit = true;
+
+ this.props.history.replace(`/courses/${courseId}/exercises/${exercise_id}/edit`);
+
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ }
+ exercise_name_change = (e) => {
+ this.setState({exercise_name: e.target.value})
+ }
+ exercise_description_change = (e) => {
+ this.setState({exercise_description: e.target.value})
+ }
+ // #问题的类型,0为单选题,1为多选题,2为判断题,3为填空题,4为主观题,5为实训题
+ _checkIsEditing = () => {
+ if (this.editingId && $(this.editingId).length ) {
+ this.props.showNotification('请先保存或取消当前正在编辑的问题。')
+ $("html").animate({ scrollTop: $(this.editingId).offset().top - 100})
+ return true
+ }
+ return false
+ }
+ onEditorCancel = () => {
+ this.editingId = null;
+ // 找到编辑或新建的item,新建就删掉item,编辑就isNew改为false
+ const { exercise_questions } = this.state
+ let index = -1;
+ for(let i = 0; i < exercise_questions.length; i++) {
+ if (exercise_questions[i].isNew == true) {
+ index = i;
+ break;
+ }
+ }
+ if (exercise_questions[index].question_id) { // 编辑
+ this.setState(
+ (prevState) => ({
+ exercise_questions : update(prevState.exercise_questions, {[index]: { isNew: {$set: false}}})
+ // update(prevState.exercise_questions, {$splice: [[index, 1]]})
+ })
+ )
+ } else { // 新建
+ this.setState(
+ (prevState) => ({
+ exercise_questions : update(prevState.exercise_questions, {$splice: [[index, 1]]})
+ })
+ )
+ }
+ }
+ addQuestion = (question_id_to_insert_after, type) => {
+ if (!this.isEdit) {
+ this.props.showNotification('请先输入试卷标题,并保存试卷')
+ return;
+ }
+ if (this._checkIsEditing()) {
+ return;
+ }
+ if (type == Q_TYPE_SHIXUN) {
+ this.addShixun(question_id_to_insert_after)
+ } else {
+ this.addEditingQuestion(type, question_id_to_insert_after)
+ }
+ }
+ chooseShixun = (array) => {
+ this.addEditingQuestion(Q_TYPE_SHIXUN, this.question_id_to_insert_after, {
+ shixun_id: array[0]
+ })
+ }
+ chooseShixunSuccess = () => {
+ this.refs.shixunChooseModal.setVisible(false)
+ }
+ addShixun = (question_id_to_insert_after) => {
+ if (!this.isEdit) {
+ this.props.showNotification('请先输入试卷标题,并保存试卷')
+ return;
+ }
+ // TODO 弹框选择实训
+ if (this._checkIsEditing()) {
+ return;
+ }
+ this.refs.shixunChooseModal.setVisible(true)
+ this.question_id_to_insert_after = question_id_to_insert_after;
+ return;
+ // 拉取实训items
+ this.addEditingQuestion(Q_TYPE_SHIXUN, question_id_to_insert_after, {
+ shixun_id: 50
+ })
+ }
+ editQestion = (index) => {
+ if (this._checkIsEditing()) {
+ return;
+ }
+ this.editingId = `#question_${index}`
+
+ this.setState(
+ (prevState) => ({
+ exercise_questions : update(prevState.exercise_questions, {[index]: { isNew: {$set: true}}})
+ })
+ )
+ }
+ onSort = (index, question_id, isUp) => {
+ if (this._checkIsEditing()) {
+ return;
+ }
+ const url = `/exercise_questions/${question_id}/up_down.json`
+ axios.post(url, { opr: isUp ? 'up' : 'down'})
+ .then((response) => {
+ if (response.data.status == 0) {
+ // this.props.showNotification('移动成功')
+ this.fetchExercise()
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ onSortDown = (index, question_id) => {
+ this.onSort(index, question_id, false)
+ }
+ onSortUp = (index, question_id) => {
+ this.onSort(index, question_id, true)
+ }
+ getInitScore = (question_type, question_id_to_insert_after) => {
+ /**
+ 1.每个题型的首个题目默认值规则如下:
+ 选择题:5分 01
+ 判断题:2分 2
+ 填空题:2分 3
+ 简答题:10分 4
+ 实训题:每个关卡5分 5
+ */
+ let init_question_score = 0;
+ if (question_type == 0 || question_type == 1) {
+ init_question_score = 5
+ } else if (question_type == 2) {
+ init_question_score = 2
+ } else if (question_type == 3) {
+ init_question_score = 2
+ } else if (question_type == 4) {
+ init_question_score = 10
+ } else if (question_type == 5) {
+ init_question_score = 5
+ }
+ const _indexBefore = question_id_to_insert_after ? this.findIndexById(question_id_to_insert_after) : this.state.exercise_questions.length - 1
+ for (let i = _indexBefore; i >= 0; i--) {
+ if(this.state.exercise_questions[i].question_type == question_type) {
+ init_question_score = this.state.exercise_questions[i].question_score
+ break;
+ }
+ }
+ return init_question_score;
+ }
+ addEditingQuestion = (question_type, question_id_to_insert_after, otherAttributes) => {
+
+ let init_question_score = this.getInitScore(question_type, question_id_to_insert_after)
+
+ let questionObj = {
+ question_type: question_type, // 需要这个通过类型判断
+ init_question_score: init_question_score,
+ isNew: true, // 新建或编辑,用是否有id区分是新建还是编辑
+ question_id_to_insert_after,
+ ...otherAttributes
+ }
+ const { exercise_questions } = this.state;
+ let new_exercise_questions = exercise_questions.slice(0)
+ let newIndex = new_exercise_questions.length;
+
+ if (question_id_to_insert_after) {
+ const _indexBefore = this.findIndexById(question_id_to_insert_after)
+ new_exercise_questions.splice(_indexBefore + 1, 0, questionObj)
+ newIndex = _indexBefore + 1
+ } else {
+ new_exercise_questions.push(questionObj)
+ }
+ this.editingId = `#question_${newIndex}`
+ this.setState({ exercise_questions: new_exercise_questions }, () => {
+ setTimeout(() => {
+ $(this.editingId).length && $("html").animate({ scrollTop: $(this.editingId).offset().top - 100})
+ }, 500)
+ })
+ }
+ findIndexById = (id) => {
+ const { exercise_questions } = this.state
+ for(let i = 0; i < exercise_questions.length; i++) {
+ if (exercise_questions[i].question_id == id) {
+ return i;
+ }
+ }
+ }
+ onQestionDelete = (question_id) => {
+ this.props.confirm({
+ content: `确认要删除这个问题吗?`,
+ onOk: () => {
+ const url = `/exercise_questions/${question_id}.json`
+ axios.delete(url)
+ .then((response) => {
+ if (response.data.status == 0) {
+ this.props.showNotification('删除成功')
+ const { exercise_questions } = this.state
+ const index = this.findIndexById(question_id)
+
+ this.setState(
+ (prevState) => ({
+ exercise_questions : update(prevState.exercise_questions, {$splice: [[index, 1]]})
+ })
+ )
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ }
+ })
+ }
+ addSuccess = () => {
+ this.editingId = null;
+ this.fetchExercise()
+ }
+ goToPreview = () => {
+ const exercise_id = this.props.match.params.Id
+ const courseId = this.props.match.params.coursesId
+ this.props.history.push(`/courses/${courseId}/exercises/${exercise_id}/student_exercise_list?tab=2`)
+ }
+ render() {
+ let { exercise_name, exercise_description, course_id, exercise_types,
+ exercise_questions, left_banner_id } = this.state;
+ // if (this.isEdit && !exercise_types) {
+ // return ''
+ // }
+ // const { getFieldDecorator } = this.props.form;
+ const { q_counts, q_scores, q_doubles, q_doubles_scores, q_judges, q_judges_scores,
+ q_mains, q_mains_scores, q_nulls, q_nulls_scores, q_shixuns, q_shixuns_scores, q_singles, q_singles_scores} = exercise_types;
+ const formItemLayout = {
+ labelCol: {
+ xs: { span: 24 },
+ // sm: { span: 8 },
+ sm: { span: 24 },
+ },
+ wrapperCol: {
+ xs: { span: 24 },
+ // sm: { span: 16 },
+ sm: { span: 24 },
+ },
+ };
+
+ const { current_user } = this.props
+ const isAdmin = this.props.isAdmin()
+ const courseId=this.props.match.params.coursesId;
+ const exercise_id = this.props.match.params.Id
+
+ const isEdit = this.isEdit
+ const commonHandler = {
+ onQestionDelete: this.onQestionDelete,
+ addSuccess: this.addSuccess,
+ addQuestion: this.addQuestion,
+ onEditorCancel: this.onEditorCancel,
+ editQestion: this.editQestion,
+ onSortDown: this.onSortDown,
+ onSortUp: this.onSortUp,
+ displayCount: exercise_questions.length,
+ exercise_status: this.state.exercise_status,
+ exerciseIsPublish: this.state.exercise_status >= 2
+ }
+ return(
+
+
+
+
+ { current_user &&
}
+
+
+ {this.isEdit ? "编辑" : "新建"}试卷
+ this.props.history.length == 1 ? this.props.history.push(`/courses/${courseId}/exercises/${left_banner_id}`): this.props.history.goBack()}>
+ 返回
+
+
+
+ {!this.state.editMode &&
}
+ {this.state.editMode &&
+
+
+ {/* {getFieldDecorator('subject', {
+ rules: [{
+ required: true, message: '请输入标题',
+ }, {
+ max: 20, message: '最大限制为20个字符',
+ }],
+ })( */}
+
+ {/* )} */}
+
+
+
+ {/* {getFieldDecorator('select_board_id', {
+ // initialValue: '3779',
+ })( */}
+
+ {/* )} */}
+
+
+ {/* defalutSubmitbtn */}
+
+ 保存
+
+ { this.isEdit && this.setState({editMode: false})} className="defalutCancelbtn fr mt4"
+ style={{height: '30px', width: '70px', fontSize: '14px', lineHeight: '30px', marginRight: '16px'}}>取消 }
+ {/* 保存 */}
+
+
+ {/* */}
+ }
+
+
+
+
+ { !!q_singles && 单选题{q_singles}题,共{q_singles_scores}分 }
+ { !!q_doubles && 多选题{q_doubles}题,共{q_doubles_scores}分 }
+ { !!q_judges && 判断题{q_judges}题,共{q_judges_scores}分 }
+ { !!q_nulls && 填空题{q_nulls}题,共{q_nulls_scores}分 }
+ { !!q_mains && 简答题{q_mains}题,共{q_mains_scores}分 }
+ { !!q_shixuns && 实训题{q_shixuns}题,共{q_shixuns_scores}分 }
+
+
+ { !!q_counts &&
+
+ 合计 {q_counts} 题,
+ 共 100 ? 'color-red font-bd' : 'color-orange'}`}>{q_scores} 分
+
+ }
+
+
+
+ { exercise_questions.map((item, index) => {
+ if (item.question_type == 0 || item.question_type == 1) {
+ if (item.isNew) {
+ return
+ } else {
+ return
+ }
+ } else if (item.question_type == 2) {
+ if (item.isNew) {
+ return
+ } else {
+ return
+ }
+ } else if (item.question_type == 3) {
+ if (item.isNew) {
+ return
+ } else {
+ return
+ }
+ } else if (item.question_type == 4) {
+ if (item.isNew) {
+ return
+ } else {
+ return
+ }
+ } else if (item.question_type == 5) {
+ if (item.isNew) {
+ return
+ } else {
+ return
+ }
+ }
+ return
+ })}
+
+ {!commonHandler.exerciseIsPublish &&
+
this.addQuestion(null, Q_TYPE_SINGLE)}>
+ 选择题
+
+
this.addQuestion(null, Q_TYPE_JUDGE)}>
+ 判断题
+
+
this.addQuestion(null, Q_TYPE_NULL)}>
+ 填空题
+
+
this.addQuestion(null, Q_TYPE_MAIN)}>
+ 简答题
+
+
this.addShixun(null)}>
+ 实训题
+
+
+ {exercise_id &&
this.goToPreview()}>
+ {/* */}
+ 试卷预览
+ }
+
}
+
+
+
+
+ )
+ }
+}
+// RouteHOC()
export default (ExerciceNew);
\ No newline at end of file
diff --git a/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js b/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js
index b99bc783b..bcc0d85a3 100644
--- a/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js
+++ b/public/react/src/modules/courses/exercise/Testpapersettinghomepage.js
@@ -171,7 +171,8 @@ class Testpapersettinghomepage extends Component{
}
console.log("170");
console.log(params);
- axios.get(url+`?${queryString.stringify(params)}`+ '&export=true').then((response) => {
+ const urll=url+`?${queryString.stringify(params)}`;
+ axios.get(urll+ '&export=true').then((response) => {
if(response===undefined){
return
}
@@ -195,13 +196,13 @@ class Testpapersettinghomepage extends Component{
}else {
this.setState({ donwloading: true })
downloadFile({
- url: url+`?${queryString.stringify(params)}`,
+ url: urll,
successCallback: (url) => {
- this.setState({ donwloading: false });
+ this.setState({ donwloading: false })
console.log('successCallback')
},
failCallback: (responseHtml, url) => {
- this.setState({ donwloading: false });
+ this.setState({ donwloading: false })
console.log('failCallback')
}
})
diff --git a/public/react/src/modules/courses/exercise/new/JudgeEditor.js b/public/react/src/modules/courses/exercise/new/JudgeEditor.js
index 586d77ed0..50224e125 100644
--- a/public/react/src/modules/courses/exercise/new/JudgeEditor.js
+++ b/public/react/src/modules/courses/exercise/new/JudgeEditor.js
@@ -187,7 +187,7 @@ class SingleEditor extends Component{
(客观题,由系统自动评分,请设置标准答案)
-
this.setState({ question_title: val})}
ref="titleEditor"
>
diff --git a/public/react/src/modules/courses/exercise/new/MainEditor.js b/public/react/src/modules/courses/exercise/new/MainEditor.js
index e9dd3b105..9a3eda659 100644
--- a/public/react/src/modules/courses/exercise/new/MainEditor.js
+++ b/public/react/src/modules/courses/exercise/new/MainEditor.js
@@ -152,14 +152,14 @@ class MainEditor extends Component{
(主观题,未作答的情况下自动评为零分)
-
this.setState({ question_title: val})}
noStorage={true} ref="titleEditor"
>
参考答案
-
this.setState({ standard_answers: [val]})}
noStorage={true}
>
diff --git a/public/react/src/modules/courses/exercise/new/NullChildEditor.js b/public/react/src/modules/courses/exercise/new/NullChildEditor.js
index 9e50e2ad3..5146f05ec 100644
--- a/public/react/src/modules/courses/exercise/new/NullChildEditor.js
+++ b/public/react/src/modules/courses/exercise/new/NullChildEditor.js
@@ -57,7 +57,7 @@ class NullChildEditor extends Component{
className={'nullChildEditor'}
placeholder={`请输入参考答案${itemIndex == 0 ?'':'(可选)'}`}
toMDMode={toMDMode} noStorage={true}
- mdID={`answer_${index}${itemIndex}`} height={155} watch={false}
+ mdID={`answer_${index}${itemIndex}`} height={155}
initValue={item} onChange={(val) => onAnswerChange(index, itemIndex, val)}
>
diff --git a/public/react/src/modules/courses/exercise/new/NullEditor.js b/public/react/src/modules/courses/exercise/new/NullEditor.js
index 299daf904..8cfb21a5f 100644
--- a/public/react/src/modules/courses/exercise/new/NullEditor.js
+++ b/public/react/src/modules/courses/exercise/new/NullEditor.js
@@ -297,7 +297,7 @@ class NullEditor extends Component{
(客观题,由系统自动评分,允许手动调分,请设置标准答案 ;支持最多5个空,每空得分按照本题的总分平均计算)
-
this.setState({ question_title: val})}
onPlaceholderChange={this.onPlaceholderChange} showNullButton={exerciseIsPublish ? false : true}
ref="titleEditor"
diff --git a/public/react/src/modules/courses/exercise/new/ShixunEditor.js b/public/react/src/modules/courses/exercise/new/ShixunEditor.js
index 29ba724af..543e840bc 100644
--- a/public/react/src/modules/courses/exercise/new/ShixunEditor.js
+++ b/public/react/src/modules/courses/exercise/new/ShixunEditor.js
@@ -250,7 +250,7 @@ class ShixunEditor extends Component{
style={{ marginBottom: '10px'}}
>
{/* {shixun_name}
*/}
- this.setState({ question_title: val})}
noStorage={true}
>
diff --git a/public/react/src/modules/courses/exercise/new/SingleEditor.js b/public/react/src/modules/courses/exercise/new/SingleEditor.js
index 8e68a593c..f339e5680 100644
--- a/public/react/src/modules/courses/exercise/new/SingleEditor.js
+++ b/public/react/src/modules/courses/exercise/new/SingleEditor.js
@@ -242,7 +242,7 @@ class SingleEditor extends Component{
(客观题,由系统自动评分,请设置标准答案)
- this.setState({ question_title: val})}
ref="titleEditor"
@@ -265,7 +265,7 @@ class SingleEditor extends Component{
this.onOptionContentChange(value, index)}
initValue={item}
>
diff --git a/public/react/src/modules/courses/graduation/tasks/index.js b/public/react/src/modules/courses/graduation/tasks/index.js
index 08639b521..80dceb562 100644
--- a/public/react/src/modules/courses/graduation/tasks/index.js
+++ b/public/react/src/modules/courses/graduation/tasks/index.js
@@ -767,7 +767,7 @@ class GraduationTasks extends Component{
diff --git a/public/react/src/modules/courses/graduation/topics/GraduateTopicDetail.js b/public/react/src/modules/courses/graduation/topics/GraduateTopicDetail.js
index c0e8fe185..b24277a2c 100644
--- a/public/react/src/modules/courses/graduation/topics/GraduateTopicDetail.js
+++ b/public/react/src/modules/courses/graduation/topics/GraduateTopicDetail.js
@@ -105,7 +105,7 @@ class GraduateTopicDetail extends Component{
- {tableData && tableData.course_name}
+ {tableData && tableData.course_name}
>
{tableData.graduation_name}
>
diff --git a/public/react/src/modules/courses/graduation/topics/GraduateTopicNew.js b/public/react/src/modules/courses/graduation/topics/GraduateTopicNew.js
index 43a0e31f5..8c46bfa0e 100644
--- a/public/react/src/modules/courses/graduation/topics/GraduateTopicNew.js
+++ b/public/react/src/modules/courses/graduation/topics/GraduateTopicNew.js
@@ -323,7 +323,7 @@ class GraduateTopicNew extends Component{
`}
- {course_name}
+ {course_name}
>
{left_banner_name}
>
diff --git a/public/react/src/modules/courses/graduation/topics/index.js b/public/react/src/modules/courses/graduation/topics/index.js
index 84b500716..6587ed0c6 100644
--- a/public/react/src/modules/courses/graduation/topics/index.js
+++ b/public/react/src/modules/courses/graduation/topics/index.js
@@ -28,7 +28,7 @@ class Boards extends Component{
checkAllValue: false,
checkBoxValues: [],
data:[],
- topicList: [],
+ topicList: undefined,
course_public:1,
page:1,
totalCount:undefined,
@@ -412,7 +412,7 @@ onBoardsNew=()=>{
}
onPressEnter={this.onPressEnter}
searchPlaceholder={"请输入名称进行搜索"}
- showSearchInput={topicList.length >= pageSize}
+ showSearchInput={topicList&&topicList.length >= pageSize}
>
{
@@ -475,7 +475,7 @@ onBoardsNew=()=>{
>
- ):(
)
+ ):(topicList && topicList.length===0?
:
)
}
{
diff --git a/public/react/src/modules/courses/members/modal/AddStudentModal.js b/public/react/src/modules/courses/members/modal/AddStudentModal.js
index 59c6e41da..1ad02c9f4 100644
--- a/public/react/src/modules/courses/members/modal/AddStudentModal.js
+++ b/public/react/src/modules/courses/members/modal/AddStudentModal.js
@@ -195,7 +195,7 @@ class AddStudentModal extends Component{
姓名:
{this.setState({name: e.target.value})}}
- style={{ width: '242px'}}
+ style={{ width: '221px'}}
>
单位:
{/* {this.setState({school_name: e.target.value})}}
@@ -210,14 +210,7 @@ class AddStudentModal extends Component{
>搜索
{/*
*/}
- {course_groups && course_groups.length &&
- 分班:
-
- { course_groups.map((item) => {
- return {item.name}
- })}
-
-
}
+
@@ -247,7 +240,12 @@ class AddStudentModal extends Component{
12 }>
- {candidate.name || ' '}
+
+ { candidate.name ?
+
+ { candidate.name }
+ : }
+
@@ -271,6 +269,14 @@ class AddStudentModal extends Component{
+ {course_groups && course_groups.length &&
+ 所选学生分班至(选填):
+
+ { course_groups.map((item) => {
+ return {item.name}
+ })}
+
+
}
:
}
diff --git a/public/react/src/modules/courses/members/studentsList.js b/public/react/src/modules/courses/members/studentsList.js
index d7c4cb85b..c3dc2c6ab 100644
--- a/public/react/src/modules/courses/members/studentsList.js
+++ b/public/react/src/modules/courses/members/studentsList.js
@@ -677,9 +677,9 @@ class studentsList extends Component{
-
+ {!this.state.isSpin &&
-
+ }
diff --git a/public/react/src/modules/courses/members/teacherList.js b/public/react/src/modules/courses/members/teacherList.js
index fc6b56313..c509cb057 100644
--- a/public/react/src/modules/courses/members/teacherList.js
+++ b/public/react/src/modules/courses/members/teacherList.js
@@ -603,7 +603,9 @@ class studentsList extends Component{
combineArray = this.state.application_list
}
const isAdminOrTeacher = this.props.isAdminOrTeacher()
+ const isSuperAdmin = this.props.isSuperAdmin()
const hasGraduationModule = this.hasGraduationModule()
+ const coursesId = this.props.match.params.coursesId
return(
@@ -624,7 +626,10 @@ class studentsList extends Component{
>
+ 教师列表
+ {!isSuperAdmin && coursesId == '1309' && (示例课堂,部分成员不可见) }
+ }
searchValue={ searchValue }
onInputSearchChange={this.onInputSearchChange}
showSearchInput={total_count >= 10}
@@ -641,6 +646,7 @@ class studentsList extends Component{
已审批({total_count})
待审批({apply_size})
+ {/* */}
:
(!!total_count ? : '')
}
diff --git a/public/react/src/modules/courses/new/CoursesNew.js b/public/react/src/modules/courses/new/CoursesNew.js
index 8a12d482e..fc4719013 100644
--- a/public/react/src/modules/courses/new/CoursesNew.js
+++ b/public/react/src/modules/courses/new/CoursesNew.js
@@ -143,6 +143,7 @@ class CoursesNew extends Component {
handleSubmit = (e) => {
e.preventDefault();
+ let first_category_url=this.props.current_user.first_category_url;
let coursesId = this.props.match.params.coursesId;
let {is_public,datatime} = this.state
// console.log(is_public)
@@ -201,7 +202,8 @@ class CoursesNew extends Component {
).then((response) => {
// debugger
if (response.data.status === 0) {
- this.goback()
+ // this.goback()
+ window.location.href=first_category_url;
}
}).catch((error) => {
console.log(error)
@@ -244,7 +246,8 @@ class CoursesNew extends Component {
}
).then((response) => {
if (response.status === 200) {
- this.goback()
+ // this.goback
+ window.location.href=response.data.first_category_url;
}
}).catch((error) => {
console.log(error)
diff --git a/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js b/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js
index 61ed59d7b..b9aac1e6a 100644
--- a/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js
+++ b/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js
@@ -1,6 +1,6 @@
import React,{ Component } from "react";
import CoursesListType from '../coursesPublic/CoursesListType';
-import { WordsBtn } from 'educoder';
+import { WordsBtn, getTaskUrlById } from 'educoder';
import {Tooltip,message,Modal} from 'antd';
import {Link} from 'react-router-dom';
import axios from 'axios';
@@ -56,16 +56,17 @@ class ShixunhomeWorkItem extends Component{
startbtn:true,
})
let url= list+".json";
+ // const w=window.open('about:blank');
axios.get(url).then((response) => {
if(response.status===200){
if(response.data.status===-2){
-
this.setState({
startbtn:false,
shixunsreplace:true,
hidestartshixunsreplacevalue:response.data.message+".json"
})
+ // w.close()
}else if(response.data.status===-1){
console.log(response)
}else if(response.data.status===-3){
@@ -74,13 +75,15 @@ class ShixunhomeWorkItem extends Component{
startshixunCombattype:true,
startbtn:false
})
+ // w.close()
}else{
-
- if(response.data.status!=401&&response.data.status!=403){
-
- const w=window.open('about:blank');
- w.location.href= "/tasks/"+response.data.game_identifier
- }
+ this.setState({
+ startbtn:false
+ })
+ // if(response.data.status!=401&&response.data.status!=403){
+ // w.location.href= "/tasks/"+response.data.game_identifier
+ // }
+ window.location.href = "/tasks/"+response.data.game_identifier
}
}
@@ -88,6 +91,8 @@ class ShixunhomeWorkItem extends Component{
this.setState({
startbtn:false
})
+ // w.close()
+
});
}
@@ -388,9 +393,15 @@ class ShixunhomeWorkItem extends Component{
{this.props.isStudent===true?this.props.course_identity===5?
- {startbtn===false?this.taskoperationId(discussMessage.task_operation[1])}>
- {discussMessage.task_operation[0]}
- :开启中 }
+ {startbtn===false?
+ (discussMessage.task_operation[0] == '继续挑战' || discussMessage.task_operation[0] == '查看实战' ?
+
+ {discussMessage.task_operation[0]}
+
+ :
+ this.taskoperationId(discussMessage.task_operation[1])}>
+ {discussMessage.task_operation[0]}
+ ):开启中 }
:"":""
}
diff --git a/public/react/src/modules/courses/shixunHomework/TraineetraininginformationModal.js b/public/react/src/modules/courses/shixunHomework/TraineetraininginformationModal.js
index 8b894db00..cb3ce3af5 100644
--- a/public/react/src/modules/courses/shixunHomework/TraineetraininginformationModal.js
+++ b/public/react/src/modules/courses/shixunHomework/TraineetraininginformationModal.js
@@ -246,7 +246,7 @@ class TraineetraininginformationModal extends Component {
{this.props.boolgalist === false?
{
- this.props.game_list === undefined?"" : this.props.game_list.length<4?
+ this.props.game_list === undefined?"" : this.props.game_list.length<5?
+
-
+
{memo.subject}
- { memo.sticky &&
置顶 }
+ { memo.sticky &&
置顶 }
{ !!memo.reward &&
{memo.reward}
}
- { current_user && (current_user.admin === true || current_user.user_id === author_info.user_id) &&
-
- }
-
- 返回
-
+
+
+ { _current_user && (_current_user.admin === true || _current_user.user_id === author_info.user_id) &&
+
+ }
+
+ 返回
+
+
{moment(memo.time).fromNow()} 发布
-
- { current_user.admin &&
+
+
+ { _current_user.admin &&
@@ -750,7 +775,7 @@ class MemoDetail extends Component {
- { memo.attachment_url && !!memo.attachment_url.length &&
+ { this.props.attachments_list &&
{this.renderAttachment()}
@@ -770,7 +795,7 @@ class MemoDetail extends Component {
{memo.replies_count}
-
{ hasMoreComments ?
-
+
diff --git a/public/react/src/modules/forums/MemoDetailMDEditor.js b/public/react/src/modules/forums/MemoDetailMDEditor.js
index f15a19e20..00a87274d 100644
--- a/public/react/src/modules/forums/MemoDetailMDEditor.js
+++ b/public/react/src/modules/forums/MemoDetailMDEditor.js
@@ -42,7 +42,7 @@ class MemoDetailMDEditor extends Component {
window.__tt = 400;
setTimeout(() => {
var commentMDEditor = window.create_editorMD_4comment("memo_comment_editorMd", '', this.props.height || 240, placeholder, imageUrl, () => {
- commentMDEditor.focus()
+ // commentMDEditor.focus()
this.isMDInited = true
this.initDrag()
diff --git a/public/react/src/modules/forums/MemoDetailMDEditortwo.js b/public/react/src/modules/forums/MemoDetailMDEditortwo.js
index 5eae90400..cc3a2b1af 100644
--- a/public/react/src/modules/forums/MemoDetailMDEditortwo.js
+++ b/public/react/src/modules/forums/MemoDetailMDEditortwo.js
@@ -1,173 +1,173 @@
-import React, { Component } from 'react';
-import { Redirect } from 'react-router';
-
-import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
-
-import PropTypes from 'prop-types';
-
-import classNames from 'classnames'
-
-import { isDev } from 'educoder'
-
-import './MemoDetailEditor.css'
-
-require('codemirror/lib/codemirror.css');
-
-const $ = window.$;
-///作业回答 专用
-class MemoDetailMDEditortwo extends Component {
- constructor(props) {
- super(props)
- this.state = {
- isInited: this.props.usingMockInput ? false : true,
- isError: false,
- errorMsg: ''
- }
- }
- componentDidUpdate(prevProps, prevState, snapshot) {
- if (this.props.memo && (!prevProps.memo || this.props.memo.id != prevProps.memo.id)) {
- // this.keEditor = window.sd_create_editor_from_data(this.props.memo.id, null, "100%", "Memo");
- // window._kk = this.keEditor
- }
- }
-
- initMDEditor = () => {
- // 因为props.memo不存在时,本组件不会被加载,这里直接在didMount里初始化即可
- const placeholder = '我要回复...'
- // const imageUrl = `/upload_with_markdown?container_id=${this.props.memo.id}&container_type=Memo`;
- const imageUrl = `/api/attachments.json`;
-
- // 执行太快了,样式不正常
- window.__tt = 400;
- setTimeout(() => {
- var commentMDEditor = window.create_editorMD_4comment("memo_comment_editorMd", '', this.props.height || 240, placeholder, imageUrl, () => {
- commentMDEditor.focus()
-
- this.initDrag()
-
- commentMDEditor.cm.on("change", (_cm, changeObj) => {
- this.setState({
- isError: false,
- errorMsg: ''
- })
- })
- }, {
- watch: false,
- dialogLockScreen: false,
- });
- this.commentMDEditor = commentMDEditor;
- window.commentMDEditor = commentMDEditor;
-
- }, window.__tt)
- }
- componentDidMount() {
- !this.props.usingMockInput && this.initMDEditor()
- }
- initDrag = () => {
- window.initMDEditorDragResize(".editor__resize", this.commentMDEditor)
- }
-
- onCommit = () => {
- const content = this.commentMDEditor.getValue();
- // this.props.showError ==
- if (this.props.showError == true) {
- if (!content || content.trim() == "") {
- this.setState({
- isError: true,
- errorMsg: '不能为空'
- })
- return;
- } else if (content.length > 2000) {
- this.setState({
- isError: true,
- errorMsg: '不能超过2000个字符'
- })
- return;
- }
-
- this.setState({
- isError: false,
- errorMsg: ''
- })
- }
- window.$(document).trigger("onReply", { commentContent: content
- , id: this.props.memo.id, editor: this.commentMDEditor } );
-
- }
-
- showEditor() {
- $("html, body").animate({ scrollTop: $('#commentInput').offset().top - 100 }, 1000, () => {
- if (this.commentMDEditor) {
- this.commentMDEditor.cm.focus()
- } else {
- $('#commentInput input')[0].click()
- }
- });
- }
- onMockInputClick = () => {
- this.setState({isInited: true})
- this.initMDEditor()
- }
- render() {
- const { match, history, memo, placeholder } = this.props
- const { isInited, errorMsg } = this.state
- if (!memo) {
- return
- }
-
- return (
-
-
-
-
-
-
- );
- }
-}
-
-export default ( MemoDetailMDEditortwo );
+import React, { Component } from 'react';
+import { Redirect } from 'react-router';
+
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+
+import PropTypes from 'prop-types';
+
+import classNames from 'classnames'
+
+import { isDev } from 'educoder'
+
+import './MemoDetailEditor.css'
+
+require('codemirror/lib/codemirror.css');
+
+const $ = window.$;
+///作业回答 专用
+class MemoDetailMDEditortwo extends Component {
+ constructor(props) {
+ super(props)
+ this.state = {
+ isInited: this.props.usingMockInput ? false : true,
+ isError: false,
+ errorMsg: ''
+ }
+ }
+ componentDidUpdate(prevProps, prevState, snapshot) {
+ if (this.props.memo && (!prevProps.memo || this.props.memo.id != prevProps.memo.id)) {
+ // this.keEditor = window.sd_create_editor_from_data(this.props.memo.id, null, "100%", "Memo");
+ // window._kk = this.keEditor
+ }
+ }
+
+ initMDEditor = () => {
+ // 因为props.memo不存在时,本组件不会被加载,这里直接在didMount里初始化即可
+ const placeholder = '我要回复...'
+ // const imageUrl = `/upload_with_markdown?container_id=${this.props.memo.id}&container_type=Memo`;
+ const imageUrl = `/api/attachments.json`;
+
+ // 执行太快了,样式不正常
+ window.__tt = 400;
+ setTimeout(() => {
+ var commentMDEditor = window.create_editorMD_4comment("memo_comment_editorMd", '', this.props.height || 240, placeholder, imageUrl, () => {
+ commentMDEditor.focus();
+
+ this.initDrag();
+
+ commentMDEditor.cm.on("change", (_cm, changeObj) => {
+ this.setState({
+ isError: false,
+ errorMsg: ''
+ })
+ })
+ }, {
+ watch: false,
+ dialogLockScreen: false,
+ });
+ this.commentMDEditor = commentMDEditor;
+ window.commentMDEditor = commentMDEditor;
+
+ }, window.__tt)
+ };
+ componentDidMount() {
+ !this.props.usingMockInput && this.initMDEditor()
+ }
+ initDrag = () => {
+ window.initMDEditorDragResize(".editor__resize", this.commentMDEditor)
+ }
+
+ onCommit = () => {
+ const content = this.commentMDEditor.getValue();
+ // this.props.showError ==
+ if (this.props.showError == true) {
+ if (!content || content.trim() == "") {
+ this.setState({
+ isError: true,
+ errorMsg: '不能为空'
+ })
+ return;
+ } else if (content.length > 2000) {
+ this.setState({
+ isError: true,
+ errorMsg: '不能超过2000个字符'
+ })
+ return;
+ }
+
+ this.setState({
+ isError: false,
+ errorMsg: ''
+ })
+ }
+ window.$(document).trigger("onReply", { commentContent: content
+ , id: this.props.memo.id, editor: this.commentMDEditor } );
+
+ }
+
+ showEditor() {
+ $("html, body").animate({ scrollTop: $('#commentInput').offset().top - 100 }, 1000, () => {
+ if (this.commentMDEditor) {
+ this.commentMDEditor.cm.focus()
+ } else {
+ $('#commentInput input')[0].click()
+ }
+ });
+ }
+ onMockInputClick = () => {
+ this.setState({isInited: true})
+ this.initMDEditor()
+ }
+ render() {
+ const { match, history, memo, placeholder } = this.props
+ const { isInited, errorMsg } = this.state
+ if (!memo) {
+ return
+ }
+
+ return (
+
+
+
+
+
+
+ );
+ }
+}
+
+export default ( MemoDetailMDEditortwo );
diff --git a/public/react/src/modules/forums/MemoNew.js b/public/react/src/modules/forums/MemoNew.js
index 1a293eae3..e6482b8b6 100644
--- a/public/react/src/modules/forums/MemoNew.js
+++ b/public/react/src/modules/forums/MemoNew.js
@@ -7,16 +7,17 @@ import PropTypes from 'prop-types';
import classNames from 'classnames'
-import { Select,Icon } from 'antd';
+import { Select,Icon, Upload, Button } from 'antd';
// demo http://react-component.github.io/upload/examples/simple.html
-import Upload from 'rc-upload';
+// import Upload from 'rc-upload';
import axios from 'axios'
import 'antd/lib/select/style/index.css'
+import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor'
-import { getUrl } from 'educoder'
+import { getUrl, getUploadActionUrl, appendFileSizeToUploadFileAll, appendFileSizeToUploadFile } from 'educoder'
const Option = Select.Option;
const $ = window.$;
@@ -130,6 +131,7 @@ const languageSeparator = '/'
class MemoNew extends Component {
constructor(props) {
super(props)
+ this.mdRef = React.createRef();
// https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js
// https://ant.design/components/upload-cn/
@@ -167,32 +169,34 @@ class MemoNew extends Component {
repertoires: [],
currentSelectRepertoiresIndex: -1,
- repertoiresTagMap: {}
+ repertoiresTagMap: {},
+
+ fileList: []
}
}
onCommit() {
const { memoSubject, memoRepertoire, memoLanguage, currentMemoId, memoType } = this.state;
- const { showSnackbar } = this.props;
+ const { showNotification } = this.props;
if (!memoSubject) {
- showSnackbar('请先输入话题名称')
+ showNotification('请先输入话题名称')
return
}
let mdVal;
try {
- mdVal = this.taskpass_editormd.getValue()
+ mdVal = this.mdRef.current.getValue()
} catch (e) {
- showSnackbar('编辑器还未加载完毕,请稍后')
+ showNotification('编辑器还未加载完毕,请稍后')
return
}
if (!mdVal) {
- showSnackbar('请先输入话题内容')
+ showNotification('请先输入话题内容')
return
}
// !memoRepertoire ||
if (memoType === 5 && ( !memoLanguage || memoLanguage.length === 0 )) {
- showSnackbar('请先选择技术标签')
+ showNotification('请先选择技术标签')
return
}
/*
@@ -205,23 +209,27 @@ class MemoNew extends Component {
// collect attachments
const $ = window.$;
const attachmentsMap = {};
- $('#attachments_fields .attachment').each(( index, item ) => {
- const filename = $(item).find('.upload_filename').val();
- // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val()
- const token = $(item).find('input:nth-child(7)').val()
- const attachment_id = parseInt($(item).children().last().val())
- attachmentsMap[index] = {
- filename,
- token,
- attachment_id
- }
+ const attachmentIds = this.state.fileList.map(item => {
+ return item.response ? item.response.id : item.id
})
+ // $('#attachments_fields .attachment').each(( index, item ) => {
+ // const filename = $(item).find('.upload_filename').val();
+ // // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val()
+ // const token = $(item).find('input:nth-child(7)').val()
+ // const attachment_id = parseInt($(item).children().last().val())
+ // attachmentsMap[index] = {
+ // filename,
+ // token,
+ // attachment_id
+ // }
+ // attachmentIds.push(attachment_id)
+ // })
if (currentMemoId) {
- this.updateMemo(attachmentsMap)
+ this.updateMemo(attachmentIds)
} else {
- this.newMemo(attachmentsMap)
+ this.newMemo(attachmentIds)
}
}
onCancel() {
@@ -235,23 +243,23 @@ class MemoNew extends Component {
}
updateMemo(attachmentsMap) {
const { memoSubject, memoRepertoire, memoLanguage, memoType, currentMemoId, content } = this.state;
- const mdVal = this.taskpass_editormd.getValue()
+ const mdVal = this.mdRef.current.getValue()
console.log('isContentEdit: ', mdVal === content);
- const newMemoUrl = `/api/v1/memos/${currentMemoId}/update`
- axios.post(newMemoUrl, {
+ const newMemoUrl = `/memos/${currentMemoId}.json`
+ axios.put(newMemoUrl, {
content_changed: this.contentChanged,
tags: memoLanguage,
- memo:{
+ // memo:{
subject: memoSubject ,
content: mdVal,
forum_id: memoType,
repertoire_name: memoRepertoire,
// language: memoLanguage.join(languageSeparator),
//
- },
- attachments: attachmentsMap
+ // },
+ attachment_ids: attachmentsMap
}, {
- withCredentials: true,
+ // withCredentials: true,
})
.then((response) => {
const { status, message, memo_id } = response.data;
@@ -259,7 +267,7 @@ class MemoNew extends Component {
window.$("html,body").animate({"scrollTop":0})
this.props.history.push(`/forums/${currentMemoId}`)
} else {
- this.props.showSnackbar(message)
+ this.props.showNotification(message)
}
}).catch((error) => {
console.log(error)
@@ -267,21 +275,21 @@ class MemoNew extends Component {
}
newMemo(attachmentsMap) {
const { memoSubject, memoRepertoire, memoLanguage, memoType } = this.state;
- const mdVal = this.taskpass_editormd.getValue()
+ const mdVal = this.mdRef.current.getValue()
- const newMemoUrl = `/api/v1/memos/create`
+ const newMemoUrl = `/memos.json`
axios.post(newMemoUrl, {
tags: memoLanguage,
- memo:{
+ // memo:{
subject: memoSubject ,
content: mdVal,
forum_id: memoType,
- repertoire_name: memoRepertoire,
+ // repertoire_name: memoRepertoire,
- },
- attachments: attachmentsMap
+ // },
+ attachment_ids: attachmentsMap
}, {
- withCredentials: true,
+ // withCredentials: true,
})
.then((response) => {
const { status, message, memo_id } = response.data;
@@ -289,16 +297,16 @@ class MemoNew extends Component {
window.$("html,body").animate({"scrollTop":0})
this.props.history.push(`/forums/${memo_id}`)
} else {
- this.props.showSnackbar(message)
+ this.props.showNotification(message)
}
}).catch((error) => {
console.log(error)
})
}
componentDidMount() {
- const newMemoUrl = `/api/v1/memos/new`
+ const newMemoUrl = `/memos/new.json`
axios.get(newMemoUrl,{
- withCredentials: true,
+ // withCredentials: true,
})
.then((response) => {
const data = response.data;
@@ -319,9 +327,9 @@ class MemoNew extends Component {
// repertoiresTagMap
})
- const user = response.data.current_user;
- user.tidding_count = response.data.tidding_count;
- this.props.initCommonState(user)
+ // const user = response.data.current_user;
+ // user.tidding_count = response.data.tidding_count;
+ // this.props.initCommonState(user)
// 初始化 csrf meta
const $ = window.$
@@ -336,26 +344,39 @@ class MemoNew extends Component {
const { match } = this.props
const memoId = match.params.memoId;
if (memoId) {
- const memoUrl = `/api/v1/memos/${match.params.memoId}/edit`;
+ const memoUrl = `/memos/${match.params.memoId}/edit.json`;
axios.get(memoUrl,{
- withCredentials: true,
+ // withCredentials: true,
})
.then((response) => {
const tag_list = response.data.tag_list
if (tag_list) {
// this.setState({...response.data})
- const { content, forum_id, id, tag, repertoire_name, subject,
- current_user, tag_list, attachments_url } = response.data;
+ const { content, forum_id, id, repertoire_name, subject,
+ current_user, tag_list, attachments_url, memo_tags, attachments } = response.data;
this.initMD(content);
// this.onRepertoiresChange(repertoire_name)
+ // tag -> memo_tags
+ const tag = memo_tags;
let memoLanguage = []
if (tag) {
memoLanguage = tag.map((item, index) => {
return item.id + ""
})
}
+ const fileList = attachments.map(item => {
+ return {
+ id: item.id,
+ uid: item.id,
+ name: appendFileSizeToUploadFile(item),
+ url: item.url,
+ filesize: item.filesize,
+ status: 'done'
+ }
+ })
this.setState({
- currentMemoId: id,
+ fileList,
+ currentMemoId: memoId,
memoSubject: subject,
memoType: forum_id,
memoRepertoire: repertoire_name,
@@ -377,7 +398,7 @@ class MemoNew extends Component {
window.$("html,body").animate({"scrollTop":0})
this.props.initForumState({
- current_user,
+ // current_user,
tag_list
})
}
@@ -394,6 +415,8 @@ class MemoNew extends Component {
}
initMD(initValue) {
+ return;
+
this.contentChanged = false;
const placeholder = "";
// amp;
@@ -458,7 +481,7 @@ class MemoNew extends Component {
onTagChange(value) {
if (value && value.length > 3) {
- this.props.showSnackbar(`最多选择3个技术标签`)
+ this.props.showNotification(`最多选择3个技术标签`)
return;
}
@@ -523,6 +546,55 @@ class MemoNew extends Component {
)
})
return attachments;
+ }
+ handleChange = (info) => {
+ let fileList = info.fileList;
+ this.setState({
+ fileList: appendFileSizeToUploadFileAll(fileList)
+ });
+ }
+ onAttachmentRemove = (file) => {
+ this.props.confirm({
+ // title: '确定要删除这个附件吗?',
+ content: '是否确认删除?',
+
+ okText: '确定',
+ cancelText: '取消',
+ // content: 'Some descriptions',
+ onOk: () => {
+ this.deleteAttachment(file)
+ },
+ onCancel() {
+ console.log('Cancel');
+ },
+ });
+ return false;
+ }
+ deleteAttachment = (file) => {
+ // 初次上传不能直接取uid
+ const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
+ axios.delete(url, {
+ })
+ .then((response) => {
+ if (response.data) {
+ const { status } = response.data;
+ if (status == 0) {
+ console.log('--- success')
+
+ this.setState((state) => {
+ const index = state.fileList.indexOf(file);
+ const newFileList = state.fileList.slice();
+ newFileList.splice(index, 1);
+ return {
+ fileList: newFileList,
+ };
+ });
+ }
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
}
render() {
const { match, history } = this.props
@@ -530,8 +602,28 @@ class MemoNew extends Component {
// repertoires, repertoiresTagMap, currentSelectRepertoiresIndex, memoRepertoire,
tag_list,
memoSubject, memoType,
- memoLanguage, attachments_url } = this.state;
+ memoLanguage, attachments_url, fileList } = this.state;
const memoId = match.params.memoId;
+
+ const uploadProps = {
+ width: 600,
+ fileList,
+ multiple: true,
+ // https://github.com/ant-design/ant-design/issues/15505
+ // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
+ // showUploadList: false,
+ action: `${getUploadActionUrl()}`,
+ onChange: this.handleChange,
+ onRemove: this.onAttachmentRemove,
+ beforeUpload: (file) => {
+ console.log('beforeUpload', file.name);
+ const isLt150M = file.size / 1024 / 1024 < 150;
+ if (!isLt150M) {
+ // message.error('文件大小必须小于150MB!');
+ }
+ return isLt150M;
+ },
+ };
return (
@@ -566,9 +658,12 @@ class MemoNew extends Component {
*
@@ -581,13 +676,13 @@ class MemoNew extends Component {
-
+ {/*
{ attachments_url && !!attachments_url.length &&
this.renderAttachment()
}
-
+
{debugger;window.addInputFiles( window.$('.file_selector')[0] ) }}
style={{'display':'none'}} type="file">
-
-
+
+ */}
+
{/*
开始上传 */}
+
+
+ 上传附件
+
+ (单个文件150M以内)
+
{/* 请求status 422 */}
-
*/}
{/* TODOTODO 这里重复的html代码太多,如果有其他页面有类似需求,需要封装*/}
diff --git a/public/react/src/modules/forums/Post.css b/public/react/src/modules/forums/Post.css
index d10857a60..e28cf6019 100644
--- a/public/react/src/modules/forums/Post.css
+++ b/public/react/src/modules/forums/Post.css
@@ -8,6 +8,9 @@
min-height: 400px;
position: relative;
}
+ #forum_index_list .forum_table .forum_table_item {
+ background: #fff;
+ }
.noMemosTip {
position: absolute;
right: 10px;
@@ -24,7 +27,7 @@
cursor: pointer;
}
#forum_list .return_btn.no_mr {
- margin-right: -16px;
+ margin-right: -24px !important;
}
div#forum_list>div {
background: #fff;
diff --git a/public/react/src/modules/forums/PostItem.js b/public/react/src/modules/forums/PostItem.js
index aa610184f..02d9fa273 100644
--- a/public/react/src/modules/forums/PostItem.js
+++ b/public/react/src/modules/forums/PostItem.js
@@ -29,7 +29,7 @@ class PostItem extends Component {
-
+
{/* target="_blank" */}
@@ -46,16 +46,16 @@ class PostItem extends Component {
-
{memo.username}
+
{memo.user_name}
{/*最后回复:todo{memo.username}
memo.language && memo.language != 'other' &&
{memo.language}
*/}
-
{moment(memo.updated_at).fromNow()}
+ {/*
{moment(memo.updated_at).fromNow()} */}
{memo.tag && memo.tag.length ?
来自 {memo.tag.join('/')} : ''}
{/*
C++ */}
-
+
{/* data-tip-down="回复数" {memo.replies_count}
{memo.praise_count}*/}
{memo.replies_count ?
diff --git a/public/react/src/modules/forums/PostPaginationHOC.js b/public/react/src/modules/forums/PostPaginationHOC.js
index 25e397318..9105be1ac 100644
--- a/public/react/src/modules/forums/PostPaginationHOC.js
+++ b/public/react/src/modules/forums/PostPaginationHOC.js
@@ -126,7 +126,7 @@ return function wrap(WrappedComponent) {
}
const orderTypeMap = {
'hottest': 'replies_count',
- 'newest': 'updated_at', // 'created_at',
+ 'newest': 'updated_at', // 'created_at',
}
const _search = this.props.history.location.search;
const parsed = queryString.parse(_search);
@@ -136,7 +136,7 @@ return function wrap(WrappedComponent) {
const params = {
// replies_count最热 created_at 最新
// s_order: 'replies_count',
- page: currentPage - 1,
+ page: currentPage,
// forum: // forum_id
// user_id
@@ -165,7 +165,7 @@ return function wrap(WrappedComponent) {
let paramsUrl = queryString.stringify(params)
- const memosUrl = '/api/v1/memos?' + paramsUrl // /${challenge.identifier}/star
+ const memosUrl = '/memos.json?' + paramsUrl // /${challenge.identifier}/star
this.setState({
currentPage,
@@ -174,7 +174,7 @@ return function wrap(WrappedComponent) {
})
// 获取memo list
axios.get(memosUrl,{
- withCredentials: true,
+ // withCredentials: true,
})
.then((response) => {
const memo_count = response.data.memo_count
@@ -186,9 +186,9 @@ return function wrap(WrappedComponent) {
this.fetchMemos(maxPage);
return;
}
- const user = response.data.current_user;
- user.tidding_count = response.data.tidding_count;
- this.props.initCommonState(user)
+ // const user = response.data.current_user;
+ // user.tidding_count = response.data.tidding_count;
+ // this.props.initCommonState(user)
this.props.initForumState(response.data)
this.setState({
p_forum_id: params.forum,
@@ -242,16 +242,18 @@ return function wrap(WrappedComponent) {
params.forum_id = this.state.p_forum_id;
}
let paramsUrl = urlStringify(params)
- const set_top_or_down_Url = `/api/v1/memos/${memo.id}/set-top-or-down?${paramsUrl}`;
+ const set_top_or_down_Url = `/memos/${memo.id}/sticky_or_cancel.json?${paramsUrl}`;
// 获取memo list
- axios.get(set_top_or_down_Url, {
- withCredentials: true,
+ axios.post(set_top_or_down_Url, {
+ // withCredentials: true,
})
.then((response) => {
const status = response.data.status
if (status === 0) {
- const { memo_list } = response.data;
- this.props.initForumState({ memo_list })
+ this.fetchMemos(1, '')
+
+ // const { memo_list } = response.data;
+ // this.props.initForumState({ memo_list })
// 刷新列表
// TODO 服务端直接返回第一页列表
// this.props.history.replace('/')
@@ -265,16 +267,16 @@ return function wrap(WrappedComponent) {
this.setTop(memo);
}
onMemoDelete(memo) {
- const deleteUrl = `/api/v1/memos/${memo.id}`;
+ const deleteUrl = `/memos/${memo.id}.json`;
// 获取memo list
axios.delete(deleteUrl, {
- withCredentials: true,
+ // withCredentials: true,
})
.then((response) => {
const status = response.data.status
if (status === 0) {
- this.props.showSnackbar('删除成功');
+ this.props.showNotification('删除成功');
// 刷新列表
this.fetchMemos();
}
diff --git a/public/react/src/modules/forums/RecommendShixun.js b/public/react/src/modules/forums/RecommendShixun.js
index 9ebaf3cae..af0ca0007 100644
--- a/public/react/src/modules/forums/RecommendShixun.js
+++ b/public/react/src/modules/forums/RecommendShixun.js
@@ -28,12 +28,12 @@ class RecommendShixun extends Component {
-
+
+ className="color-grey-6 task-hide mb10 recomment-name" style={{maxWidth:'147px'}}>
{_shixun.name}
{_shixun.myshixuns_count} 人学习
@@ -50,7 +50,7 @@ class RecommendShixun extends Component {
// 参考 TPMShixunDiscuss.js 推荐实训, 页面路径:http://localhost:3007/shixuns/uznmbg54/shixun_discuss
return (
-
推荐实训
+
推荐实训
{this.showRecommandShixun()}
diff --git a/public/react/src/modules/forums/UserSection.js b/public/react/src/modules/forums/UserSection.js
index 8ea9bad2a..96671135d 100644
--- a/public/react/src/modules/forums/UserSection.js
+++ b/public/react/src/modules/forums/UserSection.js
@@ -1,62 +1,87 @@
-import React, { Component } from 'react';
-
-import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
-
-import PropTypes from 'prop-types';
-
-import classNames from 'classnames'
-
-import axios from 'axios'
-
-class UserSection extends Component {
- constructor(props) {
- super(props)
-
- this.state = {
-
- }
- }
- /*点击关注或者取消关注*/
- AboutFocus(){
- const { author_info } = this.props
- /*http://localhost:3000/api/v1/users/155/watch?object_id=156&object_type=user*/
-
- const focusUrl = `/api/v1/users/${author_info.user_id}/${this.props.author_info.watched ? 'unwatch' : 'watch'}?object_id=${author_info.user_id}&object_type=user`
-
- axios.get(focusUrl,{
- })
- .then((response) => {
- const status = response.data.status;
- console.log(status);
- if(status == 1){
- const new_author_info = Object.assign({}, this.props.author_info)
- new_author_info.watched = !new_author_info.watched
- this.props.initForumState({author_info: new_author_info})
- }
- }).catch((error) => {
- console.log(error)
- })
- }
-
-
- render() {
- const { match, history, author_info , current_user } = this.props
- if (!author_info) {
- return
- }
- return (
-
- );
- }
-}
-
-export default UserSection;
+import React, { Component } from 'react';
+
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+
+import PropTypes from 'prop-types';
+
+import classNames from 'classnames'
+
+import axios from 'axios'
+
+class UserSection extends Component {
+ constructor(props) {
+ super(props)
+
+ this.state = {
+
+ }
+ }
+ /*点击关注或者取消关注*/
+ AboutFocus(){
+ const { author_info } = this.props
+ /*http://localhost:3000/api/v1/users/155/watch?object_id=156&object_type=user*/
+
+ // const focusUrl = `/api/v1/users/${author_info.user_id}/${this.props.author_info.watched ? 'unwatch' : 'watch'}?object_id=${author_info.user_id}&object_type=user`
+
+ // axios.get(focusUrl,{
+ // })
+ // .then((response) => {
+ // const status = response.data.status;
+ // console.log(status);
+ // if(status == 1){
+ // const new_author_info = Object.assign({}, this.props.author_info)
+ // new_author_info.watched = !new_author_info.watched
+ // this.props.initForumState({author_info: new_author_info})
+ // }
+ // }).catch((error) => {
+ // console.log(error)
+ // })
+
+ let url=`/users/${author_info.user_id}/watch.json`;
+ // 取消关注
+ if(author_info.watched){
+ axios.delete(url).then((result)=>{
+ if(result){
+ const new_author_info = Object.assign({}, this.props.author_info)
+ new_author_info.watched = !new_author_info.watched
+ this.props.initForumState({author_info: new_author_info})
+ }
+ }).catch((error)=>{
+ console.log(error)
+ })
+ }else{
+ // 关注
+ axios.post(url).then((result)=>{
+ if(result){
+ const new_author_info = Object.assign({}, this.props.author_info)
+ new_author_info.watched = !new_author_info.watched
+ this.props.initForumState({author_info: new_author_info})
+ }
+ }).catch((error)=>{
+ console.log(error);
+ })
+ }
+ }
+
+
+ render() {
+ const { match, history, author_info , current_user } = this.props
+ if (!author_info || !current_user) {
+ return
+ }
+ return (
+
+ );
+ }
+}
+
+export default UserSection;
diff --git a/public/react/src/modules/forums/shixun/MemoShixun.css b/public/react/src/modules/forums/shixun/MemoShixun.css
index c76000ccf..c1421e02f 100644
--- a/public/react/src/modules/forums/shixun/MemoShixun.css
+++ b/public/react/src/modules/forums/shixun/MemoShixun.css
@@ -11,7 +11,7 @@
height:48px;
width: 48px;
float: left;
- margin-top: 7px;
+ margin-top: 4px;
}
.shixunReply{
max-width: 604px;
diff --git a/public/react/src/modules/forums/shixun/MemoShixun.js b/public/react/src/modules/forums/shixun/MemoShixun.js
index 9d75da00d..664b844ac 100644
--- a/public/react/src/modules/forums/shixun/MemoShixun.js
+++ b/public/react/src/modules/forums/shixun/MemoShixun.js
@@ -83,7 +83,7 @@ class MemoShixun extends Component {
}
const stringifid = queryString.stringify(paramsObject);
- const url = `/api/v1/discusses?${stringifid}` // /${challenge.identifier}/star
+ const url = `/discusses/forum_discusses.json?${stringifid}` // /${challenge.identifier}/star
// 获取memo list
this.setState({
@@ -91,13 +91,13 @@ class MemoShixun extends Component {
loadingMemos: true
})
axios.get(url,{
- withCredentials: true,
+ // withCredentials: true,
})
.then((response) => {
if (response.data) {
- const user = response.data.current_user;
- user.tidding_count = response.data.tidding_count;
- this.props.initCommonState(user)
+ // const user = response.data.current_user;
+ // user.tidding_count = response.data.tidding_count;
+ // this.props.initCommonState(user)
this.props.initForumState(response.data)
// const { hot_tags } = response.data;
diff --git a/public/react/src/modules/forums/shixun/ShiXunPostItem.js b/public/react/src/modules/forums/shixun/ShiXunPostItem.js
index 1f8c0d379..961e16ff1 100644
--- a/public/react/src/modules/forums/shixun/ShiXunPostItem.js
+++ b/public/react/src/modules/forums/shixun/ShiXunPostItem.js
@@ -39,7 +39,7 @@ class ShiXunPostItem extends Component
width="48px" height="48px" className="radius"/>
-
+
{memo.subject}
diff --git a/public/react/src/modules/home/home.css b/public/react/src/modules/home/home.css
index 0739376de..1e97d5ecf 100644
--- a/public/react/src/modules/home/home.css
+++ b/public/react/src/modules/home/home.css
@@ -11,10 +11,10 @@
}
.user_navlist{
- margin-left: 40px;
+ /*margin-left: 40px;*/
}
.next-slick-list{
- margin-left: 12px;
+ /*margin-left: 12px;*/
}
.black_nav_span{
@@ -58,7 +58,7 @@
}
.educontentSlider{
- width: 1282px !important;
+ /*width: 1282px !important;*/
}
.user_navlist_white{
max-height:350px !important;
@@ -72,4 +72,8 @@
.iconfontshixundaibeijing{
font-size: 18px !important;
line-height: 24px;
+}
+
+.next-slick.next-slick-horizontal.next-slick-outer{
+ padding:0px !important;
}
\ No newline at end of file
diff --git a/public/react/src/modules/login/LoginDialog.js b/public/react/src/modules/login/LoginDialog.js
index 58cd9b7fb..f4f8a3f1c 100644
--- a/public/react/src/modules/login/LoginDialog.js
+++ b/public/react/src/modules/login/LoginDialog.js
@@ -398,23 +398,23 @@ class LoginDialog extends Component {
});
}
handleDialogClose = () => {
- // if(this.props.match===undefined){
- // window.location.href="/";
- // }else if(this.props.match.path==="/"){
- // this.setState({
- // isRender: false
- // })
- // }else{
- // window.location.href="/";
- // }
- this.setState({
- isRender: false
- })
- try {
- this.props.Modifyloginvalue();
- }catch (e) {
+ if(this.props.match===undefined){
+ window.location.href="/";
+ }else{
+ this.setState({
+ isRender: false
+ })
+ this.props.Modifyloginvalue();
}
+ // this.setState({
+ // isRender: false
+ // })
+ // try {
+ // this.props.Modifyloginvalue();
+ // }catch (e) {
+ //
+ // }
}
loginEDU=()=>{
diff --git a/public/react/src/modules/message/css/messagemy.css b/public/react/src/modules/message/css/messagemy.css
new file mode 100644
index 000000000..05d6c3511
--- /dev/null
+++ b/public/react/src/modules/message/css/messagemy.css
@@ -0,0 +1,113 @@
+.myw120{
+ width: 120px;
+}
+.myh120{
+ height: 120px;
+}
+.myimgw48{
+ width: 48px;
+}
+.myimgh48{
+ height: 48px;
+}
+.mycenter{
+ display: flex;
+ justify-content: center
+}
+.myw100baifenbi{
+ width: 100%;
+}
+.ant-modal-header{
+ border-radius: 0px !important;
+}
+.ridinglist-subs{
+ border-bottom: 1px solid #F5F5F5;
+ padding: 25px 0px;
+}
+.search-new{
+ width: 100% !important;
+ margin-bottom: 0px !important;
+height: 32px;
+position: relative;}
+.search-span{
+display: block;
+position: absolute;
+width: 100%;
+height: 100%;
+left: 0px;
+top: 0px;
+background-color: #F4F4F4;
+border: 1px solid #EAEAEA;
+border-radius: 4px;
+z-index: 1;
+}
+.search-new-input{
+width: 100% !important;
+height: 32px;
+padding-left: 5px;
+border: none;
+box-sizing: border-box;
+background: none;
+outline: none;
+position: absolute;
+left: 0px;
+top: 1px;
+z-index: 2;}
+.search-new img,.search-new a,.search-new .searchicon{
+cursor: pointer;
+position: absolute;
+right: 2px;
+top: 2px;
+z-index: 2;
+}
+.search-new a{top: 0px}
+.search-new-input:focus + .search-span{background-color: #fff;}
+.task-hide-2
+ {height: 40px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+}
+
+.msheight30{
+ height: 30px;
+}
+
+/*滚动条*/
+.private-list::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+
+.private-list::-webkit-scrollbar-thumb {
+ background-color: #E3EBF4;
+ box-shadow: 0px 0px black;
+}
+
+
+.private-list::-webkit-scrollbar-track {
+ border-radius:3px;
+ -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
+ background-color: white;
+}
+/*滚动条*/
+.dialogPanel::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+
+.dialogPanel::-webkit-scrollbar-thumb {
+ background-color: #E3EBF4;
+ box-shadow: 0px 0px black;
+}
+
+
+.dialogPanel::-webkit-scrollbar-track {
+ border-radius:3px;
+ -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
+ background-color: white;
+}
diff --git a/public/react/src/modules/message/js/Leftdialogue.js b/public/react/src/modules/message/js/Leftdialogue.js
new file mode 100644
index 000000000..c809bc9c9
--- /dev/null
+++ b/public/react/src/modules/message/js/Leftdialogue.js
@@ -0,0 +1,67 @@
+import React, { Component } from 'react';
+import {
+ Spin,
+ Pagination,
+} from "antd";
+import axios from 'axios';
+import moment from 'moment';
+import {getImageUrl,markdownToHTML,ImageLayerHook} from 'educoder';
+import "../css/messagemy.css"
+import WriteaprivateletterModal from '../messagemodal/WriteaprivateletterModal';
+//私信页面
+class Leftdialogue extends Component{
+ constructor(props) {
+ super(props);
+ this.state={
+ };
+
+ }
+
+ componentDidMount(){
+ console.log("Leftdialogue");
+ console.log(this.props);
+ };
+ componentDidUpdate(prevProps) {
+ // console.log("11111111111");
+ // console.log(prevProps);
+ // console.log("22222222222");
+ // console.log(this.props);
+ // console.log("33333333333");
+ // if(prevProps.current_user !== this.props.current_user){
+ // this.getdata(1);
+ // }
+ }
+ mydelete=(user_id,id)=>{
+ this.props.DELETEsetreplyfun(user_id,id);
+ }
+ myCome=(e)=>{
+ window.location.href="/users/"+e.login;
+ }
+
+ render() {
+
+ return (
+
+
this.myCome(this.props.objeysl.sender)}>
+ {
+ this.props.objeysl&&this.props.objeysl.sender.image_url ?
+ :""
+ }
+
+
+
{moment(this.props.objeysl.send_time).hour()}:{moment(this.props.objeysl.send_time).minute()<10?"0"+moment(this.props.objeysl.send_time).minute():moment(this.props.objeysl.send_time).minute()}
+
+ )
+ }
+}
+export default Leftdialogue;
+// onClick="delete_confirm_box('/users/innov/delete_message?mess_id=25148', '确定要删除该条记录吗?')"
\ No newline at end of file
diff --git a/public/react/src/modules/message/js/MessagChat.js b/public/react/src/modules/message/js/MessagChat.js
new file mode 100644
index 000000000..52c8d9870
--- /dev/null
+++ b/public/react/src/modules/message/js/MessagChat.js
@@ -0,0 +1,694 @@
+import React, { Component } from 'react';
+import "../css/messagemy.css"
+import {getImageUrl,markdownToHTML} from 'educoder';
+import { Modal,Input,Icon,Tooltip,Spin} from 'antd';
+import axios from 'axios';
+import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
+import moment from 'moment';
+import Rightdialogue from './Rightdialogue'
+import Leftdialogue from './Leftdialogue'
+//私信聊天页面
+class MessagChat extends Component{
+ constructor(props) {
+ super(props);
+ this.messageRef = React.createRef();
+ this.state={
+ isSpin:false,
+ isSpins:false,
+ limit:20,
+ page:1,
+ datay:[],
+ limits:20,
+ mess:false,
+ myuserl:[],
+ pages:1,
+ mypagey:20,
+ messages:[],
+ objc:[],
+ datanull:1,
+ }
+ }
+ componentDidMount(){
+ this.getdata(1);
+
+ const query = this.props.location.search;
+ let target_ids = query.split('?target_ids=');
+ this.getChatList(1,this.state.limits,target_ids[1]);
+ // console.log("MessagChat111111");
+ // console.log(this.props.myysluser);
+ this.setState({
+ myyslusers:this.props.myysluser
+ })
+ try {
+ this.props.Mtab(3);
+ }catch (e) {
+
+ }
+ // console.log("MessagChat111111");
+ // console.log(this.props);
+ // console.log(this.props.match.params.userid);
+ this.scrollToBottom();
+ this.props.triggerRef(this)
+ }
+
+ componentDidUpdate() {
+ // this.scrollToBottom();
+ }
+
+ scrollToBottom() {
+ const scrollHeight = this.messageList.scrollHeight;
+ const height = this.messageList.clientHeight;
+ const maxScrollTop = scrollHeight - height;
+ this.messageList.scrollTop = maxScrollTop > 0 ? maxScrollTop : 0;
+ }
+
+
+
+ contentViewScrolltop=(e)=>{
+ if(e.currentTarget.scrollTop===0){
+
+ if(this.state.datanull===0){
+ return
+ }
+ console.log("调用了方法1111111");
+ let {pages}=this.state;
+ let newpage=pages+1
+ const query = this.props.location.search;
+ let target_ids = query.split('?target_ids=');
+ this.shuaxingetChatList(newpage,this.state.limits,target_ids[1],true);
+ this.messageList.scrollTop=50;
+
+
+ }
+ }
+ // 滑动刷新
+ contentViewScrolledit=(e)=>{
+
+ //滑动到底判断
+ if(e.currentTarget.scrollHeight-e.currentTarget.scrollTop===e.currentTarget.clientHeight){
+ // console.log("滑动到底判断");
+ let {page}=this.state;
+ let newpage=page+1
+ this.getdata(newpage);
+ // let ls=newpage*20
+ // this.setState({
+ // limits:ls,
+ // })
+ }
+ //滑动到顶部
+ // console.log("滑动到顶部判断");
+ // console.log(e.currentTarget.clientHeight);
+ // console.log(e.currentTarget.scrollTop);
+ // console.log(e.currentTarget.scrollHeight);
+ // if(e.currentTarget.scrollHeight+e.currentTarget.scrollTop===e.currentTarget.clientHeight){
+ // console.log("滑动到顶部判断");
+ //
+ // // let ls=newpage*20
+ // // this.setState({
+ // // limits:ls,
+ // // })
+ // }
+
+ };
+
+ shuaxingetChatList=(page,listl,target_ids,bool)=>{
+ this.setState({
+ isSpin:true,
+ });
+ let url = `/users/${this.props.match.params.userid}/private_message_details.json`;
+ axios.get((url),{params:{
+ target_id:target_ids,
+ page: page,
+ per_page:listl,
+ }}).then((result) => {
+ this.setState({
+ isSpin: false,
+ });
+ if (result) {
+ // if (result.data.status === 0) {
+ if (result.data !== null) {
+ if(result.data.messages.length===0){
+ console.log("没有数据了");
+ this.setState({
+ datanull:0,
+ })
+ return
+ }
+ var laoshuju=this.state.messages;
+ var datas = [];
+ var datay = result.data.messages;
+ datay = datay.reverse();
+ datay=datay.concat(laoshuju);
+ var obj = {};
+ for (var i = 0; i < datay.length; i++) {
+ if (i === 0) {
+ var timetwoy=datay[i].send_time.slice(0,10);
+ datay[i].send_day = timetwoy;
+ obj = datay[i];
+ datas.push(datay[i]);
+ } else {
+ try {
+ var timeone=obj.send_time.slice(0,10);
+ var timetwo=datay[i].send_time.slice(0,10);
+ if (moment(timeone).isSame(timetwo)) {
+ datay[i].send_day = "";
+ } else {
+ datay[i].send_day = timetwo;
+ obj = datay[i];
+ }
+ }catch (e) {
+
+ }
+ datas.push(datay[i]);
+ }
+ }
+ console.log("新数组+++++++++++++++++++++++++++++++++++++");
+ console.log(datas)
+ //颠倒数组
+ this.setState({
+ messages: datas,
+ myuserl: result.data.target,
+ pages:page,
+ })
+ // }
+
+ }
+ }
+
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ })
+ })
+ };
+ getChatList=(page,listl,target_ids)=>{
+ this.setState({
+ isSpin:true,
+ });
+ let url = `/users/${this.props.match.params.userid}/private_message_details.json`;
+ axios.get((url),{params:{
+ target_id:target_ids,
+ page: page,
+ per_page:listl,
+ }}).then((result) => {
+ if (result) {
+ // if (result.data.status === 0) {
+ if (result.data !== null) {
+ var datas = [];
+ var datay = result.data.messages;
+ datay = datay.reverse();
+ var obj = {};
+ for (var i = 0; i < datay.length; i++) {
+ if (i === 0) {
+ var timetwoy=datay[i].send_time.slice(0,10);
+ datay[i].send_day = timetwoy;
+ obj = datay[i];
+ datas.push(datay[i]);
+ } else {
+ try {
+ var timeone=obj.send_time.slice(0,10);
+ var timetwo=datay[i].send_time.slice(0,10);
+ if (moment(timeone).isSame(timetwo)) {
+ datay[i].send_day = "";
+ } else {
+ datay[i].send_day = timetwo;
+ obj = datay[i];
+ }
+ }catch (e) {
+
+ }
+ datas.push(datay[i]);
+ }
+ }
+ //颠倒数组
+ this.setState({
+ messages: datas,
+ myuserl: result.data.target,
+ pages:page,
+ })
+ // }
+ this.scrollToBottom();
+
+ }
+ }
+ this.setState({
+ isSpin: false,
+ });
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ })
+ })
+ };
+ getChatListtwo=(pages,listls,target_ids)=>{
+ this.setState({
+ isSpin:true,
+ });
+ let url = `/users/${this.props.match.params.userid}/private_message_details.json`;
+ axios.get((url),{params:{
+ target_id:target_ids,
+ page: pages,
+ per_page:listls,
+ }}).then((result) => {
+ if (result) {
+ // if (result.data.status === 0) {
+ if (result) {
+ // if (result.data.status === 0) {
+ if (result.data !== null) {
+ var datas = [];
+ var datay = result.data.messages;
+ datay = datay.reverse();
+ var obj = {};
+ for (var i = 0; i < datay.length; i++) {
+ if (i === 0) {
+ var timetwoy=datay[i].send_time.slice(0,10);
+ datay[i].send_day = timetwoy;
+ obj = datay[i];
+ datas.push(datay[i]);
+ } else {
+ try {
+ var timeone=obj.send_time.slice(0,10);
+ var timetwo=datay[i].send_time.slice(0,10);
+ if (moment(timeone).isSame(timetwo)) {
+ datay[i].send_day = "";
+ } else {
+ datay[i].send_day = timetwo;
+ obj = datay[i];
+ }
+ }catch (e) {
+ console.log("271271271271");
+ console.log(e);
+ }
+ datas.push(datay[i]);
+ }
+ }
+
+ //颠倒数组
+ this.setState({
+ messages: datas,
+ myuserl: result.data.target,
+ pages:pages,
+ datanull:1
+ })
+ this.scrollToBottom();
+ // }
+
+ }
+ }
+ }
+ this.setState({
+ isSpin: false,
+ });
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ });
+ // this.getdatatwo(this.state.page);
+ })
+ };
+ //获取数据地方
+ getdata=(page)=>{
+
+ let{limit}=this.state;
+ let url = `/users/${this.props.match&&this.props.match.params.userid}/private_messages.json`;
+ // let url = `/users/71519/private_messages.json`;
+ axios.get((url),{params:{
+ page:page,
+ per_page:limit,
+ }}).then((result) => {
+ if (result) {
+ // console.log(types);
+ // console.log(result);
+ // console.log("调用了消失的方法");
+ // console.log("5454545454");
+ // if(result.data.status===0) {
+
+
+ if (result.data !== null) {
+ if (result.data.private_messages !== null) {
+ if (result.data.private_messages.length > 0) {
+ for (var i = 0; i < result.data.private_messages.length; i++) {
+ this.state.datay.push(result.data.private_messages[i]);
+ }
+ }
+ }
+ }
+ this.setState({
+ page: page,
+ isSpins: false,
+ datay: this.state.datay,
+ data: result.data.private_messages === null ? undefined : result.data.private_messages === undefined ? undefined : result.data.private_messages === [] ? undefined : result.data.private_messages === "[]" ? undefined : result.data.private_messages.length === 0 ? undefined : result.data.private_messages,
+ });
+ }
+ // console.log(this.state.datay);
+ // }
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpins:false,
+ })
+ })
+ };
+ //获取数据地方
+ getdatatwo=(page)=>{
+
+ let{limits}=this.state;
+ let url = `/users/${this.props.match&&this.props.match.params.userid}/private_messages.json`;
+ // let url = `/users/71519/private_messages.json`;
+ axios.get((url),{params:{
+ page:page,
+ per_page:limits,
+ }}).then((result) => {
+ if (result) {
+ // if(result.data.status===0){
+ this.setState({
+ page:page,
+ isSpins:false,
+ datay:result.data.private_messages===null?undefined:result.data.private_messages===undefined?undefined:result.data.private_messages===[]?undefined:result.data.private_messages==="[]"?undefined:result.data.private_messages.length===0?undefined:result.data.private_messages,
+ });
+ // }
+
+ // console.log(this.state.datay);
+ }
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpins:false,
+ })
+ })
+ };
+ // 跳转页面
+ smyJump =(i)=>{
+ // console.log("跳转页面");
+ // console.log(i);
+ this.props.Modifyur(i);
+ };
+ getdatas2=()=>{
+
+ }
+ // 点击了用户
+ Clickedontheuser=(user)=>{
+ // debugger
+ // console.log("点击了用户");
+ // console.log(user);
+ // this.setState({
+ // myyslusers:user,
+ // mess:true,
+ // })
+ this.setState({
+ myuserl:user,
+ })
+
+ this.props.history.replace(`/messages/${this.props.current_user.login}/message_detail?target_ids=${user.id}`);
+ // this.getdatatwo(this.state.page);
+ this.getChatListtwo(1,this.state.mypagey,user.id);
+
+ }
+ //回复
+ setreplyfun=()=>{
+ this.setState({
+ isSpin:true,
+ });
+ let contents=this.messageRef.current.getValue().trim();
+ const query = this.props.location.search;
+ let target_ids = query.split('?target_ids=');
+ let url = `/users/${this.props.match.params.userid}/private_messages.json`;
+ axios.post(url, {
+ target_id: target_ids[1],
+ content: contents
+ })
+ .then((response) => {
+ this.setState({
+ isSpin:false,
+ });
+ if(response===undefined){
+ return
+ }
+ if(response.data.status===0){
+ // console.log("回复成功");
+ // console.log(response);
+ // var datas=[];
+ // var dataso=this.state.messages;
+ // var datays=response.data.private_message;
+ // var obj={};
+ // for (var i=0;i
{
+ //user_id不用
+ // console.log("311");
+ this.setState({
+ isSpin:true,
+ });
+ let url = `/users/${this.props.match.params.userid}/private_messages/${id}.json`;
+ axios.delete(url)
+ .then((response) => {
+ if(response){
+ if(response.data.status===0){
+ if(this.state.messages.length>0){
+ for(var i=0;i{
+ //
+ // }, 200);
+ this.setState({
+ messages:this.state.messages,
+ isSpin:false,
+ // datanull:1
+ })
+
+ // this.scrollToBottom()
+ }
+ }
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ })
+ });
+ }
+
+
+
+
+
+
+
+
+
+ render() {
+ let{isSpins,datay,myyslusers,mess,limits,myuserl,messages,isSpin,datanull}=this.state;
+ // console.log(mess);
+ // console.log(myyslusers);
+ // console.log("MessagChat");
+ // console.log(this.state);
+ // console.log("112");
+ // console.log(limits);
+ // console.log(myuserl);
+ // console.log(messages);
+ return (
+
+ {/*私信对话框*/}
+
+ {/*左边*/}
+
+
+ this.smyJump(2)}>
+ {myuserl!==undefined?myuserl.name:""}与你的私信
+
+ {/*聊天页面*/}
+
{
+ this.messageList = div;
+ }}>
+
+
+ {
+ datanull===0?
+ 没有信息了~~
+ :""
+ }
+
+ {
+ messages===undefined?
+ ""
+ :messages.map((item,key)=>{
+ // console.log("-----------------================-=-==-==");
+ // console.log(item.sender_id);
+ // console.log(this.props.match.params.userid);
+ return(
+
+ {
+ item.send_day===undefined?"":item.send_day===null?"":item.send_day===""?"":
+
{item.send_day}
+ }
+ {
+ parseInt(item.sender_id)===parseInt(this.props.match.params.userid)?
+
this.DELETEsetreplyfun(user_id,id)}>
+ {/*自己的*/}
+
+
+
+ :
this.DELETEsetreplyfun(user_id,id)}>
+ {/*他人的*/}
+
+
+
+ }
+
+
+ )
+ })
+ }
+
+
+
+
+
+
+ {/*回复*/}
+
+
+
+
+
+
+ {/*右边*/}
+
+ {/*右边头部*/}
+
私信列表
+
+
+ {/*列表数据*/}
+ {
+ datay===undefined?
+ ""
+ :datay.map((item,key)=>{
+ return(
+
this.Clickedontheuser(item.target)}>
+
+
+
+
+
+ {item.target.name}
+ {item.unread === true?
+
+ :""}
+
+ {moment(item.send_time).fromNow()}
+
+
+
+
+
+
+
+
+
+ )
+ })}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
+export default MessagChat;
+
+
+// onClick="delete_confirm_box('/users/innov/delete_message?mess_id=25137', '确定要删除该条记录吗?')"
+//
+// {/*左边*/}
diff --git a/public/react/src/modules/message/js/MessagSub.js b/public/react/src/modules/message/js/MessagSub.js
new file mode 100644
index 000000000..ef0d35dd1
--- /dev/null
+++ b/public/react/src/modules/message/js/MessagSub.js
@@ -0,0 +1,610 @@
+import React, { Component } from 'react';
+import {
+ Spin,
+ Pagination,
+} from "antd";
+import axios from 'axios';
+import {getImageUrl,markdownToHTML} from 'educoder';
+import "../css/messagemy.css"
+//消息页面
+class MessagSub extends Component{
+ constructor(props) {
+ super(props);
+ this.state={
+ page:1,
+ limit:10,
+ typeysl:"",
+ count:0,
+ isSpin:false,
+ data:undefined,
+ }
+ }
+ // 初始化数据
+ componentDidMount(){
+ // console.log("初始化数据了MessagSub");
+ // console.log(this.props);
+ this.getdata("",this.state.page);
+ // this.Messageprivatemessageunreadmessage();
+ try {
+ this.props.Mtab(1);
+ }catch (e) {
+
+ }
+ this.props.triggerRef(this)
+ }
+
+ //塞选页数
+ paginationonChanges=(pageNumber)=>{
+ this.setState({
+ page: pageNumber,
+ })
+ this.getdata(this.state.typeysl,pageNumber);
+
+ }
+ //获取数据源
+ getdata=(types,page)=>{
+ this.setState({
+ isSpin:true,
+ })
+ let{limit}=this.state;
+ let url = `/users/tidings.json`;
+ axios.get((url),{params:{
+ type:types,
+ page:page,
+ per_page:limit,
+ }}).then((result) => {
+ if (result) {
+ // if (result.data.status === 0) {
+
+ this.setState({
+ page: page,
+ count: result.data.count,
+ typeysl: types,
+ isSpin: false,
+ data: result.data.tidings === null ? undefined : result.data.tidings === undefined ? undefined : result.data.tidings === [] ? undefined : result.data.tidings === "[]" ? undefined : result.data.tidings.length === 0 ? undefined : result.data.tidings,
+ })
+ // }
+ }
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ })
+ })
+ };
+ getdatas=()=>{
+ this.setState({
+ isSpin:true,
+ })
+ let{typeysl,page,limit}=this.state;
+ let url = `/users/tidings.json`;
+ axios.get((url),{params:{
+ type:typeysl,
+ page:page,
+ per_page:limit,
+ }}).then((result) => {
+ if (result) {
+ // if (result.data.status === 0) {
+
+ this.setState({
+ page: page,
+ count: result.data.count,
+ typeysl: typeysl,
+ isSpin: false,
+ data: result.data.tidings === null ? undefined : result.data.tidings === undefined ? undefined : result.data.tidings === [] ? undefined : result.data.tidings === "[]" ? undefined : result.data.tidings.length === 0 ? undefined : result.data.tidings,
+ })
+ // }
+ }
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ })
+ })
+ }
+
+ componentWillUnmount(){
+ // 卸载异步操作设置状态
+ this.setState = (state, callback) => {
+ return;
+ }
+ }
+
+ gettourl=(item)=>{
+ switch (item.container_type) {
+ case "ApplyUserAuthentication" :
+ if(item.tiding_type==="Apply"){
+ if(item.auth_type===1){
+ //系统管理页面
+ return window.open("/managements/identity_authentication");
+ }
+ if(item.auth_type===2){
+ //系统管理页面
+ return window.open("/managements/professional_authentication")
+ }
+ }
+ if(item.tiding_type ==="System"){
+ // 账号管理页-认证信息
+ return window.open("/account/certification")
+ }
+ return ;
+ case "CancelUserAuthentication" :
+ // 账号管理页-认证信息
+ return window.open("/account/certification")
+ case "CancelUserProCertification" :
+ // 账号管理页-认证信息
+ return window.open("/account/certification")
+ case "ApplyAddDepartment" :
+ if(item.tiding_type==="Apply"){
+ //部门审批
+ return window.open("/managements/depart")
+ }
+ if(item.tiding_type==="System"){
+ // 账号管理页/account/profile
+ return window.open("/account/profile")
+ }
+ return ;
+ case "ApplyAddSchools" :
+ if(item.tiding_type==="Apply"){
+ // 单位审批
+ return window.open(" /managements/unit")
+ }
+ if(item.tiding_type==="System"){
+ // 账号管理页
+ return window.open("/account/profile")
+ }
+ return ;
+ case "ApplyAction" :
+ switch (item.parent_container_type) {
+ case "ApplyShixun" :
+ if(item.tiding_type==="Apply"){
+ return window.open("/managements/shixun_authorization")
+ }
+ if(item.tiding_type==="System"){
+ // 实训详情页 :identifier = identifier
+ return window.open(`/shixuns/${item.identifier}/challenges`)
+ }
+ case "ApplySubject" :
+ if(item.tiding_type==="Apply"){
+ // 实训课程发布
+ return window.open("/managements/subject_authorization")
+ }
+ if(item.tiding_type==="System"){
+ // 实践课程详情页 :parent_container_id = parent_container_id
+
+ return window.open(`/paths/${item.parent_container_id}`)
+ }
+ case "TrialAuthorization" :
+ if(item.tiding_type==="Apply"){
+ // 试用授权页面
+ return window.open("/managements/trial_authorization")
+ }
+ if(item.tiding_type==="System"){
+ // 账号管理页
+ return window.open("/account/profile")
+ }
+ }
+ return ;
+ case 'JoinCourse' :
+ // 课堂详情页 :id =
+ return window.open(`/courses/${item.belong_container_id}/teachers`)
+ case 'StudentJoinCourse':
+ // 课堂详情页 :id = container_id
+ if(item.tiding_type === 'Apply') {
+ return window.open(`/courses/${item.belong_container_id}/teachers`);
+ }
+ if(item.tiding_type === 'System'){
+ //教学案例详情 :id = container_id
+ return window.open(`/courses/${item.belong_container_id}/students`);
+ }
+ case 'DealCourse':
+ // 课堂详情页 :id = container_id
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.container_id}`)
+ case 'TeacherJoinCourse':
+ // 课堂详情页 :id = container_id
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.container_id}`)
+ case 'Course' :
+ // 课堂详情页 :id = container_id
+ if(item.tiding_type==="Delete"){
+
+ return;
+ }
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.container_id}`)
+ case 'ArchiveCourse' :
+ // 课堂详情页 :id = container_id
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.container_id}`)
+ case "Shixun" :
+ return window.open(`/shixuns/${item.identifier}/challenges`)
+ case "Subject" :
+ // 实践课程详情页 :id = container_id
+ return window.open(`/paths/${item.container_id}`)
+ case "JournalsForMessage" :
+ switch (item.parent_container_type) {
+ case "Principal" :
+ // 反馈页 :id = parent_container_id
+ // 不用跳了
+ return '';
+ case "HomeworkCommon" :
+ //学生作业页 homework = parent_container_id
+ if(item.homework_type==="normal"){
+ //普通作业
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/question`)
+ }
+ if(item.homework_type==="group"){
+ //分组作业
+ return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/question`)
+ }
+ if(item.homework_type==="practice"){
+ //实训作业
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=1`)
+ }
+ return "";
+ case "GraduationTopic" :
+ // 毕业目标页 parent_container_id
+ return window.open(`/courses/${item.belong_container_id}/graduation_topics/${item.parent_container_id}/detail`)
+ case "StudentWorksScore" :
+ //学生作业页
+ if(item.homework_type==="normal"){
+ //普通作业
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/question`)
+ }
+ if(item.homework_type==="group"){
+ //分组作业
+ return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/question`)
+ }
+ if(item.homework_type==="practice"){
+ //实训作业
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=1`)
+ }
+ return "";
+ }
+ case "Memo" :
+ // 交流问答页 :id = parent_container_id
+ return window.open(`/forums/${item.parent_container_id}`);
+ case "Message" :
+ // 交流问答页 :id = parent_container_id
+ return window.open(`/forums/`);
+ case "Watcher" :
+ // 用户个人中心页 :id = item.trigger_user.login
+ return window.open(`/users/${item.trigger_user.login}/courses`)
+ case "PraiseTread" :
+ // 这块太复杂 不好处理
+ return '';
+ case "Grade" :
+ //个人中心页 :id = item.trigger_user.login
+ // return window.open(`/users/${item.trigger_user.login}/courses`;
+ return "";
+ case "JoinProject" :
+ //项目详情-申请加入项目审核页 :id = container_id
+ return window.open(`/projects/${item.container_id}`)
+ case 'ReporterJoinProject':
+ //项目详情页 :id = container_id
+ return window.open(`/projects/${item.container_id}`)
+ case 'DealProject':
+ //项目详情页 :id = container_id
+ return window.open(`/projects/${item.container_id}`)
+ case 'ManagerJoinProject':
+ //项目详情页 :id = container_id
+ return window.open(`/projects/${item.container_id}`)
+ case "Poll":
+ switch (item.parent_container_type) {
+ case "CommitPoll" :
+ // 课堂id belong_container_id
+ //课堂-学生已提交问卷列表 :id = container_id
+ return window.open(` /courses/${item.belong_container_id}/polls/${item.container_id}`)
+ default :
+ // 课堂-问卷列表 :id = container_id
+ return window.open(` /courses/${item.belong_container_id}/polls/${item.container_id}`)
+ }
+ case "Exercise" :
+ switch (item.parent_container_type) {
+ case "CommitExercise":
+ // 课堂-学生试卷详情 :id = container_id :user_id = trigger_user.id
+ return window.open(` /courses/${item.belong_container_id}/exercises/${item.container_id}/student_exercise_list?tab=0`);
+ //记得跳评阅页面
+ case "ExerciseScore":
+ // 课堂-学生试卷详情 :id = container_id :user_id = trigger_user.id
+ return window.open(` /courses/${item.belong_container_id}/exercises/${item.container_id}/student_exercise_list?tab=0`);
+ //记得跳评阅页面
+ default :
+ // 课堂-试卷列表详情 :id = container_id
+ return window.open(`/courses/${item.belong_container_id}/exercises/${item.container_id}`)
+ }
+ case 'StudentGraduationTopic' :
+ //课堂-毕业选题详情 :id = parent_container_id
+ return window.open(`/courses/${item.belong_container_id}/graduation_topics/${item.parent_container_id}/detail`)
+ case 'DealStudentTopicSelect' :
+ //课堂-毕业选题详情 :id = parent_container_id
+ return window.open(`/courses/${item.belong_container_id}/graduation_topics/${item.parent_container_id}/detail`)
+ case 'GraduationTask' :
+ //课堂-毕业任务页 :id = container_id
+ return window.open(`/courses/${item.belong_container_id}/graduation_tasks/${item.container_id}`)
+ case "GraduationWork" :
+ //课堂-毕业xx页 :id = container_id
+ return window.open(`/courses/${item.belong_container_id}/graduation_tasks/${item.container_id}`)
+ case "GraduationWorkScore" :
+ // 课堂-毕业xx页 :id = parent_container_id
+ return window.open(`/courses/${item.belong_container_id}/graduation_tasks/${item.parent_container_id}`)
+ case "HomeworkCommon" :
+ switch (item.parent_container_type) {
+ case "AnonymousCommentFail" :
+ // 课堂-作业列表 homework = container_id
+ if(item.homework_type==="normal"){
+ //普通作业
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="group"){
+ //分组作业
+ return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="practice"){
+ //实训作业
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=0`)
+ }
+ case "HomeworkPublish" :
+ if(item.homework_type==="normal"){
+ //普通作业
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="group"){
+ //分组作业
+ return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="practice"){
+ //实训作业
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=0`)
+ }
+ case "AnonymousAppeal" :
+ if(item.homework_type==="normal"){
+ //普通作业
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="group"){
+ //分组作业
+ return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="practice"){
+ //实训作业
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=0`)
+ }
+ default :
+ // 课堂-作业列表 homework = container_id
+ if(item.homework_type==="normal"){
+ //普通作业
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="group"){
+ //分组作业
+ return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/list`)
+ }
+ if(item.homework_type==="practice"){
+ //实训作业
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=0`)
+ }
+ }
+ case "StudentWork" :
+ //课堂-作业 :id = container_id
+ if(item.homework_type==="normal"){
+ //普通作业
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/${item.container_id}/appraise`)
+ }
+ if(item.homework_type==="group"){
+ //分组作业/courses/1208/group_homeworks/22373/1219130/appraise
+ return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/${item.container_id}/appraise`)
+ }
+ if(item.homework_type==="practice"){
+ //实训作业
+ return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=0`)
+ }
+ case "StudentWorksScore" :
+ //课堂-作业 :id = parent_container_id
+ // if(item.homework_type==="normal"){
+ // //普通作业
+ // return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/list`)
+ // }
+ // if(item.homework_type==="group"){
+ // //分组作业
+ // return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/list`)
+ // }
+ // if(item.homework_type==="practice"){
+ // //实训作业
+ // return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=0`)
+ // }
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.trigger_user.id}/${item.parent_container_id}/appraise`);
+
+ case "StudentWorksScoresAppeal" :
+ // if(item.homework_type==="normal"){
+ // //普通作业
+ // return window.open(`courses/${item.belong_container_id}/common_homeworks/${item.parent_container_id}/list`)
+ // }
+ // if(item.homework_type==="group"){
+ // //分组作业
+ // return window.open(`/courses/${item.belong_container_id}/group_homeworks/${item.parent_container_id}/list`)
+ // }
+ // if(item.homework_type==="practice"){
+ // //实训作业
+ // return window.open(`/courses/${item.belong_container_id}/shixun_homeworks/${item.parent_container_id}/list?tab=0`)
+ // }
+ return window.open(`/courses/${item.belong_container_id}/common_homeworks/${item.trigger_user.id}/${item.parent_container_id}/appraise`);
+ case "ChallengeWorkScore" :
+ return '';
+ case "SendMessage" :
+ // /managements/mirror_repository
+ return window.open(`/managements/mirror_repository`)
+ case "Journal" :
+ //项目Issue页 :id = parent_container_id
+ return window.open(`/issues/${item.parent_container_id}`);
+ case "Issue" :
+ //项目Issue页 :id = container_id
+ return window.open(`/issues/${item.container_id}`)
+ case "PullRequest" :
+ // 项目pull request页 :id = parent_container_id
+ return window.open(`/projects/${item.parent_container_id}/pull_requests`)
+ case "Department" :
+ //账号管理页
+ return window.open(`/account/profile`)
+ case "Library" :
+ if (item.tiding_type === 'Apply') {
+ // /managements/library_applies
+ return window.open(`/managements/library_applies`)
+ }
+ if(item.tiding_type === 'System'){
+ //教学案例详情 :id = container_id
+ return window.open(`/moop_cases/${item.container_id}`)
+ }
+ case "ProjectPackage" :
+ if(item.tiding_type==="Destroyed"){
+ return ;
+ }
+ if(item.tiding_type==="Destroyed_end"){
+ return ;
+ }else {
+ if (item.tiding_type === 'Apply') {
+ ///managements/project_package_applies
+ return window.open(`/managements/project_package_applies`)
+ }
+ // if(item.tiding_type === 'System'){
+ //众包详情 :id = container_id
+ return window.open(`/crowdsourcing/${item.container_id}`)
+ // }
+ }
+ case "Discuss":
+ return window.open(`/shixuns/${item.identifier}/shixun_discuss`);
+ default :
+ return window.open("/")
+ }
+
+ }
+ render() {
+ let{page,limit,typeysl,count,isSpin,data}=this.state;
+ // console.log("6868686868");
+ // console.log(data);
+ return (
+
+ {/*头部筛选数据*/}
+
+ {/*下面内容页面*/}
+
+ {/*这里可以进行数据处理*/}
+
+
+
+ {
+ data===undefined?"":data.length===0?
+
+
+
暂无数据哦~
+
+ :data.map((item,key)=>{
+ // console.log(data)
+ // ridinglist-subs
+ var boolps=true;
+ if(item.container_type==="PraiseTread"||item.container_type==="Grade"||item.container_type==="ChallengeWorkScore"){
+ boolps=false;
+ }
+ if(item.container_type==="JournalsForMessage"){
+ if(item.parent_container_type==="Principal"){
+ boolps=false;
+ }
+ if(item.parent_container_type==="HomeworkCommon"){
+ if(item.homework_type===null||item.homework_type===undefined){
+ boolps=false;
+ }
+ }
+ }
+ // if(item.container_type==="HomeworkCommon"){
+ // if(item.parent_container_type==="AnonymousAppeal"){
+ // boolps=false;
+ // }
+ // }
+ if(item.container_type==="ProjectPackage"){
+ if(item.tiding_type==="Destroyed_end"){
+ boolps=false;
+ }
+ if(item.tiding_type==="Destroyed"){
+ boolps=false;
+ }
+ }
+ if(item.container_type==="Course"){
+ if(item.tiding_type==="Delete"){
+ boolps=false;
+ }
+ }
+
+ return(
+
+
this.gettourl(item)}>
+
this.myCome(item)} src={getImageUrl("images/"+item.trigger_user.image_url)} className="radius mr10 fl myimgw48 myimgh48"/>
+
+
+
+
+
+
+ )
+ })}
+
+
+ {/*页数*/}
+ { data===undefined?""
+ :
+ (count>10?
+
:""
+ )
+
+ }
+
+
+
+
+ )
+ }
+}
+export default MessagSub;
\ No newline at end of file
diff --git a/public/react/src/modules/message/js/MessagePrivate.js b/public/react/src/modules/message/js/MessagePrivate.js
new file mode 100644
index 000000000..ec7c20121
--- /dev/null
+++ b/public/react/src/modules/message/js/MessagePrivate.js
@@ -0,0 +1,213 @@
+import React, { Component } from 'react';
+import {
+ Spin,
+ Pagination,
+} from "antd";
+import axios from 'axios';
+import moment from 'moment';
+import {getImageUrl,markdownToHTML} from 'educoder';
+import "../css/messagemy.css"
+import WriteaprivateletterModal from '../messagemodal/WriteaprivateletterModal';
+//私信页面
+class MessagePrivate extends Component{
+ constructor(props) {
+ super(props);
+ this.state={
+ page:1,
+ limit:10,
+ count:0,
+ data:undefined,
+ isSpin:false,
+ modalsType:false,
+ };
+ // console.log("MessagePrivate");
+ // console.log(this.props);
+ }
+
+ componentDidMount(){
+ this.getdata(1);
+ try {
+ this.props.Mtab(2);
+ }catch (e) {
+
+ }
+ this.props.triggerRef(this)
+ // console.log("MessagePrivate");
+ // console.log(this.props);
+ // console.log(this.props.match.params.userid);
+ };
+ componentDidUpdate(prevProps) {
+ // console.log("11111111111");
+ // console.log(prevProps);
+ // console.log("22222222222");
+ // console.log(this.props);
+ // console.log("33333333333");
+ if(prevProps.current_user !== this.props.current_user){
+ this.getdata(1);
+ }
+ }
+ //获取数据地方
+ getdata=(page)=>{
+ this.setState({
+ isSpin:true,
+ });
+ let{limit}=this.state;
+ let url = `/users/${this.props.match&&this.props.match.params.userid}/private_messages.json`;
+ // let url = `/users/71519/private_messages.json`;
+ axios.get((url),{params:{
+ page:page,
+ per_page:limit,
+ }}).then((result) => {
+ if (result) {
+ // console.log(types);
+ // console.log(result);
+
+ // console.log("调用了消失的方法");
+ // console.log("5454545454");
+ // if (result.data.status === 0) {
+
+ this.setState({
+ page: page,
+ count: result.data.count,
+ isSpin: false,
+ data: result.data.private_messages === null ? undefined : result.data.private_messages === undefined ? undefined : result.data.private_messages === [] ? undefined : result.data.private_messages === "[]" ? undefined : result.data.private_messages.length === 0 ? undefined : result.data.private_messages,
+ })
+ // }
+ }
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ })
+ })
+ };
+ getdatas2=()=>{
+ this.setState({
+ isSpin:true,
+ });
+ let{limit,page}=this.state;
+ let url = `/users/${this.props.match&&this.props.match.params.userid}/private_messages.json`;
+ // let url = `/users/71519/private_messages.json`;
+ axios.get((url),{params:{
+ page:page,
+ per_page:limit,
+ }}).then((result) => {
+ if (result) {
+ // console.log(types);
+ // console.log(result);
+
+ // console.log("调用了消失的方法");
+ // console.log("5454545454");
+ // if (result.data.status === 0) {
+
+ this.setState({
+ page: page,
+ count: result.data.count,
+ isSpin: false,
+ data: result.data.private_messages === null ? undefined : result.data.private_messages === undefined ? undefined : result.data.private_messages === [] ? undefined : result.data.private_messages === "[]" ? undefined : result.data.private_messages.length === 0 ? undefined : result.data.private_messages,
+ })
+ // }
+ }
+ }).catch((error) => {
+ console.log(error);
+ this.setState({
+ isSpin:false,
+ })
+ })
+ };
+
+ paginationonChanges=(pageNumber)=>{
+ this.setState({
+ page: pageNumber,
+ })
+ this.getdata(pageNumber);
+ };
+ okmodalsType=()=>{
+ this.setState({
+ modalsType:true,
+ })
+ }
+ cancelmodalsType=()=>{
+ this.setState({
+ modalsType:false,
+ })
+ };
+ // 跳转页面
+ smyJump =(i,id)=>{
+ // console.log("跳转页面");
+ // console.log(i);
+ this.props.Modifyur(i,id);
+ };
+ myCome=(e)=>{
+ window.location.href="/users/"+e.target.login;
+ }
+ render() {
+ let{page,limit,typeysl,count,isSpin,data,modalsType}=this.state;
+ // console.log( this.props);
+ // console.log("37");
+ return (
+
+ {
+ modalsType===true?
+
this.smyJump(is,item)} >
+ :""
+ }
+
+
+ 全部私信
+ this.okmodalsType()}>写私信
+
+
+
+ {
+ data===undefined?"":data.length===0?
+
+
+
暂无数据哦~
+
+ :data.map((item,key)=>{
+ return(
+
+ )
+ })}
+
+
+
+
+
+ {/*页数*/}
+ { data===undefined?""
+ :
+ (count>10?
+
+ :""
+ )
+
+ }
+
+
+ )
+ }
+}
+export default MessagePrivate;
\ No newline at end of file
diff --git a/public/react/src/modules/message/js/Messagerouting.js b/public/react/src/modules/message/js/Messagerouting.js
new file mode 100644
index 000000000..2667127ca
--- /dev/null
+++ b/public/react/src/modules/message/js/Messagerouting.js
@@ -0,0 +1,260 @@
+import React, { Component } from 'react';
+import {Input,Pagination,Tooltip} from 'antd';
+import {TPMIndexHOC} from "../../../modules/tpm/TPMIndexHOC";
+import { WordsBtn ,ActionBtn,SnackbarHOC,markdownToHTML,getImageUrl} from 'educoder';
+import axios from 'axios';
+import "../css/messagemy.css"
+import { Redirect } from 'react-router';
+import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
+import Loading from '../../../Loading'
+import Loadable from 'react-loadable';
+
+// MessagSub 消息自路由
+// MessagePrivate 私信
+const MessagSub = Loadable({
+ loader: () => import('./MessagSub'),
+ loading: Loading,
+})
+
+const MessagePrivate = Loadable({
+ loader: () => import('./MessagePrivate'),
+ loading: Loading,
+})
+
+const MessagChat = Loadable({
+ loader: () => import('./MessagChat'),
+ loading: Loading,
+})
+class Messagerouting extends Component{
+ constructor(props) {
+ super(props);
+ this.state={
+ routing:1,
+ unread_message_count:0,
+ unread_tiding_count:0,
+ }
+ }
+
+ componentDidMount(){
+ // console.log("Messagerouting");
+ // console.log(this.props);
+ // let courstype=this.props.location.search;
+ // // courstype=courstype.splice('/');
+ // // courstype=courstype[3];
+ // // console.log("45");
+ // console.log(courstype);
+ // console.log("Messagerouting46");
+ // console.log(this.props.current_user);
+
+ }
+
+ componentDidUpdate(prevProps) {
+ // console.log("11111111111");
+ // console.log(prevProps);
+ // console.log("22222222222");
+ // console.log(this.props);
+ // console.log("33333333333");
+ if(prevProps.current_user !== this.props.current_user){
+ this.Messageprivatemessageunreadmessage(this.props.current_user.login);
+ // console.log("Messagerouting59");
+ // console.log(this.props.current_user);
+ }
+ }
+ //消息未读
+ Messageprivatemessageunreadmessage=(user_id)=>{
+ const url=`/users/${user_id}/unread_message_info.json`
+ axios.get(url).then((result) => {
+ if(result===undefined){
+ return
+ }
+ // console.log("消息未读1");
+ // console.log(result);
+ this.setState({
+ unread_message_count:result.data.unread_message_count,
+ unread_tiding_count:result.data.unread_tiding_count,
+ })
+ }).catch((error) => {
+ console.log(error)
+ })
+ };
+
+ SwitchonClick=(value,child)=>{
+ this.setState({
+ routing:value,
+ });
+ this.Messageprivatemessageunreadmessage(this.props.current_user.login);
+ if(value===1){
+ this.props.history.replace(`/messages/${this.props.current_user.login}/user_tidings`);
+ this.homeworkendss1(child);
+ }
+ if(value===2){
+ this.props.history.replace(`/messages/${this.props.current_user.login}/private_messages`);
+ this.homeworkendss2(child);
+ }
+
+
+ };
+
+
+
+ Message2=(data)=>{
+ // console.log("64");
+ // console.log(data);
+ this.setState({
+ unread_message_count:parseInt(data.unread_message_count),
+ unread_tiding_count:parseInt(data.unread_tiding_count),
+ })
+ };
+
+ //跳转到链接
+ Modifyur=(i,id)=>{
+ // console.log("跳转到链接1");
+ // console.log(i);
+ // console.log(item);
+ // console.log("跳转到链接2");
+ if(i<3){
+ this.setState({
+ routing:i,
+ });
+ if(i===1){
+ this.props.history.replace(`/messages/${this.props.current_user.login}/user_tidings`);
+ }
+ if(i===2){
+ this.props.history.replace(`/messages/${this.props.current_user.login}/private_messages`);
+ }
+
+ }else {
+ this.setState({
+ routing:i,
+ });
+ console.log("22222222222");
+ this.props.history.replace(`/messages/${this.props.current_user.login}/message_detail?target_ids=${id}`);
+ }
+
+ };
+ myCome=(e)=>{
+ window.location.href="/users/"+e.target.login;
+ }
+
+ myxiaoxisixintab=(i)=>{
+ if(i===1){
+ this.setState({
+ routing:1,
+ });
+ }
+ if(i===2){
+ this.setState({
+ routing:2,
+ });
+
+ }
+ if(i===3){
+ this.setState({
+ routing:3,
+ });
+ }
+ };
+ bindRef = ref => { this.child = ref };
+ homeworkendss1(child){
+ // console.log(child);
+ // // console.log(this.refs.childModel);
+ // console.log(child);
+ try {
+ child.getdatas();
+ }catch (e) {
+
+ }
+
+ //
+ }
+ homeworkendss2(child){
+ // console.log(child);
+ // // console.log(this.refs.childModel);
+ // console.log(child);
+ try {
+ child.getdatas2();
+ }catch (e) {
+
+ }
+
+ //
+ }
+ render() {
+ let{routing,unread_message_count,unread_tiding_count} =this.state;
+ // console.log(this.props);
+ // console.log(routing);
+ return (
+
+
+ {/*左边*/}
+
+ {/*头像*/}
+
+ {/*路由跳转*/}
+
+
+
+ {/*右边*/}
+
+
+ {/*/!*消息自路由*!/*/}
+ {/*{routing===1?this.Message2()}> :""}*/}
+
+ {/*/!*私信*!/*/}
+ {/*{routing===2?this.Message2()} Modifyur={(i,item)=>this.Modifyur(i,item)}> :""}*/}
+
+ {/*/!*私信聊天页面*!/*/}
+ {/*{routing===3?this.Message2()} Modifyur={(i)=>this.Modifyur(i)}> :""}*/}
+
+
+ {/*/!*消息自路由*! name 是 /message/info/:userid/*/}
+ (this.Message2()} Mtab={(i)=>this.myxiaoxisixintab(i)}> )
+ }
+ >
+ {/*/!*私信*! name 是letter/*/}
+ (this.Message2()} Modifyur={(i,item)=>this.Modifyur(i,item)} Mtab={(i)=>this.myxiaoxisixintab(i)}> )
+ }
+ >
+ {/*/!*私信聊天页面*! letters/*/}
+ (this.Message2()} Modifyur={(i)=>this.Modifyur(i)} Mtab={(i)=>this.myxiaoxisixintab(i)}> )
+ }
+ >
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
+export default SnackbarHOC() (TPMIndexHOC ( Messagerouting ));
\ No newline at end of file
diff --git a/public/react/src/modules/message/js/Rightdialogue.js b/public/react/src/modules/message/js/Rightdialogue.js
new file mode 100644
index 000000000..a414f5d52
--- /dev/null
+++ b/public/react/src/modules/message/js/Rightdialogue.js
@@ -0,0 +1,67 @@
+import React, { Component } from 'react';
+import {
+ Spin,
+ Pagination,
+} from "antd";
+import axios from 'axios';
+import moment from 'moment';
+import {getImageUrl,markdownToHTML,ImageLayerHook} from 'educoder';
+import "../css/messagemy.css"
+import WriteaprivateletterModal from '../messagemodal/WriteaprivateletterModal';
+//私信页面
+class Rightdialogue extends Component{
+ constructor(props) {
+ super(props);
+ this.state={
+ };
+
+ }
+
+ componentDidMount(){
+ // console.log("Rightdialogue");
+ // console.log(this.props);
+
+ };
+ componentDidUpdate(prevProps) {
+ // console.log("11111111111");
+ // console.log(prevProps);
+ // console.log("22222222222");
+ // console.log(this.props);
+ // console.log("33333333333");
+ // if(prevProps.current_user !== this.props.current_user){
+ // this.getdata(1);
+ // }
+ }
+ mydelete=(user_id,id)=>{
+ this.props.DELETEsetreplyfun(user_id,id);
+ }
+ myCome=(e)=>{
+ window.location.href="/users/"+e.login;
+ }
+
+ render() {
+
+ return (
+
+
this.myCome(this.props.objeysl.sender)}>
+ {this.props.objeysl&&this.props.objeysl.sender.image_url ?
+ :""
+ }
+
+
+
{moment(this.props.objeysl.send_time).hour()}:{moment(this.props.objeysl.send_time).minute()<10?"0"+moment(this.props.objeysl.send_time).minute():moment(this.props.objeysl.send_time).minute()}
+
+ )
+ }
+}
+export default Rightdialogue;
\ No newline at end of file
diff --git a/public/react/src/modules/message/messagemodal/WriteaprivateletterModal.js b/public/react/src/modules/message/messagemodal/WriteaprivateletterModal.js
new file mode 100644
index 000000000..dfa27ba9a
--- /dev/null
+++ b/public/react/src/modules/message/messagemodal/WriteaprivateletterModal.js
@@ -0,0 +1,356 @@
+import React, { Component } from 'react';
+import { Modal,Input,Icon,Tooltip,Spin} from 'antd';
+import axios from 'axios';
+// import '../../modules/user/common.css';
+import {getImageUrl} from 'educoder';
+//完善个人资料
+class WriteaprivateletterModal extends Component {
+
+ constructor(props) {
+ super(props)
+ this.state ={
+ modalsType:false,
+ Pleaseselectthesender:false,
+ Pleaseselectthesenders:false,
+ inputvulue:"",
+ inputvulues:"",
+ floatingboxdisplay:false,
+ users:[],
+ Personalid:undefined,
+ isSpin:false,
+ Recentcontacts:false,
+ floatingboxdisplays:false,
+
+ }
+
+ }
+ componentDidMount() {
+ //用户id
+ //console.log(this.props.current_user.user_id);
+ this.Recentcontacts();
+
+ }
+ //获取最近联系人
+ Recentcontacts=()=>{
+ this.setState({
+ isSpin:true
+ });
+ const url =`/users/${this.props.current_user.user_id}/recent_contacts.json`
+ axios.get(url).then((result) => {
+ if(result===undefined){
+ return
+ }
+ //console.log(result);
+ this.setState({
+ users:result.data.users,
+ Recentcontacts:false,
+ floatingboxdisplay:false,
+ isSpin:false
+ })
+ }).catch((error) => {
+ //console.log(error)
+ this.setState({
+ isSpin:false
+ })
+ })
+ };
+
+ //发送私信
+ SendprivatemessageAPI=(idvalue,contentvalue)=>{
+ const url =`/users/${this.props.current_user.user_id}/private_messages.json`
+ let data={
+ target_id:idvalue,
+ content:contentvalue,
+ }
+ axios.post(url, data).then((result) => {
+ if(result===undefined){
+ return
+ }
+ this.setState({
+ floatingboxdisplays:false,
+ Pleaseselectthesender:false,
+ });
+ this.props.smyJump(3,result.data.private_message.receiver_id);
+ //console.log(result);
+ }).catch((error) => {
+ //console.log(error)
+ })
+ };
+
+ //搜索私信人
+ Retrieveprivatemessageusers=(value)=>{
+ this.setState({
+ isSpin:true
+ })
+ const url =`/users_for_private_messages.json`
+ axios.get((url),{params:{
+ keyword:value,
+ }}).then((result) => {
+ if(result===undefined){
+ return
+ }
+ this.setState({
+ users:result.data.users,
+ Recentcontacts:true,
+ floatingboxdisplay:true,
+ isSpin:false
+ })
+ //console.log(result);
+ }).catch((error) => {
+ //console.log(error)
+ this.setState({
+ isSpin:false
+ })
+ })
+ };
+
+ modalCancel=()=>{
+ // var weekArray = JSON.parse(window.sessionStorage.getItem('yslgeturls'));
+ // if(weekArray===undefined){
+ // weekArray="/";
+ // }
+ // if(weekArray===null){
+ // weekArray="/";
+ // }
+ // if(weekArray==="null"){
+ // weekArray="/";
+ // }
+ // window.location.href = weekArray;
+ }
+
+ setDownload=()=>{
+ // window.location.href ='/account/profile';
+ };
+
+ // 搜索
+ search_message_person=()=>{
+ //console.log("点击搜索按钮");
+ if(this.state.inputvulue.length===0){
+ this.Recentcontacts();
+ }else {
+ this.Retrieveprivatemessageusers(this.state.inputvulue);
+
+ }
+ };
+
+ //取消事件
+ HideModal=()=>{
+ this.props.cancelmodalsType();
+ };
+
+ //确认事件
+ OKModal=()=>{
+ let{inputvulue,Personalid,inputvulues}=this.state;
+ // console.log("发送私信了");
+ // console.log(inputvulue);
+ // console.log(Personalid);
+ // console.log(inputvulues);
+ if(inputvulue.length===0){
+ this.setState({
+ Pleaseselectthesender:true
+ });
+ return;
+
+ }
+ if(inputvulues.length===0){
+ this.setState({
+ floatingboxdisplays:true
+ })
+ return;
+ }
+ else {
+ if(Personalid===undefined){
+ this.setState({
+ Pleaseselectthesender:true
+ });
+ return
+ }
+
+
+ this.SendprivatemessageAPI(Personalid,inputvulues)
+
+ }
+ };
+
+ // 回车事件
+ Myοnkeydοwn=()=>{
+ //console.log("点击了回车事件");
+ if(this.state.inputvulue.length===0){
+ this.Recentcontacts();
+ }else {
+ this.Retrieveprivatemessageusers(this.state.inputvulue);
+
+ }
+ };
+
+ //判断点击的键盘的keyCode是否为13,是就调用上面的搜索函数
+ handleEnterKey = (e) => {
+ //console.log("");
+ if(e.nativeEvent.keyCode === 13){ //e.nativeEvent获取原生的事件对像
+ this.Myοnkeydοwn()
+ }
+ };
+ // 查找联系人输入模式
+ setdatafunsval=(e)=>{
+ if(e.target.value.length===0){
+ this.setState({
+ inputvulue:e.target.value,
+ Pleaseselectthesender:false,
+ floatingboxdisplay:true,
+ Personalid:undefined
+ });
+ this.Recentcontacts();
+ }else {
+ this.setState({
+ inputvulue:e.target.value,
+ Pleaseselectthesender:false,
+ floatingboxdisplay:true,
+ });
+ }
+
+ //console.log(e.target.value);
+ };
+ // 输入内容
+ setdatafunsvals=(e)=>{
+ //console.log(e.target.value);
+ this.setState({
+ inputvulues:e.target.value,
+ Pleaseselectthesenders:false,
+ floatingboxdisplays:false,
+ floatingboxdisplay:false,
+ });
+ }
+ //失去焦点
+ myonBlur=(e)=>{
+ //console.log("失去焦点了");
+ e.preventDefault();
+ this.setState({
+ // floatingboxdisplay:false,
+ })
+};
+ //获取焦点
+ myonFocus=(e)=>{
+ //console.log("获取到焦点了");
+ this.setState({
+ floatingboxdisplay:true,
+ })
+ };
+
+ //获取用户信息
+ Getuserinformation=(item)=>{
+ //console.log("获取到了用户信息");
+ //console.log(item.id);
+ this.setState({
+ Personalid:item.id===undefined?undefined:item.id===null?undefined:item.id,
+ inputvulue:item.name,
+ floatingboxdisplay:false,
+ })
+ }
+
+
+ render() {
+
+ let{Pleaseselectthesender,inputvulue,inputvulues,floatingboxdisplay,users,floatingboxdisplays,Recentcontacts,isSpin}=this.state;
+ //console.log(floatingboxdisplay);
+ return(
+
+
+
+ {/*搜索框*/}
+ {/*
*/}
+ {/*
*/}
+ {/*
*/}
+ {/*
this.search_message_person()}/>*/}
+ {/*
*/}
+
+ this.search_message_person()}/>
+ }
+ />
+
+ {/*搜索框下面悬浮框*/}
+
+
+ {Recentcontacts===false?"最近联系人":"搜索结果"}
+
+ {
+ users.map((item,key)=>{
+ return(
+ this.Getuserinformation(item)}>
+
+ {item.name}
+
+ )
+ })
+ }
+
+ {/*
*/}
+ {/* */}
+ {/* 实践教学 */}
+ {/*
*/}
+ {/*
*/}
+ {/* */}
+ {/* innov */}
+ {/*
*/}
+
+
+
+
+
+ {/*私信内容*/}
+
+
+ 200
+
+
+ {
+ Pleaseselectthesender === true ?
+ 请选择发送对象
+ :(floatingboxdisplays ===false?
:"")
+ }
+ {
+ floatingboxdisplays===true?
+ 请输入发送内容
+ : ""
+ }
+ {/*确认事件*/}
+
+ this.HideModal()} className="pop_close task-btn mr30">取消
+ this.OKModal()} id="submit_send_letter">确定
+
+ {/**/}
+ {/*
*/}
+ {/*
*/}
+ {/*
*/}
+
+ )
+ }
+}
+
+export default WriteaprivateletterModal;
\ No newline at end of file
diff --git a/public/react/src/modules/modals/DownloadMessage.js b/public/react/src/modules/modals/DownloadMessage.js
index b7796316c..4655d7478 100644
--- a/public/react/src/modules/modals/DownloadMessage.js
+++ b/public/react/src/modules/modals/DownloadMessage.js
@@ -18,7 +18,7 @@ class DownloadMessage extends Component {
setDownload=()=>{
this.modalCancel();
- window.open(`/users/${this.props.user.login}/message_detail?user_id=1`)
+ window.open(`/messages/${this.props.user.login}/message_detail?target_ids=1`)
}
modalCancel = () => {
this.setState({
diff --git a/public/react/src/modules/modals/DownloadMessageysl.js b/public/react/src/modules/modals/DownloadMessageysl.js
index b5c23960a..549a1478a 100644
--- a/public/react/src/modules/modals/DownloadMessageysl.js
+++ b/public/react/src/modules/modals/DownloadMessageysl.js
@@ -11,7 +11,7 @@ class DownloadMessageysl extends Component {
setDownload=()=>{
this.props.modalCancel();
- window.open(`/users/${this.props.user.login}/message_detail?user_id=1`)
+ window.open(`/messages/${this.props.user.login}/message_detail?target_ids=1`)
}
render() {
diff --git a/public/react/src/modules/page/MainContentContainer.js b/public/react/src/modules/page/MainContentContainer.js
index 829b84b16..0211b3801 100644
--- a/public/react/src/modules/page/MainContentContainer.js
+++ b/public/react/src/modules/page/MainContentContainer.js
@@ -368,17 +368,20 @@ class MainContentContainer extends Component {
}
componentDidMount() {
-
-
- window.$(window.documents).bind("submitChoose",function(){
-
- alert("hello world!");
-
- });
-
-
-
+ // if (this.binded == true) {
+ // return;
+ // } else {
+ // this.binded = true
+ // window.$(window).unload( ()=>{
+ // alert(111)
+ // var fileUpdatePromise = this.doFileUpdateRequest(true)
+ // });
+ // }
+ }
+ componentWillUnmount() {
+ // window.$(window).off( "unload" )
}
+
doFileUpdateRequestOnCodeMirrorBlur = () => {
var fileUpdatePromise = this.doFileUpdateRequest(true)
diff --git a/public/react/src/modules/page/main/ActionView.js b/public/react/src/modules/page/main/ActionView.js
index d8638efb8..0a1faa7ea 100644
--- a/public/react/src/modules/page/main/ActionView.js
+++ b/public/react/src/modules/page/main/ActionView.js
@@ -51,6 +51,13 @@ class ActionView extends Component {
componentDidMount() {
// request
+ window._tpiWidthResize = () => {
+ if (window.$('#actionView').width() < 580) {
+ window.$('.time_limit').hide()
+ } else {
+ window.$('.time_limit').show()
+ }
+ }
}
showWebDisplay(challenge) {
@@ -59,10 +66,17 @@ class ActionView extends Component {
/*耗时:0 天 3 小时 11 分钟 57 秒 */
render() {
const { onRunCodeTest, onShowPrevStage, onShowNextStage, gameBuilding
- , game, classes, st, shixun, record, challenge } = this.props;
+ , game, classes, st, shixun, record, challenge, time_limit } = this.props;
return (
+
+ {!!time_limit &&
+ {`本关最大执行时间:${time_limit}秒`} }
{!gameBuilding && record ?
{ record } 秒
@@ -73,7 +87,10 @@ class ActionView extends Component {
{/*将第一个按钮改为visibility方式隐藏,不然加载时测评按钮会出现没有垂直居中的情况*/}
this.showWebDisplay(challenge)}
- style={{ visibility: challenge.showWebDisplayButton ? '': 'hidden'}} id="showWebDisplayButton">
+ style={{ visibility: challenge.showWebDisplayButton ? '': 'hidden'}}
+ id="showWebDisplayButton"
+ // style={{ display: challenge.showWebDisplayButton ? 'flex': 'none'}}
+ >
查看效果
diff --git a/public/react/src/modules/page/tpiPageForMobile.css b/public/react/src/modules/page/tpiPageForMobile.css
index 3f1c9364d..c30f40636 100644
--- a/public/react/src/modules/page/tpiPageForMobile.css
+++ b/public/react/src/modules/page/tpiPageForMobile.css
@@ -14,7 +14,7 @@
min-width: 280px;
}
- #time-consuming span{
+ #time-consuming .time_limit {
display: none;
}
.actionViewfirstButton {
diff --git a/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js b/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js
index e7a44a3b8..ba8655d9b 100644
--- a/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js
+++ b/public/react/src/modules/projectPackages/PackageIndex/PackageConcent.js
@@ -18,7 +18,7 @@ let categorylist=[
{name:"云计算和大数据",value:"cloud_compute_and_big_data"},
{name:"人工智能",value:"ai"},
{name:"运维与测试",value:"devops_and_test"},
- {name:"其他",value:"other"},
+ {name:"其它",value:"other"},
]
//
function setcategorylist(val){
@@ -30,7 +30,6 @@ function setcategorylist(val){
}
}
)
-
return vals
}
@@ -185,6 +184,17 @@ class PackageConcent extends Component {
})
}
+ onChangePagelist=(pageNum)=> {
+
+ this.setState({
+ page: pageNum
+ })
+ let {category, keyword, sort_by, sort_direction} = this.state;
+ this.setdatas(category, keyword, sort_by, sort_direction, pageNum)
+
+ }
+
+
render() {
let {data,page,category,sort_by,sort_direction,project_packages,
isRender,AccountProfiletype
@@ -270,7 +280,7 @@ class PackageConcent extends Component {
-
+
{project_packages&&project_packages.map((item,key)=>{
return(
@@ -286,7 +296,7 @@ class PackageConcent extends Component {
-
this.onReleaseRequirements("/crowdsourcing/"+item.id)}
title={item.title}
>{item.title}
@@ -294,7 +304,7 @@ class PackageConcent extends Component {
-
+
{item.min_price===null?"":
¥{item.min_price} }
{item.max_price===null||item.min_price===null?"":
~ }
{item.max_price===null?"":
¥{item.max_price} }
@@ -338,6 +348,7 @@ class PackageConcent extends Component {
)
})}
+
{project_packages&&project_packages.length===0?
@@ -345,7 +356,7 @@ class PackageConcent extends Component {
:""}
diff --git a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js
index a1e016853..60394d52b 100644
--- a/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js
+++ b/public/react/src/modules/projectPackages/PackageIndexNEITaskDetails/PackageIndexNEITaskDetails.js
@@ -55,9 +55,11 @@ class PackageIndexNEITaskDetails extends Component {
getdatas=()=>{
let url =`/project_packages/${this.props.match.params.id}.json`;
axios.get(url).then((response) => {
- this.setState({
- data:response.data
- })
+ if(response.data.status!=401&&response.data.status!=403&&response.data.status!=408&&response.data.status!=409)[
+ this.setState({
+ data:response.data
+ })
+ ]
}).catch((error) => {
console.log(error);
@@ -236,8 +238,12 @@ class PackageIndexNEITaskDetails extends Component {
render() {
let {overtype,data}=this.state;
- // console.log(data&&data.creator.login)
- console.log(data)
+ // console.log(data&&data.creator.id)
+ let datalogin=data&&data.creator.id;
+ let userlogin=this.props.current_user&&this.props.current_user.user_id;
+
+ console.log(datalogin===userlogin)
+ // console.log(this.props.current_user&&this.props.current_user.user_id)
return (
data===undefined?"":
@@ -258,11 +264,9 @@ class PackageIndexNEITaskDetails extends Component {
{data&&data.title}
-
返回
+
返回
-
-
-
+
@@ -289,12 +293,12 @@ class PackageIndexNEITaskDetails extends Component {
{data&&data.creator.name}
- {data&&data.creator.login===this.props.current_user&&this.props.current_user.login?"":
}
@@ -304,16 +308,16 @@ class PackageIndexNEITaskDetails extends Component {
-
+
- {data&&data.title}
-
+
{data&&data.min_price===null?"":
¥{data&&data.min_price} }
{data&&data.max_price===null||data&&data.min_price===null?"":
~ }
{data&&data.max_price===null?"":
¥{data&&data.max_price} }
@@ -405,9 +409,9 @@ class PackageIndexNEITaskDetails extends Component {
return(
diff --git a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js
index 493152def..ae4983b33 100644
--- a/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js
+++ b/public/react/src/modules/projectPackages/PackageIndexNewandEdit/PackageIndexNEIBannerConcent.js
@@ -189,10 +189,10 @@ class PackageIndexNEIBannerConcent extends Component {
//短信验证
SMSverification = () => {
let {contact_phone,code}=this.state;
- var url = `/account/get_verification_code.json`;
+ var url = `/accounts/get_verification_code.json`;
axios.get((url), {
params: {
- value: contact_phone,
+ login: contact_phone,
type: 5,
}
}).then((result) => {
diff --git a/public/react/src/modules/projectPackages/ProjectPackageIndex.js b/public/react/src/modules/projectPackages/ProjectPackageIndex.js
index 097e012e0..29d4efa17 100644
--- a/public/react/src/modules/projectPackages/ProjectPackageIndex.js
+++ b/public/react/src/modules/projectPackages/ProjectPackageIndex.js
@@ -36,7 +36,8 @@ class ProjectPackageIndex extends Component {
}
render() {
-
+console.log(this.props)
+ console.log(this.state)
return (
diff --git a/public/react/src/modules/projectPackages/packageconcnet.css b/public/react/src/modules/projectPackages/packageconcnet.css
index db2decfdd..f7ee4cc06 100644
--- a/public/react/src/modules/projectPackages/packageconcnet.css
+++ b/public/react/src/modules/projectPackages/packageconcnet.css
@@ -31,8 +31,8 @@
color:#8F8F8F !important;
}
-.maxwidth700{
- max-width: 700px;
+.maxwidth670{
+ max-width: 670px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -362,4 +362,8 @@
*, *::before, *::after {
-webkit-box-sizing: border-box;
box-sizing: border-box;
+}
+
+.mtf12{
+ margin-top: -12px;
}
\ No newline at end of file
diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js
index c2b5539fd..212b17036 100644
--- a/public/react/src/modules/tpm/NewHeader.js
+++ b/public/react/src/modules/tpm/NewHeader.js
@@ -934,7 +934,7 @@ submittojoinclass=(value)=>{
{
- startbtn === false ?
+ startbtn === false && shixunsDetails.shixun_status != -1 ?
发送至
@@ -874,9 +874,17 @@ class TPMBanner extends Component {
style={{width: '100%'}}
/>
+
12?"cdefault ":"cdefault "}>
-
+
{
@@ -913,7 +921,12 @@ class TPMBanner extends Component {
已关闭
}
- {this.props.identity < 8?已删除
+ }
+
+
+ {this.props.identity < 8&&shixunsDetails.shixun_status != -1 ?
.-task-title {
.HeaderSearch{
width: 325px;
+ /*right: 20px;*/
+}
+.HeaderSearch .ant-input-search{
+ right: 20px;
}
.mainheighs{
height: 100%;
diff --git a/public/react/src/modules/tpm/TPMIndexHOC.js b/public/react/src/modules/tpm/TPMIndexHOC.js
index 3b86fc092..bbb2eb97d 100644
--- a/public/react/src/modules/tpm/TPMIndexHOC.js
+++ b/public/react/src/modules/tpm/TPMIndexHOC.js
@@ -264,7 +264,10 @@ export function TPMIndexHOC(WrappedComponent) {
"is_teacher": false,
"tidding_count": 0
}
- */
+ */
+ if(response=== undefined){
+ return
+ }
if (response.data) {
this.initCommonState(response.data)
this.setState({
diff --git a/public/react/src/modules/tpm/TPMsettings/TPMsettings.js b/public/react/src/modules/tpm/TPMsettings/TPMsettings.js
index bb318ba13..2e34bcffb 100644
--- a/public/react/src/modules/tpm/TPMsettings/TPMsettings.js
+++ b/public/react/src/modules/tpm/TPMsettings/TPMsettings.js
@@ -727,6 +727,12 @@ export default class TPMsettings extends Component {
// });
// }
submit_edit_shixun = () => {
+
+ if(this.state.status===-1){
+ this.props.showSnackbar("该实训已被删除,保存失败!");
+ return
+ }
+
let {
name, choice_main_type, choice_small_type, choice_standard_scripts, scope_partment, choice_standard_scriptssum,
evaluate_script, webssh, use_scope, trainee, can_copy, task_pass, test_set_permission, hide_code, code_hidden, forbid_copy, vnc,multi_webssh,
@@ -739,13 +745,15 @@ export default class TPMsettings extends Component {
return v1
});
- let operateauthority=this.props.identity<5&&this.state.status==0||this.props.identity===1&&this.state.status==2||this.props.identity===1&&this.state.status==1;
+ // let operateauthority=
+ // this.props.identity===1?true:this.props.identity<5&&this.state.status==0?true:false;
+ // this.props.identity<5&&this.state.status==0||this.props.identity===1&&this.state.status==2||this.props.identity===1&&this.state.status==1;
const description_editormd = this.description_editormd.getValue();
let evaluate_script_editormd;
- if(operateauthority===true){
+ if(this.state.status==0||this.state.status==1||this.state.status==2&&this.props.identity===1){
// evaluate_script_editormd = this.evaluate_script_editormd.getValue();
evaluate_script_editormd = shixunmemoMDvalue
}else{
@@ -753,6 +761,7 @@ export default class TPMsettings extends Component {
}
+
if (name === "") {
this.setState({
shixunnametype: true
@@ -826,6 +835,7 @@ export default class TPMsettings extends Component {
if(newmulti_webssh===null){
newmulti_webssh=false
}
+
//exec_time: exec_time,
let Url = `/shixuns/` + id + `.json`;
let data = {
@@ -1303,7 +1313,7 @@ export default class TPMsettings extends Component {
@@ -1381,13 +1391,13 @@ export default class TPMsettings extends Component {
})
}
-
- 列表中没有?
- 申请新建
-
+ {/*
*/}
+ {/*列表中没有?*/}
+ {/*申请新建 */}
+ {/*
*/}
diff --git a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js
index 6cd0b9977..16c7cfedf 100644
--- a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js
+++ b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js
@@ -981,7 +981,7 @@ export default class TPMevaluation extends Component {
{pathoptionvalue===1||pathoptionvalue===5||pathoptionvalue===6?
-
待处理图片路径
+
待处理文件路径
-
标准答案图片路径
+
标准答案文件路径
实名认证
-
有些课程需要实名认证才能加入哟,还能获得500金币的奖励~
+
实名认证可以增强你在平台的江湖地位,还可以获得500金币的奖励~
{
basicInfo && basicInfo.authentication =="uncertified" ?
@@ -96,7 +96,10 @@ class AccountCertification extends Component {
职业认证
-
教师认证完毕之后,可创建课堂、发布实训、免金币查看所有实训答案..
+
+ {basicInfo && (basicInfo.identity == "teacher"
+ ?
教师通过认证,可以克隆实训、免金币查看实训答案和隐藏测试集...
+ :
通过认证,可以获得500金币的奖励~
)}
{
basicInfo && basicInfo.professional_certification =="uncertified" ?
diff --git a/public/react/src/modules/user/common.css b/public/react/src/modules/user/common.css
index d23412d07..6d696a676 100644
--- a/public/react/src/modules/user/common.css
+++ b/public/react/src/modules/user/common.css
@@ -264,5 +264,5 @@
margin: 0 auto;
}
.ant-input-affix-wrapper .ant-input-prefix, .ant-input-affix-wrapper .ant-input-suffix {
- background: #ffffff!important;
+ background: transparent !important;
}
\ No newline at end of file
diff --git a/public/react/src/modules/user/usersInfo/Infos.js b/public/react/src/modules/user/usersInfo/Infos.js
index 5286c5797..343f8ac59 100644
--- a/public/react/src/modules/user/usersInfo/Infos.js
+++ b/public/react/src/modules/user/usersInfo/Infos.js
@@ -357,7 +357,7 @@ class Infos extends Component{
:
}
diff --git a/public/react/src/modules/user/usersInfo/InfosPackage.js b/public/react/src/modules/user/usersInfo/InfosPackage.js
index f2716a064..0355e2d76 100644
--- a/public/react/src/modules/user/usersInfo/InfosPackage.js
+++ b/public/react/src/modules/user/usersInfo/InfosPackage.js
@@ -4,7 +4,8 @@ import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
import {Tooltip,Menu,Pagination,Spin} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
-import NoneData from '../../courses/coursesPublic/NoneData'
+import Modals from '../../modals/Modals';
+import NoneData from '../../courses/coursesPublic/NoneData';
import "./usersInfo.css"
import moment from 'moment';
let categorylist=[
@@ -113,6 +114,38 @@ class InfosPackage extends Component{
}
}
+
+ delectprojectModal=(id)=>{
+ this.setState({
+ Modalstype: true,
+ Modalstopval: '是否确认删除?',
+ ModalSave: () => this.delectproject(id),
+ ModalCancel: this.cancelProject
+ })
+ }
+
+ cancelProject=()=>{
+ this.setState({
+ Modalstype: false,
+ })
+ }
+
+ delectproject=(id)=>{
+
+ let {category,status}=this.state;
+ debugger
+ let url=`/project_packages/${id}.json`
+
+ axios.delete(url).then((response) => {
+ if (response.data.status == 0) {
+ this.getCourses(category,status,1);
+ }
+ })
+ .catch(function (error) {
+ console.log(error);
+ });
+ this.cancelProject();
+ }
render(){
let{
category,
@@ -127,6 +160,13 @@ class InfosPackage extends Component{
// console.log(data)
return(
+ {/*提示*/}
+
this.changeCategory()}>全部
@@ -160,23 +200,29 @@ class InfosPackage extends Component{
{/*type: "bidden"*/}
-
{data===undefined?
:data.project_packages.length===0?
:data.project_packages.map((item,key)=>{
return(
-
+
+
+
+
+ {item.bidden_status==="pending"?竞标中 :""}
+ {item.bidden_status==="bidding_won"?已中标 :""}
+ {item.bidden_status==="bidding_lost"?未中标 :""}
+
-
+
{item.min_price===null?"":¥{item.min_price} }
{item.max_price===null||item.min_price===null?"":~ }
{item.max_price===null?"":¥{item.max_price} }
@@ -199,11 +245,34 @@ class InfosPackage extends Component{
{item.bidding_users_count}人竞标
-
- 发布于:{moment(item.published_at).format("YYYY-MM-DD HH:mm")}
+
+ {item.published_at===null?更新于:{moment(item.updated_at).format("YYYY-MM-DD HH:mm")} :
+ 发布于:{moment(item.published_at).format("YYYY-MM-DD HH:mm")} }
+
+ {category=="manage"?item.operation.can_edit===true&&item.operation.can_delete===true?
+
:"":""}
+
+ {category=="manage"?item.operation.can_edit===true&&item.operation.can_delete===false?
+
:"":""}
+
+
)})}
diff --git a/public/react/src/modules/user/usersInfo/InfosPath.js b/public/react/src/modules/user/usersInfo/InfosPath.js
index d23739280..b7038b0e9 100644
--- a/public/react/src/modules/user/usersInfo/InfosPath.js
+++ b/public/react/src/modules/user/usersInfo/InfosPath.js
@@ -164,11 +164,14 @@ class InfosPath extends Component{
- {item.name}
+ {item.name}
- {item.owner_name}
+ 12 ? item.owner_name : ''} style={{ maxWidth: '198px'}}
+ >{item.owner_name}
diff --git a/public/react/src/modules/user/usersInfo/usersInfo.css b/public/react/src/modules/user/usersInfo/usersInfo.css
index 0be9837bf..25cfd6e21 100644
--- a/public/react/src/modules/user/usersInfo/usersInfo.css
+++ b/public/react/src/modules/user/usersInfo/usersInfo.css
@@ -1,93 +1,122 @@
-.navInfo{
- border:none!important;
- position: absolute;
- width: 100%;
- bottom: -8px;
-}
-.navInfo li {
- float: left;
- margin: 0px 40px;
- padding:0px;
- height: 45px;
- line-height: 40px;
- font-size: 16px;
- position: relative;
-}
-.navInfo li.active::after{
- position: absolute;
- left: 0px;
- height: 2px;
- width: 100%;
- content: '';
- bottom: 0px;
- background: #05101A!important;
- color: #666!important;
-}
-.navInfo li,.navInfo li.ant-menu-item-active{
- border-bottom: none!important;
- color: #666!important;
-}
-.navInfo li.ant-menu-item-selected{
- border-bottom: 2px solid #05101A!important;
- color: #05101A!important;
-}
-.navInfo ul.ant-menu{float: left!important;border:none!important;}
-
-.substancenenew{
- width: 236px;
- height: 206px;
- background: rgba(248,248,248,1);
- border: 2px dotted rgba(225,225,225,1);
- opacity: 1;
- border-radius: 4px;
- padding-top: 50px;
- position: inherit;
-}
-
-.substancepad{
- padding: 20px 20px 0px 20px;
- border-bottom: 1px solid transparent;
-}
-.substancefont{
- height:24px;
- font-size:18px;
- font-family:Microsoft YaHei;
- font-weight:400;
- line-height:21px;
- color:rgba(153,153,153,1);
- opacity:1;
- margin-top: -8px;
-}
-.topten{
- width: 1px;
- height: 100px;
- border: 2px soild rgba(225,225,225,1);
- background: rgba(225,225,225,1);
- border: 1px solid rgba(225,225,225,1);
- margin: 0 auto;
-}
-.leftten{
- width: 100px;
- height: 1px;
- background: rgba(225,225,225,1);
- border: 1px solid rgba(225,225,225,1);
- margin: 0px auto;
- position: absolute;
- top: 120px;
- left: 88px;
-}
-.squarebox{
- position: absolute;
- top: 0px;
- left: 0px;
-}
-
-/*题库的标签--和资源标签样式相似*/
-.bankTag{max-height: 82px;overflow-y: auto}
-.bankTag #sourceTag li{margin-left: 0px;margin-right: 5px;}
-.bank_list_Tag{cursor: default}
-/*资源标签*/
-#sourceTag li,.bank_list_Tag{font-size: 12px;color: #4E7A9B;background-color: #E5F3FF;padding: 0px 4px;height: 20px;line-height: 20px; margin-left: 5px;display: inline-block;cursor: pointer;margin-bottom: 5px;}
-#sourceTag li a{color: #4e7a9b!important;}
-#sourceTag li.active{background-color: #4CACFF;color: #fff;}
-#sourceTag li.active a{background-color: #4CACFF;color: #fff!important;}
\ No newline at end of file
+.navInfo{
+ border:none!important;
+ position: absolute;
+ width: 100%;
+ bottom: -8px;
+}
+.navInfo li {
+ float: left;
+ margin: 0px 40px;
+ padding:0px;
+ height: 45px;
+ line-height: 40px;
+ font-size: 16px;
+ position: relative;
+}
+.navInfo li.active::after{
+ position: absolute;
+ left: 0px;
+ height: 2px;
+ width: 100%;
+ content: '';
+ bottom: 0px;
+ background: #05101A!important;
+ color: #666!important;
+}
+.navInfo li,.navInfo li.ant-menu-item-active{
+ border-bottom: none!important;
+ color: #666!important;
+}
+.navInfo li.ant-menu-item-selected{
+ border-bottom: 2px solid #05101A!important;
+ color: #05101A!important;
+}
+.navInfo ul.ant-menu{float: left!important;border:none!important;}
+
+.substancenenew{
+ width: 236px;
+ height: 206px;
+ background: rgba(248,248,248,1);
+ border: 2px dotted rgba(225,225,225,1);
+ opacity: 1;
+ border-radius: 4px;
+ padding-top: 50px;
+ position: inherit;
+}
+
+.substancepad{
+ padding: 20px 20px 0px 20px;
+ border-bottom: 1px solid transparent;
+}
+.substancefont{
+ height:24px;
+ font-size:18px;
+ font-family:Microsoft YaHei;
+ font-weight:400;
+ line-height:21px;
+ color:rgba(153,153,153,1);
+ opacity:1;
+ margin-top: -8px;
+}
+.topten{
+ width: 1px;
+ height: 100px;
+ border: 2px soild rgba(225,225,225,1);
+ background: rgba(225,225,225,1);
+ border: 1px solid rgba(225,225,225,1);
+ margin: 0 auto;
+}
+.leftten{
+ width: 100px;
+ height: 1px;
+ background: rgba(225,225,225,1);
+ border: 1px solid rgba(225,225,225,1);
+ margin: 0px auto;
+ position: absolute;
+ top: 120px;
+ left: 88px;
+}
+.squarebox{
+ position: absolute;
+ top: 0px;
+ left: 0px;
+}
+
+/*题库的标签--和资源标签样式相似*/
+.bankTag{max-height: 82px;overflow-y: auto}
+.bankTag #sourceTag li{margin-left: 0px;margin-right: 5px;}
+.bank_list_Tag{cursor: default}
+/*资源标签*/
+#sourceTag li,.bank_list_Tag{font-size: 12px;color: #4E7A9B;background-color: #E5F3FF;padding: 0px 4px;height: 20px;line-height: 20px; margin-left: 5px;display: inline-block;cursor: pointer;margin-bottom: 5px;}
+#sourceTag li a{color: #4e7a9b!important;}
+#sourceTag li.active{background-color: #4CACFF;color: #fff;}
+#sourceTag li.active a{background-color: #4CACFF;color: #fff!important;}
+
+.mtf15{
+ margin-top:-15px;
+}
+
+.project-package-item.with-operator .item-operator {
+ width: 0;
+ transition: width .2s;
+ -moz-transition: width .2s; /* Firefox 4 */
+ -webkit-transition: width .2s; /* Safari 和 Chrome */
+ -o-transition: width .2s; /* Opera */
+}
+.project-package-item.with-operator:hover .item-operator {
+ margin: -20px -20px -20px 20px;
+ padding: 20px 0;
+ width: 100px;
+ display: flex;
+ justify-content: space-around;
+ flex-direction: column;
+ align-items: center;
+ background: #f0f0f0;
+}
+.project-package-item.with-operator .item-operator a {
+ display: none;
+}
+.project-package-item.with-operator:hover .item-operator a {
+ display: block;
+ font-size: 20px;
+}
\ No newline at end of file
diff --git a/public/react/src/search/SearchPage.js b/public/react/src/search/SearchPage.js
index ccdb9e12a..68efca036 100644
--- a/public/react/src/search/SearchPage.js
+++ b/public/react/src/search/SearchPage.js
@@ -150,9 +150,9 @@ class SearchPage extends Component{
- 开发社区
- 实践课程
- 翻转课堂
+ 实践课程
+ 翻转课堂
+ 开发社区
交流问答
diff --git a/public/stylesheets/educoder/edu-all.css b/public/stylesheets/educoder/edu-all.css
index fa879a9e5..1889df4a5 100644
--- a/public/stylesheets/educoder/edu-all.css
+++ b/public/stylesheets/educoder/edu-all.css
@@ -580,7 +580,7 @@ p .activity-item:first-child{border-top: 1px solid #eee;}
.recently_name{float: left;line-height: 48px;display: block}
.recently_item:hover{background-color: #F9F9F9;}
/*私信对话框*/
-.private-list{min-height: 660px;max-height: 810px;overflow-y: auto}
+.private-list{min-height: 660px;max-height: 831px;overflow-y: auto;overflow-x: hidden;}
.private-list .private-part{padding-left:20px;cursor: pointer}
.private-part:hover{background-color: #F5F5F5;}
.private-part.active{background-color: #F5F5F5;}
@@ -3122,7 +3122,7 @@ a.singlepublishtwo{
height: 40px;
}
.project-package-item .item-head-title {
- max-width: 700px;
+ max-width: 650px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -3213,7 +3213,7 @@ a.singlepublishtwo{
font-size: 20px;
}
.project-package-item.with-operator:hover .item-head-title {
- max-width: 600px;
+ max-width: 650px;
}
.list-count {
diff --git a/spec/jobs/commit_exercsie_notify_job_job_spec.rb b/spec/jobs/commit_exercsie_notify_job_job_spec.rb
new file mode 100644
index 000000000..17894c9ad
--- /dev/null
+++ b/spec/jobs/commit_exercsie_notify_job_job_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe CommitExercsieNotifyJobJob, type: :job do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/jobs/commit_poll_notify_job_job_spec.rb b/spec/jobs/commit_poll_notify_job_job_spec.rb
new file mode 100644
index 000000000..da292f7fb
--- /dev/null
+++ b/spec/jobs/commit_poll_notify_job_job_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe CommitPollNotifyJobJob, type: :job do
+ pending "add some examples to (or delete) #{__FILE__}"
+end