Files
2025-03-25 17:45:16 +08:00

636 lines
27 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
$(function(){
var Cookie = {
/**
* 获取指定名称的Cookie值
* @param {string} name - Cookie名称
* @returns {string|null} - 返回Cookie值如果不存在则返回null
*/
get: function(name){
var carr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
if (carr != null){
return decodeURIComponent(carr[2]);
}
return null;
},
/**
* 设置Cookie
* @param {string} name - Cookie名称
* @param {string} value - Cookie值
* @param {number} expires - 过期时间(以毫秒为单位)
* @param {string} path - Cookie路径
* @param {string} domain - Cookie域
*/
set:function(name, value, expires, path, domain){
if(expires){
expires = new Date(+new Date() + expires);
}
var tempcookie = name + '=' + escape(value) +
((expires) ? '; expires=' + expires.toGMTString() : '') +
((path) ? '; path=' + path : '') +
((domain) ? '; domain=' + domain : '');
//Ensure the cookie's size is under the limitation
if(tempcookie.length < 4096) {
document.cookie = tempcookie;
}
},
/**
* 清除指定名称的Cookie
* @param {string} name - Cookie名称
* @param {string} path - Cookie路径
* @param {string} domain - Cookie域
*/
clear: function (name, path, domain) {
if (this.get(name)) {
document.cookie = name + "=" + ((path) ? "; path=" + path : "; path=/") + ((domain) ? "; domain=" + domain : "") + ";expires=Fri, 02-Jan-1970 00:00:00 GMT";
}
}
};
// 从页面中读取阅读设置选项
var $settings = $("#pageReadOpt")
var data = {
isLogin: book.uid, // 用户是否登录
isPublish: $settings.data("book-publish") == "0" ? 0 : 1, // 书籍是否已发布
salesMode: $settings.data("sale-modes") == "2" ? 1 : 0, // 销售模式
hasSub: $settings.data("has-sub") == "0" ? 0 : 1, // 是否有订阅
settingsStr: $settings.data("settingsStr"), // 设置字符串(可能包含阅读配置)
chapterUrl: book.chapterUrl, // 当前章节的URL
endUrl: book.url, // 书籍结束时的URL
book: book.Info, // 书籍信息
chapters: (function() {
var chapters = {};
chapters[book.chapter.id] = book.chapter; // 初始化章节数据
return chapters;
})(),
chapter: book.chapter, // 当前章节信息
scrollLastChapter: book.chapter, // 上次滚动到的章节
lastOfflineChapterId: null, // 最近离线章节的ID
isInBookShelf: 0, // 是否在书架中
catalog: null // 书籍目录
};
/**
* 检查是否处于离线状态
* @returns {boolean} - 如果离线则返回true否则返回false
*/
var isOffline = function() {
return navigator && navigator.onLine === false;
};
/**
* Book对象包含书籍阅读相关的功能
*/
var Book = {
// 初始化书籍阅读功能
init: function () {
var that = this;
that.winHeight = $(window).height(); // 获取窗口高度
that.forbidCopy(); // 禁止复制、剪切和右键功能
this.initOptionsLayer(); // 初始化选项层
this.initCatalogAside(); // 初始化目录
this.initChapterProgress(); // 初始化章节进度
this.initFontSizeSetting(); // 初始化字体大小设置
this.initSkinSetting(); // 初始化皮肤设置
this.initModeSetting(); // 初始化阅读模式设置
this.initDayNightSetting(); // 初始化日夜模式切换
this.initModes(); // 初始化阅读模式(滚动/滑动)
if ($("#pageRead").hasClass("H")) {
this.swipeReader.enable(); // 启用滑动阅读模式
} else {
this.scrollReader.enable(); // 启用滚动阅读模式
}
},
/*
* 禁止页面选中文字、copy、右键功能
* @method forbidCopy
*/
forbidCopy: function () {
//禁止copy
$('body').on('copy', function () {
return false;
});
//禁止cut
$('body').on('cut', function () {
return false;
});
//禁止鼠标右键默认弹窗
$('body').on('contextmenu', function () {
return false;
});
},
// 初始化选项层
initOptionsLayer: function() {
var $layer = $("#pageReadOpt");
var $settingsMenu = $("#readBtnMore");
$layer.on({
click: function(event) {
var target = event.target;
if (target !== this || target.avoidClick) {
return;
}
var $activeLayer = $layer.find(".jsLayerTrigger.active");
if ($activeLayer.length) {
$activeLayer.trigger("click");
}
$layer.removeClass("active");
},
touchstart: function(event) {
this.flagMoveHide = event.target === this;
},
touchmove: function(event) {
if (this.flagMoveHide) {
$layer.trigger("click");
}
event.preventDefault();
}
});
new Toggle($settingsMenu);
var $layerTrigger = $(".jsLayerTrigger");
$layerTrigger.on("click", function(event) {
var self = this;
if (event && (event.isTrusted === false || event.hasOwnProperty("_args") || event.pageY === 0 && event.screenY === 0)) {
return;
}
$layerTrigger.each(function() {
var $this = $(this);
if (this !== self && $this.hasClass("active")) {
$this.trigger("click");
}
});
});
},
// 初始化目录
initCatalogAside: function() {
var self = this;
$("#readBtnChapter").aside({
scrollable: "#catelogX",
onInit: function() {
var aside = this;
//var layer_index=layer.open({type: 2,content: '加载中'});
// $.ajax({ type : "get", url : "/home/chapter/lists",
// data : {id: data.book.Id},
// async : false,
// success : function(result){
// layer.close(layer_index);
// $("#asideChapterContent").html(result);
// $("#asideChapterContent").on("click", ".jsChapter a", function(event) {
// event.preventDefault();
// aside.hide();
// $("#pageReadOpt").trigger("click");
// self.jumpChapter($(this).data("chapter-id"), true);
// });
// }
// });
},
onShow: function() {
var nowChapterId = data.chapter.id,chapterDom = $('[data-chapter-id="'+nowChapterId+'"]');
$('#catelogX').find('.chapter-index.red').removeClass('red');
chapterDom.find('.chapter-index').addClass('red');
$('#catelogX').scrollTop(0).scrollTop(chapterDom.offset().top - $('#catelogX').offset().top);
}
});
},
// 初始化章节进度
initChapterProgress: function() {
var self = this;
var $toggle = $("#readBtnProg");
var range;
var chapterIds = [];
var chapters = {};
function refresh(chapterId) {
var chapterIndex = chapterIds.indexOf(chapterId);
if (chapterIndex < 0) {
chapterIndex = 0;
chapterId = chapterIds[chapterIndex];
}
var chapterName = chapters[chapterId];
var $currentChapter = $("#readProgVal");
$currentChapter.find("h4").html(chapterName);
$currentChapter.find("output").html((chapterIndex * 100 / chapterIds.length).toFixed(1) + "%");
}
function init(result) {
$(result).find('.chapter-li-a').each(function(){
var chapter_id = $(this).data('chapter-id');
chapterIds.push(chapter_id);
chapters[chapter_id] = $(this).text();
});
refresh(data.chapter.id);
var $chapterProgressRange = $("#readProgRange");
$chapterProgressRange.attr("max", chapterIds.length - 1);
$chapterProgressRange.val(chapterIds.indexOf(data.chapter.id));
$chapterProgressRange.on("change", function() {
var chapterId = chapterIds[this.value];
refresh(chapterId);
});
range = new Range($chapterProgressRange, {
shadow: true,
buttons: [ "#readProgPrev", "#readProgNext" ],
onChangeEnd: function() {
var chapterId = chapterIds[$chapterProgressRange.val()];
self.jumpChapter(chapterId, true);
},
});
range.shadow();
}
new Toggle($toggle, {
callback: function() {
if (range) {
range.value(chapterIds.indexOf(data.chapter.id));
range.shadow();
}
}
});
$toggle.one("click", function() {
if ($('catelogX').length != 0) {
init($('#asideChapterContent').html());
} else {
var $el = $("#readOptProg").css("opacity", 0);
var layer_index=layer.open({type: 2,content: '加载中'});
$.getJSON("/home/chapter/lists", {
id: data.book.Id
}, function(result) {
layer.close(layer_index);
$el.css("opacity", 1);
init(result);
});
}
});
},
// 初始化字体大小设置
initFontSizeSetting: function() {
var self = this;
var $toggle = $("#readBtnSet");
var $range = $("#readFontRange");
var $chapterContent = $("#chapterContent");
var lazyHandler = debounce(function(val, e) {
self.scrollReader.refresh();
self.swipeReader.refresh();
self.updateSettings({
fs: val
});
}, 300);
new Toggle($toggle);
new Range($range, {
buttons: [ "#readFontDown", "#readFontUp" ]
});
$range.on("change", function(e) {
var val = this.value;
var rem = (val * 2 + 12) / 16;
$chapterContent.css("font-size", rem + "rem");
lazyHandler(val, e);
});
},
// 初始化皮肤设置
initSkinSetting: function() {
var self = this;
var $body = $("body");
var $dn = $("#readBtnMode"); // 获取日夜模式按钮
var lazyHandler = debounce(function(val) {
self.updateSettings({
skin: val // 更新皮肤设置
});
}, 300); // 防抖处理延迟300ms执行
$("#readSetSkin").on("click", '[type="radio"]', function(){
var $this = $(this);
$body.removeClass("read-night"); // 移除夜间模式
$body.attr("class", $body.attr("class").replace(/skin-[a-z]+/g, "skin-" + $this.val())); // 替换皮肤样式
if ($dn.data("mode") === "day") {
$dn.trigger("click"); // 如果是白天模式,触发点击切换
}
lazyHandler($this.data("index")); // 调用防抖函数更新皮肤
});
},
// 更新阅读设置
initModeSetting: function() {
var self = this;
var lazyHandler = debounce(function(val){
self.updateSettings({
vh: val
});
}, 300);
$("#readSetLayout").on("click", '[type="radio"]', function() {
if (this.value === "v") {
$("#pageRead").removeClass("H");
self.scrollReader.enable();
self.swipeReader.disable();
self.jumpChapter(data.chapter.id);
} else {
$("#pageRead").addClass("H");
self.scrollReader.disable();
self.swipeReader.enable();
self.jumpChapter(data.chapter.id);
}
lazyHandler(this.value);
});
},
// 初始化日夜模式切换
initDayNightSetting: function() {
var self = this;
var $body = $("body");
var $btn = $("#readBtnMode");
var $title = $btn.find("h4");
var DAY = "day";
var NIGHT = "night";
var lazyHandler = debounce(function(val) {
self.updateSettings({
dn: val
});
}, 300);
$btn.on("click", function() {
var mode = $btn.data("mode");
if (mode === DAY) {
$btn.data("mode", NIGHT);
$title.html($title.html().replace("日", "夜"));
$body.removeClass("read-night");
var skin = $body.attr("class").match(/skin-([a-z]+)/);
if (skin) {
skin = skin[1];
$('#readSetSkin [type="radio"][value="' + skin + '"]').prop("checked", true);
}
lazyHandler("d");
} else if (mode === NIGHT) {
$btn.data("mode", DAY);
$title.html($title.html().replace("夜", "日"));
$body.addClass("read-night");
$('#readSetSkin [type="radio"]').each(function() {
var $this = $(this);
if ($this.prop("checked")) {
$this.prop("checked", false);
}
});
lazyHandler("n");
}
});
},
// 初始化阅读模式(滚动/滑动)
initModes: function() {
var self = this;
var $goEnd = $("#aGotoBookEnd");
// 当前章节id
function isChapterShown(chapterId) {
return $(".jsChapterWrapper").map(function() {
return $(this).data("chapter-id");
}).indexOf(chapterId) > -1;
}
var scrollReader = this.scrollReader = new ScrollReader({
wrapperSelector: "#readContent",
prevSelector: "#readLoadPrev",
nextSelector: "#readLoadNext",
nextTriggerSelector: "#btnLoadNextChapter",
markSelector: "#readPageMark",
onPrevClick: function(e) {
//点击向前滚动
},
onCenterClick: function() {
$settings[0].avoidClick = true;
setTimeout(function() {
$settings[0].avoidClick = false;
}, 500);
$settings.addClass("active");
},
onNextClick: function(e) {
//点击向后滚动
},
onScroll: function(y) {
var isViewportChapterId;
scrollReader.$wrapper.find(".jsChapterWrapper").each(function() {
if (isViewportChapterId) {
return;
}
var $this = $(this);
var offset = $this.offset();
if (offset.top < y && offset.top + offset.height > y) {
isViewportChapterId = $this.data("chapter-id");
}
});
if (isViewportChapterId) {
self.setReadChapter(isViewportChapterId);
}
},
onScrollPrev: function(resolve, reject) {
var chapterId = data.chapter.prevId;
if (chapterId) {
self.jumpChapter(chapterId, false, resolve, reject);
} else {
layer.open({content:'已经是第一章了',skin:'msg',time:2});
reject();
}
},
onScrollNext: function(resolve, reject) {
var chapterId = data.scrollLastChapter.nextId;
if (chapterId) {
self.getChapter(chapterId, false, function(result) {
data.scrollLastChapter = result.data.chapterInfo;
if (!isChapterShown(chapterId)) {
$("#chapterContent").append('<section class="read-section jsChapterWrapper" data-chapter-id="'+result.data.chapterInfo.id+'"><h3>'+result.data.chapterInfo.title+'</h3>'+result.data.chapterInfo.content+'</section>');
if (data.scrollLastChapter.nextId) {
scrollReader.$nextTrigger.show();
$goEnd.hide();
} else {
scrollReader.$nextTrigger.hide();
$goEnd.show();
}
resolve();
} else {
reject();
}
}, reject);
}
},
onWillScrollNext: function(resolve, reject) {
var chapterId = data.scrollLastChapter.nextId;
if (chapterId && !(data.scrollLastChapter.vipStatus && $("#swiChk1").prop("checked"))) {
self.getChapter(chapterId, false, function(result) {
data.scrollLastChapter = result.data.chapterInfo;
if (!isChapterShown(chapterId)) {
$("#chapterContent").append('<section class="read-section jsChapterWrapper" data-chapter-id="'+result.data.chapterInfo.id+'"><h3>'+result.data.chapterInfo.title+'</h3>'+result.data.chapterInfo.content+'</section>');
if (data.scrollLastChapter.nextId) {
scrollReader.$nextTrigger.show();
$goEnd.hide();
} else {
scrollReader.$nextTrigger.hide();
$goEnd.show();
}
resolve();
} else {
reject();
}
}, reject);
} else {
reject();
}
}
});
this.swipeReader = new SwipeReader({
wrapperSelector: "#readContent",
scrollerSelector: ".jsChapterWrapper",
pagerSelector: "#pageNum",
onCenterClick: function() {
$settings[0].avoidClick = true;
setTimeout(function() {
$settings[0].avoidClick = false;
}, 500);
$settings.addClass("active");
},
onSwipePrev: function(resolve, reject) {
var chapterId = data.chapter.prevId;
if (chapterId) {
self.jumpChapter(chapterId, false, resolve, reject);
} else {
layer.open({content:'已经是第一章了',skin:'msg',time:2});
reject();
}
},
onSwipeNext: function(resolve, reject) {
var chapterId = data.chapter.nextId;
if (chapterId) {
self.jumpChapter(chapterId, false, resolve, reject);
}else{
location.href = data.endUrl;
}
},
onWillSwipeNext: function(resolve, reject) {
var chapterId = data.chapter.nextId;
if (chapterId) {
self.getChapter(chapterId, false, resolve, reject);
} else {
reject();
}
}
});
},
// 开始章节
jumpChapter: function(chapterId, isShowLoading, resolve, reject) {
var self = this;
if (!history.replaceState) {
location.href = data.chapterUrl.replace("chapterId", chapterId);
} else {
self.getChapter(chapterId, isShowLoading, function(result) {
var chapter = result.data.chapterInfo;
data.chapter = data.scrollLastChapter = chapter;
if (chapter.nextId) {
$("#btnLoadNextChapter").show();
$("#aGotoBookEnd").hide();
} else {
$("#btnLoadNextChapter").hide();
$("#aGotoBookEnd").show();
}
$("#chapterTitle").html(chapter.title);
$("#chapterContent").html('<section class="read-section jsChapterWrapper" data-chapter-id="'+chapter.id+'"><h3>'+chapter.title+'</h3>'+chapter.content+'</section>');
self.updateReadProgress();
history.replaceState(null, null, data.chapterUrl.replace("chapterId", chapterId));
if ($.isFunction(resolve)) {
resolve();
} else if (self.scrollReader.enabled) {
self.scrollReader.restart();
} else if (self.swipeReader.enabled) {
self.swipeReader.restart();
}
}, reject || function() {});
}
},
updateSettings: function(settings) {
$.each(settings, function(key, value) {
data.settingsStr = data.settingsStr.replace(new RegExp(key + ":[^|]+"), key + ":" + value);
});
var settingsStr = data.settingsStr.replace(/[^:|]+:/g, "");
Cookie.set('reader_config_wap', settingsStr, 86400000 * 365, '/');
},
updateReadProgress: function() {
if (isOffline()) {
return;
}
if(!data.isLogin){
return;
}
//更新阅读记录
// $.get("/user/Chapter/UpdRead", {
// bookId: data.book.bookId,
// chapterId: data.chapter.chapterId,
// chapterName: data.chapter.chapterName
// });
},
getChapter: function(chapterId, isShowLoading, resolve, reject) {
var self = this;
var layer_index;
if (isOffline()) {
$("#readLoadNext").css("opacity", 1);
}
if (data.chapters[chapterId]) {
resolve({
data: {
bookInfo: data.book,
chapterInfo: data.chapters[chapterId]
}
});
} else {
if (isOffline()) {
if (data.chapter.chapterId === data.lastOfflineChapterId) {
$("#readLoadNext").css("opacity", 0);
layer.open({content:'已显示全部离线章节',skin:'msg',time:2});
}
return reject();
}
if (isShowLoading) {
layer_index=layer.open({type: 2,content: '加载中'});
}
$.getJSON("/home/chapter/info", {id: book.chapter.source_id , key: chapterId}, function(result) {
if (isShowLoading) {
layer.close(layer_index);
}
if (result.code === 1) {
var chapter = {
id : result.data.chapter.id,
title:result.data.chapter.title,
vipStatus : 0,
content : result.data.chapter.content,
prevId : result.data.chapter.prev.id,
nextId : result.data.chapter.next.id
};
data.chapters[chapter.id] = chapter;
data.book = {
"Id": result.data.id,
"Name": result.data.title,
"authorName": result.data.author
};
resolve({
data: {
bookInfo: data.book,
chapterInfo: chapter
}
});
} else {
if (isShowLoading) {
layer.open({content:'获取章节内容失败,请稍候再试',skin:'msg',time:2});
}
reject();
}
});
}
},
setReadChapter: function(chapterId) {
var self = this;
var chapter = data.chapters[chapterId];
if (!chapter || chapter.id === data.chapter.id) {
return;
}
data.chapter = chapter;
$("#chapterTitle").html(chapter.title);
self.updateReadProgress();
history.replaceState(null, null, data.chapterUrl.replace("chapterId", chapterId));
}
}
Book.init();
});