first commit 2
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* ==========================================================================
|
||||
* 💡 베이스 모듈(Base Module) 전용 스타일시트
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
/* --- 1. 섹션 기본 스타일 --- */
|
||||
.item-section {
|
||||
width: 100%;
|
||||
padding: 80px 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/* --- 2. 섹션 헤더 (제목, 부제) --- */
|
||||
.section-header {
|
||||
text-align: center;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.section-header .subtitle {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #0056b3;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
font-size: 36px;
|
||||
font-weight: 900;
|
||||
color: #25282B;
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.section-header p {
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
color: #666;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* --- 3. 아이템 카드 그리드 --- */
|
||||
.item-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
/* --- 4. 개별 아이템 카드 --- */
|
||||
.item-card {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* --- 5. 카드 내부 요소 --- */
|
||||
.item-image {
|
||||
width: 100%;
|
||||
aspect-ratio: 4 / 3;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.item-image.is-patent {
|
||||
padding: 20px;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.item-image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.4s ease;
|
||||
}
|
||||
|
||||
.item-card:hover .item-image img {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.item-info {
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
.item-info h3 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.item-info p {
|
||||
font-size: 0.95rem;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* --- 9. 스크롤 애니메이션 (공용) --- */
|
||||
.reveal-up, .reveal-fade {
|
||||
opacity: 0;
|
||||
transition: opacity 0.8s ease-out, transform 0.8s ease-out;
|
||||
}
|
||||
.reveal-up { transform: translateY(40px); }
|
||||
.reveal-fade { transform: scale(0.95); }
|
||||
.reveal-up.is-revealed, .reveal-fade.is-revealed {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* --- 10. [모듈 전용] 이미지 팝업 모달 스타일 (개선) --- */
|
||||
.image-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1050;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40px 20px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.image-modal.is-active {
|
||||
display: flex;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,.5);
|
||||
animation: modal-slide-down 0.4s ease-out;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@keyframes modal-slide-down {
|
||||
from {
|
||||
transform: translateY(-50px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-content .modal-image {
|
||||
display: block;
|
||||
max-width: 90vw;
|
||||
max-height: 80vh;
|
||||
object-fit: contain;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.modal-info {
|
||||
padding: 20px 25px;
|
||||
max-width: 800px; /* 텍스트 영역의 최대 너비는 제한 */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.modal-info .modal-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
.modal-info .modal-desc {
|
||||
font-size: 1rem;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 25px;
|
||||
font-size: 35px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
text-shadow: 0 1px 3px rgba(0,0,0,0.5);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.close-btn:hover,
|
||||
.close-btn:focus {
|
||||
color: #ccc;
|
||||
text-decoration: none;
|
||||
}
|
||||
/* --- 11. [개선] 가독성 향상을 위한 줄바꿈 처리 --- */
|
||||
.section-header h2,
|
||||
.section-header p,
|
||||
.product-info-trend h3,
|
||||
.product-info-trend p,
|
||||
.item-info h3,
|
||||
.item-info p {
|
||||
word-break: keep-all;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
/* --- 12. [개선] 카드 설명 텍스트 잘림 방지 및 높이 고정 --- */
|
||||
.product-info-trend p,
|
||||
.item-info p {
|
||||
height: 3.04rem;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* --- 13. [최종 수정] 모듈 스크롤바 완전 숨김 처리 --- */
|
||||
/* 1. 기본 상태: 스크롤바를 완전히 투명하게 만듭니다. */
|
||||
.image-modal {
|
||||
/* Firefox: 스크롤바 색상을 양쪽 모두 투명하게 설정 */
|
||||
scrollbar-color: transparent transparent;
|
||||
scrollbar-width: thin;
|
||||
transition: scrollbar-color 0.3s ease;
|
||||
}
|
||||
|
||||
.image-modal::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.image-modal::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.image-modal::-webkit-scrollbar-thumb {
|
||||
/* Webkit: 스크롤바 막대를 투명하게 */
|
||||
background-color: transparent;
|
||||
border-radius: 10px;
|
||||
border: 3px solid transparent;
|
||||
background-clip: padding-box;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
/* 2. :hover 상태: 마우스를 올리면 스크롤바가 나타납니다. */
|
||||
.image-modal:hover {
|
||||
/* Firefox: 스크롤바 색상을 보이게 변경 */
|
||||
scrollbar-color: rgba(0, 0, 0, 0.4) transparent;
|
||||
}
|
||||
|
||||
.image-modal:hover::-webkit-scrollbar-thumb {
|
||||
/* Webkit: 스크롤바 막대 색상을 보이게 변경 */
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// TODO: 'initBaseModule'을 고유한 함수 이름으로 변경하세요. (예: initNewsModule)
|
||||
function initBaseModule(moduleId) {
|
||||
const moduleElement = document.getElementById(moduleId);
|
||||
if (!moduleElement || moduleElement.classList.contains('initialized')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const section = moduleElement.querySelector('.base-section');
|
||||
const itemGrid = moduleElement.querySelector('.item-grid');
|
||||
const modal = moduleElement.querySelector('.image-modal');
|
||||
|
||||
if (!section || !itemGrid || !modal) {
|
||||
return;
|
||||
}
|
||||
|
||||
function renderGrid() {
|
||||
const itemsJson = section.dataset.items;
|
||||
let itemsData;
|
||||
|
||||
try {
|
||||
itemsData = JSON.parse(itemsJson);
|
||||
} catch (e) {
|
||||
itemGrid.innerHTML = '<p>데이터를 불러오는 데 실패했습니다.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!itemsData || itemsData.length === 0) {
|
||||
itemGrid.innerHTML = '<p>표시할 항목이 없습니다.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
const itemCardsHTML = itemsData.map(item => `
|
||||
<div class="item-card js-modal-trigger" data-title="${item.title}" data-desc="${item.description}" data-img="${item.image}">
|
||||
<div class="item-image">
|
||||
<img src="${item.image}" alt="${item.title}">
|
||||
</div>
|
||||
<div class="item-info">
|
||||
<h3>${item.title}</h3>
|
||||
<p>${item.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
itemGrid.innerHTML = itemCardsHTML;
|
||||
}
|
||||
|
||||
function setupModalEvents() {
|
||||
const modalImage = modal.querySelector('.modal-image');
|
||||
const modalTitle = modal.querySelector('.modal-title');
|
||||
const modalDesc = modal.querySelector('.modal-desc');
|
||||
const closeBtn = modal.querySelector('.close-btn');
|
||||
|
||||
function closeModal() {
|
||||
modal.classList.remove('is-active');
|
||||
}
|
||||
|
||||
itemGrid.addEventListener('click', function(event) {
|
||||
const card = event.target.closest('.js-modal-trigger');
|
||||
if (card) {
|
||||
modalImage.src = card.dataset.img;
|
||||
modalTitle.textContent = card.dataset.title;
|
||||
modalDesc.textContent = card.dataset.desc;
|
||||
modal.classList.add('is-active');
|
||||
}
|
||||
});
|
||||
|
||||
closeBtn.addEventListener('click', closeModal);
|
||||
modal.addEventListener('click', (e) => (e.target === modal) && closeModal());
|
||||
document.addEventListener('keydown', (e) => (e.key === 'Escape' && modal.classList.contains('is-active')) && closeModal());
|
||||
}
|
||||
|
||||
renderGrid();
|
||||
setupModalEvents();
|
||||
moduleElement.classList.add('initialized');
|
||||
}
|
||||
|
||||
// TODO: 'initBaseModule'을 고유한 함수 이름으로 변경하세요.
|
||||
window.initBaseModule = initBaseModule;
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
// =================================================================================
|
||||
// 💡 [사용법] 이 파일을 복사하여 새 모듈을 만들 때 아래 TODO 항목들을 수정하세요.
|
||||
// =================================================================================
|
||||
|
||||
// TODO: 'board_name'을 실제 게시판 테이블명으로 변경하세요. (예: 'gallery', 'news' 등)
|
||||
$bo_table_name = 'board_name';
|
||||
|
||||
// TODO: 가져올 게시물 수를 변경할 수 있습니다.
|
||||
$limit = 3;
|
||||
|
||||
// --- 데이터 처리 ---
|
||||
$module_data = array();
|
||||
$sql = " SELECT wr_id, wr_subject, wr_content FROM {$g5['write_prefix']}{$bo_table_name} WHERE wr_is_comment = 0 ORDER BY wr_num, wr_reply LIMIT {$limit} ";
|
||||
$result = sql_query($sql);
|
||||
|
||||
for ($i=0; $row=sql_fetch_array($result); $i++) {
|
||||
$files = get_file($bo_table_name, $row['wr_id']);
|
||||
$image_url = (isset($files[0]['path']) && isset($files[0]['file'])) ? $files[0]['path'].'/'.$files[0]['file'] : G5_THEME_URL.'/img/no_image.png';
|
||||
|
||||
$module_data[] = array(
|
||||
'id' => $row['wr_id'],
|
||||
'title' => get_text($row['wr_subject']),
|
||||
'description' => get_text(cut_str(strip_tags($row['wr_content']), 100)),
|
||||
'image' => $image_url
|
||||
);
|
||||
}
|
||||
$module_json = json_encode($module_data, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// CSS와 JS 파일의 버전을 파일 수정 시간으로 자동 갱신
|
||||
$module_css_path = G5_THEME_PATH.'/rb.custom/_base_module/module.css';
|
||||
$module_js_path = G5_THEME_PATH.'/rb.custom/_base_module/module.js';
|
||||
$module_css_ver = file_exists($module_css_path) ? filemtime($module_css_path) : G5_CSS_VER;
|
||||
$module_js_ver = file_exists($module_js_path) ? filemtime($module_js_path) : G5_JS_VER;
|
||||
|
||||
// 이 모듈만의 고유 ID를 생성합니다.
|
||||
$module_id = 'base_module_'.uniqid();
|
||||
?>
|
||||
|
||||
<!-- 모듈의 가장 바깥 요소에 고유 ID를 부여합니다. -->
|
||||
<div id="<?php echo $module_id; ?>" class="base-module">
|
||||
<section class="item-section" data-items='<?php echo htmlspecialchars($module_json, ENT_QUOTES, 'UTF-8'); ?>'>
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<!-- TODO: 모듈의 제목과 설명을 수정하세요. -->
|
||||
<span class="subtitle">Module Subtitle</span>
|
||||
<h2>모듈 제목</h2>
|
||||
<p>이곳에 모듈에 대한 간단한 설명을 입력하세요.</p>
|
||||
</div>
|
||||
<div class="item-grid">
|
||||
<!-- JS로 아이템 카드가 생성될 영역 -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 모듈 내부에 모달 HTML을 포함시킵니다. -->
|
||||
<div class="image-modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-btn">×</span>
|
||||
<img class="modal-image" src="" alt="이미지">
|
||||
<div class="modal-info">
|
||||
<h3 class="modal-title"></h3>
|
||||
<p class="modal-desc"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 이 모듈에 필요한 CSS 파일을 불러옵니다. -->
|
||||
<link rel="stylesheet" href="<?php echo G5_THEME_URL; ?>/rb.custom/_item_module/module.css?ver=<?php echo $module_css_ver; ?>">
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const currentModuleId = '<?php echo $module_id; ?>';
|
||||
// TODO: 'inititemModule'을 고유한 함수 이름으로 변경하세요. (예: initNewsModule)
|
||||
const initFunctionName = 'inititemModule';
|
||||
// TODO: 'item-module-script'를 고유한 스크립트 ID로 변경하세요. (예: news-module-script)
|
||||
const scriptId = 'item-module-script';
|
||||
|
||||
if (document.getElementById(scriptId)) {
|
||||
if (typeof window[initFunctionName] === 'function') {
|
||||
window[initFunctionName](currentModuleId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.id = scriptId;
|
||||
// TODO: JS 파일 경로를 실제 모듈 경로로 수정하세요.
|
||||
script.src = '<?php echo G5_THEME_URL; ?>/rb.custom/_base_module/module.js?ver=<?php echo $module_js_ver; ?>';
|
||||
script.async = true;
|
||||
|
||||
script.onload = () => {
|
||||
if (typeof window[initFunctionName] === 'function') {
|
||||
window[initFunctionName](currentModuleId);
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
|
||||
?>
|
||||
<!-- 💡 [핵심] 사이트 전체에서 사용할 공용 문의하기 모달입니다. 기본적으로 숨겨져 있습니다. -->
|
||||
<div id="global-contact-modal" class="global-contact-modal-container" style="display: none;">
|
||||
<div class="modal-overlay-bg"></div>
|
||||
<div class="modal-content-wrapper">
|
||||
<button type="button" class="modal-close">×</button>
|
||||
<div class="section-header">
|
||||
<span class="subtitle">Contact Us</span>
|
||||
<h2>공간의 가능성을 열어보세요.</h2>
|
||||
<p>성진미도어의 전문가와 상담하고, 당신의 공간에 꼭 맞는 솔루션을 찾아보세요.</p>
|
||||
</div>
|
||||
<div class="contact-wrapper">
|
||||
<div class="contact-info">
|
||||
<h3>Information</h3>
|
||||
<div class="info-item"><strong>본사 및 전시장</strong><p>충청남도 아산시 음봉면 월산로 128-130</p></div>
|
||||
<div class="info-item"><strong>대표 연락처</strong><p>T. 041-532-0555 / H. 010-5434-4126</p></div>
|
||||
<div class="info-item"><strong>청주 전시장</strong><p>T. 043-235-2352 / H. 010-2066-4126</p></div>
|
||||
<div class="info-item"><strong>운영시간</strong><p>평일 09:00 - 18:00 (주말 및 공휴일 휴무)</p></div>
|
||||
</div>
|
||||
<form name="contactForm" id="contactForm" class="contact-form" method="post">
|
||||
<h3>상담 신청</h3>
|
||||
<div id="form-messages" class="form-message-area"></div>
|
||||
<input type="text" name="contact_name" placeholder="이름" required>
|
||||
<input type="tel" name="contact_hp" placeholder="연락처" required>
|
||||
<input type="email" name="contact_email" placeholder="이메일" required>
|
||||
<textarea name="contact_message" placeholder="문의 내용을 입력해주세요." rows="5" required></textarea>
|
||||
<button type="submit" id="contact-submit-btn" class="cta-button">상담 신청하기</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,37 @@
|
||||
/* 독립 문의하기 모듈 스타일 */
|
||||
.contact-section-trigger { padding: 80px 0; text-align: center; background-color: #f8f9fa; }
|
||||
.contact-section-trigger .cta-button { padding: 15px 30px; border-radius: 50px; font-weight: 700; }
|
||||
|
||||
.contact-modal-local { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 1010; }
|
||||
.contact-modal-local.is-active { display: block; }
|
||||
.contact-modal-local .modal-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); animation: fadeIn 0.3s ease; }
|
||||
.contact-modal-local .modal-content-local { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 900px; background: #fff; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); animation: slideDown 0.4s ease-out; padding: 40px; }
|
||||
.contact-modal-local .modal-close { position: absolute; top: 15px; right: 20px; font-size: 2rem; color: #aaa; background: none; border: none; cursor: pointer; line-height: 1; }
|
||||
|
||||
.contact-modal-local .section-header { text-align: center; margin-bottom: 40px; }
|
||||
.contact-modal-local .section-header .subtitle { color: #0056b3; }
|
||||
.contact-modal-local .section-header h2 { font-size: 2rem; }
|
||||
.contact-modal-local .section-header p { max-width: 100%; }
|
||||
|
||||
.contact-wrapper { display: flex; gap: 40px; }
|
||||
.contact-info, .contact-form { flex: 1; }
|
||||
.contact-info h3, .contact-form h3 { font-size: 1.3rem; margin-bottom: 20px; border-bottom: 2px solid #eee; padding-bottom: 15px; }
|
||||
.info-item { margin-bottom: 15px; }
|
||||
.info-item strong { display: block; font-weight: 700; margin-bottom: 5px; }
|
||||
.info-item p { margin: 0; color: #666; }
|
||||
|
||||
.contact-form input, .contact-form textarea { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 5px; margin-bottom: 15px; }
|
||||
.contact-form .cta-button { width: 100%; padding: 15px; }
|
||||
.contact-form .cta-button:disabled { background-color: #ccc; cursor: not-allowed; }
|
||||
|
||||
.form-message-area .message { padding: 10px; margin-bottom: 15px; border-radius: 5px; text-align: center; }
|
||||
.form-message-area .success { background-color: #d4edda; color: #155724; }
|
||||
.form-message-area .error { background-color: #f8d7da; color: #721c24; }
|
||||
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes slideDown { from { opacity: 0; transform: translate(-50%, -60%); } to { opacity: 1; transform: translate(-50%, -50%); } }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contact-wrapper { flex-direction: column; }
|
||||
.contact-modal-local .modal-content-local { padding: 25px; max-height: 85vh; overflow-y: auto; }
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
function initContactModule(moduleId) {
|
||||
const moduleElement = document.getElementById(moduleId);
|
||||
if (!moduleElement || moduleElement.classList.contains('initialized')) return;
|
||||
|
||||
const openBtn = moduleElement.querySelector('.btn-open-contact-modal');
|
||||
const modal = moduleElement.querySelector('.contact-modal-local');
|
||||
const closeBtn = modal.querySelector('.modal-close');
|
||||
const overlay = modal.querySelector('.modal-overlay');
|
||||
const form = modal.querySelector('form');
|
||||
const formMessages = modal.querySelector('.form-message-area');
|
||||
|
||||
const openModal = () => {
|
||||
modal.classList.add('is-active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
modal.classList.remove('is-active');
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
openBtn.addEventListener('click', openModal);
|
||||
closeBtn.addEventListener('click', closeModal);
|
||||
overlay.addEventListener('click', closeModal);
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-active')) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// 💡 [핵심 수정] universalMailer를 사용한 폼 제출 로직
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const submitBtn = this.querySelector('button[type="submit"]');
|
||||
const originalBtnText = submitBtn.textContent;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = '전송 중...';
|
||||
formMessages.innerHTML = ''; // 이전 메시지 초기화
|
||||
|
||||
const formData = new FormData(form);
|
||||
const variables = {
|
||||
contact_name: formData.get('contact_name'),
|
||||
contact_hp: formData.get('contact_hp'),
|
||||
contact_email: formData.get('contact_email'),
|
||||
contact_message: formData.get('contact_message').replace(/\n/g, '<br>')
|
||||
};
|
||||
|
||||
// universalMailer 객체가 있는지 확인
|
||||
if (window.universalMailer && typeof window.universalMailer.send === 'function') {
|
||||
window.universalMailer.send({
|
||||
template_code: 'contact_inquiry', // 관리자에서 생성한 템플릿 코드
|
||||
// to_email: variables.contact_email, //수신자임 문의 하기 같은경우 관리자가 받아야 해서 비워둔다
|
||||
variables: variables,
|
||||
onSuccess: function(response) {
|
||||
alert(response.message || '상담 신청이 성공적으로 접수되었습니다.');
|
||||
form.reset();
|
||||
closeModal();
|
||||
},
|
||||
onError: function(errorMessage) {
|
||||
formMessages.innerHTML = `<div class="message error">${errorMessage || '오류가 발생했습니다.'}</div>`;
|
||||
},
|
||||
onComplete: function() {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalBtnText;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert('메일 발송 기능에 오류가 발생했습니다. 관리자에게 문의해주세요.');
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalBtnText;
|
||||
}
|
||||
});
|
||||
|
||||
moduleElement.classList.add('initialized');
|
||||
}
|
||||
|
||||
window.initContactModule = initContactModule;
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
|
||||
// CSS와 JS 파일의 버전을 파일 수정 시간으로 자동 갱신
|
||||
$module_css_path = './module.css';
|
||||
$module_js_path = './module.js';
|
||||
$module_css_ver = file_exists($module_css_path) ? filemtime($module_css_path) : G5_CSS_VER;
|
||||
$module_js_ver = file_exists($module_js_path) ? filemtime($module_js_path) : G5_JS_VER;
|
||||
|
||||
// 이 모듈만의 고유 ID를 생성합니다.
|
||||
$module_id = 'contact_module_'.uniqid();
|
||||
?>
|
||||
|
||||
<!-- 모듈의 가장 바깥 요소에 고유 ID를 부여합니다. -->
|
||||
<div id="<?php echo $module_id; ?>" class="contact-module">
|
||||
|
||||
<!-- 💡 [핵심] 이 모듈에 종속된 모달 HTML (사용자가 제공한 디자인 적용) -->
|
||||
<div class="contact-modal-local">
|
||||
<div class="modal-overlay"></div>
|
||||
<div class="modal-content-local">
|
||||
<button type="button" class="modal-close">×</button>
|
||||
<div class="section-header">
|
||||
<span class="subtitle">Contact Us</span>
|
||||
<h2>공간의 가능성을 열어보세요.</h2>
|
||||
<p>성진미도어의 전문가와 상담하고, 당신의 공간에 꼭 맞는 솔루션을 찾아보세요.</p>
|
||||
</div>
|
||||
<div class="contact-wrapper">
|
||||
<div class="contact-info">
|
||||
<h3>Information</h3>
|
||||
<div class="info-item"><strong>본사 및 전시장</strong><p>충청남도 아산시 음봉면 월산로 128-130</p></div>
|
||||
<div class="info-item"><strong>대표 연락처</strong><p>T. 041-532-0555 / H. 010-5434-4126</p></div>
|
||||
<div class="info-item"><strong>청주 전시장</strong><p>T. 043-235-2352 / H. 010-2066-4126</p></div>
|
||||
<div class="info-item"><strong>운영시간</strong><p>평일 09:00 - 18:00 (주말 및 공휴일 휴무)</p></div>
|
||||
</div>
|
||||
<form name="fcontactform_<?php echo $module_id; ?>" id="fcontactform_<?php echo $module_id; ?>" class="contact-form" method="post">
|
||||
<h3>상담 신청</h3>
|
||||
<div class="form-message-area"></div>
|
||||
<input type="text" name="contact_name" placeholder="이름" required>
|
||||
<input type="tel" name="contact_hp" placeholder="연락처" required>
|
||||
<input type="email" name="contact_email" placeholder="이메일" required>
|
||||
<textarea name="contact_message" placeholder="문의 내용을 입력해주세요." rows="5" required></textarea>
|
||||
<button type="submit" class="cta-button">상담 신청하기</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 💡 [핵심] 모듈의 실제 내용 (페이지에 표시될 부분) -->
|
||||
<div class="contact-section-trigger">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<span class="subtitle">Get a Quote</span>
|
||||
<h2>궁금한 점이 있으신가요?</h2>
|
||||
<p>전문가의 상담을 통해 당신의 공간에 가장 적합한 솔루션을 찾아보세요.</p>
|
||||
</div>
|
||||
<button type="button" class="btn-open-contact-modal cta-button">무료 상담 신청하기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 이 모듈에 필요한 CSS와 JS를 불러옵니다. -->
|
||||
<link rel="stylesheet" href="./module.css?ver=<?php echo $module_css_ver; ?>">
|
||||
<script>
|
||||
(function() {
|
||||
const currentModuleId = '<?php echo $module_id; ?>';
|
||||
const scriptId = 'contact-module-script';
|
||||
|
||||
if (document.getElementById(scriptId)) {
|
||||
if (typeof window.initContactModule === 'function') {
|
||||
window.initContactModule(currentModuleId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.id = scriptId;
|
||||
script.src = './module.js?ver=<?php echo $module_js_ver; ?>';
|
||||
script.async = true;
|
||||
|
||||
script.onload = () => {
|
||||
if (typeof window.initContactModule === 'function') {
|
||||
window.initContactModule(currentModuleId);
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
|
||||
$base_module_php_path = G5_THEME_PATH.'/rb.custom/contact/base/global_modal.php';
|
||||
$module_php_path = G5_THEME_PATH.'/rb.custom/contact/'.$config['cf_theme'].'/global_modal.php';
|
||||
|
||||
if(file_exists($module_php_path)){
|
||||
include_once ($module_php_path);
|
||||
}else {
|
||||
include_once ($base_module_php_path);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
|
||||
$base_module_php_path = G5_THEME_PATH.'/rb.custom/contact/base/module.php';
|
||||
$module_php_path = G5_THEME_PATH.'/rb.custom/contact/'.$config['cf_theme'].'/module.php';
|
||||
|
||||
if(file_exists($module_php_path)){
|
||||
include_once ($module_php_path);
|
||||
}else {
|
||||
include_once ($base_module_php_path);
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
?>
|
||||
|
||||
<!-- 💡 [핵심] 사이트 전체에서 사용할 공용 문의하기 모달입니다. 기본적으로 숨겨져 있습니다. -->
|
||||
<div id="global-contact-modal" class="global-contact-modal-container" style="display: none;">
|
||||
<div class="modal-overlay-bg"></div>
|
||||
<div class="modal-content-wrapper">
|
||||
<button type="button" class="modal-close">×</button>
|
||||
<div class="section-header">
|
||||
<span class="subtitle">Contact Us</span>
|
||||
<h2>레이저 기술의 미래, 지금 문의하세요.</h2>
|
||||
<p>월간 레이저기술에 대한 광고, 구독, 기사 제보 등 모든 문의를 환영합니다.</p>
|
||||
</div>
|
||||
<div class="contact-wrapper">
|
||||
<div class="contact-info">
|
||||
<h3>연락 정보</h3>
|
||||
<div class="info-item">
|
||||
<strong>(주)레이저월드</strong>
|
||||
<p>서울특별시 금천구 가산디지털1로 1 (대표 주소)</p>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>대표 연락처</strong>
|
||||
<p>T. 02-123-4567 / F. 02-123-4568</p>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>이메일</strong>
|
||||
<p>contact@laserworld.com</p>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>운영시간</strong>
|
||||
<p>평일 09:00 - 18:00 (주말 및 공휴일 휴무)</p>
|
||||
</div>
|
||||
</div>
|
||||
<form name="contactForm" id="contactForm" class="contact-form" method="post">
|
||||
<h3>문의 및 제보</h3>
|
||||
<div id="form-messages" class="form-message-area"></div> <!-- 💡 메시지 표시 영역 -->
|
||||
<input type="text" name="contact_name" placeholder="이름" required>
|
||||
<input type="tel" name="contact_hp" placeholder="연락처" required>
|
||||
<input type="email" name="contact_email" placeholder="이메일" required>
|
||||
<textarea name="contact_message" placeholder="문의 내용을 입력해주세요." rows="5" required></textarea>
|
||||
<button type="submit" id="contact-submit-btn" class="cta-button">문의하기</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,38 @@
|
||||
/* 독립 문의하기 모듈 스타일 */
|
||||
.contact-section-trigger { padding: 80px 0; text-align: center; background-color: #f8f9fa; }
|
||||
.contact-section-trigger .cta-button { padding: 15px 30px; border-radius: 50px; font-weight: 700; }
|
||||
|
||||
.contact-modal-local { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 1010; }
|
||||
.contact-modal-local.is-active { display: block; }
|
||||
.contact-modal-local .modal-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); animation: fadeIn 0.3s ease; }
|
||||
.contact-modal-local .modal-content-local { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 900px; background: #fff; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); animation: slideDown 0.4s ease-out; padding: 40px; }
|
||||
.contact-modal-local .modal-close { position: absolute; top: 15px; right: 20px; font-size: 2rem; color: #aaa; background: none; border: none; cursor: pointer; line-height: 1; }
|
||||
|
||||
.contact-modal-local .section-header { text-align: center; margin-bottom: 40px; }
|
||||
.contact-modal-local .section-header .subtitle { color: #0056b3; }
|
||||
.contact-modal-local .section-header h2 { font-size: 2rem; }
|
||||
.contact-modal-local .section-header p { max-width: 100%; }
|
||||
|
||||
.contact-wrapper { display: flex; gap: 40px; }
|
||||
.contact-info, .contact-form { flex: 1; }
|
||||
.contact-info h3, .contact-form h3 { font-size: 1.3rem; margin-bottom: 20px; border-bottom: 2px solid #eee; padding-bottom: 15px; }
|
||||
.info-item { margin-bottom: 15px; }
|
||||
.info-item strong { display: block; font-weight: 700; margin-bottom: 5px; }
|
||||
.info-item p { margin: 0; color: #666; }
|
||||
|
||||
.contact-form input, .contact-form textarea { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 5px; margin-bottom: 15px; }
|
||||
.contact-form .cta-button { width: 100%; padding: 15px; }
|
||||
.contact-form .cta-button:disabled { background-color: #ccc; cursor: not-allowed; }
|
||||
.contact-form h3 { font-size: 1.3rem; margin-bottom: 20px; border-bottom: 2px solid #eee; padding-bottom: 15px; color: #fff }
|
||||
|
||||
.form-message-area .message { padding: 10px; margin-bottom: 15px; border-radius: 5px; text-align: center; }
|
||||
.form-message-area .success { background-color: #d4edda; color: #155724; }
|
||||
.form-message-area .error { background-color: #f8d7da; color: #721c24; }
|
||||
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes slideDown { from { opacity: 0; transform: translate(-50%, -60%); } to { opacity: 1; transform: translate(-50%, -50%); } }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contact-wrapper { flex-direction: column; }
|
||||
.contact-modal-local .modal-content-local { padding: 25px; max-height: 85vh; overflow-y: auto; }
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
function initContactModule(moduleId) {
|
||||
const moduleElement = document.getElementById(moduleId);
|
||||
if (!moduleElement || moduleElement.classList.contains('initialized')) return;
|
||||
|
||||
const modal = moduleElement.querySelector('.contact-modal-local');
|
||||
const closeBtn = modal.querySelector('.modal-close');
|
||||
const overlay = modal.querySelector('.modal-overlay');
|
||||
const form = modal.querySelector('form');
|
||||
const formMessages = modal.querySelector('.form-message-area');
|
||||
|
||||
const openModal = (e) => {
|
||||
if (e) e.preventDefault();
|
||||
modal.classList.add('is-active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
modal.classList.remove('is-active');
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
// 💡 [수정] document 객체에 이벤트 리스너 등록 (더 확실한 위임)
|
||||
document.addEventListener('click', function(e) {
|
||||
// 클릭된 요소가 .btn-open-contact-modal 클래스를 가지고 있거나, 그 내부 요소인 경우
|
||||
const targetBtn = e.target.matches('.btn-open-contact-modal') ? e.target : e.target.closest('.btn-open-contact-modal');
|
||||
|
||||
if (targetBtn) {
|
||||
openModal(e);
|
||||
}
|
||||
});
|
||||
|
||||
closeBtn.addEventListener('click', closeModal);
|
||||
overlay.addEventListener('click', closeModal);
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-active')) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// universalMailer를 사용한 폼 제출 로직
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const submitBtn = this.querySelector('button[type="submit"]');
|
||||
const originalBtnText = submitBtn.textContent;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = '전송 중...';
|
||||
formMessages.innerHTML = ''; // 이전 메시지 초기화
|
||||
|
||||
const formData = new FormData(form);
|
||||
const variables = {
|
||||
contact_name: formData.get('contact_name'),
|
||||
contact_hp: formData.get('contact_hp'),
|
||||
contact_email: formData.get('contact_email'),
|
||||
contact_message: formData.get('contact_message').replace(/\n/g, '<br>')
|
||||
};
|
||||
|
||||
// universalMailer 객체가 있는지 확인
|
||||
if (window.universalMailer && typeof window.universalMailer.send === 'function') {
|
||||
window.universalMailer.send({
|
||||
template_code: 'contact_inquiry', // 관리자에서 생성한 템플릿 코드
|
||||
// to_email: variables.contact_email, //수신자임 문의 하기 같은경우 관리자가 받아야 해서 비워둔다
|
||||
variables: variables,
|
||||
onSuccess: function(response) {
|
||||
alert(response.message || '상담 신청이 성공적으로 접수되었습니다.');
|
||||
form.reset();
|
||||
closeModal();
|
||||
},
|
||||
onError: function(errorMessage) {
|
||||
formMessages.innerHTML = `<div class="message error">${errorMessage || '오류가 발생했습니다.'}</div>`;
|
||||
},
|
||||
onComplete: function() {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalBtnText;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert('메일 발송 기능에 오류가 발생했습니다. 관리자에게 문의해주세요.');
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalBtnText;
|
||||
}
|
||||
});
|
||||
|
||||
moduleElement.classList.add('initialized');
|
||||
}
|
||||
|
||||
window.initContactModule = initContactModule;
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
|
||||
// 💡 [수정] 파일 경로(filemtime용)와 URL(src용)을 분리
|
||||
$module_css_file = G5_THEME_PATH.'/rb.custom/contact/'.$config['cf_theme'].'/module.css';
|
||||
$module_js_file = G5_THEME_PATH.'/rb.custom/contact/'.$config['cf_theme'].'/module.js';
|
||||
|
||||
$module_css_url = G5_THEME_URL.'/rb.custom/contact/'.$config['cf_theme'].'/module.css';
|
||||
$module_js_url = G5_THEME_URL.'/rb.custom/contact/'.$config['cf_theme'].'/module.js';
|
||||
|
||||
$module_css_ver = file_exists($module_css_file) ? filemtime($module_css_file) : G5_CSS_VER;
|
||||
$module_js_ver = file_exists($module_js_file) ? filemtime($module_js_file) : G5_JS_VER;
|
||||
|
||||
// 이 모듈만의 고유 ID를 생성합니다.
|
||||
$module_id = 'contact_module_'.uniqid();
|
||||
?>
|
||||
|
||||
<!-- 모듈의 가장 바깥 요소에 고유 ID를 부여합니다. -->
|
||||
<div id="<?php echo $module_id; ?>" class="contact-module">
|
||||
|
||||
<!-- 💡 [핵심] 이 모듈에 종속된 모달 HTML (사용자가 제공한 디자인 적용) -->
|
||||
<div class="contact-modal-local">
|
||||
<div class="modal-overlay"></div>
|
||||
<div class="modal-content-local">
|
||||
<button type="button" class="modal-close">×</button>
|
||||
<section class="cta-section">
|
||||
<div class="container">
|
||||
<div class="cta-content">
|
||||
<div class="cta-text">
|
||||
<h2>귀사의 기술을 알리고 싶으신가요?</h2>
|
||||
<p>월간 레이저 기술이 귀사의 비즈니스 파트너가 되어드립니다.</p>
|
||||
</div>
|
||||
<form name="fcontactform_<?php echo $module_id; ?>" id="fcontactform_<?php echo $module_id; ?>" class="contact-form" method="post">
|
||||
<h3>상담 신청</h3>
|
||||
<div class="form-message-area"></div>
|
||||
<input type="text" name="contact_name" placeholder="이름" required>
|
||||
<input type="tel" name="contact_hp" placeholder="연락처" required>
|
||||
<input type="email" name="contact_email" placeholder="이메일" required>
|
||||
<textarea name="contact_message" placeholder="문의 내용을 입력해주세요." rows="5" required></textarea>
|
||||
<button type="submit" class="cta-button">정기 구독 신청 및 광고 문의</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 이 모듈에 필요한 CSS와 JS를 불러옵니다. -->
|
||||
<link rel="stylesheet" href="<?php echo $module_css_url; ?>?ver=<?php echo $module_css_ver; ?>">
|
||||
<script>
|
||||
(function() {
|
||||
const currentModuleId = '<?php echo $module_id; ?>';
|
||||
const scriptId = 'contact-module-script';
|
||||
|
||||
if (document.getElementById(scriptId)) {
|
||||
if (typeof window.initContactModule === 'function') {
|
||||
window.initContactModule(currentModuleId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.id = scriptId;
|
||||
// 💡 [수정] URL 경로 사용
|
||||
script.src = '<?php echo $module_js_url; ?>?ver=<?php echo $module_js_ver; ?>';
|
||||
script.async = true;
|
||||
|
||||
script.onload = () => {
|
||||
if (typeof window.initContactModule === 'function') {
|
||||
window.initContactModule(currentModuleId);
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
?>
|
||||
|
||||
<!-- 💡 [핵심] 사이트 전체에서 사용할 공용 문의하기 모달입니다. 기본적으로 숨겨져 있습니다. -->
|
||||
<div id="global-contact-modal" class="global-contact-modal-container" style="display: none;">
|
||||
<div class="modal-overlay-bg"></div>
|
||||
<div class="modal-content-wrapper">
|
||||
<button type="button" class="modal-close">×</button>
|
||||
<div class="section-header">
|
||||
<span class="subtitle">Contact Us</span>
|
||||
<h2>레이저 기술의 미래, 지금 문의하세요.</h2>
|
||||
<p>월간 레이저기술에 대한 광고, 구독, 기사 제보 등 모든 문의를 환영합니다.</p>
|
||||
</div>
|
||||
<div class="contact-wrapper">
|
||||
<div class="contact-info">
|
||||
<h3>연락 정보</h3>
|
||||
<div class="info-item">
|
||||
<strong>(주)레이저월드</strong>
|
||||
<p>서울특별시 금천구 가산디지털1로 1 (대표 주소)</p>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>대표 연락처</strong>
|
||||
<p>T. 02-123-4567 / F. 02-123-4568</p>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>이메일</strong>
|
||||
<p>contact@laserworld.com</p>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>운영시간</strong>
|
||||
<p>평일 09:00 - 18:00 (주말 및 공휴일 휴무)</p>
|
||||
</div>
|
||||
</div>
|
||||
<form name="contactForm" id="contactForm" class="contact-form" method="post">
|
||||
<h3>문의 및 제보</h3>
|
||||
<div id="form-messages" class="form-message-area"></div> <!-- 💡 메시지 표시 영역 -->
|
||||
<input type="text" name="contact_name" placeholder="이름" required>
|
||||
<input type="tel" name="contact_hp" placeholder="연락처" required>
|
||||
<input type="email" name="contact_email" placeholder="이메일" required>
|
||||
<textarea name="contact_message" placeholder="문의 내용을 입력해주세요." rows="5" required></textarea>
|
||||
<button type="submit" id="contact-submit-btn" class="cta-button">문의하기</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,38 @@
|
||||
/* 독립 문의하기 모듈 스타일 */
|
||||
.contact-section-trigger { padding: 80px 0; text-align: center; background-color: #f8f9fa; }
|
||||
.contact-section-trigger .cta-button { padding: 15px 30px; border-radius: 50px; font-weight: 700; }
|
||||
|
||||
.contact-modal-local { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 1010; }
|
||||
.contact-modal-local.is-active { display: block; }
|
||||
.contact-modal-local .modal-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.6); animation: fadeIn 0.3s ease; }
|
||||
.contact-modal-local .modal-content-local { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 900px; background: #fff; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); animation: slideDown 0.4s ease-out; padding: 40px; }
|
||||
.contact-modal-local .modal-close { position: absolute; top: 15px; right: 20px; font-size: 2rem; color: #aaa; background: none; border: none; cursor: pointer; line-height: 1; }
|
||||
|
||||
.contact-modal-local .section-header { text-align: center; margin-bottom: 40px; }
|
||||
.contact-modal-local .section-header .subtitle { color: #0056b3; }
|
||||
.contact-modal-local .section-header h2 { font-size: 2rem; }
|
||||
.contact-modal-local .section-header p { max-width: 100%; }
|
||||
|
||||
.contact-wrapper { display: flex; gap: 40px; }
|
||||
.contact-info, .contact-form { flex: 1; }
|
||||
.contact-info h3, .contact-form h3 { font-size: 1.3rem; margin-bottom: 20px; border-bottom: 2px solid #eee; padding-bottom: 15px; }
|
||||
.info-item { margin-bottom: 15px; }
|
||||
.info-item strong { display: block; font-weight: 700; margin-bottom: 5px; }
|
||||
.info-item p { margin: 0; color: #666; }
|
||||
|
||||
.contact-form input, .contact-form textarea { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 5px; margin-bottom: 15px; }
|
||||
.contact-form .cta-button { width: 100%; padding: 15px; }
|
||||
.contact-form .cta-button:disabled { background-color: #ccc; cursor: not-allowed; }
|
||||
.contact-form h3 { font-size: 1.3rem; margin-bottom: 20px; border-bottom: 2px solid #eee; padding-bottom: 15px; color: #fff }
|
||||
|
||||
.form-message-area .message { padding: 10px; margin-bottom: 15px; border-radius: 5px; text-align: center; }
|
||||
.form-message-area .success { background-color: #d4edda; color: #155724; }
|
||||
.form-message-area .error { background-color: #f8d7da; color: #721c24; }
|
||||
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes slideDown { from { opacity: 0; transform: translate(-50%, -60%); } to { opacity: 1; transform: translate(-50%, -50%); } }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.contact-wrapper { flex-direction: column; }
|
||||
.contact-modal-local .modal-content-local { padding: 25px; max-height: 85vh; overflow-y: auto; }
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
function initContactModule(moduleId) {
|
||||
const moduleElement = document.getElementById(moduleId);
|
||||
if (!moduleElement || moduleElement.classList.contains('initialized')) return;
|
||||
|
||||
const modal = moduleElement.querySelector('.contact-modal-local');
|
||||
const closeBtn = modal.querySelector('.modal-close');
|
||||
const overlay = modal.querySelector('.modal-overlay');
|
||||
const form = modal.querySelector('form');
|
||||
const formMessages = modal.querySelector('.form-message-area');
|
||||
|
||||
const openModal = (e) => {
|
||||
if (e) e.preventDefault();
|
||||
modal.classList.add('is-active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
modal.classList.remove('is-active');
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
// 💡 [수정] document 객체에 이벤트 리스너 등록 (더 확실한 위임)
|
||||
document.addEventListener('click', function(e) {
|
||||
// 클릭된 요소가 .btn-open-contact-modal 클래스를 가지고 있거나, 그 내부 요소인 경우
|
||||
const targetBtn = e.target.matches('.btn-open-contact-modal') ? e.target : e.target.closest('.btn-open-contact-modal');
|
||||
|
||||
if (targetBtn) {
|
||||
openModal(e);
|
||||
}
|
||||
});
|
||||
|
||||
closeBtn.addEventListener('click', closeModal);
|
||||
overlay.addEventListener('click', closeModal);
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && modal.classList.contains('is-active')) {
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
|
||||
// universalMailer를 사용한 폼 제출 로직
|
||||
form.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const submitBtn = this.querySelector('button[type="submit"]');
|
||||
const originalBtnText = submitBtn.textContent;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = '전송 중...';
|
||||
formMessages.innerHTML = ''; // 이전 메시지 초기화
|
||||
|
||||
const formData = new FormData(form);
|
||||
const variables = {
|
||||
contact_name: formData.get('contact_name'),
|
||||
contact_hp: formData.get('contact_hp'),
|
||||
contact_email: formData.get('contact_email'),
|
||||
contact_message: formData.get('contact_message').replace(/\n/g, '<br>')
|
||||
};
|
||||
|
||||
// universalMailer 객체가 있는지 확인
|
||||
if (window.universalMailer && typeof window.universalMailer.send === 'function') {
|
||||
window.universalMailer.send({
|
||||
template_code: 'contact_inquiry', // 관리자에서 생성한 템플릿 코드
|
||||
// to_email: variables.contact_email, //수신자임 문의 하기 같은경우 관리자가 받아야 해서 비워둔다
|
||||
variables: variables,
|
||||
onSuccess: function(response) {
|
||||
alert(response.message || '상담 신청이 성공적으로 접수되었습니다.');
|
||||
form.reset();
|
||||
closeModal();
|
||||
},
|
||||
onError: function(errorMessage) {
|
||||
formMessages.innerHTML = `<div class="message error">${errorMessage || '오류가 발생했습니다.'}</div>`;
|
||||
},
|
||||
onComplete: function() {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalBtnText;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert('메일 발송 기능에 오류가 발생했습니다. 관리자에게 문의해주세요.');
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = originalBtnText;
|
||||
}
|
||||
});
|
||||
|
||||
moduleElement.classList.add('initialized');
|
||||
}
|
||||
|
||||
window.initContactModule = initContactModule;
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit; // 개별 페이지 접근 불가
|
||||
|
||||
// 💡 [수정] 파일 경로(filemtime용)와 URL(src용)을 분리
|
||||
$module_css_file = G5_THEME_PATH.'/rb.custom/contact/'.$config['cf_theme'].'/module.css';
|
||||
$module_js_file = G5_THEME_PATH.'/rb.custom/contact/'.$config['cf_theme'].'/module.js';
|
||||
|
||||
$module_css_url = G5_THEME_URL.'/rb.custom/contact/'.$config['cf_theme'].'/module.css';
|
||||
$module_js_url = G5_THEME_URL.'/rb.custom/contact/'.$config['cf_theme'].'/module.js';
|
||||
|
||||
$module_css_ver = file_exists($module_css_file) ? filemtime($module_css_file) : G5_CSS_VER;
|
||||
$module_js_ver = file_exists($module_js_file) ? filemtime($module_js_file) : G5_JS_VER;
|
||||
|
||||
// 이 모듈만의 고유 ID를 생성합니다.
|
||||
$module_id = 'contact_module_'.uniqid();
|
||||
?>
|
||||
|
||||
<!-- 모듈의 가장 바깥 요소에 고유 ID를 부여합니다. -->
|
||||
<div id="<?php echo $module_id; ?>" class="contact-module">
|
||||
|
||||
<!-- 💡 [핵심] 이 모듈에 종속된 모달 HTML (사용자가 제공한 디자인 적용) -->
|
||||
<div class="contact-modal-local">
|
||||
<div class="modal-overlay"></div>
|
||||
<div class="modal-content-local">
|
||||
<button type="button" class="modal-close">×</button>
|
||||
<section class="cta-section">
|
||||
<div class="container">
|
||||
<div class="cta-content">
|
||||
<div class="cta-text">
|
||||
<h2>귀사의 기술을 알리고 싶으신가요?</h2>
|
||||
<p>월간 레이저 기술이 귀사의 비즈니스 파트너가 되어드립니다.</p>
|
||||
</div>
|
||||
<form name="fcontactform_<?php echo $module_id; ?>" id="fcontactform_<?php echo $module_id; ?>" class="contact-form" method="post">
|
||||
<h3>상담 신청</h3>
|
||||
<div class="form-message-area"></div>
|
||||
<input type="text" name="contact_name" placeholder="이름" required>
|
||||
<input type="tel" name="contact_hp" placeholder="연락처" required>
|
||||
<input type="email" name="contact_email" placeholder="이메일" required>
|
||||
<textarea name="contact_message" placeholder="문의 내용을 입력해주세요." rows="5" required></textarea>
|
||||
<button type="submit" class="cta-button">정기 구독 신청 및 광고 문의</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 이 모듈에 필요한 CSS와 JS를 불러옵니다. -->
|
||||
<link rel="stylesheet" href="<?php echo $module_css_url; ?>?ver=<?php echo $module_css_ver; ?>">
|
||||
<script>
|
||||
(function() {
|
||||
const currentModuleId = '<?php echo $module_id; ?>';
|
||||
const scriptId = 'contact-module-script';
|
||||
|
||||
if (document.getElementById(scriptId)) {
|
||||
if (typeof window.initContactModule === 'function') {
|
||||
window.initContactModule(currentModuleId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.id = scriptId;
|
||||
// 💡 [수정] URL 경로 사용
|
||||
script.src = '<?php echo $module_js_url; ?>?ver=<?php echo $module_js_ver; ?>';
|
||||
script.async = true;
|
||||
|
||||
script.onload = () => {
|
||||
if (typeof window.initContactModule === 'function') {
|
||||
window.initContactModule(currentModuleId);
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
/**
|
||||
* rb.custom :: ebook_section/config.php
|
||||
* E-Book 모듈 설정 파일
|
||||
*/
|
||||
|
||||
$ebook_config = [
|
||||
// 관리자 페이지에서 'ebook' 이라는 ID로 게시판을 생성해주세요.
|
||||
'bo_table' => 'journal',
|
||||
|
||||
// 'ebook' 게시판에 작성된 게시물 중, E-Book으로 보여줄 게시물의 ID를 입력하세요.
|
||||
'wr_id' => 1,
|
||||
|
||||
// E-Book의 크기 설정
|
||||
'width' => 922,
|
||||
'height' => 600,
|
||||
|
||||
// 💡 [추가] 기능 사용 여부 설정
|
||||
'use_download' => true, // 다운로드 버튼 사용 여부
|
||||
'use_print' => true, // 프린트 버튼 사용 여부
|
||||
];
|
||||
?>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
/**
|
||||
* rb.custom :: ebook_section/ebook_view.php
|
||||
*
|
||||
* 게시판 스킨 등에서 E-Book 뷰어를 간편하게 인클루드하기 위한 파일입니다.
|
||||
*/
|
||||
|
||||
// 필수 변수 확인
|
||||
if (!isset($bo_table) || !$bo_table || !isset($wr_id) || !$wr_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// PDF 파일 존재 여부 확인
|
||||
$has_pdf = false;
|
||||
$sql = " SELECT count(*) as cnt FROM {$g5['board_file_table']} WHERE bo_table = '{$bo_table}' AND wr_id = '{$wr_id}' ";
|
||||
$row = sql_fetch($sql);
|
||||
|
||||
if ($row['cnt'] > 0) {
|
||||
$sql = " SELECT bf_file FROM {$g5['board_file_table']} WHERE bo_table = '{$bo_table}' AND wr_id = '{$wr_id}' ";
|
||||
$result = sql_query($sql);
|
||||
while ($file = sql_fetch_array($result)) {
|
||||
if (preg_match('/\.pdf$/i', $file['bf_file'])) {
|
||||
$has_pdf = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PDF가 있을 때만 뷰어 출력
|
||||
if ($has_pdf) {
|
||||
echo '<div class="ebook-viewer-wrapper" style="margin-top:30px;">';
|
||||
|
||||
// 💡 [핵심 수정] module.php에 전달할 변수 설정
|
||||
$ebook_bo_table = $bo_table;
|
||||
$ebook_wr_id = $wr_id;
|
||||
|
||||
// 스킨 경로 설정 (module.php에서 사용)
|
||||
$ebook_skin_url = G5_THEME_URL . '/rb.custom/ebook_section';
|
||||
|
||||
include(dirname(__FILE__) . '/module.php');
|
||||
echo '</div>';
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,225 @@
|
||||
/* E-Book Section Style - Final Fix & Dark Mode */
|
||||
|
||||
:root {
|
||||
--ebook-bg: #f0f2f5;
|
||||
--ebook-control-bg: #fff;
|
||||
--ebook-text: #333;
|
||||
--ebook-btn-bg: #f8f9fa;
|
||||
--ebook-btn-hover: #e2e6ea;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--ebook-bg: #1a1a1a;
|
||||
--ebook-control-bg: #2d2d2d;
|
||||
--ebook-text: #e0e0e0;
|
||||
--ebook-btn-bg: #3d3d3d;
|
||||
--ebook-btn-hover: #4d4d4d;
|
||||
}
|
||||
|
||||
.ebook-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 40px 0;
|
||||
background: var(--ebook-bg);
|
||||
min-height: 600px;
|
||||
max-height: 90vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.ebook-loading-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--ebook-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.page-loading-alert {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: #fff;
|
||||
padding: 15px 30px;
|
||||
border-radius: 30px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
z-index: 10000;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 20px;
|
||||
font-size: 16px;
|
||||
color: var(--ebook-text);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 4px solid rgba(0,0,0,0.1);
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.flipbook-viewport {
|
||||
transition: transform 0.3s ease;
|
||||
transform-origin: center top;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
/* 💡 [추가] 3D 효과를 위한 원근감 설정 */
|
||||
perspective: 2000px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flipbook {
|
||||
max-width: 100%;
|
||||
/*margin: 20px;*/
|
||||
/* 💡 [추가] 책 전체에 입체감 부여 */
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.flipbook .page {
|
||||
background-color: white;
|
||||
/* 💡 [수정] 그림자 효과 강화 */
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* 💡 [추가] 왼쪽 페이지 안쪽(오른쪽) 그림자 - 책이 접히는 느낌 */
|
||||
.flipbook .even {
|
||||
background: linear-gradient(to right, #fff 95%, #e0e0e0 100%);
|
||||
}
|
||||
.flipbook .even::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 30px; /* 그림자 너비 */
|
||||
height: 100%;
|
||||
background: linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,0.15) 100%);
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* 💡 [추가] 오른쪽 페이지 안쪽(왼쪽) 그림자 - 책이 접히는 느낌 */
|
||||
.flipbook .odd {
|
||||
background: linear-gradient(to left, #fff 95%, #e0e0e0 100%);
|
||||
}
|
||||
.flipbook .odd::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 30px; /* 그림자 너비 */
|
||||
height: 100%;
|
||||
background: linear-gradient(to left, rgba(0,0,0,0) 0%, rgba(0,0,0,0.15) 100%);
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.flipbook canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.nav-arrow {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: rgba(0,0,0,0.1);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
color: var(--ebook-text);
|
||||
font-size: 20px;
|
||||
z-index: 100;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.nav-arrow:hover {
|
||||
background: rgba(0,0,0,0.3);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav-prev { left: 20px; }
|
||||
.nav-next { right: 20px; }
|
||||
|
||||
.ebook-controls {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
background: var(--ebook-control-bg);
|
||||
padding: 10px 20px;
|
||||
border-radius: 50px;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
||||
z-index: 100;
|
||||
transition: opacity 0.5s, background 0.3s;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.control-group { display: flex; align-items: center; gap: 10px; }
|
||||
.ebook-controls .btn { background: var(--ebook-btn-bg); color: var(--ebook-text); border: 1px solid rgba(0,0,0,0.1); width: 40px; height: 40px; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.2s; font-size: 16px; text-decoration: none; }
|
||||
.ebook-controls .btn:hover { background: var(--ebook-btn-hover); }
|
||||
.page-input-wrap { display: flex; align-items: center; gap: 5px; font-size: 14px; font-weight: 600; color: var(--ebook-text); }
|
||||
|
||||
#page-input, .page-input {
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
border: 1px solid rgba(0,0,0,0.2);
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
background: var(--ebook-btn-bg);
|
||||
color: var(--ebook-text);
|
||||
}
|
||||
|
||||
/* 💡 [핵심 수정] 숫자 입력창 화살표 숨기기 */
|
||||
#page-input::-webkit-outer-spin-button,
|
||||
#page-input::-webkit-inner-spin-button,
|
||||
.page-input::-webkit-outer-spin-button,
|
||||
.page-input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
#page-input[type=number],
|
||||
.page-input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
.ebook-empty { text-align: center; padding: 50px; color: var(--ebook-text); border: 2px dashed rgba(0,0,0,0.2); border-radius: 10px; }
|
||||
@@ -0,0 +1,208 @@
|
||||
(function($) {
|
||||
"use strict";
|
||||
|
||||
if (typeof window.initEbookModule === 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
window.initEbookModule = function(moduleId, pdfUrl, config) {
|
||||
var $module = $('#' + moduleId);
|
||||
if (!$module.length || !pdfUrl) return;
|
||||
|
||||
var pdfDoc = null;
|
||||
var pageCount = 0;
|
||||
var currentScale = 1.0;
|
||||
var initialLoadCount = 6;
|
||||
var isInitialized = false;
|
||||
var loadedPageCount = 0;
|
||||
var renderedCount = 0;
|
||||
|
||||
var $flipbook = $module.find('.flipbook');
|
||||
var $loadingOverlay = $module.find('.ebook-loading-overlay');
|
||||
var $loadingText = $module.find('.loading-text');
|
||||
var $viewport = $module.find('.flipbook-viewport');
|
||||
var $controls = $module.find('.ebook-controls');
|
||||
var $totalPages = $module.find('.total-pages');
|
||||
var $loadedPages = $module.find('.loaded-pages');
|
||||
var $pageInput = $module.find('.page-input');
|
||||
var $totalPagesWrap = $module.find('.total-pages-wrap');
|
||||
var $alertMsg = $module.find('.page-loading-alert');
|
||||
|
||||
function startEbookProcess() {
|
||||
if ($flipbook.turn('is')) {
|
||||
$flipbook.turn('destroy');
|
||||
}
|
||||
$flipbook.empty();
|
||||
$loadingOverlay.show();
|
||||
$viewport.add($controls).addClass('loading');
|
||||
|
||||
var availableWidth = $viewport.width() || config.width || 922;
|
||||
var availableHeight = $viewport.height() || config.height || 600;
|
||||
|
||||
var bookWidth, bookHeight;
|
||||
|
||||
function renderAllPages(pdf) {
|
||||
pdfDoc = pdf;
|
||||
pageCount = pdf.numPages;
|
||||
$totalPages.text(pageCount);
|
||||
$pageInput.attr('max', pageCount);
|
||||
|
||||
pdf.getPage(1).then(function(page) {
|
||||
var viewport = page.getViewport({ scale: 1 });
|
||||
var pageRatio = viewport.width / viewport.height;
|
||||
var bookRatio = pageRatio * 2;
|
||||
|
||||
bookWidth = availableWidth;
|
||||
bookHeight = bookWidth / bookRatio;
|
||||
|
||||
if (bookHeight > availableHeight) {
|
||||
bookHeight = availableHeight;
|
||||
bookWidth = bookHeight * bookRatio;
|
||||
}
|
||||
|
||||
var initialPromises = [];
|
||||
var loadLimit = Math.min(pageCount, initialLoadCount);
|
||||
|
||||
for (var i = 1; i <= loadLimit; i++) {
|
||||
initialPromises.push(renderPage(i, bookWidth, bookHeight, true, loadLimit));
|
||||
}
|
||||
|
||||
Promise.all(initialPromises).then(function(pages) {
|
||||
pages.forEach(function(pageDiv) {
|
||||
$flipbook.append(pageDiv);
|
||||
});
|
||||
|
||||
initTurnJs(bookWidth, bookHeight);
|
||||
isInitialized = true;
|
||||
loadedPageCount = loadLimit;
|
||||
updatePageDisplay();
|
||||
|
||||
$loadingOverlay.fadeOut(500);
|
||||
$viewport.add($controls).removeClass('loading');
|
||||
|
||||
if (pageCount > initialLoadCount) {
|
||||
loadRemainingPages(initialLoadCount + 1, bookWidth, bookHeight);
|
||||
} else {
|
||||
updatePageDisplay(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (pdfDoc) {
|
||||
run(pdfDoc);
|
||||
} else {
|
||||
pdfjsLib.getDocument(pdfUrl).promise.then(renderAllPages);
|
||||
}
|
||||
}
|
||||
|
||||
function loadRemainingPages(pageNum, bookWidth, bookHeight) {
|
||||
if (pageNum > pageCount) {
|
||||
updatePageDisplay(true);
|
||||
return;
|
||||
}
|
||||
renderPage(pageNum, bookWidth, bookHeight, false).then(function(pageDiv) {
|
||||
if ($flipbook.turn('is')) {
|
||||
$flipbook.turn('addPage', pageDiv, pageNum);
|
||||
}
|
||||
loadedPageCount = pageNum;
|
||||
updatePageDisplay();
|
||||
loadRemainingPages(pageNum + 1, bookWidth, bookHeight);
|
||||
});
|
||||
}
|
||||
|
||||
function updatePageDisplay(isComplete = false) {
|
||||
if (isComplete) {
|
||||
$totalPagesWrap.hide();
|
||||
$loadedPages.text(pageCount);
|
||||
} else {
|
||||
$loadedPages.text(loadedPageCount);
|
||||
$totalPagesWrap.show();
|
||||
}
|
||||
}
|
||||
|
||||
function renderPage(num, bookWidth, bookHeight, isInitial, loadLimit) {
|
||||
return pdfDoc.getPage(num).then(function(page) {
|
||||
var viewport = page.getViewport({ scale: 1.5 });
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
var pageWidth = bookWidth / 2;
|
||||
var pageHeight = bookHeight;
|
||||
var scaleX = pageWidth / viewport.width;
|
||||
var scaleY = pageHeight / viewport.height;
|
||||
var fitScale = Math.max(scaleX, scaleY);
|
||||
var fitViewport = page.getViewport({ scale: fitScale });
|
||||
|
||||
canvas.height = pageHeight;
|
||||
canvas.width = pageWidth;
|
||||
|
||||
var pageDiv = $('<div />').append(canvas);
|
||||
|
||||
var renderContext = { canvasContext: ctx, viewport: fitViewport };
|
||||
|
||||
return page.render(renderContext).promise.then(function() {
|
||||
if (isInitial) {
|
||||
renderedCount++;
|
||||
var percent = Math.round((renderedCount / loadLimit) * 100);
|
||||
$loadingText.text('Loading... (' + percent + '%)');
|
||||
}
|
||||
return pageDiv;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initTurnJs(bookWidth, bookHeight) {
|
||||
if (typeof $flipbook.turn !== 'function') return;
|
||||
if ($flipbook.turn('is')) $flipbook.turn('destroy');
|
||||
|
||||
$flipbook.turn({
|
||||
width: bookWidth,
|
||||
height: bookHeight,
|
||||
autoCenter: true,
|
||||
gradients: true,
|
||||
acceleration: true,
|
||||
elevation: 50,
|
||||
display: 'double',
|
||||
pages: pageCount,
|
||||
when: {
|
||||
turned: function(event, page, view) {
|
||||
$pageInput.val(page);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startEbookProcess();
|
||||
|
||||
// 이벤트 핸들러 (한 번만 등록)
|
||||
$module.find('#prev-btn, .nav-prev').off().on('click', function() { $flipbook.turn('previous'); });
|
||||
$module.find('#next-btn, .nav-next').off().on('click', function() { $flipbook.turn('next'); });
|
||||
$pageInput.off().on('change keyup', function(e) {
|
||||
if (e.type === 'keyup' && e.keyCode !== 13) return;
|
||||
var page = parseInt($(this).val());
|
||||
if (page > 0 && page <= pageCount) $flipbook.turn('page', page);
|
||||
});
|
||||
function updateZoom() {
|
||||
$viewport.css('transform', 'scale(' + currentScale + ')');
|
||||
$module.find('.zoom-level').text(Math.round(currentScale * 100) + '%');
|
||||
}
|
||||
$module.find('#zoom-in-btn').off().on('click', function() { if (currentScale < 2.0) { currentScale += 0.2; updateZoom(); } });
|
||||
$module.find('#zoom-out-btn').off().on('click', function() { if (currentScale > 0.6) { currentScale -= 0.2; updateZoom(); } });
|
||||
$module.find('#zoom-reset-btn').off().on('click', function() { currentScale = 1.0; updateZoom(); });
|
||||
$module.find('#dark-mode-btn').off().on('click', function() {
|
||||
var currentTheme = $module.attr('data-theme');
|
||||
var newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
||||
$module.attr('data-theme', newTheme);
|
||||
$(this).find('i').toggleClass('fa-sun fa-moon');
|
||||
});
|
||||
$module.find('#print-btn').off().on('click', function() {
|
||||
var $iframe = $module.find('iframe');
|
||||
$iframe.attr('src', pdfUrl);
|
||||
$iframe.on('load', function() {
|
||||
try { this.contentWindow.print(); }
|
||||
catch (e) { window.open(pdfUrl, '_blank').print(); }
|
||||
});
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,352 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
// 1. 설정 파일 로드
|
||||
$config_path = __DIR__ . '/config.php';
|
||||
if (file_exists($config_path)) include_once($config_path);
|
||||
|
||||
// 2. 데이터 가져오기
|
||||
$target_bo_table = '';
|
||||
$target_wr_id = '';
|
||||
|
||||
if (isset($ebook_bo_table) && $ebook_bo_table) {
|
||||
$target_bo_table = $ebook_bo_table;
|
||||
} elseif (isset($ebook_config['bo_table'])) {
|
||||
$target_bo_table = $ebook_config['bo_table'];
|
||||
}
|
||||
|
||||
if (isset($ebook_wr_id) && $ebook_wr_id) {
|
||||
$target_wr_id = $ebook_wr_id;
|
||||
} elseif (isset($ebook_config['wr_id'])) {
|
||||
$target_wr_id = $ebook_config['wr_id'];
|
||||
}
|
||||
|
||||
// 옵션값
|
||||
$use_download = isset($use_download) ? $use_download : (isset($ebook_config['use_download']) ? $ebook_config['use_download'] : true);
|
||||
$use_print = isset($use_print) ? $use_print : (isset($ebook_config['use_print']) ? $ebook_config['use_print'] : true);
|
||||
|
||||
$pdfjs_url = G5_THEME_URL . '/js/pdfjs';
|
||||
$pdf_file_url = '';
|
||||
$pdf_download_url = '';
|
||||
|
||||
if ($target_bo_table && $target_wr_id) {
|
||||
$sql = " SELECT * FROM {$g5['board_file_table']} WHERE bo_table = '{$target_bo_table}' AND wr_id = '{$target_wr_id}' ORDER BY bf_no ASC ";
|
||||
$result = sql_query($sql);
|
||||
for ($i=0; $row=sql_fetch_array($result); $i++) {
|
||||
if (isset($row['bf_file']) && preg_match('/\.pdf$/i', $row['bf_file'])) {
|
||||
$pdf_file_url = G5_DATA_URL . '/file/' . $target_bo_table . '/' . urlencode($row['bf_file']);
|
||||
$pdf_download_url = $pdf_file_url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ebook_id = 'ebook_' . uniqid();
|
||||
$popup_url = G5_THEME_URL . '/rb.custom/ebook_section/popup.php?bo_table=' . $target_bo_table . '&wr_id=' . $target_wr_id;
|
||||
?>
|
||||
|
||||
<!-- Rebuilder 표준 구조 -->
|
||||
<div class="rb_layout_box" data-id="ebook_section" data-title="E-Book">
|
||||
<?php if (isset($is_admin) && $is_admin) { ?>
|
||||
<div class="rb_module_set">
|
||||
<a href="javascript:;" onclick="set_module_send(this);" class="btn_module_setup"><i class="fa fa-cog"></i></a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<div class="ebook-section" id="<?php echo $ebook_id; ?>" data-theme="light">
|
||||
<?php if ($pdf_file_url): ?>
|
||||
|
||||
<div class="ebook-loading-overlay" style="display:flex;">
|
||||
<div class="spinner"></div>
|
||||
<p class="loading-text">E-Book을 준비 중입니다... (0%)</p>
|
||||
</div>
|
||||
|
||||
<div class="page-loading-alert" style="display:none;">잠시만 기다려 주세요...</div>
|
||||
|
||||
<div class="nav-arrow nav-prev" title="이전 페이지"><i class="fa fa-chevron-left"></i></div>
|
||||
<div class="nav-arrow nav-next" title="다음 페이지"><i class="fa fa-chevron-right"></i></div>
|
||||
|
||||
<div class="flipbook-viewport loading">
|
||||
<div class="container">
|
||||
<div class="flipbook"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ebook-controls loading">
|
||||
<div class="control-group">
|
||||
<button id="prev-btn" class="btn" title="이전 페이지"><i class="fa fa-chevron-left"></i></button>
|
||||
<div class="page-input-wrap">
|
||||
<input type="number" class="page-input" value="1" min="1"> / <span class="loaded-pages">0</span><span class="total-pages-wrap">(<span class="total-pages">0</span>)</span>
|
||||
</div>
|
||||
<button id="next-btn" class="btn" title="다음 페이지"><i class="fa fa-chevron-right"></i></button>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<button id="zoom-out-btn" class="btn" title="축소"><i class="fa fa-search-minus"></i></button>
|
||||
<span class="zoom-level" title="현재 배율">100%</span>
|
||||
<button id="zoom-reset-btn" class="btn" title="배율 초기화"><i class="fa fa-compress"></i></button>
|
||||
<button id="zoom-in-btn" class="btn" title="확대"><i class="fa fa-search-plus"></i></button>
|
||||
|
||||
<button id="dark-mode-btn" class="btn" title="다크 모드"><i class="fa fa-moon"></i></button>
|
||||
|
||||
<?php if ($use_print): ?>
|
||||
<button id="print-btn" class="btn" title="PDF 인쇄"><i class="fa fa-print"></i></button>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($use_download): ?>
|
||||
<a href="<?php echo $pdf_download_url; ?>" class="btn download-btn" download target="_blank" title="PDF 다운로드">
|
||||
<i class="fa fa-download"></i>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<a href="<?php echo $popup_url; ?>" class="btn popup-btn" target="_blank" onclick="window.open(this.href, 'ebook_popup', 'width=1200,height=800'); return false;" title="새 창으로 보기">
|
||||
<i class="fa fa-expand"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<iframe id="print-frame-<?php echo $ebook_id; ?>" style="display:none;"></iframe>
|
||||
|
||||
<?php else: ?>
|
||||
<div class="ebook-empty">
|
||||
PDF 파일이 없습니다.<br>
|
||||
<?php if ($target_bo_table && $target_wr_id): ?>
|
||||
게시판: <?php echo $target_bo_table; ?>, 게시물: <?php echo $target_wr_id; ?>
|
||||
<?php else: ?>
|
||||
설정 파일(config.php)을 확인해주세요.
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<link rel="stylesheet" href="<?php echo G5_THEME_URL; ?>/rb.custom/ebook_section/module.css?ver=<?php echo G5_CSS_VER; ?>">
|
||||
|
||||
<script src="<?php echo $pdfjs_url; ?>/pdf.min.js"></script>
|
||||
<script src="<?php echo G5_THEME_URL; ?>/rb.custom/ebook_section/turnjs4/lib/turn.min.js"></script>
|
||||
|
||||
<script>
|
||||
(function($) {
|
||||
if (!'<?php echo $pdf_file_url; ?>') return;
|
||||
|
||||
var resizeTimer; // 💡 [추가] 리사이즈 타이머 변수
|
||||
var pdfDoc = null;
|
||||
var pageCount = 0;
|
||||
var currentScale = 1.0;
|
||||
var initialLoadCount = 6;
|
||||
var loadedPageCount = 0;
|
||||
var renderedCount = 0;
|
||||
var isInitialized = false;
|
||||
|
||||
var $container = $('#<?php echo $ebook_id; ?>');
|
||||
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = '<?php echo $pdfjs_url; ?>/pdf.worker.min.js';
|
||||
|
||||
function startEbookProcess() {
|
||||
var $flipbook = $container.find('.flipbook');
|
||||
|
||||
if ($flipbook.turn('is')) {
|
||||
$flipbook.turn('destroy');
|
||||
}
|
||||
$flipbook.empty();
|
||||
$container.find('.ebook-loading-overlay').show();
|
||||
$container.find('.flipbook-viewport, .ebook-controls').addClass('loading');
|
||||
|
||||
var containerWidth = $container.width();
|
||||
if (!containerWidth || containerWidth < 100) containerWidth = 900;
|
||||
|
||||
var maxWidth = <?php echo isset($ebook_config['width']) ? $ebook_config['width'] : 1200; ?>;
|
||||
var maxHeight = <?php echo isset($ebook_config['height']) ? $ebook_config['height'] : 800; ?>;
|
||||
|
||||
var targetWidth = Math.min(containerWidth - 40, maxWidth);
|
||||
var bookWidth, bookHeight;
|
||||
|
||||
// 💡 [수정] 로딩 관련 변수 초기화
|
||||
renderedCount = 0;
|
||||
isInitialized = false;
|
||||
loadedPageCount = 0;
|
||||
$container.find('.loading-text').text('E-Book을 준비 중입니다... (0%)');
|
||||
|
||||
function run(pdf) {
|
||||
pdfDoc = pdf;
|
||||
pageCount = pdf.numPages;
|
||||
$container.find('.total-pages').text(pageCount);
|
||||
$container.find('.page-input').attr('max', pageCount);
|
||||
|
||||
pdf.getPage(1).then(function(page) {
|
||||
var viewport = page.getViewport({ scale: 1 });
|
||||
var pageRatio = viewport.width / viewport.height;
|
||||
var bookRatio = pageRatio * 2;
|
||||
|
||||
bookWidth = targetWidth;
|
||||
bookHeight = bookWidth / bookRatio;
|
||||
|
||||
if (bookHeight > maxHeight) {
|
||||
bookHeight = maxHeight;
|
||||
bookWidth = bookHeight * bookRatio;
|
||||
}
|
||||
|
||||
var initialPromises = [];
|
||||
var loadLimit = Math.min(pageCount, initialLoadCount);
|
||||
|
||||
for (var i = 1; i <= loadLimit; i++) {
|
||||
initialPromises.push(renderPage(i, bookWidth, bookHeight, true, loadLimit));
|
||||
}
|
||||
|
||||
Promise.all(initialPromises).then(function(pages) {
|
||||
pages.forEach(function(pageDiv) {
|
||||
$flipbook.append(pageDiv);
|
||||
});
|
||||
|
||||
initTurnJs(bookWidth, bookHeight);
|
||||
isInitialized = true;
|
||||
loadedPageCount = loadLimit;
|
||||
updatePageDisplay();
|
||||
|
||||
$container.find('.ebook-loading-overlay').fadeOut(500);
|
||||
$container.find('.flipbook-viewport, .ebook-controls').removeClass('loading');
|
||||
|
||||
if (pageCount > initialLoadCount) {
|
||||
loadRemainingPages(initialLoadCount + 1, bookWidth, bookHeight);
|
||||
} else {
|
||||
updatePageDisplay(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (pdfDoc) {
|
||||
run(pdfDoc);
|
||||
} else {
|
||||
pdfjsLib.getDocument('<?php echo $pdf_file_url; ?>').promise.then(run);
|
||||
}
|
||||
}
|
||||
|
||||
function loadRemainingPages(pageNum, bookWidth, bookHeight) {
|
||||
if (pageNum > pageCount) {
|
||||
updatePageDisplay(true);
|
||||
return;
|
||||
}
|
||||
renderPage(pageNum, bookWidth, bookHeight, false).then(function(pageDiv) {
|
||||
var $flipbook = $container.find('.flipbook');
|
||||
if ($flipbook.turn('is')) {
|
||||
$flipbook.turn('addPage', pageDiv, pageNum);
|
||||
}
|
||||
loadedPageCount = pageNum;
|
||||
updatePageDisplay();
|
||||
loadRemainingPages(pageNum + 1, bookWidth, bookHeight);
|
||||
});
|
||||
}
|
||||
|
||||
function updatePageDisplay(isComplete = false) {
|
||||
if (isComplete) {
|
||||
$container.find('.total-pages-wrap').hide();
|
||||
$container.find('.loaded-pages').text(pageCount);
|
||||
} else {
|
||||
$container.find('.loaded-pages').text(loadedPageCount);
|
||||
$container.find('.total-pages-wrap').show();
|
||||
}
|
||||
}
|
||||
|
||||
function renderPage(num, bookWidth, bookHeight, isInitial, loadLimit) {
|
||||
return pdfDoc.getPage(num).then(function(page) {
|
||||
var viewport = page.getViewport({ scale: 1.5 });
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
var pageWidth = bookWidth / 2;
|
||||
var pageHeight = bookHeight;
|
||||
var scaleX = pageWidth / viewport.width;
|
||||
var scaleY = pageHeight / viewport.height;
|
||||
var fitScale = Math.max(scaleX, scaleY);
|
||||
var fitViewport = page.getViewport({ scale: fitScale });
|
||||
|
||||
canvas.height = pageHeight;
|
||||
canvas.width = pageWidth;
|
||||
|
||||
var pageDiv = $('<div />').append(canvas);
|
||||
|
||||
var renderContext = { canvasContext: ctx, viewport: fitViewport };
|
||||
|
||||
return page.render(renderContext).promise.then(function() {
|
||||
if (isInitial) {
|
||||
renderedCount++;
|
||||
var percent = Math.round((renderedCount / loadLimit) * 100);
|
||||
$container.find('.loading-text').text('E-Book을 준비 중입니다... (' + percent + '%)');
|
||||
}
|
||||
return pageDiv;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initTurnJs(bookWidth, bookHeight) {
|
||||
var $flipbook = $container.find('.flipbook');
|
||||
if (typeof $flipbook.turn !== 'function') return;
|
||||
if ($flipbook.turn('is')) $flipbook.turn('destroy');
|
||||
|
||||
$flipbook.turn({
|
||||
width: bookWidth,
|
||||
height: bookHeight,
|
||||
autoCenter: true,
|
||||
gradients: true,
|
||||
acceleration: true,
|
||||
elevation: 50,
|
||||
display: 'double',
|
||||
pages: pageCount,
|
||||
when: {
|
||||
turned: function(event, page, view) {
|
||||
$container.find('.page-input').val(page);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 초기 실행
|
||||
startEbookProcess();
|
||||
|
||||
// 💡 [추가] 화면 리사이즈 시 이북 다시 로드
|
||||
$(window).on('resize', function() {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(startEbookProcess, 250);
|
||||
});
|
||||
|
||||
// 이벤트 핸들러
|
||||
$container.find('#prev-btn, .nav-prev').click(function() { $container.find('.flipbook').turn('previous'); });
|
||||
$container.find('#next-btn, .nav-next').click(function() { $container.find('.flipbook').turn('next'); });
|
||||
$container.find('.page-input').on('change keyup', function(e) {
|
||||
if (e.type === 'keyup' && e.keyCode !== 13) return;
|
||||
var page = parseInt($(this).val());
|
||||
if (page > 0 && page <= pageCount) $container.find('.flipbook').turn('page', page);
|
||||
});
|
||||
function updateZoom() {
|
||||
$container.find('.flipbook-viewport').css('transform', 'scale(' + currentScale + ')');
|
||||
$container.find('.zoom-level').text(Math.round(currentScale * 100) + '%');
|
||||
}
|
||||
$container.find('#zoom-in-btn').click(function() { if (currentScale < 2.0) { currentScale += 0.2; updateZoom(); } });
|
||||
$container.find('#zoom-out-btn').click(function() { if (currentScale > 0.6) { currentScale -= 0.2; updateZoom(); } });
|
||||
$container.find('#zoom-reset-btn').click(function() { currentScale = 1.0; updateZoom(); });
|
||||
$container.find('#dark-mode-btn').click(function() {
|
||||
var currentTheme = $container.attr('data-theme');
|
||||
var newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
||||
$container.attr('data-theme', newTheme);
|
||||
$(this).find('i').toggleClass('fa-sun fa-moon');
|
||||
});
|
||||
$container.find('#print-btn').click(function() {
|
||||
var $iframe = $container.find('iframe');
|
||||
$iframe.attr('src', '<?php echo $pdf_file_url; ?>');
|
||||
$iframe.on('load', function() {
|
||||
try { this.contentWindow.print(); }
|
||||
catch (e) { window.open('<?php echo $pdf_file_url; ?>', '_blank').print(); }
|
||||
});
|
||||
});
|
||||
var wheelTimeout;
|
||||
$container.on('wheel', function(e) {
|
||||
e.preventDefault();
|
||||
if (wheelTimeout) return;
|
||||
wheelTimeout = setTimeout(function() { wheelTimeout = null; }, 300);
|
||||
if (e.originalEvent.deltaY > 0) $container.find('.flipbook').turn('next');
|
||||
else $container.find('.flipbook').turn('previous');
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
</script>
|
||||
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
include_once('../../../../common.php');
|
||||
|
||||
$bo_table = isset($_GET['bo_table']) ? $_GET['bo_table'] : '';
|
||||
$wr_id = isset($_GET['wr_id']) ? $_GET['wr_id'] : '';
|
||||
|
||||
if (!$bo_table || !$wr_id) {
|
||||
alert_close('잘못된 접근입니다.');
|
||||
}
|
||||
|
||||
$sql = " SELECT * FROM {$g5['board_file_table']} WHERE bo_table = '{$bo_table}' AND wr_id = '{$wr_id}' ORDER BY bf_no ASC ";
|
||||
$result = sql_query($sql);
|
||||
$pdf_file_url = '';
|
||||
for ($i=0; $row=sql_fetch_array($result); $i++) {
|
||||
if (isset($row['bf_file']) && preg_match('/\.pdf$/i', $row['bf_file'])) {
|
||||
$pdf_file_url = G5_DATA_URL . '/file/' . $bo_table . '/' . urlencode($row['bf_file']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$pdf_file_url) {
|
||||
alert_close('PDF 파일이 없습니다.');
|
||||
}
|
||||
$pop_use_download = true;
|
||||
$pop_use_print = true;
|
||||
|
||||
$g5['title'] = 'E-Book Viewer';
|
||||
include_once(G5_PATH.'/head.sub.php');
|
||||
?>
|
||||
|
||||
<!-- 💡 [수정] module.css 파일을 불러오도록 변경 -->
|
||||
<link rel="stylesheet" href="./module.css?ver=<?php echo G5_CSS_VER; ?>">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||
|
||||
<style>
|
||||
/* 팝업 전용 스타일 */
|
||||
body, html { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; }
|
||||
.ebook-section { height: 100%; padding: 0; max-height: none; }
|
||||
.ebook-controls { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 1000; }
|
||||
.nav-arrow { width: 60px; height: 60px; font-size: 24px; }
|
||||
.nav-prev { left: 30px; }
|
||||
.nav-next { right: 30px; }
|
||||
</style>
|
||||
|
||||
<div class="ebook-section" id="ebook-popup" data-theme="dark">
|
||||
<div class="ebook-loading-overlay">
|
||||
<div class="spinner"></div>
|
||||
<p class="loading-text">Loading... (0%)</p>
|
||||
</div>
|
||||
|
||||
<div class="page-loading-alert" style="display:none;">잠시만 기다려 주세요...</div>
|
||||
|
||||
<div class="nav-arrow nav-prev" title="이전"><i class="fa fa-chevron-left"></i></div>
|
||||
<div class="nav-arrow nav-next" title="다음"><i class="fa fa-chevron-right"></i></div>
|
||||
|
||||
<div class="flipbook-viewport loading">
|
||||
<div class="flipbook"></div>
|
||||
</div>
|
||||
|
||||
<div class="ebook-controls loading">
|
||||
<div class="control-group">
|
||||
<button id="prev-btn" class="btn" title="이전"><i class="fa fa-chevron-left"></i></button>
|
||||
<div class="page-input-wrap">
|
||||
<input type="number" id="page-input" value="1" min="1"> / <span class="loaded-pages">0</span><span class="total-pages-wrap">(<span class="total-pages">0</span>)</span>
|
||||
</div>
|
||||
<button id="next-btn" class="btn" title="다음"><i class="fa fa-chevron-right"></i></button>
|
||||
</div>
|
||||
<div class="divider" style="width: 1px; height: 20px; background: rgba(128,128,128,0.5); margin: 0 5px;"></div>
|
||||
<div class="control-group">
|
||||
<button id="zoom-out-btn" class="btn" title="축소"><i class="fa fa-search-minus"></i></button>
|
||||
<span class="zoom-level" style="min-width: 45px; text-align: center;">100%</span>
|
||||
<button id="zoom-reset-btn" class="btn" title="초기화"><i class="fa fa-compress"></i></button>
|
||||
<button id="zoom-in-btn" class="btn" title="확대"><i class="fa fa-search-plus"></i></button>
|
||||
</div>
|
||||
<div class="divider" style="width: 1px; height: 20px; background: rgba(128,128,128,0.5); margin: 0 5px;"></div>
|
||||
<div class="control-group">
|
||||
<?php if ($pop_use_print): ?>
|
||||
<button id="print-btn" class="btn" title="인쇄"><i class="fa fa-print"></i></button>
|
||||
<?php endif; ?>
|
||||
<?php if ($pop_use_download): ?>
|
||||
<a href="<?php echo $pdf_file_url; ?>" class="btn" download target="_blank" title="다운로드"><i class="fa fa-download"></i></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<iframe id="print-frame" style="display:none;"></iframe>
|
||||
</div>
|
||||
|
||||
<?php if(!defined('G5_HEAD_SUB_FILE')) { ?>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
|
||||
<?php } ?>
|
||||
<script src="<?php echo G5_THEME_URL; ?>/rb.custom/ebook_section/turnjs4/lib/turn.min.js"></script>
|
||||
<script src="<?php echo G5_THEME_URL; ?>/js/pdfjs/pdf.min.js"></script>
|
||||
|
||||
<script>
|
||||
(function($) {
|
||||
var resizeTimer;
|
||||
var pdfDoc = null;
|
||||
var pageCount = 0;
|
||||
var currentScale = 1.0;
|
||||
var initialLoadCount = 6;
|
||||
var loadedPageCount = 0;
|
||||
var renderedCount = 0;
|
||||
var isInitialized = false;
|
||||
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = '<?php echo G5_THEME_URL; ?>/js/pdfjs/pdf.worker.min.js';
|
||||
|
||||
function startEbookProcess() {
|
||||
var $flipbook = $('.flipbook');
|
||||
|
||||
if ($flipbook.turn('is')) {
|
||||
$flipbook.turn('destroy');
|
||||
}
|
||||
$flipbook.empty();
|
||||
$('.ebook-loading-overlay').show();
|
||||
$('.flipbook-viewport, .ebook-controls').addClass('loading');
|
||||
|
||||
var canvasWidth = $(window).width() - 40;
|
||||
var canvasHeight = $(window).height() - 140;
|
||||
|
||||
if (canvasWidth > canvasHeight * 1.5) {
|
||||
canvasWidth = canvasHeight * 1.5;
|
||||
} else {
|
||||
canvasHeight = canvasWidth / 1.5;
|
||||
}
|
||||
|
||||
// 💡 [수정] 로딩 관련 변수 초기화
|
||||
renderedCount = 0;
|
||||
isInitialized = false;
|
||||
loadedPageCount = 0;
|
||||
$('.loading-text').text('Loading... (0%)'); // 로딩 텍스트도 초기화
|
||||
|
||||
function run(pdf) {
|
||||
pdfDoc = pdf;
|
||||
pageCount = pdf.numPages;
|
||||
$('.total-pages').text(pageCount);
|
||||
$('#page-input').attr('max', pageCount);
|
||||
|
||||
pdf.getPage(1).then(function(page) {
|
||||
var viewport = page.getViewport({ scale: 1 });
|
||||
var pageRatio = viewport.width / viewport.height;
|
||||
var bookRatio = pageRatio * 2;
|
||||
|
||||
var bookWidth = canvasWidth;
|
||||
var bookHeight = bookWidth / bookRatio;
|
||||
|
||||
if (bookHeight > canvasHeight) {
|
||||
bookHeight = canvasHeight;
|
||||
bookWidth = bookHeight * bookRatio;
|
||||
}
|
||||
|
||||
var initialPromises = [];
|
||||
var loadLimit = Math.min(pageCount, initialLoadCount);
|
||||
|
||||
for (var i = 1; i <= loadLimit; i++) {
|
||||
initialPromises.push(renderPage(i, bookWidth, bookHeight, true, loadLimit));
|
||||
}
|
||||
|
||||
Promise.all(initialPromises).then(function(pages) {
|
||||
pages.forEach(function(pageDiv) {
|
||||
$flipbook.append(pageDiv);
|
||||
});
|
||||
|
||||
initTurnJs(bookWidth, bookHeight);
|
||||
isInitialized = true;
|
||||
loadedPageCount = loadLimit;
|
||||
updatePageDisplay();
|
||||
|
||||
$('.ebook-loading-overlay').fadeOut(500);
|
||||
$('.flipbook-viewport, .ebook-controls').removeClass('loading');
|
||||
|
||||
if (pageCount > initialLoadCount) {
|
||||
loadRemainingPages(initialLoadCount + 1, bookWidth, bookHeight);
|
||||
} else {
|
||||
updatePageDisplay(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (pdfDoc) {
|
||||
run(pdfDoc);
|
||||
} else {
|
||||
pdfjsLib.getDocument('<?php echo $pdf_file_url; ?>').promise.then(run);
|
||||
}
|
||||
}
|
||||
|
||||
function loadRemainingPages(pageNum, bookWidth, bookHeight) {
|
||||
if (pageNum > pageCount) {
|
||||
updatePageDisplay(true);
|
||||
return;
|
||||
}
|
||||
renderPage(pageNum, bookWidth, bookHeight, false).then(function(pageDiv) {
|
||||
var $flipbook = $('.flipbook');
|
||||
if ($flipbook.turn('is')) {
|
||||
$flipbook.turn('addPage', pageDiv, pageNum);
|
||||
}
|
||||
loadedPageCount = pageNum;
|
||||
updatePageDisplay();
|
||||
loadRemainingPages(pageNum + 1, bookWidth, bookHeight);
|
||||
});
|
||||
}
|
||||
|
||||
function updatePageDisplay(isComplete = false) {
|
||||
if (isComplete) {
|
||||
$('.total-pages-wrap').hide();
|
||||
$('.loaded-pages').text(pageCount);
|
||||
} else {
|
||||
$('.loaded-pages').text(loadedPageCount);
|
||||
$('.total-pages-wrap').show();
|
||||
}
|
||||
}
|
||||
|
||||
function renderPage(num, bookWidth, bookHeight, isInitial, loadLimit) {
|
||||
return pdfDoc.getPage(num).then(function(page) {
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d', { willReadFrequently: true });
|
||||
|
||||
var pageWidth = bookWidth / 2;
|
||||
var pageHeight = bookHeight;
|
||||
|
||||
var viewport = page.getViewport({ scale: 1.5 });
|
||||
var scale = Math.min(pageWidth / viewport.width, pageHeight / viewport.height);
|
||||
var scaledViewport = page.getViewport({ scale: scale * 1.5 });
|
||||
|
||||
canvas.height = scaledViewport.height;
|
||||
canvas.width = scaledViewport.width;
|
||||
|
||||
$(canvas).css({ width: '100%', height: '100%' });
|
||||
|
||||
var pageDiv = $('<div />').append(canvas);
|
||||
|
||||
var renderContext = { canvasContext: ctx, viewport: scaledViewport };
|
||||
|
||||
return page.render(renderContext).promise.then(function() {
|
||||
if (isInitial) {
|
||||
renderedCount++;
|
||||
var percent = Math.round((renderedCount / loadLimit) * 100);
|
||||
$('.loading-text').text('Loading... (' + percent + '%)');
|
||||
}
|
||||
return pageDiv;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initTurnJs(bookWidth, bookHeight) {
|
||||
var $flipbook = $('.flipbook');
|
||||
if (typeof $flipbook.turn !== 'function') return;
|
||||
if ($flipbook.turn('is')) $flipbook.turn('destroy');
|
||||
|
||||
$flipbook.turn({
|
||||
width: bookWidth,
|
||||
height: bookHeight,
|
||||
autoCenter: true,
|
||||
gradients: true,
|
||||
acceleration: true,
|
||||
elevation: 50,
|
||||
display: 'double',
|
||||
pages: pageCount,
|
||||
when: {
|
||||
turning: function(event, page, view) {
|
||||
if (page > loadedPageCount) {
|
||||
event.preventDefault();
|
||||
$('.page-loading-alert').fadeIn(200).delay(1000).fadeOut(200);
|
||||
}
|
||||
},
|
||||
turned: function(event, page, view) {
|
||||
$('#page-input').val(page);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 초기 실행
|
||||
startEbookProcess();
|
||||
|
||||
$(window).on('resize', function() {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(startEbookProcess, 250);
|
||||
});
|
||||
|
||||
// 이벤트 핸들러
|
||||
$('#prev-btn, .nav-prev').click(function() { $('.flipbook').turn('previous'); });
|
||||
$('#next-btn, .nav-next').click(function() {
|
||||
var nextPage = $('.flipbook').turn('page') + 2;
|
||||
if (nextPage > loadedPageCount) {
|
||||
$('.page-loading-alert').fadeIn(200).delay(1000).fadeOut(200);
|
||||
return;
|
||||
}
|
||||
$('.flipbook').turn('next');
|
||||
});
|
||||
$('#page-input').on('change keyup', function(e) {
|
||||
if (e.type === 'keyup' && e.keyCode !== 13) return;
|
||||
var page = parseInt($(this).val());
|
||||
if (page > loadedPageCount) {
|
||||
$('.page-loading-alert').fadeIn(200).delay(1000).fadeOut(200);
|
||||
$(this).val($('.flipbook').turn('page'));
|
||||
return;
|
||||
}
|
||||
if (page > 0 && page <= pageCount) $('.flipbook').turn('page', page);
|
||||
});
|
||||
function updateZoom() {
|
||||
$('.flipbook-viewport').css('transform', 'scale(' + currentScale + ')');
|
||||
$('.zoom-level').text(Math.round(currentScale * 100) + '%');
|
||||
}
|
||||
$('#zoom-in-btn').click(function() { if (currentScale < 2.0) { currentScale += 0.2; updateZoom(); } });
|
||||
$('#zoom-out-btn').click(function() { if (currentScale > 0.6) { currentScale -= 0.2; updateZoom(); } });
|
||||
$('#zoom-reset-btn').click(function() { currentScale = 1.0; updateZoom(); });
|
||||
$('#dark-mode-btn').click(function() {
|
||||
var $section = $('#ebook-popup');
|
||||
var currentTheme = $section.attr('data-theme');
|
||||
var newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||
$section.attr('data-theme', newTheme);
|
||||
$(this).find('i').toggleClass('fa-sun fa-moon');
|
||||
});
|
||||
$('#print-btn').click(function() {
|
||||
var pdfUrl = '<?php echo $pdf_file_url; ?>';
|
||||
var $iframe = $('#print-frame');
|
||||
$iframe.attr('src', pdfUrl);
|
||||
$iframe.on('load', function() {
|
||||
try { this.contentWindow.print(); }
|
||||
catch (e) { window.open(pdfUrl, '_blank').print(); }
|
||||
});
|
||||
});
|
||||
var wheelTimeout;
|
||||
window.addEventListener('wheel', function(e) {
|
||||
e.preventDefault();
|
||||
if (wheelTimeout) return;
|
||||
wheelTimeout = setTimeout(function() { wheelTimeout = null; }, 300);
|
||||
if (e.deltaY > 0) {
|
||||
var nextPage = $('.flipbook').turn('page') + 2;
|
||||
if (nextPage > loadedPageCount) {
|
||||
$('.page-loading-alert').fadeIn(200).delay(1000).fadeOut(200);
|
||||
return;
|
||||
}
|
||||
$('.flipbook').turn('next');
|
||||
} else {
|
||||
$('.flipbook').turn('previous');
|
||||
}
|
||||
}, { passive: false });
|
||||
$(window).on('keydown', function(e) {
|
||||
if (e.keyCode == 37) $('.flipbook').turn('previous');
|
||||
else if (e.keyCode == 39) $('.flipbook').turn('next');
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
</script>
|
||||
|
||||
<?php
|
||||
include_once(G5_PATH.'/tail.sub.php');
|
||||
?>
|
||||
@@ -0,0 +1,139 @@
|
||||
Turn.js
|
||||
www.turnjs.com
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.1.0 - 2012/11/65
|
||||
------------------------------------------------------
|
||||
|
||||
+ Added support to the Android's default browser
|
||||
+ Fixed the hard page effect in IE9
|
||||
+ Fixed issue #220
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.9 - 2012/08/03
|
||||
------------------------------------------------------
|
||||
|
||||
+ Fixed issue when using the .own-size class
|
||||
+ Event zoom.change now is preventable
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.8 - 2012/07/16
|
||||
------------------------------------------------------
|
||||
|
||||
+ Added option direction
|
||||
+ Added method direction
|
||||
+ Added property direction
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.7 - 2012/07/12
|
||||
------------------------------------------------------
|
||||
|
||||
+ Fixed a issue of the pages method
|
||||
+ Fixed issue #112
|
||||
+ corner argument of the start event now returns null when using the methods next, previous and page
|
||||
+ Fixed issue of certain samples in IE8
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.6 - 2012/07/10
|
||||
------------------------------------------------------
|
||||
|
||||
+ Fixed a issue of the peel method when using the single display
|
||||
+ Fixed issue of using all the corners in single display mode
|
||||
+ Added method version
|
||||
+ Added option turnCorner
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.5 - 2012/06/16
|
||||
------------------------------------------------------
|
||||
|
||||
+ Fixed some visualization issues of the zoom viewport
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.4 - 2012/06/16
|
||||
------------------------------------------------------
|
||||
|
||||
+ Fixed a problem of the method page and event start
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.3 - 2012/06/16
|
||||
------------------------------------------------------
|
||||
|
||||
+ Fixed minor issues of HTML4 version
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.2 - 2012/06/16
|
||||
------------------------------------------------------
|
||||
|
||||
+ New Zoom viewport
|
||||
+ New magazine sample
|
||||
|
||||
------------------------------------------------------
|
||||
Turn.js 4.0.1 - 2012/06/12
|
||||
------------------------------------------------------
|
||||
|
||||
+ Fixed some issues when calculating z-index of pages
|
||||
+ Added method peel
|
||||
|
||||
------------------------------------------------------
|
||||
Release 4 Commercial - 2012/06/07
|
||||
------------------------------------------------------
|
||||
|
||||
+ Added option autoCenter
|
||||
+ Added option zoom
|
||||
+ Added property animating
|
||||
+ Added property zoom
|
||||
+ Added method center
|
||||
+ Added method destroy
|
||||
+ Added method is
|
||||
+ Added method zoom
|
||||
+ Added event missing
|
||||
+ Added event zooming
|
||||
+ Added class .even
|
||||
+ Added class .fixed
|
||||
+ Added class .hard
|
||||
+ Added class .odd
|
||||
+ Added class .own-size
|
||||
+ Added class .sheet
|
||||
+ Added class .sheet
|
||||
+ Added the ignore attribute
|
||||
+ New turn.html4.js
|
||||
+ New scissors.js
|
||||
+ Changed the class .turn-page to .page
|
||||
+ Improved the animation frame generator with requestAnimationFrame
|
||||
+ Improved the animation speed for hard pages with CSS3 transitions
|
||||
+ Redesigned the event sequence to listen to only three events
|
||||
+ Fixed issue #79
|
||||
+ Fixed issue #91
|
||||
+ Fixed issue about the event order turning
|
||||
+ turned
|
||||
+ Fixed issue about appending pages in wrong locations
|
||||
|
||||
------------------------------------------------------
|
||||
Release 3 - 2012/03/01
|
||||
------------------------------------------------------
|
||||
|
||||
+ Added 'range'
|
||||
+ Added 'addPage'
|
||||
+ Added 'removePage'
|
||||
+ Added 'hasPage'
|
||||
+ Added 'pages'
|
||||
+ Added 'display'
|
||||
+ Added 'when' to the initial configuration
|
||||
+ Added 'pages' to the initial configuration
|
||||
+ Added 'inclination' to the initial configuration
|
||||
+ Added 'first' event
|
||||
+ Added 'last' event
|
||||
+ Added gradients for non-webkit browsers
|
||||
|
||||
------------------------------------------------------
|
||||
Release 2 - 2012/02/15
|
||||
------------------------------------------------------
|
||||
|
||||
+ Added 'size'.
|
||||
+ Bug in Chrome 17-18 Beta about losing background-image was fixed.
|
||||
|
||||
------------------------------------------------------
|
||||
Release 1 - 2012/02/05
|
||||
------------------------------------------------------
|
||||
+ First alpha release
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
@@ -0,0 +1,12 @@
|
||||
/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
|
||||
* Licensed under the MIT License (LICENSE.txt).
|
||||
*
|
||||
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
|
||||
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
|
||||
* Thanks to: Seamus Leahy for adding deltaX and deltaY
|
||||
*
|
||||
* Version: 3.0.6
|
||||
*
|
||||
* Requires: 1.2.2+
|
||||
*/
|
||||
(function(a){function d(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=!0,g=0,h=0;return b=a.event.fix(c),b.type="mousewheel",c.wheelDelta&&(e=c.wheelDelta/120),c.detail&&(e=-c.detail/3),h=e,c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS&&(h=0,g=-1*e),c.wheelDeltaY!==undefined&&(h=c.wheelDeltaY/120),c.wheelDeltaX!==undefined&&(g=-1*c.wheelDeltaX/120),d.unshift(b,e,g,h),(a.event.dispatch||a.event.handle).apply(this,d)}var b=["DOMMouseScroll","mousewheel"];if(a.event.fixHooks)for(var c=b.length;c;)a.event.fixHooks[b[--c]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=b.length;a;)this.addEventListener(b[--a],d,!1);else this.onmousewheel=d},teardown:function(){if(this.removeEventListener)for(var a=b.length;a;)this.removeEventListener(b[--a],d,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery)
|
||||
@@ -0,0 +1,45 @@
|
||||
#/bin/sh
|
||||
# Requires Closure Compiler Application
|
||||
# https://developers.google.com/closure/compiler/docs/gettingstarted_app
|
||||
|
||||
# --compilation_level ADVANCED_OPTIMIZATIONS
|
||||
|
||||
SCRIPTS=("turn" "turn.html4" "zoom" "scissor")
|
||||
SCRIPTS_LEN=${#SCRIPTS[@]}
|
||||
SCRIPTS_COMMENT="/* turn.js 4.1.0 | Copyright (c) 2012 Emmanuel Garcia | turnjs.com | turnjs.com/license.txt */"
|
||||
|
||||
echo -e "${SCRIPTS_COMMENT}\n" > comment.js
|
||||
|
||||
if [ ! -f /tmp/compiler.jar ];
|
||||
then
|
||||
echo "Downloading Google Closure Compiler..."
|
||||
curl --silent -L http://closure-compiler.googlecode.com/files/compiler-latest.zip > /tmp/compiler-latest.zip
|
||||
unzip -o /tmp/compiler-latest.zip -d /tmp
|
||||
rm /tmp/compiler-latest.zip
|
||||
chmod +x /tmp/compiler.jar
|
||||
fi
|
||||
|
||||
echo "Making Minimized files..."
|
||||
|
||||
for (( i=0; i<${SCRIPTS_LEN}; i++ ));
|
||||
do
|
||||
java -jar "/tmp/compiler.jar" --js ${SCRIPTS[$i]}.js > ${SCRIPTS[$i]}.closure.js
|
||||
|
||||
cat comment.js ${SCRIPTS[$i]}.closure.js > ${SCRIPTS[$i]}.min.js
|
||||
|
||||
rm ${SCRIPTS[$i]}.closure.js
|
||||
|
||||
m=$(ls -la ${SCRIPTS[$i]}.min.js | awk '{ print $5}')
|
||||
gzip -nfc --best ${SCRIPTS[$i]}.min.js > ${SCRIPTS[$i]}.min.js.gz
|
||||
g=$(ls -la ${SCRIPTS[$i]}.min.js.gz | awk '{ print $5}')
|
||||
echo " ${SCRIPTS[$i]}.js: $m bytes minified, $g bytes gzipped"
|
||||
|
||||
rm ${SCRIPTS[$i]}.min.js.gz
|
||||
|
||||
if [ "--test" == "$1" ]; then
|
||||
rm ${SCRIPTS[$i]}.min.js
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
rm comment.js
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* hash.js
|
||||
*
|
||||
* Copyright (C) 2012 Emmanuel Garcia
|
||||
* MIT Licensed
|
||||
*
|
||||
* ****************************************
|
||||
*
|
||||
* Hash.pushState(true);
|
||||
*
|
||||
* Hash.on('/page/([0-9]+)$',
|
||||
* {yep: function(path, parts) { }, nop: function() { }},
|
||||
* 'Page $1');
|
||||
*
|
||||
* Hash.go('/page/1');
|
||||
**/
|
||||
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
var hashes = {},
|
||||
regexp = {},
|
||||
history = [],
|
||||
freq = 100,
|
||||
num = 0,
|
||||
pushState = false,
|
||||
timer = null,
|
||||
currentUrl = null,
|
||||
|
||||
freeze = function(obj) {
|
||||
if (Object.freeze) return Object.freeze(obj);
|
||||
return obj;
|
||||
},
|
||||
|
||||
getHashParts = function() {
|
||||
return window.location.href.split('#');
|
||||
},
|
||||
|
||||
startTimer = function() {
|
||||
|
||||
if (!timer)
|
||||
timer = setInterval(function() {
|
||||
if (num>0 && currentUrl!=window.location.href) {
|
||||
currentUrl = window.location.href;
|
||||
window.Hash.check();
|
||||
}
|
||||
}, freq);
|
||||
|
||||
},
|
||||
|
||||
stopTimer = function() {
|
||||
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
window.Hash = freeze({
|
||||
|
||||
pushState: function(yes) {
|
||||
|
||||
if (window.history && window.history.pushState)
|
||||
pushState = yes;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
fragment: function() {
|
||||
|
||||
var hash = getHashParts();
|
||||
return (pushState) ?
|
||||
window.location.pathname + ((hash[1]) ? '#' + hash[1] : '')
|
||||
: hash[1] || '';
|
||||
|
||||
},
|
||||
|
||||
get: function(path, params) {
|
||||
|
||||
var p, fragment = '', parameters = [];
|
||||
|
||||
for(p in params) {
|
||||
if (!Object.prototype.hasOwnProperty(p))
|
||||
continue;
|
||||
parameters.push(encodeURIComponent(p) + '=' + encodeURIComponent(params[p]));
|
||||
}
|
||||
|
||||
if (parameters.length>0)
|
||||
parameters = '?' + parameters.join('&');
|
||||
|
||||
return (pushState) ? path + parameters :
|
||||
getHashParts()[0] + '#' + path + parameters;
|
||||
|
||||
},
|
||||
|
||||
go: function(hash, params) {
|
||||
|
||||
if (this.fragment()!=hash) {
|
||||
var to = this.get(hash, params);
|
||||
|
||||
if (pushState)
|
||||
window.history.pushState(null, document.title, to);
|
||||
else
|
||||
window.location.href = to;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
update: function () {
|
||||
|
||||
currentUrl = window.location.href;
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
on: function(hash, callback, title) {
|
||||
|
||||
if (!hashes[hash])
|
||||
hashes[hash] = {title: title, listeners: []};
|
||||
|
||||
hashes[hash].listeners.push(callback);
|
||||
num++;
|
||||
startTimer();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
check: function() {
|
||||
|
||||
var i,
|
||||
hash,
|
||||
parts,
|
||||
fragment = this.fragment();
|
||||
|
||||
|
||||
for (hash in hashes) {
|
||||
if (!Object.prototype.hasOwnProperty.call(hashes, hash))
|
||||
continue;
|
||||
|
||||
hashes[hash].regexp = hashes[hash].regexp || new RegExp(hash);
|
||||
|
||||
if ((parts = hashes[hash].regexp.exec(fragment))) {
|
||||
if (hashes[hash].title)
|
||||
document.title = hashes[hash].title;
|
||||
|
||||
for (i = 0; i<hashes[hash].listeners.length; i++)
|
||||
if (hashes[hash].listeners[i].yep)
|
||||
hashes[hash].listeners[i].yep(fragment, parts);
|
||||
} else {
|
||||
for (i = 0; i<hashes[hash].listeners.length; i++)
|
||||
if (hashes[hash].listeners[i].nop)
|
||||
hashes[hash].listeners[i].nop(fragment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* scissor.js
|
||||
*
|
||||
* Copyright (C) 2012 Emmanuel Garcia
|
||||
* MIT Licensed
|
||||
*
|
||||
* Cuts paper for you! and cardboard too ;)
|
||||
**/
|
||||
|
||||
(function($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
$.extend($.fn, {
|
||||
scissor: function() {
|
||||
this.each(function() {
|
||||
|
||||
var element = $(this),
|
||||
pageProperties = {
|
||||
width: element.width()/2,
|
||||
height: element.height(),
|
||||
overflow: 'hidden'
|
||||
},
|
||||
newElement = element.clone(true);
|
||||
|
||||
var leftPage = $('<div />', {css: pageProperties}),
|
||||
rightPage = $('<div />', {css: pageProperties});
|
||||
|
||||
element.after(leftPage);
|
||||
leftPage.after(rightPage);
|
||||
|
||||
element.css({
|
||||
marginLeft: 0
|
||||
}).appendTo(leftPage);
|
||||
|
||||
newElement.css({
|
||||
marginLeft: -pageProperties.width
|
||||
}).appendTo(rightPage);
|
||||
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,3 @@
|
||||
/* turn.js 4.1.0 | Copyright (c) 2012 Emmanuel Garcia | turnjs.com | turnjs.com/license.txt */
|
||||
|
||||
(function(a){a.extend(a.fn,{scissor:function(){this.each(function(){var b=a(this),c={width:b.width()/2,height:b.height(),overflow:"hidden"},f=b.clone(!0),d=a("<div />",{css:c}),e=a("<div />",{css:c});b.after(d);d.after(e);b.css({marginLeft:0}).appendTo(d);f.css({marginLeft:-c.width}).appendTo(e)});return this}})})(jQuery);
|
||||
@@ -0,0 +1,48 @@
|
||||
/* turn.js 4.1.0 | Copyright (c) 2012 Emmanuel Garcia | turnjs.com | turnjs.com/license.txt */
|
||||
|
||||
(function(f){function s(a,b,c){if(!c[0]||"object"==typeof c[0])return b.init.apply(a,c);if(b[c[0]])return b[c[0]].apply(a,Array.prototype.slice.call(c,1));throw k(c[0]+" is an invalid value");}function q(a,b,c,d){return{css:{position:"absolute",top:a,left:b,overflow:d||"hidden","z-index":c||"auto"}}}function t(a,b,c,d,e){var g=1-e,f=g*g*g,l=e*e*e;return m(Math.round(f*a.x+3*e*g*g*b.x+3*e*e*g*c.x+l*d.x),Math.round(f*a.y+3*e*g*g*b.y+3*e*e*g*c.y+l*d.y))}function m(a,b){return{x:a,y:b}}function j(a,b){return Object.prototype.hasOwnProperty.call(b,
|
||||
a)}function k(a){function b(a){this.name="TurnJsError";this.message=a}b.prototype=Error();b.prototype.constructor=b;return new b(a)}function v(){return""}var r="",n={down:"mousedown",move:"mousemove",up:"mouseup",over:"mouseover",out:"mouseout"},p={backward:["l"],forward:["r"],all:["l","r"]},x=["single","double"],y=["ltr","rtl"],z={acceleration:!0,display:"double",duration:600,page:1,gradients:!0,when:null},A={acceleration:!0,corners:"forward",cornerSize:100,duration:600,gradients:!0},i={init:function(a){if(1<
|
||||
this.length)throw k("This selector has more than 1 element");for(var b=["Moz","Webkit","Khtml","O","ms"],c=b.length,d="";c--;)b[c]+"Transform"in document.body.style&&(d="-"+b[c].toLowerCase()+"-");r=d;var e,b=0,g=this.data(),c=this.children(),a=f.extend({width:this.width(),height:this.height(),direction:this.attr("dir")||this.css("direction")||"ltr"},z,a);g.opts=a;g.pageObjs={};g.pages={};g.pageWrap={};g.pagePlace={};g.pageMv=[];g.zoom=1;g.totalPages=a.pages||0;g.docEvents={mouseStart:function(a){for(var b in g.pages)if(j(b,
|
||||
g.pages)&&!1===h._eventStart.call(g.pages[b],a))return!1},mouseMove:function(a){for(var b in g.pages)j(b,g.pages)&&h._eventMove.call(g.pages[b],a)},mouseEnd:function(a){for(var b in g.pages)j(b,g.pages)&&h._eventEnd.call(g.pages[b],a)}};if(a.when)for(e in a.when)j(e,a.when)&&this.bind(e,a.when[e]);this.css({position:"relative",width:a.width,height:a.height});this.turn("display",a.display);""!==a.direction&&this.turn("direction",a.direction);for(e=0;e<c.length;e++)"1"!=f(c[e]).attr("ignore")&&this.turn("addPage",
|
||||
c[e],++b);f(this).bind(n.down,g.docEvents.mouseStart).bind("start",i._start).bind("end",i._end).bind("pressed",i._pressed).bind("released",i._released).bind("flip",i._flip);f(document).bind(n.move,g.docEvents.mouseMove).bind(n.up,g.docEvents.mouseEnd);this.turn("page",a.page);g.done=!0;return this},addPage:function(a,b){var c,d=!1,e=this.data(),g=e.totalPages+1;if(e.destroying)return!1;if(c=/\bp([0-9]+)\b/.exec(f(a).attr("class")))b=parseInt(c[1],10);if(b)if(b==g)d=!0;else{if(b>g)throw k('Page "'+
|
||||
b+'" cannot be inserted');}else b=g,d=!0;1<=b&&b<=g&&(c="double"==e.display?b%2?" odd":" even":"",e.done&&this.turn("stop"),b in e.pageObjs&&i._movePages.call(this,b,1),d&&(e.totalPages=g),e.pageObjs[b]=f(a).css({"float":"left"}).addClass("page p"+b+c),i._addPage.call(this,b),e.done&&this.turn("update"),i._removeFromDOM.call(this));return this},_addPage:function(a){var b=this.data(),c=b.pageObjs[a];if(c)if(i._necessPage.call(this,a)){if(!b.pageWrap[a]){var d=i._pageSize.call(this,a,!0);c.css({width:d.width,
|
||||
height:d.height});b.pagePlace[a]=a;b.pageWrap[a]=f("<div/>",{"class":"turn-page-wrapper",page:a,css:{position:"absolute",overflow:"hidden"}}).css(d);this.append(b.pageWrap[a]);b.pageWrap[a].prepend(b.pageObjs[a])}(!a||1==i._setPageLoc.call(this,a))&&i._makeFlip.call(this,a)}else b.pagePlace[a]=0,b.pageObjs[a]&&b.pageObjs[a].remove()},hasPage:function(a){return j(a,this.data().pageObjs)},center:function(a){var b=this.data(),c=f(this).turn("size"),d=c.width/(2*b.zoom)-c.width/2;"double"==b.display&&
|
||||
(a=this.turn("view",a||b.tpage||b.page),"ltr"==b.direction?a[0]?a[1]||(d+=c.width/4):d-=c.width/4:a[0]?a[1]||(d-=c.width/4):d+=c.width/4);f(this).css({marginLeft:d});return this},destroy:function(){var a=this.data();a.destroying=!0;f(this).unbind(n.down).unbind("end").unbind("first").unbind("flip").unbind("last").unbind("pressed").unbind("released").unbind("start").unbind("turning").unbind("turned").unbind("zooming");for(f(document).unbind(n.move,a.docEvents.mouseMove).unbind(n.up,a.docEvents.mouseEnd);0!==
|
||||
a.totalPages;)this.turn("removePage",a.totalPages);a.fparent&&a.fparent.remove();a.shadow&&a.shadow.remove();this.removeData();return this},is:function(){return"object"==typeof this.data().pages},zoom:function(a){var b=this.data();if("number"==typeof a){if(0.0010>a||100<a)throw k(a+" is not a value for zoom");var c=f.Event("zooming");this.trigger(c,[a,b.zoom]);if(c.isDefaultPrevented())return this;var c=f(this).turn("size"),d=1/b.zoom,e=Math.round(c.width*d*a),g=Math.round(c.height*d*a);b.zoom=a;
|
||||
f(this).turn("stop").turn("size",e,g).css({marginTop:c.height*d/2-g/2});b.opts.autoCenter?this.turn("center"):f(this).css({marginLeft:c.width*d/2-e/2});i._updateShadow.call(this);return this}return b.zoom},_pageSize:function(a,b){var c=this.data(),d={};if("single"==c.display)d.width=this.width(),d.height=this.height(),b&&(d.top=0,d.left=0,d.right="auto");else{var e=this.width()/2,g=this.height();c.pageObjs[a].hasClass("own-size")?(d.width=c.pageObjs[a].width(),d.height=c.pageObjs[a].height()):(d.width=
|
||||
e,d.height=g);if(b){var f=a%2;d.top=(g-d.height)/2;"ltr"==c.direction?(d[f?"right":"left"]=e-d.width,d[f?"left":"right"]="auto"):(d[f?"left":"right"]=e-d.width,d[f?"right":"left"]="auto")}}return d},_makeFlip:function(a){var b=this.data();if(!b.pages[a]&&b.pagePlace[a]==a){var c="single"==b.display,d=a%2;b.pages[a]=b.pageObjs[a].css(i._pageSize.call(this,a)).flip({page:a,next:d||c?a+1:a-1,turn:this,duration:b.opts.duration,acceleration:b.opts.acceleration,gradients:b.opts.gradients}).flip("disable",
|
||||
b.disabled)}return b.pages[a]},_makeRange:function(){var a,b;if(!(1>this.data().totalPages)){b=this.turn("range");for(a=b[0];a<=b[1];a++)i._addPage.call(this,a)}},range:function(a){var b,c,d,e=this.data(),a=a||e.tpage||e.page||1;d=i._view.call(this,a);if(1>a||a>e.totalPages)throw k('"'+a+'" is not a page for range');d[1]=d[1]||d[0];1<=d[0]&&d[1]<=e.totalPages?(a=Math.floor(2),e.totalPages-d[1]>d[0]?(b=Math.min(d[0]-1,a),c=2*a-b):(c=Math.min(e.totalPages-d[1],a),b=2*a-c)):c=b=5;return[Math.max(1,d[0]-
|
||||
b),Math.min(e.totalPages,d[1]+c)]},_necessPage:function(a){if(0===a)return!0;var b=this.data(),c=this.turn("range");return b.pageObjs[a].hasClass("fixed")||a>=c[0]&&a<=c[1]},_removeFromDOM:function(){var a,b=this.data();for(a in b.pageWrap)j(a,b.pageWrap)&&!i._necessPage.call(this,a)&&i._removePageFromDOM.call(this,a)},_removePageFromDOM:function(a){var b=this.data();if(b.pages[a]){var c=b.pages[a].data();h._moveFoldingPage.call(b.pages[a],!1);c.f&&c.f.fwrapper&&c.f.fwrapper.remove();b.pages[a].removeData();
|
||||
b.pages[a].remove();delete b.pages[a]}b.pageObjs[a]&&b.pageObjs[a].remove();b.pageWrap[a]&&(b.pageWrap[a].remove(),delete b.pageWrap[a]);delete b.pagePlace[a]},removePage:function(a){var b=this.data();if(1>a||a>b.totalPages)throw k("The page "+a+" doesn't exist");b.pageObjs[a]&&(this.turn("stop"),i._removePageFromDOM.call(this,a),delete b.pageObjs[a]);i._movePages.call(this,a,-1);b.totalPages-=1;b.page>b.totalPages?this.turn("page",b.totalPages):i._makeRange.call(this);return this},_movePages:function(a,
|
||||
b){var c,d=this,e=this.data(),g="single"==e.display,f=function(a){var c=a+b,f=c%2,h=f?" odd ":" even ";e.pageObjs[a]&&(e.pageObjs[c]=e.pageObjs[a].removeClass("p"+a+" odd even").addClass("p"+c+h));e.pagePlace[a]&&e.pageWrap[a]&&(e.pagePlace[c]=c,e.pageWrap[c]=e.pageObjs[c].hasClass("fixed")?e.pageWrap[a].attr("page",c):e.pageWrap[a].css(i._pageSize.call(d,c,!0)).attr("page",c),e.pages[a]&&(e.pages[c]=e.pages[a].flip("options",{page:c,next:g||f?c+1:c-1,corners:g?"all":f?"forward":"backward"})),b&&
|
||||
(delete e.pages[a],delete e.pagePlace[a],delete e.pageObjs[a],delete e.pageWrap[a],delete e.pageObjs[a]))};if(0<b)for(c=e.totalPages;c>=a;c--)f(c);else for(c=a;c<=e.totalPages;c++)f(c)},display:function(a){var b=this.data(),c=b.display;if(a){if(-1==f.inArray(a,x))throw k('"'+a+'" is not a value for display');"single"==a?b.pageObjs[0]||(this.turn("stop").css({overflow:"hidden"}),b.pageObjs[0]=f("<div />",{"class":"page p-temporal"}).css({width:this.width(),height:this.height()}).appendTo(this)):b.pageObjs[0]&&
|
||||
(this.turn("stop").css({overflow:""}),b.pageObjs[0].remove(),delete b.pageObjs[0]);b.display=a;c&&(a=this.turn("size"),i._movePages.call(this,1,0),this.turn("size",a.width,a.height).turn("update"));return this}return c},direction:function(a){var b=this.data();if("undefined"==typeof a)return b.direction;a=a.toLowerCase();if(-1==f.inArray(a,y))throw k('"'+a+'" is not a value for direction');"rtl"==a&&f(this).attr("dir","ltr").css({direction:"ltr"});b.direction=a;b.done&&this.turn("size",f(this).width(),
|
||||
f(this).height());return this},animating:function(){return 0<this.data().pageMv.length},disable:function(a){var b,c=this.data(),d=this.turn("view");c.disabled=void 0===a||!0===a;for(b in c.pages)j(b,c.pages)&&c.pages[b].flip("disable",a?f.inArray(b,d):!1);return this},disabled:function(a){return void 0===a?!0===this.data().disabled:this.turn("disable",a)},size:function(a,b){if(a&&b){var c,d,e=this.data();d="double"==e.display?a/2:a;this.css({width:a,height:b});e.pageObjs[0]&&e.pageObjs[0].css({width:d,
|
||||
height:b});for(c in e.pageWrap)j(c,e.pageWrap)&&(d=i._pageSize.call(this,c,!0),e.pageObjs[c].css({width:d.width,height:d.height}),e.pageWrap[c].css(d),e.pages[c]&&e.pages[c].css({width:d.width,height:d.height}));this.turn("resize");return this}return{width:this.width(),height:this.height()}},resize:function(){var a,b=this.data();b.pages[0]&&(b.pageWrap[0].css({left:-this.width()}),b.pages[0].flip("resize",!0));for(a=1;a<=b.totalPages;a++)b.pages[a]&&b.pages[a].flip("resize",!0)},_removeMv:function(a){var b,
|
||||
c=this.data();for(b=0;b<c.pageMv.length;b++)if(c.pageMv[b]==a)return c.pageMv.splice(b,1),!0;return!1},_addMv:function(a){var b=this.data();i._removeMv.call(this,a);b.pageMv.push(a)},_view:function(a){var b=this.data(),a=a||b.page;return"double"==b.display?a%2?[a-1,a]:[a,a+1]:[a]},view:function(a){var b=this.data(),a=i._view.call(this,a);return"double"==b.display?[0<a[0]?a[0]:0,a[1]<=b.totalPages?a[1]:0]:[0<a[0]&&a[0]<=b.totalPages?a[0]:0]},stop:function(){if(this.turn("animating")){var a,b,c,d=this.data(),
|
||||
e=d.pageMv;d.pageMv=[];d.tpage&&(d.page=d.tpage,delete d.tpage);for(a=0;a<e.length;a++)c=d.pages[e[a]],b=c.data().f.opts,c.flip("hideFoldedPage",!1),h._moveFoldingPage.call(c,!1),d.pagePlace[b.next]=b.next,b.force&&(b.next=0===b.page%2?b.page-1:b.page+1,delete b.force)}this.turn("update");return this},pages:function(a){var b=this.data();if(a){if(a<b.totalPages){for(var c=a+1;c<=b.totalPages;c++)this.turn("removePage",c);this.turn("page")>a&&this.turn("page",a)}b.totalPages=a;return this}return b.totalPages},
|
||||
_missing:function(a){for(var b=this.data(),c=this.turn("range",a),d=[],a=c[0];a<=c[1];a++)b.pageObjs[a]||d.push(a);0<d.length&&this.trigger("missing",[d])},_fitPage:function(a){var b=this.data(),c=this.turn("view",a);i._missing.call(this,a);b.pageObjs[a]&&(b.page=a,this.turn("stop"),i._removeFromDOM.call(this),i._makeRange.call(this),i._updateShadow.call(this),this.trigger("turned",[a,c]),b.opts.autoCenter&&this.turn("center"))},_turnPage:function(a,b){var c,d,e=this.data(),g=e.pagePlace[a],h=this.turn("view"),
|
||||
l=this.turn("view",a);if(e.page!=a){var w=f.Event("turning");this.trigger(w,[a,l]);if(w.isDefaultPrevented())return;-1!=f.inArray(1,l)&&this.trigger("first");-1!=f.inArray(e.totalPages,l)&&this.trigger("last")}if(b)this.turn("stop",g);else{i._missing.call(this,a);if(!e.pageObjs[a])return;this.turn("stop");e.page=a}i._makeRange.call(this);"single"==e.display?(c=h[0],d=l[0]):h[1]&&a>h[1]?(c=h[1],d=l[0]):h[0]&&a<h[0]&&(c=h[0],d=l[1]);e.pages[c]&&(g=e.pages[c].data().f.opts,e.tpage=d,g.next!=d&&(g.next=
|
||||
d,e.pagePlace[d]=g.page,g.force=!0),"single"==e.display?"ltr"==e.direction?e.pages[c].flip("turnPage",l[0]>h[0]?"r":"l"):e.pages[c].flip("turnPage",l[0]>h[0]?"l":"r"):e.pages[c].flip("turnPage"))},page:function(a){var a=parseInt(a,10),b=this.data();return 0<a&&a<=b.totalPages?(!b.done||-1!=f.inArray(a,this.turn("view"))?i._fitPage.call(this,a):i._turnPage.call(this,a),this):b.page},next:function(){return this.turn("page",i._view.call(this,this.data().page).pop()+1)},previous:function(){return this.turn("page",
|
||||
i._view.call(this,this.data().page).shift()-1)},peel:function(){return this},_addMotionPage:function(){var a=f(this).data().f.opts,b=a.turn,c=b.data();i._addMv.call(b,a.page);c.pagePlace[a.next]=a.page;b.turn("update")},_start:function(a,b,c){var d=b.turn.data();a.isDefaultPrevented()||("single"==d.display&&c&&("l"==c&&"ltr"==d.direction||"r"==c&&"rtl"==d.direction?(b.next=b.next<b.page?b.next:b.page-1,b.force=!0):b.next=b.next>b.page?b.next:b.page+1),i._addMotionPage.call(a.target));i._updateShadow.call(b.turn)},
|
||||
_end:function(a,b,c){f(a.target).data();var a=b.turn,d=a.data();if(c||d.tpage){if(d.tpage==b.next||d.tpage==b.page)delete d.tpage,i._fitPage.call(a,d.tpage||b.next,!0)}else i._removeMv.call(a,b.page),i._updateShadow.call(a),a.turn("update")},_pressed:function(a){a.stopPropagation();var b,a=f(a.target).data().f,c=a.opts.turn.data().pages;for(b in c)b!=a.opts.page&&c[b].flip("disable",!0);return a.time=(new Date).getTime()},_released:function(a,b){a.stopPropagation();var c,d=f(a.target),e=d.data().f,
|
||||
g=e.opts.turn,u=g.data();c="single"==u.display?"r"==b.corner?b.x<d.width()/2:b.x>d.width()/2:0>b.x||b.x>d.width();if(200>(new Date).getTime()-e.time||c)a.preventDefault(),i._turnPage.call(g,e.opts.next,!1===h._cornerActivated.call(d,b,1));u.mouseAction=!1},_flip:function(a){a.stopPropagation();a=f(a.target).data().f.opts;a.turn.trigger("turn",[a.next]);a.turn.data().opts.autoCenter&&a.turn.turn("center",a.next)},calculateZ:function(a){var b,c,d,e,g=this,f=this.data();b=this.turn("view");var h=b[0]||
|
||||
b[1],i={pageZ:{},partZ:{},pageV:{}},j=function(a){a=g.turn("view",a);a[0]&&(i.pageV[a[0]]=!0);a[1]&&(i.pageV[a[1]]=!0)};for(b=0;b<a.length;b++)c=a[b],d=f.pages[c].data().f.opts.next,e=f.pagePlace[c],j(c),j(d),c=f.pagePlace[d]==d?d:c,i.pageZ[c]=f.totalPages-Math.abs(h-c),i.partZ[e]=2*f.totalPages+Math.abs(h-c);return i},update:function(){var a,b=this.data();if(b.pageMv.length&&0!==b.pageMv[0]){var c,d=this.turn("calculateZ",b.pageMv);this.turn("view",b.tpage);for(a in b.pageWrap)if(j(a,b.pageWrap)&&
|
||||
(c=b.pageObjs[a].hasClass("fixed"),b.pageWrap[a].css({display:d.pageV[a]||c?"":"none","z-index":d.pageZ[a]||(c?-1:0)}),c=b.pages[a]))c.flip("z",d.partZ[a]||null),d.pageV[a]&&c.flip("resize"),b.tpage&&c.flip("disable",!0)}else for(a in b.pageWrap)j(a,b.pageWrap)&&(d=i._setPageLoc.call(this,a),b.pages[a]&&b.pages[a].flip("disable",b.disabled||1!=d).flip("z",null))},_updateShadow:function(){var a,b,c=this.data(),d=this.width(),e=this.height(),g="single"==c.display?d:d/2;a=this.turn("view");c.shadow||
|
||||
(c.shadow=f("<div />",{"class":"shadow",css:q(0,0,0).css}).appendTo(this));for(var h=0;h<c.pageMv.length&&a[0]&&a[1];h++)a=this.turn("view",c.pages[c.pageMv[h]].data().f.opts.next),b=this.turn("view",c.pageMv[h]),a[0]=a[0]&&b[0],a[1]=a[1]&&b[1];switch(a[0]?a[1]?3:"ltr"==c.direction?2:1:"ltr"==c.direction?1:2){case 1:c.shadow.css({width:g,height:e,top:0,left:g});break;case 2:c.shadow.css({width:g,height:e,top:0,left:0});break;case 3:c.shadow.css({width:d,height:e,top:0,left:0})}},_setPageLoc:function(a){var b=
|
||||
this.data(),c=this.turn("view");if(a==c[0]||a==c[1])return b.pageWrap[a].css({zIndex:b.totalPages,display:""}),1;if("single"==b.display&&a==c[0]+1||"double"==b.display&&a==c[0]-2||a==c[1]+2)return b.pageWrap[a].css({zIndex:b.totalPages-1,display:""}),2;b.pageWrap[a].css({zIndex:0,display:b.pageObjs[a].hasClass("fixed")?"":"none"});return 0},options:function(a){if(void 0===a)return this.data().opts;var b=this.data();f.extend(b.opts,a);a.pages&&this.turn("pages",a.pages);a.page&&this.turn("page",a.page);
|
||||
a.display&&this.turn("display",a.display);a.direction&&this.turn("direction",a.direction);a.width&&a.height&&this.turn("size",a.width,a.height);if(a.when)for(var c in a.when)j(c,a.when)&&this.unbind(c).bind(c,a.when[c]);return this},version:function(){return"4.1.0"}},h={init:function(a){this.data({f:{effect:"r"==a.corners||"l"==a.corners?"hard":"sheet"}});this.flip("options",a);h._addPageWrapper.call(this);return this},setData:function(a){var b=this.data();b.f=f.extend(b.f,a);return this},options:function(a){var b=
|
||||
this.data().f;return a?(h.setData.call(this,{opts:f.extend({},b.opts||A,a)}),this):b.opts},z:function(a){var b=this.data().f;b.fwrapper&&(b.opts["z-index"]=a,b.fwrapper.css({"z-index":a||parseInt(b.parent.css("z-index"),10)||0}));return this},_cAllowed:function(){var a=this.data().f,b=a.opts.turn.data(),a=a.opts.page,c=a%2;return"single"==b.display?1==a?"ltr"==b.direction?p.forward:p.backward:a==b.totalPages?"ltr"==b.direction?p.backward:p.forward:p.all:"ltr"==b.direction?p[c?"forward":"backward"]:
|
||||
p[c?"backward":"forward"]},_cornerActivated:function(a){var b=this.data().f,c=b.parent.offset(),d=this.width(),e=this.height(),a={x:Math.max(0,a.pageX-c.left),y:Math.max(0,a.pageY-c.top)},b=b.opts.cornerSize;if(0>=a.x||0>=a.y||a.x>=d||a.y>=e)return!1;e=h._cAllowed.call(this);if(a.x>d-b)a.corner="r";else if(a.x<b)a.corner="l";else return!1;return-1==f.inArray(a.corner,e)?!1:a},_c:function(a,b){b=b||0;switch(a){case "l":return m(b,0);case "r":return m(this.width()-b,0)}},_c2:function(a){switch(a){case "l":return m(2*
|
||||
this.width(),0);case "r":return m(-this.width(),0)}},_foldingPage:function(){var a=this.data().f,b=a.opts;if(a.folding)return a.folding;if(b.turn)return a=b.turn.data(),"single"==a.display?a.pageObjs[b.next]?a.pageObjs[0]:null:a.pageObjs[b.next]},_backGradient:function(){var a=this.data().f,b=a.opts.turn;return a.opts.gradients&&(!b||"single"==b.data().display||2!=a.opts.page&&a.opts.page!=b.data().totalPages-1)},resize:function(a){var b=this.data().f,c=this.width(),d=this.height();a&&(b.wrapper.css({width:c,
|
||||
height:d}),b.fpage.css({width:c,height:d}))},_addPageWrapper:function(){var a=this.data().f,b=this.parent();a.parent=b;if(!a.wrapper){var c={};a.wrapper=f("<div/>",q(0,0,2)).css(c).appendTo(b).prepend(this);a.fpage=f("<div/>",q(0,0,1)).css(c).appendTo(b)}h.resize.call(this,!0)},_fold:function(a){var b=this.data().f,c=h._c.call(this,a.corner),c=c.x?c.x-a.x:a.x,d=this.width();this.height();c=Math.min(2*d,Math.max(0,c));switch(a.corner){case "r":b.wrapper.css({width:Math.max(0,d-c)});this.css({position:"relative",
|
||||
left:-c});b.fpage.css({left:-c+d,width:Math.max(0,c-d)});break;case "l":b.wrapper.css({width:d}),this.css({position:"relative",left:c}),b.fpage.css({left:d,width:Math.max(0,c-d)}),b.folding&&b.folding.css({position:"relative",left:2*-d+c})}b.parent.css({overflow:"visible"});b.point=a},_moveFoldingPage:function(a){var b=this.data().f;if(a){var a=h._foldingPage.call(this),c=b.opts.turn;if(a){if(b.folding){if(b.folding===a)return;h._moveFoldingPage.call(this,!1)}h.setData.call(this,{backParent:a.parent(),
|
||||
folding:a});b.fpage.prepend(a)}c.turn("update")}else b.backParent&&(b.backParent.prepend(b.folding),delete b.backParent,delete b.folding)},_showFoldedPage:function(a,b){var c=h._foldingPage.call(this),d=this.data(),e=d.f,g=e.visible;if(!g||!e.point||e.point.corner!=a.corner){e.opts.turn.data();var i=f.Event("start");this.trigger(i,[e.opts,a.corner]);g=!1;if(i.isDefaultPrevented())return!1}if(c){if(b){var l=this,c=e.point&&e.point.corner==a.corner?e.point:h._c.call(this,a.corner,1);this.animatef({from:[c.x,
|
||||
c.y],to:[a.x,a.y],duration:500,frame:function(b){a.x=Math.round(b[0]);a.y=Math.round(b[1]);h._fold.call(l,a)}})}else h._fold.call(this,a),d.effect&&!d.effect.turning&&this.animatef(!1);g||(e.visible=!0,h._moveFoldingPage.call(this,!0),e.fpage.show());return!0}return!1},hide:function(){var a=this.data().f;h._foldingPage.call(this);this.css({position:"",left:"auto"});a.wrapper.css({width:this.width()});a.fpage.css({width:this.width()});a.folding&&a.folding.css({position:"",left:"auto"});a.fpage.hide();
|
||||
a.visible=!1;return this},hideFoldedPage:function(a){var b=this.data().f;if(b.point){var c=this,d=b.point,e=function(){b.point=null;c.flip("hide");c.trigger("end",[b.opts,!1])};if(a){var g=h._c.call(this,d.corner),a="t"==d.corner.substr(0,1)?Math.min(0,d.y-g.y)/2:Math.max(0,d.y-g.y)/2,f=m(d.x,d.y+a),i=m(g.x,g.y-a);this.animatef({from:0,to:1,frame:function(a){a=t(d,f,i,g,a);d.x=a.x;d.y=a.y;h._fold.call(c,d)},complete:e,duration:800,hiding:!0})}else this.animatef(!1),e()}},turnPage:function(a){var b=
|
||||
this,c=this.data().f,a={corner:c.corner?c.corner.corner:a||h._cAllowed.call(this)[0]},d=c.point||h._c.call(this,a.corner,c.opts.turn?c.opts.turn.data().opts.elevation:0),e=h._c2.call(this,a.corner);this.trigger("flip").animatef({from:0,to:1,frame:function(c){c=t(d,d,e,e,c);a.x=c.x;a.y=c.y;h._showFoldedPage.call(b,a)},complete:function(){b.trigger("end",[c.opts,!0])},duration:c.opts.duration,turning:!0});c.corner=null},moving:function(){return"effect"in this.data()},isTurning:function(){return this.flip("moving")&&
|
||||
this.data().effect.turning},_eventStart:function(a){var b=this.data().f;if(!b.disabled&&!this.flip("isTurning")){b.corner=h._cornerActivated.call(this,a);if(b.corner&&h._foldingPage.call(this,b.corner))return h._showFoldedPage.call(this,b.corner)&&this.trigger("pressed",[b.point]),!1;b.corner=null}},_eventMove:function(a){var b=this.data().f;if(!b.disabled)if(a=[a],b.corner){var c=b.parent.offset();b.corner.x=a[0].pageX-c.left;b.corner.y=a[0].pageY-c.top;h._showFoldedPage.call(this,b.corner)}else!this.data().effect&&
|
||||
this.is(":visible")&&((a=h._cornerActivated.call(this,a[0]))?(b=h._c.call(this,a.corner,b.opts.cornerSize/2),a.x=b.x,a.y=b.y,h._showFoldedPage.call(this,a,!0)):h.hideFoldedPage.call(this,!0))},_eventEnd:function(){var a=this.data().f;if(!a.disabled&&a.point){var b=f.Event("released");this.trigger(b,[a.point]);b.isDefaultPrevented()||h.hideFoldedPage.call(this,!0)}a.corner=null},disable:function(a){h.setData.call(this,{disabled:a});return this}};window.requestAnim=function(a){window.setTimeout(a,1E3/
|
||||
60)};f.extend(f.fn,{flip:function(a,b){return s(this,h,arguments)},turn:function(a){return s(this,i,arguments)},transform:function(a,b){var c={};b&&(c[r+"transform-origin"]=b);c[r+"transform"]=a;return this.css(c)},animatef:function(a){var b=this.data();b.effect&&b.effect.stop();if(a){a.to.length||(a.to=[a.to]);a.from.length||(a.from=[a.from]);for(var c=[],d=a.to.length,e=!0,g=this,h=(new Date).getTime(),i=function(){if(b.effect&&e){for(var f=[],j=Math.min(a.duration,(new Date).getTime()-h),k=0;k<
|
||||
d;k++)f.push(b.effect.easing(1,j,a.from[k],c[k],a.duration));a.frame(1==d?f[0]:f);j==a.duration?(delete b.effect,g.data(b),a.complete&&a.complete()):window.requestAnim(i)}},j=0;j<d;j++)c.push(a.to[j]-a.from[j]);b.effect=f.extend({stop:function(){e=!1},easing:function(a,b,c,d,e){return d*Math.sqrt(1-(b=b/e-1)*b)+c}},a);this.data(b);i()}else delete b.effect}});f.isTouch=!1;f.mouseEvents=n;f.cssPrefix=v;f.cssTransitionEnd=v;f.findPos=function(a){var b={top:0,left:0};do b.left+=a.offsetLeft,b.top+=a.offsetTop;
|
||||
while(a=a.offsetParent);return b}})(jQuery);
|
||||
@@ -0,0 +1,68 @@
|
||||
/* turn.js 4.1.0 | Copyright (c) 2012 Emmanuel Garcia | turnjs.com | turnjs.com/license.txt */
|
||||
|
||||
(function(f){function J(a,b,c){if(!c[0]||"object"==typeof c[0])return b.init.apply(a,c);if(b[c[0]])return b[c[0]].apply(a,Array.prototype.slice.call(c,1));throw q(c[0]+" is not a method or property");}function l(a,b,c,d){return{css:{position:"absolute",top:a,left:b,overflow:d||"hidden",zIndex:c||"auto"}}}function S(a,b,c,d,e){var h=1-e,f=h*h*h,g=e*e*e;return j(Math.round(f*a.x+3*e*h*h*b.x+3*e*e*h*c.x+g*d.x),Math.round(f*a.y+3*e*h*h*b.y+3*e*e*h*c.y+g*d.y))}function j(a,b){return{x:a,y:b}}function F(a,
|
||||
b,c){return z&&c?" translate3d("+a+"px,"+b+"px, 0px) ":" translate("+a+"px, "+b+"px) "}function G(a){return" rotate("+a+"deg) "}function n(a,b){return Object.prototype.hasOwnProperty.call(b,a)}function T(){for(var a=["Moz","Webkit","Khtml","O","ms"],b=a.length,c="";b--;)a[b]+"Transform"in document.body.style&&(c="-"+a[b].toLowerCase()+"-");return c}function P(a,b,c,d,e){var h,f=[];if("-webkit-"==w){for(h=0;h<e;h++)f.push("color-stop("+d[h][0]+", "+d[h][1]+")");a.css({"background-image":"-webkit-gradient(linear, "+
|
||||
b.x+"% "+b.y+"%,"+c.x+"% "+c.y+"%, "+f.join(",")+" )"})}else{var b={x:b.x/100*a.width(),y:b.y/100*a.height()},c={x:c.x/100*a.width(),y:c.y/100*a.height()},g=c.x-b.x;h=c.y-b.y;var i=Math.atan2(h,g),x=i-Math.PI/2,x=Math.abs(a.width()*Math.sin(x))+Math.abs(a.height()*Math.cos(x)),g=Math.sqrt(h*h+g*g),c=j(c.x<b.x?a.width():0,c.y<b.y?a.height():0),k=Math.tan(i);h=-1/k;k=(h*c.x-c.y-k*b.x+b.y)/(h-k);c=h*k-h*c.x+c.y;b=Math.sqrt(Math.pow(k-b.x,2)+Math.pow(c-b.y,2));for(h=0;h<e;h++)f.push(" "+d[h][1]+" "+100*
|
||||
(b+g*d[h][0])/x+"%");a.css({"background-image":w+"linear-gradient("+-i+"rad,"+f.join(",")+")"})}}function t(a,b,c){a=f.Event(a);b.trigger(a,c);return a.isDefaultPrevented()?"prevented":a.isPropagationStopped()?"stopped":""}function q(a){function b(a){this.name="TurnJsError";this.message=a}b.prototype=Error();b.prototype.constructor=b;return new b(a)}function D(a){var b={top:0,left:0};do b.left+=a.offsetLeft,b.top+=a.offsetTop;while(a=a.offsetParent);return b}var z,U,w="",K=Math.PI,L=K/2,u="ontouchstart"in
|
||||
window,r=u?{down:"touchstart",move:"touchmove",up:"touchend",over:"touchstart",out:"touchend"}:{down:"mousedown",move:"mousemove",up:"mouseup",over:"mouseover",out:"mouseout"},p={backward:["bl","tl"],forward:["br","tr"],all:"tl bl tr br l r".split(" ")},V=["single","double"],W=["ltr","rtl"],X={acceleration:!0,display:"double",duration:600,page:1,gradients:!0,turnCorners:"bl,br",when:null},Y={cornerSize:100},g={init:function(a){z="WebKitCSSMatrix"in window||"MozPerspective"in document.body.style;var b;
|
||||
U=(b=/AppleWebkit\/([0-9\.]+)/i.exec(navigator.userAgent))?534.3<parseFloat(b[1]):!0;w=T();var c;b=0;var d=this.data(),e=this.children(),a=f.extend({width:this.width(),height:this.height(),direction:this.attr("dir")||this.css("direction")||"ltr"},X,a);d.opts=a;d.pageObjs={};d.pages={};d.pageWrap={};d.pageZoom={};d.pagePlace={};d.pageMv=[];d.zoom=1;d.totalPages=a.pages||0;d.eventHandlers={touchStart:f.proxy(g._touchStart,this),touchMove:f.proxy(g._touchMove,this),touchEnd:f.proxy(g._touchEnd,this),
|
||||
start:f.proxy(g._eventStart,this)};if(a.when)for(c in a.when)n(c,a.when)&&this.bind(c,a.when[c]);this.css({position:"relative",width:a.width,height:a.height});this.turn("display",a.display);""!==a.direction&&this.turn("direction",a.direction);z&&(!u&&a.acceleration)&&this.transform(F(0,0,!0));for(c=0;c<e.length;c++)"1"!=f(e[c]).attr("ignore")&&this.turn("addPage",e[c],++b);f(this).bind(r.down,d.eventHandlers.touchStart).bind("end",g._eventEnd).bind("pressed",g._eventPressed).bind("released",g._eventReleased).bind("flip",
|
||||
g._flip);f(this).parent().bind("start",d.eventHandlers.start);f(document).bind(r.move,d.eventHandlers.touchMove).bind(r.up,d.eventHandlers.touchEnd);this.turn("page",a.page);d.done=!0;return this},addPage:function(a,b){var c,d=!1,e=this.data(),h=e.totalPages+1;if(e.destroying)return!1;if(c=/\bp([0-9]+)\b/.exec(f(a).attr("class")))b=parseInt(c[1],10);if(b)if(b==h)d=!0;else{if(b>h)throw q('Page "'+b+'" cannot be inserted');}else b=h,d=!0;1<=b&&b<=h&&(c="double"==e.display?b%2?" odd":" even":"",e.done&&
|
||||
this.turn("stop"),b in e.pageObjs&&g._movePages.call(this,b,1),d&&(e.totalPages=h),e.pageObjs[b]=f(a).css({"float":"left"}).addClass("page p"+b+c),-1!=navigator.userAgent.indexOf("MSIE 9.0")&&e.pageObjs[b].hasClass("hard")&&e.pageObjs[b].removeClass("hard"),g._addPage.call(this,b),g._removeFromDOM.call(this));return this},_addPage:function(a){var b=this.data(),c=b.pageObjs[a];if(c)if(g._necessPage.call(this,a)){if(!b.pageWrap[a]){b.pageWrap[a]=f("<div/>",{"class":"page-wrapper",page:a,css:{position:"absolute",
|
||||
overflow:"hidden"}});this.append(b.pageWrap[a]);b.pagePlace[a]||(b.pagePlace[a]=a,b.pageObjs[a].appendTo(b.pageWrap[a]));var d=g._pageSize.call(this,a,!0);c.css({width:d.width,height:d.height});b.pageWrap[a].css(d)}b.pagePlace[a]==a&&g._makeFlip.call(this,a)}else b.pagePlace[a]=0,b.pageObjs[a]&&b.pageObjs[a].remove()},hasPage:function(a){return n(a,this.data().pageObjs)},center:function(a){var b=this.data(),c=f(this).turn("size"),d=0;b.noCenter||("double"==b.display&&(a=this.turn("view",a||b.tpage||
|
||||
b.page),"ltr"==b.direction?a[0]?a[1]||(d+=c.width/4):d-=c.width/4:a[0]?a[1]||(d-=c.width/4):d+=c.width/4),f(this).css({marginLeft:d}));return this},destroy:function(){var a=this,b=this.data(),c="end first flip last pressed released start turning turned zooming missing".split(" ");if("prevented"!=t("destroying",this)){b.destroying=!0;f.each(c,function(b,c){a.unbind(c)});this.parent().unbind("start",b.eventHandlers.start);for(f(document).unbind(r.move,b.eventHandlers.touchMove).unbind(r.up,b.eventHandlers.touchEnd);0!==
|
||||
b.totalPages;)this.turn("removePage",b.totalPages);b.fparent&&b.fparent.remove();b.shadow&&b.shadow.remove();this.removeData();b=null;return this}},is:function(){return"object"==typeof this.data().pages},zoom:function(a){var b=this.data();if("number"==typeof a){if(0.0010>a||100<a)throw q(a+" is not a value for zoom");if("prevented"==t("zooming",this,[a,b.zoom]))return this;var c=this.turn("size"),d=this.turn("view"),e=1/b.zoom,h=Math.round(c.width*e*a),c=Math.round(c.height*e*a);b.zoom=a;f(this).turn("stop").turn("size",
|
||||
h,c);b.opts.autoCenter&&this.turn("center");g._updateShadow.call(this);for(a=0;a<d.length;a++)d[a]&&b.pageZoom[d[a]]!=b.zoom&&(this.trigger("zoomed",[d[a],d,b.pageZoom[d[a]],b.zoom]),b.pageZoom[d[a]]=b.zoom);return this}return b.zoom},_pageSize:function(a,b){var c=this.data(),d={};if("single"==c.display)d.width=this.width(),d.height=this.height(),b&&(d.top=0,d.left=0,d.right="auto");else{var e=this.width()/2,h=this.height();c.pageObjs[a].hasClass("own-size")?(d.width=c.pageObjs[a].width(),d.height=
|
||||
c.pageObjs[a].height()):(d.width=e,d.height=h);if(b){var f=a%2;d.top=(h-d.height)/2;"ltr"==c.direction?(d[f?"right":"left"]=e-d.width,d[f?"left":"right"]="auto"):(d[f?"left":"right"]=e-d.width,d[f?"right":"left"]="auto")}}return d},_makeFlip:function(a){var b=this.data();if(!b.pages[a]&&b.pagePlace[a]==a){var c="single"==b.display,d=a%2;b.pages[a]=b.pageObjs[a].css(g._pageSize.call(this,a)).flip({page:a,next:d||c?a+1:a-1,turn:this}).flip("disable",b.disabled);g._setPageLoc.call(this,a);b.pageZoom[a]=
|
||||
b.zoom}return b.pages[a]},_makeRange:function(){var a,b;if(!(1>this.data().totalPages)){b=this.turn("range");for(a=b[0];a<=b[1];a++)g._addPage.call(this,a)}},range:function(a){var b,c,d,e=this.data(),a=a||e.tpage||e.page||1;d=g._view.call(this,a);if(1>a||a>e.totalPages)throw q('"'+a+'" is not a valid page');d[1]=d[1]||d[0];1<=d[0]&&d[1]<=e.totalPages?(a=Math.floor(2),e.totalPages-d[1]>d[0]?(b=Math.min(d[0]-1,a),c=2*a-b):(c=Math.min(e.totalPages-d[1],a),b=2*a-c)):c=b=5;return[Math.max(1,d[0]-b),Math.min(e.totalPages,
|
||||
d[1]+c)]},_necessPage:function(a){if(0===a)return!0;var b=this.turn("range");return this.data().pageObjs[a].hasClass("fixed")||a>=b[0]&&a<=b[1]},_removeFromDOM:function(){var a,b=this.data();for(a in b.pageWrap)n(a,b.pageWrap)&&!g._necessPage.call(this,a)&&g._removePageFromDOM.call(this,a)},_removePageFromDOM:function(a){var b=this.data();if(b.pages[a]){var c=b.pages[a].data();i._moveFoldingPage.call(b.pages[a],!1);c.f&&c.f.fwrapper&&c.f.fwrapper.remove();b.pages[a].removeData();b.pages[a].remove();
|
||||
delete b.pages[a]}b.pageObjs[a]&&b.pageObjs[a].remove();b.pageWrap[a]&&(b.pageWrap[a].remove(),delete b.pageWrap[a]);g._removeMv.call(this,a);delete b.pagePlace[a];delete b.pageZoom[a]},removePage:function(a){var b=this.data();if("*"==a)for(;0!==b.totalPages;)this.turn("removePage",b.totalPages);else{if(1>a||a>b.totalPages)throw q("The page "+a+" doesn't exist");b.pageObjs[a]&&(this.turn("stop"),g._removePageFromDOM.call(this,a),delete b.pageObjs[a]);g._movePages.call(this,a,-1);b.totalPages-=1;b.page>
|
||||
b.totalPages?(b.page=null,g._fitPage.call(this,b.totalPages)):(g._makeRange.call(this),this.turn("update"))}return this},_movePages:function(a,b){var c,d=this,e=this.data(),h="single"==e.display,f=function(a){var c=a+b,f=c%2,i=f?" odd ":" even ";e.pageObjs[a]&&(e.pageObjs[c]=e.pageObjs[a].removeClass("p"+a+" odd even").addClass("p"+c+i));e.pagePlace[a]&&e.pageWrap[a]&&(e.pagePlace[c]=c,e.pageWrap[c]=e.pageObjs[c].hasClass("fixed")?e.pageWrap[a].attr("page",c):e.pageWrap[a].css(g._pageSize.call(d,
|
||||
c,!0)).attr("page",c),e.pages[a]&&(e.pages[c]=e.pages[a].flip("options",{page:c,next:h||f?c+1:c-1})),b&&(delete e.pages[a],delete e.pagePlace[a],delete e.pageZoom[a],delete e.pageObjs[a],delete e.pageWrap[a]))};if(0<b)for(c=e.totalPages;c>=a;c--)f(c);else for(c=a;c<=e.totalPages;c++)f(c)},display:function(a){var b=this.data(),c=b.display;if(void 0===a)return c;if(-1==f.inArray(a,V))throw q('"'+a+'" is not a value for display');switch(a){case "single":b.pageObjs[0]||(this.turn("stop").css({overflow:"hidden"}),
|
||||
b.pageObjs[0]=f("<div />",{"class":"page p-temporal"}).css({width:this.width(),height:this.height()}).appendTo(this));this.addClass("shadow");break;case "double":b.pageObjs[0]&&(this.turn("stop").css({overflow:""}),b.pageObjs[0].remove(),delete b.pageObjs[0]),this.removeClass("shadow")}b.display=a;c&&(a=this.turn("size"),g._movePages.call(this,1,0),this.turn("size",a.width,a.height).turn("update"));return this},direction:function(a){var b=this.data();if(void 0===a)return b.direction;a=a.toLowerCase();
|
||||
if(-1==f.inArray(a,W))throw q('"'+a+'" is not a value for direction');"rtl"==a&&f(this).attr("dir","ltr").css({direction:"ltr"});b.direction=a;b.done&&this.turn("size",f(this).width(),f(this).height());return this},animating:function(){return 0<this.data().pageMv.length},corner:function(){var a,b,c=this.data();for(b in c.pages)if(n(b,c.pages)&&(a=c.pages[b].flip("corner")))return a;return!1},data:function(){return this.data()},disable:function(a){var b,c=this.data(),d=this.turn("view");c.disabled=
|
||||
void 0===a||!0===a;for(b in c.pages)n(b,c.pages)&&c.pages[b].flip("disable",c.disabled?!0:-1==f.inArray(parseInt(b,10),d));return this},disabled:function(a){return void 0===a?!0===this.data().disabled:this.turn("disable",a)},size:function(a,b){if(void 0===a||void 0===b)return{width:this.width(),height:this.height()};this.turn("stop");var c,d,e=this.data();d="double"==e.display?a/2:a;this.css({width:a,height:b});e.pageObjs[0]&&e.pageObjs[0].css({width:d,height:b});for(c in e.pageWrap)n(c,e.pageWrap)&&
|
||||
(d=g._pageSize.call(this,c,!0),e.pageObjs[c].css({width:d.width,height:d.height}),e.pageWrap[c].css(d),e.pages[c]&&e.pages[c].css({width:d.width,height:d.height}));this.turn("resize");return this},resize:function(){var a,b=this.data();b.pages[0]&&(b.pageWrap[0].css({left:-this.width()}),b.pages[0].flip("resize",!0));for(a=1;a<=b.totalPages;a++)b.pages[a]&&b.pages[a].flip("resize",!0);g._updateShadow.call(this);b.opts.autoCenter&&this.turn("center")},_removeMv:function(a){var b,c=this.data();for(b=
|
||||
0;b<c.pageMv.length;b++)if(c.pageMv[b]==a)return c.pageMv.splice(b,1),!0;return!1},_addMv:function(a){var b=this.data();g._removeMv.call(this,a);b.pageMv.push(a)},_view:function(a){var b=this.data(),a=a||b.page;return"double"==b.display?a%2?[a-1,a]:[a,a+1]:[a]},view:function(a){var b=this.data(),a=g._view.call(this,a);return"double"==b.display?[0<a[0]?a[0]:0,a[1]<=b.totalPages?a[1]:0]:[0<a[0]&&a[0]<=b.totalPages?a[0]:0]},stop:function(a,b){if(this.turn("animating")){var c,d,e,h=this.data();h.tpage&&
|
||||
(h.page=h.tpage,delete h.tpage);for(c=0;c<h.pageMv.length;c++)h.pageMv[c]&&h.pageMv[c]!==a&&(e=h.pages[h.pageMv[c]],d=e.data().f.opts,e.flip("hideFoldedPage",b),b||i._moveFoldingPage.call(e,!1),d.force&&(d.next=0===d.page%2?d.page-1:d.page+1,delete d.force))}this.turn("update");return this},pages:function(a){var b=this.data();if(a){if(a<b.totalPages)for(var c=b.totalPages;c>a;c--)this.turn("removePage",c);b.totalPages=a;g._fitPage.call(this,b.page);return this}return b.totalPages},_missing:function(a){var b=
|
||||
this.data();if(!(1>b.totalPages)){for(var c=this.turn("range",a),d=[],a=c[0];a<=c[1];a++)b.pageObjs[a]||d.push(a);0<d.length&&this.trigger("missing",[d])}},_fitPage:function(a){var b=this.data(),c=this.turn("view",a);g._missing.call(this,a);if(b.pageObjs[a]){b.page=a;this.turn("stop");for(var d=0;d<c.length;d++)c[d]&&b.pageZoom[c[d]]!=b.zoom&&(this.trigger("zoomed",[c[d],c,b.pageZoom[c[d]],b.zoom]),b.pageZoom[c[d]]=b.zoom);g._removeFromDOM.call(this);g._makeRange.call(this);g._updateShadow.call(this);
|
||||
this.trigger("turned",[a,c]);this.turn("update");b.opts.autoCenter&&this.turn("center")}},_turnPage:function(a){var b,c,d=this.data(),e=d.pagePlace[a],h=this.turn("view"),i=this.turn("view",a);if(d.page!=a){var j=d.page;if("prevented"==t("turning",this,[a,i])){j==d.page&&-1!=f.inArray(e,d.pageMv)&&d.pages[e].flip("hideFoldedPage",!0);return}-1!=f.inArray(1,i)&&this.trigger("first");-1!=f.inArray(d.totalPages,i)&&this.trigger("last")}"single"==d.display?(b=h[0],c=i[0]):h[1]&&a>h[1]?(b=h[1],c=i[0]):
|
||||
h[0]&&a<h[0]&&(b=h[0],c=i[1]);e=d.opts.turnCorners.split(",");h=d.pages[b].data().f;i=h.opts;j=h.point;g._missing.call(this,a);d.pageObjs[a]&&(this.turn("stop"),d.page=a,g._makeRange.call(this),d.tpage=c,i.next!=c&&(i.next=c,i.force=!0),this.turn("update"),h.point=j,"hard"==h.effect?"ltr"==d.direction?d.pages[b].flip("turnPage",a>b?"r":"l"):d.pages[b].flip("turnPage",a>b?"l":"r"):"ltr"==d.direction?d.pages[b].flip("turnPage",e[a>b?1:0]):d.pages[b].flip("turnPage",e[a>b?0:1]))},page:function(a){var b=
|
||||
this.data();if(void 0===a)return b.page;if(!b.disabled&&!b.destroying){a=parseInt(a,10);if(0<a&&a<=b.totalPages)return a!=b.page&&(!b.done||-1!=f.inArray(a,this.turn("view"))?g._fitPage.call(this,a):g._turnPage.call(this,a)),this;throw q("The page "+a+" does not exist");}},next:function(){return this.turn("page",Math.min(this.data().totalPages,g._view.call(this,this.data().page).pop()+1))},previous:function(){return this.turn("page",Math.max(1,g._view.call(this,this.data().page).shift()-1))},peel:function(a,
|
||||
b){var c=this.data(),d=this.turn("view"),b=void 0===b?!0:!0===b;!1===a?this.turn("stop",null,b):"single"==c.display?c.pages[c.page].flip("peel",a,b):(d="ltr"==c.direction?-1!=a.indexOf("l")?d[0]:d[1]:-1!=a.indexOf("l")?d[1]:d[0],c.pages[d]&&c.pages[d].flip("peel",a,b));return this},_addMotionPage:function(){var a=f(this).data().f.opts,b=a.turn;b.data();g._addMv.call(b,a.page)},_eventStart:function(a,b,c){var d=b.turn.data(),e=d.pageZoom[b.page];a.isDefaultPrevented()||(e&&e!=d.zoom&&(b.turn.trigger("zoomed",
|
||||
[b.page,b.turn.turn("view",b.page),e,d.zoom]),d.pageZoom[b.page]=d.zoom),"single"==d.display&&c&&("l"==c.charAt(1)&&"ltr"==d.direction||"r"==c.charAt(1)&&"rtl"==d.direction?(b.next=b.next<b.page?b.next:b.page-1,b.force=!0):b.next=b.next>b.page?b.next:b.page+1),g._addMotionPage.call(a.target));g._updateShadow.call(b.turn)},_eventEnd:function(a,b,c){f(a.target).data();var a=b.turn,d=a.data();if(c){if(c=d.tpage||d.page,c==b.next||c==b.page)delete d.tpage,g._fitPage.call(a,c||b.next,!0)}else g._removeMv.call(a,
|
||||
b.page),g._updateShadow.call(a),a.turn("update")},_eventPressed:function(a){var a=f(a.target).data().f,b=a.opts.turn;b.data().mouseAction=!0;b.turn("update");return a.time=(new Date).getTime()},_eventReleased:function(a,b){var c;c=f(a.target);var d=c.data().f,e=d.opts.turn,h=e.data();c="single"==h.display?"br"==b.corner||"tr"==b.corner?b.x<c.width()/2:b.x>c.width()/2:0>b.x||b.x>c.width();if(200>(new Date).getTime()-d.time||c)a.preventDefault(),g._turnPage.call(e,d.opts.next);h.mouseAction=!1},_flip:function(a){a.stopPropagation();
|
||||
a=f(a.target).data().f.opts;a.turn.trigger("turn",[a.next]);a.turn.data().opts.autoCenter&&a.turn.turn("center",a.next)},_touchStart:function(){var a=this.data(),b;for(b in a.pages)if(n(b,a.pages)&&!1===i._eventStart.apply(a.pages[b],arguments))return!1},_touchMove:function(){var a=this.data(),b;for(b in a.pages)n(b,a.pages)&&i._eventMove.apply(a.pages[b],arguments)},_touchEnd:function(){var a=this.data(),b;for(b in a.pages)n(b,a.pages)&&i._eventEnd.apply(a.pages[b],arguments)},calculateZ:function(a){var b,
|
||||
c,d,e,h=this,f=this.data();b=this.turn("view");var i=b[0]||b[1],g=a.length-1,j={pageZ:{},partZ:{},pageV:{}},k=function(a){a=h.turn("view",a);a[0]&&(j.pageV[a[0]]=!0);a[1]&&(j.pageV[a[1]]=!0)};for(b=0;b<=g;b++)c=a[b],d=f.pages[c].data().f.opts.next,e=f.pagePlace[c],k(c),k(d),c=f.pagePlace[d]==d?d:c,j.pageZ[c]=f.totalPages-Math.abs(i-c),j.partZ[e]=2*f.totalPages-g+b;return j},update:function(){var a,b=this.data();if(this.turn("animating")&&0!==b.pageMv[0]){var c,d=this.turn("calculateZ",b.pageMv),e=
|
||||
this.turn("corner"),h=this.turn("view"),i=this.turn("view",b.tpage);for(a in b.pageWrap)if(n(a,b.pageWrap)&&(c=b.pageObjs[a].hasClass("fixed"),b.pageWrap[a].css({display:d.pageV[a]||c?"":"none",zIndex:(b.pageObjs[a].hasClass("hard")?d.partZ[a]:d.pageZ[a])||(c?-1:0)}),c=b.pages[a]))c.flip("z",d.partZ[a]||null),d.pageV[a]&&c.flip("resize"),b.tpage?c.flip("hover",!1).flip("disable",-1==f.inArray(parseInt(a,10),b.pageMv)&&a!=i[0]&&a!=i[1]):c.flip("hover",!1===e).flip("disable",a!=h[0]&&a!=h[1])}else for(a in b.pageWrap)n(a,
|
||||
b.pageWrap)&&(d=g._setPageLoc.call(this,a),b.pages[a]&&b.pages[a].flip("disable",b.disabled||1!=d).flip("hover",!0).flip("z",null));return this},_updateShadow:function(){var a,b,c=this.data(),d=this.width(),e=this.height(),h="single"==c.display?d:d/2;a=this.turn("view");c.shadow||(c.shadow=f("<div />",{"class":"shadow",css:l(0,0,0).css}).appendTo(this));for(var i=0;i<c.pageMv.length&&a[0]&&a[1];i++)a=this.turn("view",c.pages[c.pageMv[i]].data().f.opts.next),b=this.turn("view",c.pageMv[i]),a[0]=a[0]&&
|
||||
b[0],a[1]=a[1]&&b[1];switch(a[0]?a[1]?3:"ltr"==c.direction?2:1:"ltr"==c.direction?1:2){case 1:c.shadow.css({width:h,height:e,top:0,left:h});break;case 2:c.shadow.css({width:h,height:e,top:0,left:0});break;case 3:c.shadow.css({width:d,height:e,top:0,left:0})}},_setPageLoc:function(a){var b=this.data(),c=this.turn("view"),d=0;if(a==c[0]||a==c[1])d=1;else if("single"==b.display&&a==c[0]+1||"double"==b.display&&a==c[0]-2||a==c[1]+2)d=2;if(!this.turn("animating"))switch(d){case 1:b.pageWrap[a].css({zIndex:b.totalPages,
|
||||
display:""});break;case 2:b.pageWrap[a].css({zIndex:b.totalPages-1,display:""});break;case 0:b.pageWrap[a].css({zIndex:0,display:b.pageObjs[a].hasClass("fixed")?"":"none"})}return d},options:function(a){if(void 0===a)return this.data().opts;var b=this.data();f.extend(b.opts,a);a.pages&&this.turn("pages",a.pages);a.page&&this.turn("page",a.page);a.display&&this.turn("display",a.display);a.direction&&this.turn("direction",a.direction);a.width&&a.height&&this.turn("size",a.width,a.height);if(a.when)for(var c in a.when)n(c,
|
||||
a.when)&&this.unbind(c).bind(c,a.when[c]);return this},version:function(){return"4.1.0"}},i={init:function(a){this.data({f:{disabled:!1,hover:!1,effect:this.hasClass("hard")?"hard":"sheet"}});this.flip("options",a);i._addPageWrapper.call(this);return this},setData:function(a){var b=this.data();b.f=f.extend(b.f,a);return this},options:function(a){var b=this.data().f;return a?(i.setData.call(this,{opts:f.extend({},b.opts||Y,a)}),this):b.opts},z:function(a){var b=this.data().f;b.opts["z-index"]=a;b.fwrapper&&
|
||||
b.fwrapper.css({zIndex:a||parseInt(b.parent.css("z-index"),10)||0});return this},_cAllowed:function(){var a=this.data().f,b=a.opts.page,c=a.opts.turn.data(),d=b%2;return"hard"==a.effect?"ltr"==c.direction?[d?"r":"l"]:[d?"l":"r"]:"single"==c.display?1==b?"ltr"==c.direction?p.forward:p.backward:b==c.totalPages?"ltr"==c.direction?p.backward:p.forward:p.all:"ltr"==c.direction?p[d?"forward":"backward"]:p[d?"backward":"forward"]},_cornerActivated:function(a){var b=this.data().f,c=this.width(),d=this.height(),
|
||||
a={x:a.x,y:a.y,corner:""},e=b.opts.cornerSize;if(0>=a.x||0>=a.y||a.x>=c||a.y>=d)return!1;var h=i._cAllowed.call(this);switch(b.effect){case "hard":if(a.x>c-e)a.corner="r";else if(a.x<e)a.corner="l";else return!1;break;case "sheet":if(a.y<e)a.corner+="t";else if(a.y>=d-e)a.corner+="b";else return!1;if(a.x<=e)a.corner+="l";else if(a.x>=c-e)a.corner+="r";else return!1}return!a.corner||-1==f.inArray(a.corner,h)?!1:a},_isIArea:function(a){var b=this.data().f.parent.offset(),a=u&&a.originalEvent?a.originalEvent.touches[0]:
|
||||
a;return i._cornerActivated.call(this,{x:a.pageX-b.left,y:a.pageY-b.top})},_c:function(a,b){b=b||0;switch(a){case "tl":return j(b,b);case "tr":return j(this.width()-b,b);case "bl":return j(b,this.height()-b);case "br":return j(this.width()-b,this.height()-b);case "l":return j(b,0);case "r":return j(this.width()-b,0)}},_c2:function(a){switch(a){case "tl":return j(2*this.width(),0);case "tr":return j(-this.width(),0);case "bl":return j(2*this.width(),this.height());case "br":return j(-this.width(),
|
||||
this.height());case "l":return j(2*this.width(),0);case "r":return j(-this.width(),0)}},_foldingPage:function(){var a=this.data().f;if(a){var b=a.opts;if(b.turn)return a=b.turn.data(),"single"==a.display?1<b.next||1<b.page?a.pageObjs[0]:null:a.pageObjs[b.next]}},_backGradient:function(){var a=this.data().f,b=a.opts.turn.data();if((b=b.opts.gradients&&("single"==b.display||2!=a.opts.page&&a.opts.page!=b.totalPages-1))&&!a.bshadow)a.bshadow=f("<div/>",l(0,0,1)).css({position:"",width:this.width(),height:this.height()}).appendTo(a.parent);
|
||||
return b},type:function(){return this.data().f.effect},resize:function(a){var b=this.data().f,c=b.opts.turn.data(),d=this.width(),e=this.height();switch(b.effect){case "hard":a&&(b.wrapper.css({width:d,height:e}),b.fpage.css({width:d,height:e}),c.opts.gradients&&(b.ashadow.css({width:d,height:e}),b.bshadow.css({width:d,height:e})));break;case "sheet":a&&(a=Math.round(Math.sqrt(Math.pow(d,2)+Math.pow(e,2))),b.wrapper.css({width:a,height:a}),b.fwrapper.css({width:a,height:a}).children(":first-child").css({width:d,
|
||||
height:e}),b.fpage.css({width:d,height:e}),c.opts.gradients&&b.ashadow.css({width:d,height:e}),i._backGradient.call(this)&&b.bshadow.css({width:d,height:e})),b.parent.is(":visible")&&(c=D(b.parent[0]),b.fwrapper.css({top:c.top,left:c.left}),c=D(b.opts.turn[0]),b.fparent.css({top:-c.top,left:-c.left})),this.flip("z",b.opts["z-index"])}},_addPageWrapper:function(){var a=this.data().f,b=a.opts.turn.data(),c=this.parent();a.parent=c;if(!a.wrapper)switch(a.effect){case "hard":var d={};d[w+"transform-style"]=
|
||||
"preserve-3d";d[w+"backface-visibility"]="hidden";a.wrapper=f("<div/>",l(0,0,2)).css(d).appendTo(c).prepend(this);a.fpage=f("<div/>",l(0,0,1)).css(d).appendTo(c);b.opts.gradients&&(a.ashadow=f("<div/>",l(0,0,0)).hide().appendTo(c),a.bshadow=f("<div/>",l(0,0,0)));break;case "sheet":var d=this.width(),e=this.height();Math.round(Math.sqrt(Math.pow(d,2)+Math.pow(e,2)));a.fparent=a.opts.turn.data().fparent;a.fparent||(d=f("<div/>",{css:{"pointer-events":"none"}}).hide(),d.data().flips=0,d.css(l(0,0,"auto",
|
||||
"visible").css).appendTo(a.opts.turn),a.opts.turn.data().fparent=d,a.fparent=d);this.css({position:"absolute",top:0,left:0,bottom:"auto",right:"auto"});a.wrapper=f("<div/>",l(0,0,this.css("z-index"))).appendTo(c).prepend(this);a.fwrapper=f("<div/>",l(c.offset().top,c.offset().left)).hide().appendTo(a.fparent);a.fpage=f("<div/>",l(0,0,0,"visible")).css({cursor:"default"}).appendTo(a.fwrapper);b.opts.gradients&&(a.ashadow=f("<div/>",l(0,0,1)).appendTo(a.fpage));i.setData.call(this,a)}i.resize.call(this,
|
||||
!0)},_fold:function(a){var b=this.data().f,c=b.opts.turn.data(),d=i._c.call(this,a.corner),e=this.width(),h=this.height();switch(b.effect){case "hard":a.x="l"==a.corner?Math.min(Math.max(a.x,0),2*e):Math.max(Math.min(a.x,e),-e);var f,g,s,x,k,n=c.totalPages,l=b.opts["z-index"]||n,q={overflow:"visible"},p=d.x?(d.x-a.x)/e:a.x/e,r=90*p,t=90>r;switch(a.corner){case "l":x="0% 50%";k="100% 50%";t?(f=0,g=0<b.opts.next-1,s=1):(f="100%",g=b.opts.page+1<n,s=0);break;case "r":x="100% 50%",k="0% 50%",r=-r,e=-e,
|
||||
t?(f=0,g=b.opts.next+1<n,s=0):(f="-100%",g=1!=b.opts.page,s=1)}q[w+"perspective-origin"]=k;b.wrapper.transform("rotateY("+r+"deg)translate3d(0px, 0px, "+(this.attr("depth")||0)+"px)",k);b.fpage.transform("translateX("+e+"px) rotateY("+(180+r)+"deg)",x);b.parent.css(q);t?(p=-p+1,b.wrapper.css({zIndex:l+1}),b.fpage.css({zIndex:l})):(p-=1,b.wrapper.css({zIndex:l}),b.fpage.css({zIndex:l+1}));c.opts.gradients&&(g?b.ashadow.css({display:"",left:f,backgroundColor:"rgba(0,0,0,"+0.5*p+")"}).transform("rotateY(0deg)"):
|
||||
b.ashadow.hide(),b.bshadow.css({opacity:-p+1}),t?b.bshadow.parent()[0]!=b.wrapper[0]&&b.bshadow.appendTo(b.wrapper):b.bshadow.parent()[0]!=b.fpage[0]&&b.bshadow.appendTo(b.fpage),P(b.bshadow,j(100*s,0),j(100*(-s+1),0),[[0,"rgba(0,0,0,0.3)"],[1,"rgba(0,0,0,0)"]],2));break;case "sheet":var u=this,H=0,z,A,B,M,y,N,D,v=j(0,0),Q=j(0,0),m=j(0,0),J=i._foldingPage.call(this);Math.tan(0);var O=c.opts.acceleration,R=b.wrapper.height(),E="t"==a.corner.substr(0,1),C="l"==a.corner.substr(1,1),I=function(){var b=
|
||||
j(0,0),f=j(0,0);b.x=d.x?d.x-a.x:a.x;b.y=U?d.y?d.y-a.y:a.y:0;f.x=C?e-b.x/2:a.x+b.x/2;f.y=b.y/2;var g=L-Math.atan2(b.y,b.x),k=g-Math.atan2(f.y,f.x),k=Math.max(0,Math.sin(k)*Math.sqrt(Math.pow(f.x,2)+Math.pow(f.y,2)));H=180*(g/K);m=j(k*Math.sin(g),k*Math.cos(g));if(g>L&&(m.x+=Math.abs(m.y*b.y/b.x),m.y=0,Math.round(m.x*Math.tan(K-g))<h))return a.y=Math.sqrt(Math.pow(h,2)+2*f.x*b.x),E&&(a.y=h-a.y),I();g>L&&(b=K-g,f=R-h/Math.sin(b),v=j(Math.round(f*Math.cos(b)),Math.round(f*Math.sin(b))),C&&(v.x=-v.x),
|
||||
E&&(v.y=-v.y));z=Math.round(m.y/Math.tan(g)+m.x);b=e-z;f=b*Math.cos(2*g);k=b*Math.sin(2*g);Q=j(Math.round(C?b-f:z+f),Math.round(E?k:h-k));c.opts.gradients&&(y=b*Math.sin(g),b=i._c2.call(u,a.corner),b=Math.sqrt(Math.pow(b.x-a.x,2)+Math.pow(b.y-a.y,2))/e,D=Math.sin(L*(1<b?2-b:b)),N=Math.min(b,1),M=100<y?(y-100)/y:0,A=j(100*(y*Math.sin(g)/e),100*(y*Math.cos(g)/h)),i._backGradient.call(u)&&(B=j(100*(1.2*y*Math.sin(g)/e),100*(1.2*y*Math.cos(g)/h)),C||(B.x=100-B.x),E||(B.y=100-B.y)));m.x=Math.round(m.x);
|
||||
m.y=Math.round(m.y);return!0};f=function(a,d,f,g){var k=["0","auto"],m=(e-R)*f[0]/100,l=(h-R)*f[1]/100,d={left:k[d[0]],top:k[d[1]],right:k[d[2]],bottom:k[d[3]]},k={},n=90!=g&&-90!=g?C?-1:1:0,s=f[0]+"% "+f[1]+"%";u.css(d).transform(G(g)+F(a.x+n,a.y,O),s);b.fpage.css(d).transform(G(g)+F(a.x+Q.x-v.x-e*f[0]/100,a.y+Q.y-v.y-h*f[1]/100,O)+G((180/g-2)*g),s);b.wrapper.transform(F(-a.x+m-n,-a.y+l,O)+G(-g),s);b.fwrapper.transform(F(-a.x+v.x+m,-a.y+v.y+l,O)+G(-g),s);c.opts.gradients&&(f[0]&&(A.x=100-A.x),f[1]&&
|
||||
(A.y=100-A.y),k["box-shadow"]="0 0 20px rgba(0,0,0,"+0.5*D+")",J.css(k),P(b.ashadow,j(C?100:0,E?0:100),j(A.x,A.y),[[M,"rgba(0,0,0,0)"],[0.8*(1-M)+M,"rgba(0,0,0,"+0.2*N+")"],[1,"rgba(255,255,255,"+0.2*N+")"]],3,0),i._backGradient.call(u)&&P(b.bshadow,j(C?0:100,E?0:100),j(B.x,B.y),[[0.6,"rgba(0,0,0,0)"],[0.8,"rgba(0,0,0,"+0.3*N+")"],[1,"rgba(0,0,0,0)"]],3))};switch(a.corner){case "tl":a.x=Math.max(a.x,1);I();f(m,[1,0,0,1],[100,0],H);break;case "tr":a.x=Math.min(a.x,e-1);I();f(j(-m.x,m.y),[0,0,0,1],
|
||||
[0,0],-H);break;case "bl":a.x=Math.max(a.x,1);I();f(j(m.x,-m.y),[1,1,0,0],[100,100],-H);break;case "br":a.x=Math.min(a.x,e-1),I(),f(j(-m.x,-m.y),[0,1,1,0],[0,100],H)}}b.point=a},_moveFoldingPage:function(a){var b=this.data().f;if(b){var c=b.opts.turn,d=c.data(),e=d.pagePlace;a?(d=b.opts.next,e[d]!=b.opts.page&&(b.folding&&i._moveFoldingPage.call(this,!1),i._foldingPage.call(this).appendTo(b.fpage),e[d]=b.opts.page,b.folding=d),c.turn("update")):b.folding&&(d.pages[b.folding]?(c=d.pages[b.folding].data().f,
|
||||
d.pageObjs[b.folding].appendTo(c.wrapper)):d.pageWrap[b.folding]&&d.pageObjs[b.folding].appendTo(d.pageWrap[b.folding]),b.folding in e&&(e[b.folding]=b.folding),delete b.folding)}},_showFoldedPage:function(a,b){var c=i._foldingPage.call(this),d=this.data(),e=d.f,f=e.visible;if(c){if(!f||!e.point||e.point.corner!=a.corner)if(c="hover"==e.status||"peel"==e.status||e.opts.turn.data().mouseAction?a.corner:null,f=!1,"prevented"==t("start",this,[e.opts,c]))return!1;if(b){var g=this,d=e.point&&e.point.corner==
|
||||
a.corner?e.point:i._c.call(this,a.corner,1);this.animatef({from:[d.x,d.y],to:[a.x,a.y],duration:500,frame:function(b){a.x=Math.round(b[0]);a.y=Math.round(b[1]);i._fold.call(g,a)}})}else i._fold.call(this,a),d.effect&&!d.effect.turning&&this.animatef(!1);if(!f)switch(e.effect){case "hard":e.visible=!0;i._moveFoldingPage.call(this,!0);e.fpage.show();e.opts.shadows&&e.bshadow.show();break;case "sheet":e.visible=!0,e.fparent.show().data().flips++,i._moveFoldingPage.call(this,!0),e.fwrapper.show(),e.bshadow&&
|
||||
e.bshadow.show()}return!0}return!1},hide:function(){var a=this.data().f,b=a.opts.turn.data(),c=i._foldingPage.call(this);switch(a.effect){case "hard":b.opts.gradients&&(a.bshadowLoc=0,a.bshadow.remove(),a.ashadow.hide());a.wrapper.transform("");a.fpage.hide();break;case "sheet":0===--a.fparent.data().flips&&a.fparent.hide(),this.css({left:0,top:0,right:"auto",bottom:"auto"}).transform(""),a.wrapper.transform(""),a.fwrapper.hide(),a.bshadow&&a.bshadow.hide(),c.transform("")}a.visible=!1;return this},
|
||||
hideFoldedPage:function(a){var b=this.data().f;if(b.point){var c=this,d=b.point,e=function(){b.point=null;b.status="";c.flip("hide");c.trigger("end",[b.opts,!1])};if(a){var f=i._c.call(this,d.corner),a="t"==d.corner.substr(0,1)?Math.min(0,d.y-f.y)/2:Math.max(0,d.y-f.y)/2,g=j(d.x,d.y+a),l=j(f.x,f.y-a);this.animatef({from:0,to:1,frame:function(a){a=S(d,g,l,f,a);d.x=a.x;d.y=a.y;i._fold.call(c,d)},complete:e,duration:800,hiding:!0})}else this.animatef(!1),e()}},turnPage:function(a){var b=this,c=this.data().f,
|
||||
d=c.opts.turn.data(),a={corner:c.corner?c.corner.corner:a||i._cAllowed.call(this)[0]},e=c.point||i._c.call(this,a.corner,c.opts.turn?d.opts.elevation:0),f=i._c2.call(this,a.corner);this.trigger("flip").animatef({from:0,to:1,frame:function(c){c=S(e,e,f,f,c);a.x=c.x;a.y=c.y;i._showFoldedPage.call(b,a)},complete:function(){b.trigger("end",[c.opts,!0])},duration:d.opts.duration,turning:!0});c.corner=null},moving:function(){return"effect"in this.data()},isTurning:function(){return this.flip("moving")&&
|
||||
this.data().effect.turning},corner:function(){return this.data().f.corner},_eventStart:function(a){var b=this.data().f,c=b.opts.turn;if(!b.corner&&!b.disabled&&!this.flip("isTurning")&&b.opts.page==c.data().pagePlace[b.opts.page]){b.corner=i._isIArea.call(this,a);if(b.corner&&i._foldingPage.call(this))return this.trigger("pressed",[b.point]),i._showFoldedPage.call(this,b.corner),!1;b.corner=null}},_eventMove:function(a){var b=this.data().f;if(!b.disabled)if(a=u?a.originalEvent.touches:[a],b.corner){var c=
|
||||
b.parent.offset();b.corner.x=a[0].pageX-c.left;b.corner.y=a[0].pageY-c.top;i._showFoldedPage.call(this,b.corner)}else if(b.hover&&!this.data().effect&&this.is(":visible"))if(a=i._isIArea.call(this,a[0])){if("sheet"==b.effect&&2==a.corner.length||"hard"==b.effect)b.status="hover",b=i._c.call(this,a.corner,b.opts.cornerSize/2),a.x=b.x,a.y=b.y,i._showFoldedPage.call(this,a,!0)}else"hover"==b.status&&(b.status="",i.hideFoldedPage.call(this,!0))},_eventEnd:function(){var a=this.data().f,b=a.corner;!a.disabled&&
|
||||
b&&"prevented"!=t("released",this,[a.point||b])&&i.hideFoldedPage.call(this,!0);a.corner=null},disable:function(a){i.setData.call(this,{disabled:a});return this},hover:function(a){i.setData.call(this,{hover:a});return this},peel:function(a,b){var c=this.data().f;if(a){if(-1==f.inArray(a,p.all))throw q("Corner "+a+" is not permitted");if(-1!=f.inArray(a,i._cAllowed.call(this))){var d=i._c.call(this,a,c.opts.cornerSize/2);c.status="peel";i._showFoldedPage.call(this,{corner:a,x:d.x,y:d.y},b)}}else c.status=
|
||||
"",i.hideFoldedPage.call(this,b);return this}};window.requestAnim=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)};f.extend(f.fn,{flip:function(){return J(f(this[0]),i,arguments)},turn:function(){return J(f(this[0]),g,arguments)},transform:function(a,b){var c={};b&&(c[w+"transform-origin"]=b);c[w+"transform"]=a;return this.css(c)},animatef:function(a){var b=
|
||||
this.data();b.effect&&b.effect.stop();if(a){a.to.length||(a.to=[a.to]);a.from.length||(a.from=[a.from]);for(var c=[],d=a.to.length,e=!0,g=this,i=(new Date).getTime(),j=function(){if(b.effect&&e){for(var f=[],k=Math.min(a.duration,(new Date).getTime()-i),l=0;l<d;l++)f.push(b.effect.easing(1,k,a.from[l],c[l],a.duration));a.frame(1==d?f[0]:f);k==a.duration?(delete b.effect,g.data(b),a.complete&&a.complete()):window.requestAnim(j)}},l=0;l<d;l++)c.push(a.to[l]-a.from[l]);b.effect=f.extend({stop:function(){e=
|
||||
!1},easing:function(a,b,c,d,e){return d*Math.sqrt(1-(b=b/e-1)*b)+c}},a);this.data(b);j()}else delete b.effect}});f.isTouch=u;f.mouseEvents=r;f.cssPrefix=T;f.cssTransitionEnd=function(){var a,b=document.createElement("fakeelement"),c={transition:"transitionend",OTransition:"oTransitionEnd",MSTransition:"transitionend",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(a in c)if(void 0!==b.style[a])return c[a]};f.findPos=D})(jQuery);
|
||||
@@ -0,0 +1,26 @@
|
||||
/* turn.js 4.1.0 | Copyright (c) 2012 Emmanuel Garcia | turnjs.com | turnjs.com/license.txt */
|
||||
|
||||
(function(f){function r(a,b){return a[0]==b[0]?!1:a.attr("page")?!0:a.parent()[0]?r(a.parent(),b):!1}function u(a){function b(a){this.name="TurnJsError";this.message=a}b.prototype=Error();b.prototype.constructor=b;return new b(a)}function t(a,b,d){return q&&d?" translate3d("+a+"px,"+b+"px, 0px) ":" translate("+a+"px, "+b+"px) "}function v(a,b){return q&&b?" scale3d("+a+", "+a+", 1) ":" scale("+a+") "}function h(a,b){return{x:a,y:b}}function m(a,b){return function(){return a.apply(b,arguments)}}var q,
|
||||
w={max:2,flipbook:null,easeFunction:"ease-in-out",duration:500,when:{}},j={init:function(a){var b=this,d=this.data(),a=f.extend({},w,a);if(!a.flipbook||!a.flipbook.turn("is"))throw u("options.flipbook is required");q="WebKitCSSMatrix"in window||"MozPerspective"in document.body.style;if("function"!=typeof a.max){var e=a.max;a.max=function(){return e}}d.zoom={opts:a,axis:h(0,0),scrollPos:h(0,0),eventQueue:[],mouseupEvent:function(){return j._eMouseUp.apply(b,arguments)},eventTouchStart:m(j._eTouchStart,
|
||||
b),eventTouchMove:m(j._eTouchMove,b),eventTouchEnd:m(j._eTouchEnd,b),flipbookEvents:{zooming:m(j._eZoom,b),pressed:m(j._ePressed,b),released:m(j._eReleased,b),start:m(j._eStart,b),turning:m(j._eTurning,b),turned:m(j._eTurned,b),destroying:m(j._eDestroying,b)}};for(var c in a.when)Object.prototype.hasOwnProperty.call(a.when,c)&&this.bind("zoom."+c,a.when[c]);for(c in d.zoom.flipbookEvents)Object.prototype.hasOwnProperty.call(d.zoom.flipbookEvents,c)&&a.flipbook.bind(c,d.zoom.flipbookEvents[c]);this.css({position:"relative",
|
||||
overflow:"hidden"});f.isTouch?(a.flipbook.bind("touchstart",d.zoom.eventTouchStart).bind("touchmove",d.zoom.eventTouchMove).bind("touchend",d.zoom.eventTouchEnd),this.bind("touchstart",j._tap)):this.mousedown(j._mousedown).click(j._tap)},_tap:function(a){var b=f(this),d=b.data().zoom;!d.draggingCorner&&!d.dragging&&r(f(a.target),b)&&(j._addEvent.call(b,"tap",a),(a=j._eventSeq.call(b))&&b.trigger(a))},_addEvent:function(a,b){var d=this.data().zoom,e=(new Date).getTime();d.eventQueue.push({name:a,timestamp:e,
|
||||
event:b});10<d.eventQueue.length&&d.eventQueue.splice(0,1)},_eventSeq:function(){var a=this.data().zoom.eventQueue,b=a.length-1;if(0<b&&"tap"==a[b].name&&"tap"==a[b-1].name&&a[b].event.pageX==a[b-1].event.pageX&&a[b].event.pageY==a[b-1].event.pageY&&200>a[b].timestamp-a[b-1].timestamp&&50<a[b].timestamp-a[b-1].timestamp)return f.extend(a[b].event,{type:"zoom.doubleTap"});if("tap"==a[b].name)return f.extend(a[b].event,{type:"zoom.tap"})},_prepareZoom:function(){var a,b=0,d=this.data().zoom,e=1/this.zoom("value");
|
||||
a=d.opts.flipbook;var c=a.turn("direction"),j=a.data(),l=a.offset(),i=this.offset(),g={height:a.height()},k=a.turn("view");"double"==a.turn("display")&&a.data().opts.autoCenter?k[0]?k[1]?(g.width=a.width(),a=h(l.left-i.left,l.top-i.top)):(g.width=a.width()/2,b="ltr"==c?0:g.width,a=h("ltr"==c?l.left-i.left:l.left-i.left+g.width,l.top-i.top)):(g.width=a.width()/2,b="ltr"==c?g.width:0,a=h("ltr"==c?l.left-i.left+g.width:l.left-i.left,l.top-i.top)):(g.width=a.width(),a=h(l.left-i.left,l.top-i.top));d.zoomer||
|
||||
(d.zoomer=f("<div />",{"class":"zoomer",css:{overflow:"hidden",position:"absolute",zIndex:"1000000"}}).mousedown(function(){return!1}).appendTo(this));d.zoomer.css({top:a.y,left:a.x,width:g.width,height:g.height});c=k.join(",");if(c!=d.zoomerView){d.zoomerView=c;d.zoomer.find("*").remove();for(c=0;c<k.length;c++)if(k[c]){var i=j.pageObjs[k[c]].offset(),m=f(j.pageObjs[k[c]]);m.clone().transform("").css({width:m.width()*e,height:m.height()*e,position:"absolute",display:"",top:(i.top-l.top)*e,left:(i.left-
|
||||
l.left-b)*e}).appendTo(d.zoomer)}}return{pos:a,size:g}},value:function(){return this.data().zoom.opts.flipbook.turn("zoom")},zoomIn:function(a){var b=this,d=this.data().zoom,e=d.opts.flipbook,c=d.opts.max();e.offset();var s=this.offset();if(d.zoomIn)return this;e.turn("stop");var l=f.Event("zoom.change");this.trigger(l,[c]);if(l.isDefaultPrevented())return this;var i=j._prepareZoom.call(this),g=i.pos,k=h(i.size.width/2,i.size.height/2),l=f.cssPrefix(),m=f.cssTransitionEnd(),q=e.data().opts.autoCenter;
|
||||
d.scale=c;e.data().noCenter=!0;a="undefined"!=typeof a?"x"in a&&"y"in a?h(a.x-g.x,a.y-g.y):f.isTouch?h(a.originalEvent.touches[0].pageX-g.x-s.left,a.originalEvent.touches[0].pageY-g.y-s.top):h(a.pageX-g.x-s.left,a.pageY-g.y-s.top):h(k.x,k.y);if(0>a.x||0>a.y||a.x>i.width||a.y>i.height)a.x=k.x,a.y=k.y;var n=h((a.x-k.x)*c+k.x,(a.y-k.y)*c+k.y),a=h(i.size.width*c>this.width()?a.x-n.x:0,i.size.height*c>this.height()?a.y-n.y:0),n=h(Math.abs(i.size.width*c-this.width()),Math.abs(i.size.height*c-this.height())),
|
||||
i=h(Math.min(0,i.size.width*c-this.width()),Math.min(0,i.size.height*c-this.height())),p=h(k.x*c-k.x-g.x-a.x,k.y*c-k.y-g.y-a.y);p.y>n.y?a.y=p.y-n.y+a.y:p.y<i.y&&(a.y=p.y-i.y+a.y);p.x>n.x?a.x=p.x-n.x+a.x:p.x<i.x&&(a.x=p.x-i.x+a.x);p=h(k.x*c-k.x-g.x-a.x,k.y*c-k.y-g.y-a.y);g={};g[l+"transition"]=l+"transform "+d.opts.easeFunction+" "+d.opts.duration+"ms";var r=function(){b.trigger("zoom.zoomIn");d.zoomIn=!0;d.flipPosition=h(e.css("left"),e.css("top"));e.turn("zoom",c).css({position:"absolute",margin:"",
|
||||
top:0,left:0});var a=e.offset();d.axis=h(a.left-s.left,a.top-s.top);if(q&&"double"==e.turn("display")&&("ltr"==e.turn("direction")&&!e.turn("view")[0]||"rtl"==e.turn("direction")&&!e.turn("view")[1]))d.axis.x+=e.width()/2;b.zoom("scroll",p);b.bind(f.mouseEvents.down,j._eMouseDown);b.bind(f.mouseEvents.move,j._eMouseMove);f(document).bind(f.mouseEvents.up,d.mouseupEvent);b.bind("mousewheel",j._eMouseWheel);setTimeout(function(){d.zoomer.hide();d.zoomer.remove();d.zoomer=null;d.zoomerView=null},50)};
|
||||
d.zoomer.css(g).show();m?d.zoomer.bind(m,function(){f(this).unbind(m);r()}):setTimeout(r,d.opts.duration);d.zoomer.transform(t(a.x,a.y,!0)+v(c,!0));return this},zoomOut:function(a){var b,d=this,e=this.data().zoom,c=e.opts.flipbook,m=1/e.scale,l=f.cssPrefix(),i=f.cssTransitionEnd();b=this.offset();a="undefined"!=typeof a?a:e.opts.duration;if(e.zoomIn){var g=f.Event("zoom.change");this.trigger(g,[1]);if(g.isDefaultPrevented())return this;e.zoomIn=!1;e.scale=1;c.data().noCenter=!1;d.unbind(f.mouseEvents.down,
|
||||
j._eMouseDown);d.unbind(f.mouseEvents.move,j._eMouseMove);f(document).unbind(f.mouseEvents.up,e.mouseupEvent);d.unbind("mousewheel",j._eMouseWheel);g={};g[l+"transition"]=l+"transform "+e.opts.easeFunction+" "+a+"ms";c.css(g);var k=f("<div />",{css:{position:"relative",top:e.flipPosition.y,left:e.flipPosition.x,width:c.width()*m,height:c.height()*m,background:"blue"}}).appendTo(c.parent()),g=h(k.offset().left-b.left,k.offset().top-b.top);k.remove();var q=c.data().opts.autoCenter;q&&"double"==c.turn("display")&&
|
||||
(c.turn("view")[0]?c.turn("view")[1]||(g.x="ltr"==c.turn("direction")?g.x+k.width()/4:g.x-k.width()/4):g.x="ltr"==c.turn("direction")?g.x-k.width()/4:g.x+k.width()/4);var r=f.findPos(c[0]);b=h(-c.width()/2-r.left+k.width()/2+g.x+b.left,-c.height()/2-r.top+k.height()/2+g.y+b.top);var n=function(){c[0].style.removeProperty?(c[0].style.removeProperty(l+"transition"),c.transform(c.turn("options").acceleration?t(0,0,!0):"").turn("zoom",1),c[0].style.removeProperty("margin"),c.css({position:"relative",
|
||||
top:e.flipPosition.y,left:e.flipPosition.x})):c.transform("none").turn("zoom",1).css({margin:"",top:e.flipPosition.y,left:e.flipPosition.x,position:"relative"});q&&c.turn("center");d.trigger("zoom.zoomOut")};0===a?n():(i?c.bind(i,function(){f(this).unbind(i);n()}):setTimeout(n,a),c.transform(t(b.x,b.y,!0)+v(m,!0)));return this}},flipbookWidth:function(){var a=this.data().zoom.opts.flipbook,b=a.turn("view");return"double"==a.turn("display")&&(!b[0]||!b[1])?a.width()/2:a.width()},scroll:function(a,
|
||||
b,d){var e=this.data().zoom,c=e.opts.flipbook,j=this.zoom("flipbookWidth"),l=f.cssPrefix();if(q){var i={};i[l+"transition"]=d?l+"transform 200ms":"none";c.css(i);c.transform(t(-e.axis.x-a.x,-e.axis.y-a.y,!0))}else c.css({top:-e.axis.y-a.y,left:-e.axis.x-a.x});if(!b){var g,b=h(Math.min(0,(j-this.width())/2),Math.min(0,(c.height()-this.height())/2)),c=h(j>this.width()?j-this.width():(j-this.width())/2,c.height()>this.height()?c.height()-this.height():(c.height()-this.height())/2);a.y<b.y?(a.y=b.y,g=
|
||||
!0):a.y>c.y&&(a.y=c.y,g=!0);a.x<b.x?(a.x=b.x,g=!0):a.x>c.x&&(a.x=c.x,g=!0);g&&this.zoom("scroll",a,!0,!0)}e.scrollPos=h(a.x,a.y)},resize:function(){var a=this.data().zoom,b=a.opts.flipbook;if(1<this.zoom("value")){var d=b.offset(),e=this.offset();a.axis=h(d.left-e.left+(a.axis.x+a.scrollPos.x),d.top-e.top+(a.axis.y+a.scrollPos.y));"double"==b.turn("display")&&("ltr"==b.turn("direction")&&!b.turn("view")[0])&&(a.axis.x+=b.width()/2);this.zoom("scroll",a.scrollPos)}},_eZoom:function(){for(var a=this.data().zoom,
|
||||
b=a.opts.flipbook,d=b.turn("view"),e=0;e<d.length;e++)d[e]&&this.trigger("zoom.resize",[a.scale,d[e],b.data().pageObjs[d[e]]])},_eStart:function(a){1!=this.zoom("value")&&a.preventDefault()},_eTurning:function(a,b,d){var e=this,a=this.zoom("value"),c=this.data().zoom,b=c.opts.flipbook;c.page=b.turn("page");if(1!=a){for(c=0;c<d.length;c++)d[c]&&this.trigger("zoom.resize",[a,d[c],b.data().pageObjs[d[c]]]);setTimeout(function(){e.zoom("resize")},0)}},_eTurned:function(a,b){if(1!=this.zoom("value")){var d=
|
||||
this.data().zoom,e=d.opts.flipbook;b>d.page?this.zoom("scroll",h(0,d.scrollPos.y),!1,!0):b<d.page&&this.zoom("scroll",h(e.width(),d.scrollPos.y),!1,!0)}},_ePressed:function(){f(this).data().zoom.draggingCorner=!0},_eReleased:function(){var a=f(this).data().zoom;setTimeout(function(){a.draggingCorner=!1},1)},_eMouseDown:function(a){f(this).data().zoom.draggingCur=f.isTouch?h(a.originalEvent.touches[0].pageX,a.originalEvent.touches[0].pageY):h(a.pageX,a.pageY);return!1},_eMouseMove:function(a){var b=
|
||||
f(this).data().zoom;if(b.draggingCur){b.dragging=!0;var a=f.isTouch?h(a.originalEvent.touches[0].pageX,a.originalEvent.touches[0].pageY):h(a.pageX,a.pageY),d=h(a.x-b.draggingCur.x,a.y-b.draggingCur.y);f(this).zoom("scroll",h(b.scrollPos.x-d.x,b.scrollPos.y-d.y),!0);b.draggingCur=a;return!1}},_eMouseUp:function(){var a=f(this).data().zoom;a.dragging&&f(this).zoom("scroll",a.scrollPos);a.draggingCur=null;setTimeout(function(){a.dragging=!1},1)},_eMouseWheel:function(a,b,d,e){a=f(this).data().zoom;d=
|
||||
h(a.scrollPos.x+10*d,a.scrollPos.y-10*e);f(this).zoom("scroll",d,!1,!0)},_eTouchStart:function(a){var b=f(this).data().zoom,a=h(a.originalEvent.touches[0].pageX,a.originalEvent.touches[0].pageY);b.touch={};b.touch.initial=a;b.touch.last=a;b.touch.timestamp=(new Date).getTime();b.touch.speed=h(0,0)},_eTouchMove:function(a){var b=f(this).data().zoom,d=f(this).zoom("value"),e=b.opts.flipbook,c=(new Date).getTime(),a=h(a.originalEvent.touches[0].pageX,a.originalEvent.touches[0].pageY);b.touch&&(1==d&&
|
||||
!e.data().mouseAction)&&(b.touch.motion=h(a.x-b.touch.last.x,a.y-b.touch.last.y),b.touch.speed.x=0===b.touch.speed.x?b.touch.motion.x/(c-b.touch.timestamp):(b.touch.speed.x+b.touch.motion.x/(c-b.touch.timestamp))/2,b.touch.last=a,b.touch.timestamp=c)},_eTouchEnd:function(){var a=f(this).data().zoom;if(a.touch&&1==f(this).zoom("value")){var b=Math.abs(a.touch.initial.y-a.touch.last.y);50>b&&(-1>a.touch.speed.x||-100>a.touch.last.x-a.touch.initial.x)?this.trigger("zoom.swipeLeft"):50>b&&(1<a.touch.speed.x||
|
||||
100<a.touch.last.x-a.touch.initial.x)&&this.trigger("zoom.swipeRight")}},_eDestroying:function(){var a=this,b=this.data().zoom,d=b.opts.flipbook;this.zoom("zoomOut",0);f.each("tap doubleTap resize zoomIn zoomOut swipeLeft swipeRight".split(" "),function(b,d){a.unbind("zoom."+d)});for(var e in b.flipbookEvents)Object.prototype.hasOwnProperty.call(b.flipbookEvents,e)&&d.unbind(e,b.flipbookEvents[e]);d.unbind("touchstart",b.eventTouchStart).unbind("touchmove",b.eventTouchMove).unbind("touchend",b.eventTouchEnd);
|
||||
this.unbind("touchstart",j._tap).unbind("click",j._tap);b=null;this.data().zoom=null}};f.extend(f.fn,{zoom:function(){var a=arguments;if(!a[0]||"object"==typeof a[0])return j.init.apply(f(this[0]),a);if(j[a[0]])return j[a[0]].apply(f(this[0]),Array.prototype.slice.call(a,1));throw u(a[0]+" is not a method");}})})(jQuery);
|
||||
@@ -0,0 +1,67 @@
|
||||
/* Basic sample */
|
||||
|
||||
body{
|
||||
overflow:hidden;
|
||||
background-color:#fcfcfc;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.flipbook-viewport{
|
||||
overflow:hidden;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.flipbook-viewport .container{
|
||||
position:absolute;
|
||||
top:50%;
|
||||
left:50%;
|
||||
margin:auto;
|
||||
}
|
||||
|
||||
.flipbook-viewport .flipbook{
|
||||
width:922px;
|
||||
height:600px;
|
||||
left:-461px;
|
||||
top:-300px;
|
||||
}
|
||||
|
||||
.flipbook-viewport .page{
|
||||
width:461px;
|
||||
height:600px;
|
||||
background-color:white;
|
||||
background-repeat:no-repeat;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
|
||||
.flipbook .page{
|
||||
-webkit-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-moz-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-ms-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-o-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.flipbook-viewport .page img{
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.flipbook-viewport .shadow{
|
||||
-webkit-transition: -webkit-box-shadow 0.5s;
|
||||
-moz-transition: -moz-box-shadow 0.5s;
|
||||
-o-transition: -webkit-box-shadow 0.5s;
|
||||
-ms-transition: -ms-box-shadow 0.5s;
|
||||
|
||||
-webkit-box-shadow:0 0 20px #ccc;
|
||||
-moz-box-shadow:0 0 20px #ccc;
|
||||
-o-box-shadow:0 0 20px #ccc;
|
||||
-ms-box-shadow:0 0 20px #ccc;
|
||||
box-shadow:0 0 20px #ccc;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<!doctype html>
|
||||
<!--[if lt IE 7 ]> <html lang="en" class="ie6"> <![endif]-->
|
||||
<!--[if IE 7 ]> <html lang="en" class="ie7"> <![endif]-->
|
||||
<!--[if IE 8 ]> <html lang="en" class="ie8"> <![endif]-->
|
||||
<!--[if IE 9 ]> <html lang="en" class="ie9"> <![endif]-->
|
||||
<!--[if !IE]><!--> <html lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta name="viewport" content="width = 1050, user-scalable = no" />
|
||||
<script type="text/javascript" src="../../extras/jquery.min.1.7.js"></script>
|
||||
<script type="text/javascript" src="../../extras/modernizr.2.5.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="flipbook-viewport">
|
||||
<div class="container">
|
||||
<div class="flipbook">
|
||||
<div style="background-image:url(pages/1.jpg)"></div>
|
||||
<div style="background-image:url(pages/2.jpg)"></div>
|
||||
<div style="background-image:url(pages/3.jpg)"></div>
|
||||
<div style="background-image:url(pages/4.jpg)"></div>
|
||||
<div style="background-image:url(pages/5.jpg)"></div>
|
||||
<div style="background-image:url(pages/6.jpg)"></div>
|
||||
<div style="background-image:url(pages/7.jpg)"></div>
|
||||
<div style="background-image:url(pages/8.jpg)"></div>
|
||||
<div style="background-image:url(pages/9.jpg)"></div>
|
||||
<div style="background-image:url(pages/10.jpg)"></div>
|
||||
<div style="background-image:url(pages/11.jpg)"></div>
|
||||
<div style="background-image:url(pages/12.jpg)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function loadApp() {
|
||||
|
||||
// Create the flipbook
|
||||
|
||||
$('.flipbook').turn({
|
||||
// Width
|
||||
|
||||
width:922,
|
||||
|
||||
// Height
|
||||
|
||||
height:600,
|
||||
|
||||
// Elevation
|
||||
|
||||
elevation: 50,
|
||||
|
||||
// Enable gradients
|
||||
|
||||
gradients: true,
|
||||
|
||||
// Auto center this flipbook
|
||||
|
||||
autoCenter: true
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Load the HTML4 version if there's not CSS transform
|
||||
|
||||
yepnope({
|
||||
test : Modernizr.csstransforms,
|
||||
yep: ['../../lib/turn.js'],
|
||||
nope: ['../../lib/turn.html4.min.js'],
|
||||
both: ['css/basic.css'],
|
||||
complete: loadApp
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Basic sample
|
||||
*/
|
||||
|
||||
function addPage(page, book) {
|
||||
|
||||
var id, pages = book.turn('pages');
|
||||
|
||||
// Create a new element for this page
|
||||
var element = $('<div />', {});
|
||||
|
||||
// Add the page to the flipbook
|
||||
if (book.turn('addPage', element, page)) {
|
||||
|
||||
// Add the initial HTML
|
||||
// It will contain a loader indicator and a gradient
|
||||
element.html('<div class="gradient"></div><div class="loader"></div>');
|
||||
|
||||
// Load the page
|
||||
loadPage(page, element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function loadPage(page, pageElement) {
|
||||
|
||||
// Create an image element
|
||||
|
||||
var img = $('<img />');
|
||||
|
||||
img.mousedown(function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
img.load(function() {
|
||||
|
||||
// Set the size
|
||||
$(this).css({width: '100%', height: '100%'});
|
||||
|
||||
// Add the image to the page after loaded
|
||||
|
||||
$(this).appendTo(pageElement);
|
||||
|
||||
// Remove the loader indicator
|
||||
|
||||
pageElement.find('.loader').remove();
|
||||
});
|
||||
|
||||
// Load the page
|
||||
|
||||
img.attr('src', 'pages/' + page + '.jpg');
|
||||
|
||||
}
|
||||
|
||||
|
||||
function loadLargePage(page, pageElement) {
|
||||
|
||||
var img = $('<img />');
|
||||
|
||||
img.load(function() {
|
||||
|
||||
var prevImg = pageElement.find('img');
|
||||
$(this).css({width: '100%', height: '100%'});
|
||||
$(this).appendTo(pageElement);
|
||||
prevImg.remove();
|
||||
|
||||
});
|
||||
|
||||
// Loadnew page
|
||||
|
||||
img.attr('src', 'pages/' + page + '-large.jpg');
|
||||
}
|
||||
|
||||
|
||||
function loadSmallPage(page, pageElement) {
|
||||
|
||||
var img = pageElement.find('img');
|
||||
|
||||
img.css({width: '100%', height: '100%'});
|
||||
|
||||
img.unbind('load');
|
||||
// Loadnew page
|
||||
|
||||
img.attr('src', 'pages/' + page + '.jpg');
|
||||
}
|
||||
|
||||
|
||||
|
||||
// http://code.google.com/p/chromium/issues/detail?id=128488
|
||||
function isChrome() {
|
||||
|
||||
return navigator.userAgent.indexOf('Chrome')!=-1;
|
||||
|
||||
}
|
||||
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 72 KiB |
@@ -0,0 +1,73 @@
|
||||
/* Basic sample */
|
||||
|
||||
body{
|
||||
overflow:hidden;
|
||||
background-color:#fcfcfc;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.flipbook-viewport{
|
||||
overflow:hidden;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.flipbook-viewport .container{
|
||||
position:absolute;
|
||||
top:50%;
|
||||
left:50%;
|
||||
margin:auto;
|
||||
}
|
||||
|
||||
.flipbook-viewport .flipbook{
|
||||
width:800px;
|
||||
height:400px;
|
||||
left:-400px;
|
||||
top:-200px;
|
||||
}
|
||||
|
||||
.flipbook-viewport .page{
|
||||
width:400px;
|
||||
height:400px;
|
||||
background-color:white;
|
||||
background-repeat:no-repeat;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
|
||||
.flipbook .page{
|
||||
-webkit-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-moz-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-ms-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-o-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.flipbook-viewport .page img{
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.flipbook-viewport .shadow{
|
||||
-webkit-transition: -webkit-box-shadow 0.5s;
|
||||
-moz-transition: -moz-box-shadow 0.5s;
|
||||
-o-transition: -webkit-box-shadow 0.5s;
|
||||
-ms-transition: -ms-box-shadow 0.5s;
|
||||
|
||||
-webkit-box-shadow:0 0 20px #ccc;
|
||||
-moz-box-shadow:0 0 20px #ccc;
|
||||
-o-box-shadow:0 0 20px #ccc;
|
||||
-ms-box-shadow:0 0 20px #ccc;
|
||||
box-shadow:0 0 20px #ccc;
|
||||
}
|
||||
|
||||
.flipbook-viewport .double{
|
||||
width:800px;
|
||||
height:400px;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<!doctype html>
|
||||
<!--[if lt IE 7 ]> <html lang="en" class="ie6"> <![endif]-->
|
||||
<!--[if IE 7 ]> <html lang="en" class="ie7"> <![endif]-->
|
||||
<!--[if IE 8 ]> <html lang="en" class="ie8"> <![endif]-->
|
||||
<!--[if IE 9 ]> <html lang="en" class="ie9"> <![endif]-->
|
||||
<!--[if !IE]><!--> <html lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta name="viewport" content="width = 1050, user-scalable = no" />
|
||||
<script type="text/javascript" src="../../extras/jquery.min.1.7.js"></script>
|
||||
<script type="text/javascript" src="../../extras/modernizr.2.5.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="flipbook-viewport">
|
||||
<div class="container">
|
||||
<div class="flipbook">
|
||||
<div class="page" style="background-image:url(pages/1.jpg)"></div>
|
||||
<div class="double" style="background-image:url(pages/2.jpg)"></div>
|
||||
<div class="double" style="background-image:url(pages/3.jpg)"></div>
|
||||
<div class="double" style="background-image:url(pages/4.jpg)"></div>
|
||||
<div class="double" style="background-image:url(pages/5.jpg)"></div>
|
||||
<div class="double" style="background-image:url(pages/6.jpg)"></div>
|
||||
<div class="page" style="background-image:url(pages/7.jpg)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function loadApp() {
|
||||
|
||||
var flipbook = $('.flipbook');
|
||||
|
||||
// Check if the CSS was already loaded
|
||||
|
||||
if (flipbook.width()==0 || flipbook.height()==0) {
|
||||
setTimeout(loadApp, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
$('.flipbook .double').scissor();
|
||||
|
||||
// Create the flipbook
|
||||
|
||||
$('.flipbook').turn({
|
||||
// Elevation
|
||||
|
||||
elevation: 50,
|
||||
|
||||
// Enable gradients
|
||||
|
||||
gradients: true,
|
||||
|
||||
// Auto center this flipbook
|
||||
|
||||
autoCenter: true
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Load the HTML4 version if there's not CSS transform
|
||||
|
||||
yepnope({
|
||||
test : Modernizr.csstransforms,
|
||||
yep: ['../../lib/turn.min.js'],
|
||||
nope: ['../../lib/turn.html4.min.js'],
|
||||
both: ['../../lib/scissor.min.js', 'css/double-page.css'],
|
||||
complete: loadApp
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,143 @@
|
||||
.turnjs-slider{
|
||||
width:600px;
|
||||
height:8px;
|
||||
background:rgba(0,0,0, 0.2);
|
||||
-webkit-border-radius:5px;
|
||||
-moz-border-radius:5px;
|
||||
-o-border-radius:5px;
|
||||
-ms-border-radius:5px;
|
||||
border-radius:5px;
|
||||
margin:20px auto;
|
||||
}
|
||||
|
||||
.turnjs-slider .thumbnail{
|
||||
width:115px;
|
||||
height:85px;
|
||||
position:absolute;
|
||||
background:rgba(0,0,0, 0.5);
|
||||
z-index:10000;
|
||||
top:-100px;
|
||||
left:-17px;
|
||||
display:none;
|
||||
|
||||
-webkit-transform:translate3d(0px, 50px, 0px) scale(0.1, 0.1);
|
||||
-webkit-transition:-webkit-transform 0.2s;
|
||||
-webkit-border-radius:5px;
|
||||
|
||||
-moz-transform:translate3d(0px, 50px, 0px) scale(0.1, 0.1);
|
||||
-moz-transition:-moz-transform 0.2s;
|
||||
-moz-border-radius:5px;
|
||||
|
||||
-o-transform:translate3d(0px, 50px, 0px) scale(0.1, 0.1);
|
||||
-o-transition:-o-transform 0.2s;
|
||||
-o-border-radius:5px;
|
||||
|
||||
-ms-transform:translate3d(0px, 50px, 0px) scale(0.1, 0.1);
|
||||
-ms-transition:-ms-transform 0.2s;
|
||||
-ms-border-radius:5px;
|
||||
|
||||
transform:translate3d(0px, 50px, 0px) scale(0.1, 0.1);
|
||||
transition:transform: 0.2s;
|
||||
border-radius:5px;
|
||||
}
|
||||
|
||||
.no-transition{
|
||||
-webkit-transition:none;
|
||||
-moz-transition:none;
|
||||
-o-transition:none;
|
||||
-ms-transition:none;
|
||||
}
|
||||
|
||||
.turnjs-slider .thumbnail div{
|
||||
width:100px;
|
||||
margin:7px;
|
||||
height:70px;
|
||||
background-color:white;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-state-hover .thumbnail{
|
||||
display:block;
|
||||
opacity:0;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-state-active .thumbnail{
|
||||
display:block;
|
||||
opacity:1;
|
||||
-webkit-transform:scale(1, 1);
|
||||
-moz-transform:scale(1, 1);
|
||||
-o-transform:scale(1, 1);
|
||||
-ms-transform:scale(1, 1);
|
||||
transform:scale(1, 1);
|
||||
}
|
||||
|
||||
/* Layout helpers
|
||||
----------------------------------*/
|
||||
|
||||
/* Interaction Cues
|
||||
----------------------------------*/
|
||||
.ui-state-disabled {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
/* Misc visuals
|
||||
----------------------------------*/
|
||||
|
||||
/* Overlays */
|
||||
.turnjs-slider .ui-widget-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-slider {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-slider-handle{
|
||||
position: absolute;
|
||||
z-index:0;
|
||||
width:80px;
|
||||
height: 8px;
|
||||
cursor: default;
|
||||
-webkit-border-radius:5px;
|
||||
-moz-border-radius:5px;
|
||||
-ms-border-radius:5px;
|
||||
border-radius:5px;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-slider-horizontal {
|
||||
height: 8px;
|
||||
width:520px;
|
||||
margin-left:39px;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-slider-horizontal .ui-slider-handle {
|
||||
margin-left:-40px;
|
||||
margin-top:-1px;
|
||||
}
|
||||
|
||||
/* Interaction states
|
||||
----------------------------------*/
|
||||
.turnjs-slider .ui-slider-handle{
|
||||
border:1px solid white;
|
||||
background-color:black;
|
||||
opacity:0.2;
|
||||
display:block;
|
||||
-webkit-transition:opacity 0.2s;
|
||||
-moz-transition:opacity 0.2s;
|
||||
-ms-transition:opacity 0.2s;
|
||||
-o-transition:opacity 0.2s;
|
||||
transition:opacity 0.2s;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-state-hover{
|
||||
opacity:0.4;
|
||||
}
|
||||
|
||||
.turnjs-slider .ui-state-active{
|
||||
opacity:1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
.turnjs-slide{
|
||||
width:600px;
|
||||
height:8px;
|
||||
background-color:#B4B4B4;
|
||||
border-radius:5px;
|
||||
margin:20px auto;
|
||||
}
|
||||
|
||||
.turnjs-slide .ui-slider .ui-slider-handle{
|
||||
background-color:#8F8F8F;
|
||||
z-index:10000;
|
||||
}
|
||||
|
||||
.turnjs-slide .thumbnail{
|
||||
background: #666;
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
body{
|
||||
overflow:hidden;
|
||||
background-color:#fcfcfc;
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.magazine-viewport .container{
|
||||
position:absolute;
|
||||
top:50%;
|
||||
left:50%;
|
||||
width:922px;
|
||||
height:600px;
|
||||
margin:auto;
|
||||
}
|
||||
|
||||
.magazine-viewport .magazine{
|
||||
width:922px;
|
||||
height:600px;
|
||||
left:-461px;
|
||||
top:-300px;
|
||||
}
|
||||
|
||||
.magazine-viewport .page{
|
||||
width:461px;
|
||||
height:600px;
|
||||
background-color:white;
|
||||
background-repeat:no-repeat;
|
||||
background-size:100% 100%;
|
||||
}
|
||||
|
||||
.magazine-viewport .zoomer .region{
|
||||
display:none;
|
||||
}
|
||||
|
||||
.magazine .region{
|
||||
position:absolute;
|
||||
overflow:hidden;
|
||||
background:#0066FF;
|
||||
opacity:0.2;
|
||||
-webkit-border-radius:10px;
|
||||
-moz-border-radius:10px;
|
||||
-ms-border-radius:10px;
|
||||
-o-border-radius:10px;
|
||||
border-radius:10px;
|
||||
cursor:pointer;
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
|
||||
filter: alpha(opacity=20);
|
||||
}
|
||||
|
||||
.magazine .region:hover{
|
||||
opacity:0.5;
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
|
||||
filter: alpha(opacity=50);
|
||||
}
|
||||
|
||||
.magazine .region.zoom{
|
||||
opacity:0.01;
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=1)";
|
||||
filter: alpha(opacity=1);
|
||||
}
|
||||
|
||||
.magazine .region.zoom:hover{
|
||||
opacity:0.2;
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
|
||||
filter: alpha(opacity=20);
|
||||
}
|
||||
|
||||
.magazine .page{
|
||||
-webkit-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-moz-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-ms-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
-o-box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
box-shadow:0 0 20px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.magazine-viewport .page img{
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.magazine .even .gradient{
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
|
||||
background:-webkit-gradient(linear, left top, right top, color-stop(0.95, rgba(0,0,0,0)), color-stop(1, rgba(0,0,0,0.2)));
|
||||
background-image:-webkit-linear-gradient(left, rgba(0,0,0,0) 95%, rgba(0,0,0,0.2) 100%);
|
||||
background-image:-moz-linear-gradient(left, rgba(0,0,0,0) 95%, rgba(0,0,0,0.2) 100%);
|
||||
background-image:-ms-linear-gradient(left, rgba(0,0,0,0) 95%, rgba(0,0,0,0.2) 100%);
|
||||
background-image:-o-linear-gradient(left, rgba(0,0,0,0) 95%, rgba(0,0,0,0.2) 100%);
|
||||
background-image:linear-gradient(left, rgba(0,0,0,0) 95%, rgba(0,0,0,0.2) 100%);
|
||||
}
|
||||
|
||||
.magazine .odd .gradient{
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
|
||||
background:-webkit-gradient(linear, right top, left top, color-stop(0.95, rgba(0,0,0,0)), color-stop(1, rgba(0,0,0,0.15)));
|
||||
background-image:-webkit-linear-gradient(right, rgba(0,0,0,0) 95%, rgba(0,0,0,0.15) 100%);
|
||||
background-image:-moz-linear-gradient(right, rgba(0,0,0,0) 95%, rgba(0,0,0,0.15) 100%);
|
||||
background-image:-ms-linear-gradient(right, rgba(0,0,0,0) 95%, rgba(0,0,0,0.15) 100%);
|
||||
background-image:-o-linear-gradient(right, rgba(0,0,0,0) 95%, rgba(0,0,0,0.15) 100%);
|
||||
background-image:linear-gradient(right, rgba(0,0,0,0) 95%, rgba(0,0,0,0.15) 100%);
|
||||
}
|
||||
|
||||
.magazine-viewport .zoom-in .even .gradient,
|
||||
.magazine-viewport .zoom-in .odd .gradient{
|
||||
|
||||
display:none;
|
||||
|
||||
}
|
||||
|
||||
.magazine-viewport .loader{
|
||||
background-image:url(../pics/loader.gif);
|
||||
width:22px;
|
||||
height:22px;
|
||||
position:absolute;
|
||||
top:280px;
|
||||
left:219px;
|
||||
}
|
||||
|
||||
.magazine-viewport .shadow{
|
||||
-webkit-transition: -webkit-box-shadow 0.5s;
|
||||
-moz-transition: -moz-box-shadow 0.5s;
|
||||
-o-transition: -webkit-box-shadow 0.5s;
|
||||
-ms-transition: -ms-box-shadow 0.5s;
|
||||
|
||||
-webkit-box-shadow:0 0 20px #ccc;
|
||||
-moz-box-shadow:0 0 20px #ccc;
|
||||
-o-box-shadow:0 0 20px #ccc;
|
||||
-ms-box-shadow:0 0 20px #ccc;
|
||||
box-shadow:0 0 20px #ccc;
|
||||
}
|
||||
|
||||
.magazine-viewport .next-button,
|
||||
.magazine-viewport .previous-button{
|
||||
width:22px;
|
||||
height:600px;
|
||||
position:absolute;
|
||||
top:0;
|
||||
}
|
||||
|
||||
.magazine-viewport .next-button{
|
||||
right:-22px;
|
||||
-webkit-border-radius:0 15px 15px 0;
|
||||
-moz-border-radius:0 15px 15px 0;
|
||||
-ms-border-radius:0 15px 15px 0;
|
||||
-o-border-radius:0 15px 15px 0;
|
||||
border-radius:0 15px 15px 0;
|
||||
}
|
||||
|
||||
.magazine-viewport .previous-button{
|
||||
left:-22px;
|
||||
-webkit-border-radius:15px 0 0 15px;
|
||||
-moz-border-radius:15px 0 0 15px;
|
||||
-ms-border-radius:15px 0 0 15px;
|
||||
-o-border-radius:15px 0 0 15px;
|
||||
border-radius:15px 0 0 15px;
|
||||
}
|
||||
|
||||
.magazine-viewport .previous-button-hover,
|
||||
.magazine-viewport .next-button-hover{
|
||||
background-color:rgba(0,0,0, 0.2);
|
||||
}
|
||||
|
||||
.magazine-viewport .previous-button-hover,
|
||||
.magazine-viewport .previous-button-down{
|
||||
background-image:url(../pics/arrows.png);
|
||||
background-position:-4px 284px;
|
||||
background-repeat:no-repeat;
|
||||
}
|
||||
|
||||
.magazine-viewport .previous-button-down,
|
||||
.magazine-viewport .next-button-down{
|
||||
background-color:rgba(0,0,0, 0.4);
|
||||
}
|
||||
|
||||
.magazine-viewport .next-button-hover,
|
||||
.magazine-viewport .next-button-down{
|
||||
background-image:url(../pics/arrows.png);
|
||||
background-position:-38px 284px;
|
||||
background-repeat:no-repeat;
|
||||
}
|
||||
|
||||
.magazine-viewport .zoom-in .next-button,
|
||||
.magazine-viewport .zoom-in .previous-button{
|
||||
display:none;
|
||||
}
|
||||
|
||||
.animated{
|
||||
-webkit-transition:margin-left 0.5s;
|
||||
-moz-transition:margin-left 0.5s;
|
||||
-ms-transition:margin-left 0.5s;
|
||||
-o-transition:margin-left 0.5s;
|
||||
transition:margin-left 0.5s;
|
||||
}
|
||||
|
||||
.thumbnails{
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
height:140px;
|
||||
z-index:1;
|
||||
}
|
||||
|
||||
.thumbnails > div{
|
||||
width:1050px;
|
||||
height:100px;
|
||||
margin:20px auto;
|
||||
}
|
||||
|
||||
.thumbnails ul{
|
||||
margin:0;
|
||||
padding:0;
|
||||
text-align:center;
|
||||
-webkit-transform:scale3d(0.5, 0.5, 1);
|
||||
-moz-transform:scale3d(0.5, 0.5, 1);
|
||||
-o-transform:scale3d(0.5, 0.5, 1);
|
||||
-ms-transform:scale3d(0.5, 0.5, 1);
|
||||
transform:scale3d(0.5, 0.5, 1);
|
||||
-webkit-transition:-webkit-transform ease-in-out 100ms;
|
||||
-moz-transition:-moz-transform ease-in-out 100ms;
|
||||
-ms-transition:-ms-transform ease-in-out 100ms;
|
||||
-o-transition:-o-transform ease-in-out 100ms;
|
||||
transition:transform ease-in-out 100ms;
|
||||
}
|
||||
|
||||
.thumbanils-touch ul{
|
||||
-webkit-transform:none;
|
||||
-moz-transform:none;
|
||||
-o-transform:none;
|
||||
-ms-transform:none;
|
||||
transform:none;
|
||||
}
|
||||
|
||||
.thumbnails-hover ul{
|
||||
-webkit-transform:scale3d(0.6, 0.6, 1);
|
||||
-moz-transform:scale3d(0.6, 0.6, 1);
|
||||
-o-transform:scale3d(0.6, 0.6, 1);
|
||||
-ms-transform:scale3d(0.6, 0.6, 1);
|
||||
transform:scale3d(0.6, 0.6, 1);
|
||||
}
|
||||
|
||||
.thumbnails li{
|
||||
list-style:none;
|
||||
display:inline-block;
|
||||
margin:0 5px;
|
||||
-webkit-box-shadow:0 0 10px #ccc;
|
||||
-moz-box-shadow:0 0 10px #ccc;
|
||||
-ms-box-shadow:0 0 10px #ccc;
|
||||
-o-box-shadow:0 0 10px #ccc;
|
||||
box-shadow:0 0 10px #ccc;
|
||||
-webkit-transition:-webkit-transform 60ms;
|
||||
-moz-transition:-webkit-transform 60ms;
|
||||
-o-transition:-webkit-transform 60ms;
|
||||
-ms-transition:-webkit-transform 60ms;
|
||||
transition:-webkit-transform 60ms;
|
||||
}
|
||||
|
||||
.thumbnails li span{
|
||||
display:none;
|
||||
}
|
||||
|
||||
.thumbnails .current{
|
||||
-webkit-box-shadow:0 0 10px red;
|
||||
-moz-box-shadow:0 0 10px red;
|
||||
-ms-box-shadow:0 0 10px red;
|
||||
-o-box-shadow:0 0 10px red;
|
||||
box-shadow:0 0 10px red;
|
||||
}
|
||||
|
||||
.thumbnails .thumb-hover{
|
||||
-webkit-transform:scale3d(1.3, 1.3, 1);
|
||||
-moz-transform:scale3d(1.3, 1.3, 1);
|
||||
-o-transform:scale3d(1.3, 1.3, 1);
|
||||
-ms-transform:scale3d(1.3, 1.3, 1);
|
||||
transform:scale3d(1.3, 1.3, 1);
|
||||
|
||||
-webkit-box-shadow:0 0 10px #666;
|
||||
-moz-box-shadow:0 0 10px #666;
|
||||
-ms-box-shadow:0 0 10px #666;
|
||||
-o-box-shadow:0 0 10px #666;
|
||||
box-shadow:0 0 10px #666;
|
||||
}
|
||||
|
||||
.thumbanils-touch .thumb-hover{
|
||||
-webkit-transform:none;
|
||||
-moz-transform:none;
|
||||
-o-transform:none;
|
||||
-ms-transform:none;
|
||||
transform:none;
|
||||
}
|
||||
|
||||
.thumbnails .thumb-hover span{
|
||||
position:absolute;
|
||||
bottom:-30px;
|
||||
left:0;
|
||||
z-index:2;
|
||||
width:100%;
|
||||
height:30px;
|
||||
font:bold 15px arial;
|
||||
line-height:30px;
|
||||
color:#666;
|
||||
display:block;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
.thumbnails img{
|
||||
float:left;
|
||||
}
|
||||
|
||||
.exit-message{
|
||||
position: absolute;
|
||||
top:10px;
|
||||
left:0;
|
||||
width:100%;
|
||||
height:40px;
|
||||
z-index:10000;
|
||||
}
|
||||
|
||||
.exit-message > div{
|
||||
width:140px;
|
||||
height:30px;
|
||||
margin:auto;
|
||||
background:rgba(0,0,0,0.5);
|
||||
text-align:center;
|
||||
font:12px arial;
|
||||
line-height:30px;
|
||||
color:white;
|
||||
-webkit-border-radius:10px;
|
||||
-moz-border-radius:10px;
|
||||
-ms-border-radius:10px;
|
||||
-o-border-radius:10px;
|
||||
border-radius:10px;
|
||||
}
|
||||
|
||||
.zoom-icon{
|
||||
position:absolute;
|
||||
z-index:1000;
|
||||
width:22px;
|
||||
height:22px;
|
||||
top:10px;
|
||||
right:10px;
|
||||
background-image:url(../pics/zoom-icons.png);
|
||||
background-size:88px 22px;
|
||||
}
|
||||
|
||||
.zoom-icon-in{
|
||||
background-position:0 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.zoom-icon-in.zoom-icon-in-hover{
|
||||
background-position:-22px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.zoom-icon-out{
|
||||
background-position:-44px 0;
|
||||
}
|
||||
|
||||
.zoom-icon-out.zoom-icon-out-hover{
|
||||
background-position:-66px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bottom{
|
||||
position:absolute;
|
||||
left:0;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
<!doctype html>
|
||||
<!--[if lt IE 7 ]> <html lang="en" class="ie6"> <![endif]-->
|
||||
<!--[if IE 7 ]> <html lang="en" class="ie7"> <![endif]-->
|
||||
<!--[if IE 8 ]> <html lang="en" class="ie8"> <![endif]-->
|
||||
<!--[if IE 9 ]> <html lang="en" class="ie9"> <![endif]-->
|
||||
<!--[if !IE]><!--> <html lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>Using turn.js and the new zoom feature</title>
|
||||
<meta name="viewport" content="width = 1050, user-scalable = no" />
|
||||
<script type="text/javascript" src="../../extras/jquery.min.1.7.js"></script>
|
||||
<script type="text/javascript" src="../../extras/modernizr.2.5.3.min.js"></script>
|
||||
<script type="text/javascript" src="../../lib/hash.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="canvas">
|
||||
|
||||
<div class="zoom-icon zoom-icon-in"></div>
|
||||
|
||||
<div class="magazine-viewport">
|
||||
<div class="container">
|
||||
<div class="magazine">
|
||||
<!-- Next button -->
|
||||
<div ignore="1" class="next-button"></div>
|
||||
<!-- Previous button -->
|
||||
<div ignore="1" class="previous-button"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Thumbnails -->
|
||||
<div class="thumbnails">
|
||||
<div>
|
||||
<ul>
|
||||
<li class="i">
|
||||
<img src="pages/1-thumb.jpg" width="76" height="100" class="page-1">
|
||||
<span>1</span>
|
||||
</li>
|
||||
<li class="d">
|
||||
<img src="pages/2-thumb.jpg" width="76" height="100" class="page-2">
|
||||
<img src="pages/3-thumb.jpg" width="76" height="100" class="page-3">
|
||||
<span>2-3</span>
|
||||
</li>
|
||||
<li class="d">
|
||||
<img src="pages/4-thumb.jpg" width="76" height="100" class="page-4">
|
||||
<img src="pages/5-thumb.jpg" width="76" height="100" class="page-5">
|
||||
<span>4-5</span>
|
||||
</li>
|
||||
<li class="d">
|
||||
<img src="pages/6-thumb.jpg" width="76" height="100" class="page-6">
|
||||
<img src="pages/7-thumb.jpg" width="76" height="100" class="page-7">
|
||||
<span>6-7</span>
|
||||
</li>
|
||||
<li class="d">
|
||||
<img src="pages/8-thumb.jpg" width="76" height="100" class="page-8">
|
||||
<img src="pages/9-thumb.jpg" width="76" height="100" class="page-9">
|
||||
<span>8-9</span>
|
||||
</li>
|
||||
<li class="d">
|
||||
<img src="pages/10-thumb.jpg" width="76" height="100" class="page-10">
|
||||
<img src="pages/11-thumb.jpg" width="76" height="100" class="page-11">
|
||||
<span>10-11</span>
|
||||
</li>
|
||||
<li class="i">
|
||||
<img src="pages/12-thumb.jpg" width="76" height="100" class="page-12">
|
||||
<span>12</span>
|
||||
</li>
|
||||
<ul>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function loadApp() {
|
||||
|
||||
$('#canvas').fadeIn(1000);
|
||||
|
||||
var flipbook = $('.magazine');
|
||||
|
||||
// Check if the CSS was already loaded
|
||||
|
||||
if (flipbook.width()==0 || flipbook.height()==0) {
|
||||
setTimeout(loadApp, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the flipbook
|
||||
|
||||
flipbook.turn({
|
||||
|
||||
// Magazine width
|
||||
|
||||
width: 922,
|
||||
|
||||
// Magazine height
|
||||
|
||||
height: 600,
|
||||
|
||||
// Duration in millisecond
|
||||
|
||||
duration: 1000,
|
||||
|
||||
// Hardware acceleration
|
||||
|
||||
acceleration: !isChrome(),
|
||||
|
||||
// Enables gradients
|
||||
|
||||
gradients: true,
|
||||
|
||||
// Auto center this flipbook
|
||||
|
||||
autoCenter: true,
|
||||
|
||||
// Elevation from the edge of the flipbook when turning a page
|
||||
|
||||
elevation: 50,
|
||||
|
||||
// The number of pages
|
||||
|
||||
pages: 12,
|
||||
|
||||
// Events
|
||||
|
||||
when: {
|
||||
turning: function(event, page, view) {
|
||||
|
||||
var book = $(this),
|
||||
currentPage = book.turn('page'),
|
||||
pages = book.turn('pages');
|
||||
|
||||
// Update the current URI
|
||||
|
||||
Hash.go('page/' + page).update();
|
||||
|
||||
// Show and hide navigation buttons
|
||||
|
||||
disableControls(page);
|
||||
|
||||
|
||||
$('.thumbnails .page-'+currentPage).
|
||||
parent().
|
||||
removeClass('current');
|
||||
|
||||
$('.thumbnails .page-'+page).
|
||||
parent().
|
||||
addClass('current');
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
turned: function(event, page, view) {
|
||||
|
||||
disableControls(page);
|
||||
|
||||
$(this).turn('center');
|
||||
|
||||
if (page==1) {
|
||||
$(this).turn('peel', 'br');
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
missing: function (event, pages) {
|
||||
|
||||
// Add pages that aren't in the magazine
|
||||
|
||||
for (var i = 0; i < pages.length; i++)
|
||||
addPage(pages[i], $(this));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Zoom.js
|
||||
|
||||
$('.magazine-viewport').zoom({
|
||||
flipbook: $('.magazine'),
|
||||
|
||||
max: function() {
|
||||
|
||||
return largeMagazineWidth()/$('.magazine').width();
|
||||
|
||||
},
|
||||
|
||||
when: {
|
||||
|
||||
swipeLeft: function() {
|
||||
|
||||
$(this).zoom('flipbook').turn('next');
|
||||
|
||||
},
|
||||
|
||||
swipeRight: function() {
|
||||
|
||||
$(this).zoom('flipbook').turn('previous');
|
||||
|
||||
},
|
||||
|
||||
resize: function(event, scale, page, pageElement) {
|
||||
|
||||
if (scale==1)
|
||||
loadSmallPage(page, pageElement);
|
||||
else
|
||||
loadLargePage(page, pageElement);
|
||||
|
||||
},
|
||||
|
||||
zoomIn: function () {
|
||||
|
||||
$('.thumbnails').hide();
|
||||
$('.made').hide();
|
||||
$('.magazine').removeClass('animated').addClass('zoom-in');
|
||||
$('.zoom-icon').removeClass('zoom-icon-in').addClass('zoom-icon-out');
|
||||
|
||||
if (!window.escTip && !$.isTouch) {
|
||||
escTip = true;
|
||||
|
||||
$('<div />', {'class': 'exit-message'}).
|
||||
html('<div>Press ESC to exit</div>').
|
||||
appendTo($('body')).
|
||||
delay(2000).
|
||||
animate({opacity:0}, 500, function() {
|
||||
$(this).remove();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
zoomOut: function () {
|
||||
|
||||
$('.exit-message').hide();
|
||||
$('.thumbnails').fadeIn();
|
||||
$('.made').fadeIn();
|
||||
$('.zoom-icon').removeClass('zoom-icon-out').addClass('zoom-icon-in');
|
||||
|
||||
setTimeout(function(){
|
||||
$('.magazine').addClass('animated').removeClass('zoom-in');
|
||||
resizeViewport();
|
||||
}, 0);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Zoom event
|
||||
|
||||
if ($.isTouch)
|
||||
$('.magazine-viewport').bind('zoom.doubleTap', zoomTo);
|
||||
else
|
||||
$('.magazine-viewport').bind('zoom.tap', zoomTo);
|
||||
|
||||
|
||||
// Using arrow keys to turn the page
|
||||
|
||||
$(document).keydown(function(e){
|
||||
|
||||
var previous = 37, next = 39, esc = 27;
|
||||
|
||||
switch (e.keyCode) {
|
||||
case previous:
|
||||
|
||||
// left arrow
|
||||
$('.magazine').turn('previous');
|
||||
e.preventDefault();
|
||||
|
||||
break;
|
||||
case next:
|
||||
|
||||
//right arrow
|
||||
$('.magazine').turn('next');
|
||||
e.preventDefault();
|
||||
|
||||
break;
|
||||
case esc:
|
||||
|
||||
$('.magazine-viewport').zoom('zoomOut');
|
||||
e.preventDefault();
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// URIs - Format #/page/1
|
||||
|
||||
Hash.on('^page\/([0-9]*)$', {
|
||||
yep: function(path, parts) {
|
||||
var page = parts[1];
|
||||
|
||||
if (page!==undefined) {
|
||||
if ($('.magazine').turn('is'))
|
||||
$('.magazine').turn('page', page);
|
||||
}
|
||||
|
||||
},
|
||||
nop: function(path) {
|
||||
|
||||
if ($('.magazine').turn('is'))
|
||||
$('.magazine').turn('page', 1);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(window).resize(function() {
|
||||
resizeViewport();
|
||||
}).bind('orientationchange', function() {
|
||||
resizeViewport();
|
||||
});
|
||||
|
||||
// Events for thumbnails
|
||||
|
||||
$('.thumbnails').click(function(event) {
|
||||
|
||||
var page;
|
||||
|
||||
if (event.target && (page=/page-([0-9]+)/.exec($(event.target).attr('class'))) ) {
|
||||
|
||||
$('.magazine').turn('page', page[1]);
|
||||
}
|
||||
});
|
||||
|
||||
$('.thumbnails li').
|
||||
bind($.mouseEvents.over, function() {
|
||||
|
||||
$(this).addClass('thumb-hover');
|
||||
|
||||
}).bind($.mouseEvents.out, function() {
|
||||
|
||||
$(this).removeClass('thumb-hover');
|
||||
|
||||
});
|
||||
|
||||
if ($.isTouch) {
|
||||
|
||||
$('.thumbnails').
|
||||
addClass('thumbanils-touch').
|
||||
bind($.mouseEvents.move, function(event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
$('.thumbnails ul').mouseover(function() {
|
||||
|
||||
$('.thumbnails').addClass('thumbnails-hover');
|
||||
|
||||
}).mousedown(function() {
|
||||
|
||||
return false;
|
||||
|
||||
}).mouseout(function() {
|
||||
|
||||
$('.thumbnails').removeClass('thumbnails-hover');
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Regions
|
||||
|
||||
if ($.isTouch) {
|
||||
$('.magazine').bind('touchstart', regionClick);
|
||||
} else {
|
||||
$('.magazine').click(regionClick);
|
||||
}
|
||||
|
||||
// Events for the next button
|
||||
|
||||
$('.next-button').bind($.mouseEvents.over, function() {
|
||||
|
||||
$(this).addClass('next-button-hover');
|
||||
|
||||
}).bind($.mouseEvents.out, function() {
|
||||
|
||||
$(this).removeClass('next-button-hover');
|
||||
|
||||
}).bind($.mouseEvents.down, function() {
|
||||
|
||||
$(this).addClass('next-button-down');
|
||||
|
||||
}).bind($.mouseEvents.up, function() {
|
||||
|
||||
$(this).removeClass('next-button-down');
|
||||
|
||||
}).click(function() {
|
||||
|
||||
$('.magazine').turn('next');
|
||||
|
||||
});
|
||||
|
||||
// Events for the next button
|
||||
|
||||
$('.previous-button').bind($.mouseEvents.over, function() {
|
||||
|
||||
$(this).addClass('previous-button-hover');
|
||||
|
||||
}).bind($.mouseEvents.out, function() {
|
||||
|
||||
$(this).removeClass('previous-button-hover');
|
||||
|
||||
}).bind($.mouseEvents.down, function() {
|
||||
|
||||
$(this).addClass('previous-button-down');
|
||||
|
||||
}).bind($.mouseEvents.up, function() {
|
||||
|
||||
$(this).removeClass('previous-button-down');
|
||||
|
||||
}).click(function() {
|
||||
|
||||
$('.magazine').turn('previous');
|
||||
|
||||
});
|
||||
|
||||
|
||||
resizeViewport();
|
||||
|
||||
$('.magazine').addClass('animated');
|
||||
|
||||
}
|
||||
|
||||
// Zoom icon
|
||||
|
||||
$('.zoom-icon').bind('mouseover', function() {
|
||||
|
||||
if ($(this).hasClass('zoom-icon-in'))
|
||||
$(this).addClass('zoom-icon-in-hover');
|
||||
|
||||
if ($(this).hasClass('zoom-icon-out'))
|
||||
$(this).addClass('zoom-icon-out-hover');
|
||||
|
||||
}).bind('mouseout', function() {
|
||||
|
||||
if ($(this).hasClass('zoom-icon-in'))
|
||||
$(this).removeClass('zoom-icon-in-hover');
|
||||
|
||||
if ($(this).hasClass('zoom-icon-out'))
|
||||
$(this).removeClass('zoom-icon-out-hover');
|
||||
|
||||
}).bind('click', function() {
|
||||
|
||||
if ($(this).hasClass('zoom-icon-in'))
|
||||
$('.magazine-viewport').zoom('zoomIn');
|
||||
else if ($(this).hasClass('zoom-icon-out'))
|
||||
$('.magazine-viewport').zoom('zoomOut');
|
||||
|
||||
});
|
||||
|
||||
$('#canvas').hide();
|
||||
|
||||
|
||||
// Load the HTML4 version if there's not CSS transform
|
||||
|
||||
yepnope({
|
||||
test : Modernizr.csstransforms,
|
||||
yep: ['../../lib/turn.js'],
|
||||
nope: ['../../lib/turn.html4.min.js'],
|
||||
both: ['../../lib/zoom.min.js', 'js/magazine.js', 'css/magazine.css'],
|
||||
complete: loadApp
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Magazine sample
|
||||
*/
|
||||
|
||||
function addPage(page, book) {
|
||||
|
||||
var id, pages = book.turn('pages');
|
||||
|
||||
// Create a new element for this page
|
||||
var element = $('<div />', {});
|
||||
|
||||
// Add the page to the flipbook
|
||||
if (book.turn('addPage', element, page)) {
|
||||
|
||||
// Add the initial HTML
|
||||
// It will contain a loader indicator and a gradient
|
||||
element.html('<div class="gradient"></div><div class="loader"></div>');
|
||||
|
||||
// Load the page
|
||||
loadPage(page, element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function loadPage(page, pageElement) {
|
||||
|
||||
// Create an image element
|
||||
|
||||
var img = $('<img />');
|
||||
|
||||
img.mousedown(function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
img.load(function() {
|
||||
|
||||
// Set the size
|
||||
$(this).css({width: '100%', height: '100%'});
|
||||
|
||||
// Add the image to the page after loaded
|
||||
|
||||
$(this).appendTo(pageElement);
|
||||
|
||||
// Remove the loader indicator
|
||||
|
||||
pageElement.find('.loader').remove();
|
||||
});
|
||||
|
||||
// Load the page
|
||||
|
||||
img.attr('src', 'pages/' + page + '.jpg');
|
||||
|
||||
loadRegions(page, pageElement);
|
||||
|
||||
}
|
||||
|
||||
// Zoom in / Zoom out
|
||||
|
||||
function zoomTo(event) {
|
||||
|
||||
setTimeout(function() {
|
||||
if ($('.magazine-viewport').data().regionClicked) {
|
||||
$('.magazine-viewport').data().regionClicked = false;
|
||||
} else {
|
||||
if ($('.magazine-viewport').zoom('value')==1) {
|
||||
$('.magazine-viewport').zoom('zoomIn', event);
|
||||
} else {
|
||||
$('.magazine-viewport').zoom('zoomOut');
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Load regions
|
||||
|
||||
function loadRegions(page, element) {
|
||||
|
||||
$.getJSON('pages/'+page+'-regions.json').
|
||||
done(function(data) {
|
||||
|
||||
$.each(data, function(key, region) {
|
||||
addRegion(region, element);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add region
|
||||
|
||||
function addRegion(region, pageElement) {
|
||||
|
||||
var reg = $('<div />', {'class': 'region ' + region['class']}),
|
||||
options = $('.magazine').turn('options'),
|
||||
pageWidth = options.width/2,
|
||||
pageHeight = options.height;
|
||||
|
||||
reg.css({
|
||||
top: Math.round(region.y/pageHeight*100)+'%',
|
||||
left: Math.round(region.x/pageWidth*100)+'%',
|
||||
width: Math.round(region.width/pageWidth*100)+'%',
|
||||
height: Math.round(region.height/pageHeight*100)+'%'
|
||||
}).attr('region-data', $.param(region.data||''));
|
||||
|
||||
|
||||
reg.appendTo(pageElement);
|
||||
}
|
||||
|
||||
// Process click on a region
|
||||
|
||||
function regionClick(event) {
|
||||
|
||||
var region = $(event.target);
|
||||
|
||||
if (region.hasClass('region')) {
|
||||
|
||||
$('.magazine-viewport').data().regionClicked = true;
|
||||
|
||||
setTimeout(function() {
|
||||
$('.magazine-viewport').data().regionClicked = false;
|
||||
}, 100);
|
||||
|
||||
var regionType = $.trim(region.attr('class').replace('region', ''));
|
||||
|
||||
return processRegion(region, regionType);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Process the data of every region
|
||||
|
||||
function processRegion(region, regionType) {
|
||||
|
||||
data = decodeParams(region.attr('region-data'));
|
||||
|
||||
switch (regionType) {
|
||||
case 'link' :
|
||||
|
||||
window.open(data.url);
|
||||
|
||||
break;
|
||||
case 'zoom' :
|
||||
|
||||
var regionOffset = region.offset(),
|
||||
viewportOffset = $('.magazine-viewport').offset(),
|
||||
pos = {
|
||||
x: regionOffset.left-viewportOffset.left,
|
||||
y: regionOffset.top-viewportOffset.top
|
||||
};
|
||||
|
||||
$('.magazine-viewport').zoom('zoomIn', pos);
|
||||
|
||||
break;
|
||||
case 'to-page' :
|
||||
|
||||
$('.magazine').turn('page', data.page);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Load large page
|
||||
|
||||
function loadLargePage(page, pageElement) {
|
||||
|
||||
var img = $('<img />');
|
||||
|
||||
img.load(function() {
|
||||
|
||||
var prevImg = pageElement.find('img');
|
||||
$(this).css({width: '100%', height: '100%'});
|
||||
$(this).appendTo(pageElement);
|
||||
prevImg.remove();
|
||||
|
||||
});
|
||||
|
||||
// Loadnew page
|
||||
|
||||
img.attr('src', 'pages/' + page + '-large.jpg');
|
||||
}
|
||||
|
||||
// Load small page
|
||||
|
||||
function loadSmallPage(page, pageElement) {
|
||||
|
||||
var img = pageElement.find('img');
|
||||
|
||||
img.css({width: '100%', height: '100%'});
|
||||
|
||||
img.unbind('load');
|
||||
// Loadnew page
|
||||
|
||||
img.attr('src', 'pages/' + page + '.jpg');
|
||||
}
|
||||
|
||||
// http://code.google.com/p/chromium/issues/detail?id=128488
|
||||
|
||||
function isChrome() {
|
||||
|
||||
return navigator.userAgent.indexOf('Chrome')!=-1;
|
||||
|
||||
}
|
||||
|
||||
function disableControls(page) {
|
||||
if (page==1)
|
||||
$('.previous-button').hide();
|
||||
else
|
||||
$('.previous-button').show();
|
||||
|
||||
if (page==$('.magazine').turn('pages'))
|
||||
$('.next-button').hide();
|
||||
else
|
||||
$('.next-button').show();
|
||||
}
|
||||
|
||||
// Set the width and height for the viewport
|
||||
|
||||
function resizeViewport() {
|
||||
|
||||
var width = $(window).width(),
|
||||
height = $(window).height(),
|
||||
options = $('.magazine').turn('options');
|
||||
|
||||
$('.magazine').removeClass('animated');
|
||||
|
||||
$('.magazine-viewport').css({
|
||||
width: width,
|
||||
height: height
|
||||
}).
|
||||
zoom('resize');
|
||||
|
||||
|
||||
if ($('.magazine').turn('zoom')==1) {
|
||||
var bound = calculateBound({
|
||||
width: options.width,
|
||||
height: options.height,
|
||||
boundWidth: Math.min(options.width, width),
|
||||
boundHeight: Math.min(options.height, height)
|
||||
});
|
||||
|
||||
if (bound.width%2!==0)
|
||||
bound.width-=1;
|
||||
|
||||
|
||||
if (bound.width!=$('.magazine').width() || bound.height!=$('.magazine').height()) {
|
||||
|
||||
$('.magazine').turn('size', bound.width, bound.height);
|
||||
|
||||
if ($('.magazine').turn('page')==1)
|
||||
$('.magazine').turn('peel', 'br');
|
||||
|
||||
$('.next-button').css({height: bound.height, backgroundPosition: '-38px '+(bound.height/2-32/2)+'px'});
|
||||
$('.previous-button').css({height: bound.height, backgroundPosition: '-4px '+(bound.height/2-32/2)+'px'});
|
||||
}
|
||||
|
||||
$('.magazine').css({top: -bound.height/2, left: -bound.width/2});
|
||||
}
|
||||
|
||||
var magazineOffset = $('.magazine').offset(),
|
||||
boundH = height - magazineOffset.top - $('.magazine').height(),
|
||||
marginTop = (boundH - $('.thumbnails > div').height()) / 2;
|
||||
|
||||
if (marginTop<0) {
|
||||
$('.thumbnails').css({height:1});
|
||||
} else {
|
||||
$('.thumbnails').css({height: boundH});
|
||||
$('.thumbnails > div').css({marginTop: marginTop});
|
||||
}
|
||||
|
||||
if (magazineOffset.top<$('.made').height())
|
||||
$('.made').hide();
|
||||
else
|
||||
$('.made').show();
|
||||
|
||||
$('.magazine').addClass('animated');
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Number of views in a flipbook
|
||||
|
||||
function numberOfViews(book) {
|
||||
return book.turn('pages') / 2 + 1;
|
||||
}
|
||||
|
||||
// Current view in a flipbook
|
||||
|
||||
function getViewNumber(book, page) {
|
||||
return parseInt((page || book.turn('page'))/2 + 1, 10);
|
||||
}
|
||||
|
||||
function moveBar(yes) {
|
||||
if (Modernizr && Modernizr.csstransforms) {
|
||||
$('#slider .ui-slider-handle').css({zIndex: yes ? -1 : 10000});
|
||||
}
|
||||
}
|
||||
|
||||
function setPreview(view) {
|
||||
|
||||
var previewWidth = 112,
|
||||
previewHeight = 73,
|
||||
previewSrc = 'pages/preview.jpg',
|
||||
preview = $(_thumbPreview.children(':first')),
|
||||
numPages = (view==1 || view==$('#slider').slider('option', 'max')) ? 1 : 2,
|
||||
width = (numPages==1) ? previewWidth/2 : previewWidth;
|
||||
|
||||
_thumbPreview.
|
||||
addClass('no-transition').
|
||||
css({width: width + 15,
|
||||
height: previewHeight + 15,
|
||||
top: -previewHeight - 30,
|
||||
left: ($($('#slider').children(':first')).width() - width - 15)/2
|
||||
});
|
||||
|
||||
preview.css({
|
||||
width: width,
|
||||
height: previewHeight
|
||||
});
|
||||
|
||||
if (preview.css('background-image')==='' ||
|
||||
preview.css('background-image')=='none') {
|
||||
|
||||
preview.css({backgroundImage: 'url(' + previewSrc + ')'});
|
||||
|
||||
setTimeout(function(){
|
||||
_thumbPreview.removeClass('no-transition');
|
||||
}, 0);
|
||||
|
||||
}
|
||||
|
||||
preview.css({backgroundPosition:
|
||||
'0px -'+((view-1)*previewHeight)+'px'
|
||||
});
|
||||
}
|
||||
|
||||
// Width of the flipbook when zoomed in
|
||||
|
||||
function largeMagazineWidth() {
|
||||
|
||||
return 2214;
|
||||
|
||||
}
|
||||
|
||||
// decode URL Parameters
|
||||
|
||||
function decodeParams(data) {
|
||||
|
||||
var parts = data.split('&'), d, obj = {};
|
||||
|
||||
for (var i =0; i<parts.length; i++) {
|
||||
d = parts[i].split('=');
|
||||
obj[decodeURIComponent(d[0])] = decodeURIComponent(d[1]);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Calculate the width and height of a square within another square
|
||||
|
||||
function calculateBound(d) {
|
||||
|
||||
var bound = {width: d.width, height: d.height};
|
||||
|
||||
if (bound.width>d.boundWidth || bound.height>d.boundHeight) {
|
||||
|
||||
var rel = bound.width/bound.height;
|
||||
|
||||
if (d.boundWidth/rel>d.boundHeight && d.boundHeight*rel<=d.boundWidth) {
|
||||
|
||||
bound.width = Math.round(d.boundHeight*rel);
|
||||
bound.height = d.boundHeight;
|
||||
|
||||
} else {
|
||||
|
||||
bound.width = d.boundWidth;
|
||||
bound.height = Math.round(d.boundWidth/rel);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return bound;
|
||||
}
|
||||
|
After Width: | Height: | Size: 759 KiB |
@@ -0,0 +1,12 @@
|
||||
[{
|
||||
"x":22,
|
||||
"y":568,
|
||||
"width":130,
|
||||
"height":12,
|
||||
"class":"link",
|
||||
"data":
|
||||
{
|
||||
"url": "http://latimes.com/shopping/vegas"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 422 KiB |
@@ -0,0 +1,8 @@
|
||||
[{
|
||||
"x":0,
|
||||
"y":135,
|
||||
"width":423,
|
||||
"height":182,
|
||||
"class":"zoom"
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 413 KiB |
@@ -0,0 +1,15 @@
|
||||
[{
|
||||
"x":181,
|
||||
"y":386,
|
||||
"width":102,
|
||||
"height":214,
|
||||
"class":"zoom"
|
||||
},
|
||||
{
|
||||
"x":289,
|
||||
"y":253,
|
||||
"width":173,
|
||||
"height":312,
|
||||
"class":"zoom"
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
@@ -0,0 +1 @@
|
||||
[]
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1 @@
|
||||
[]
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 792 KiB |
@@ -0,0 +1,45 @@
|
||||
[{
|
||||
"x":256,
|
||||
"y":161,
|
||||
"width":128,
|
||||
"height":15,
|
||||
"class":"to-page",
|
||||
"data":
|
||||
{
|
||||
"page": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"x":256,
|
||||
"y":202,
|
||||
"width":114,
|
||||
"height":15,
|
||||
"class":"to-page",
|
||||
"data":
|
||||
{
|
||||
"page": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"x":256,
|
||||
"y":244,
|
||||
"width":126,
|
||||
"height":15,
|
||||
"class":"to-page",
|
||||
"data":
|
||||
{
|
||||
"page": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"x":256,
|
||||
"y":286,
|
||||
"width":68,
|
||||
"height":15,
|
||||
"class":"to-page",
|
||||
"data":
|
||||
{
|
||||
"page": 12
|
||||
}
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1,22 @@
|
||||
[{
|
||||
"x":287,
|
||||
"y":0,
|
||||
"width":171,
|
||||
"height":143,
|
||||
"class":"zoom"
|
||||
},
|
||||
{
|
||||
"x":287,
|
||||
"y":155,
|
||||
"width":175,
|
||||
"height":134,
|
||||
"class":"zoom"
|
||||
},
|
||||
{
|
||||
"x":0,
|
||||
"y":264,
|
||||
"width":177,
|
||||
"height":123,
|
||||
"class":"zoom"
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 755 KiB |
@@ -0,0 +1 @@
|
||||
[]
|
||||
|
After Width: | Height: | Size: 2.6 KiB |