├── images
├── loading.gif
└── media_icon.png
├── upload
├── MPreview_DOC_1.jpg
└── MPreview_PPT_1.jpg
├── data.json
├── PPT.html
├── index.html
├── css
├── base.css
└── MPreview.css
├── api.php
├── README.md
└── js
├── MPreviewPPT.js
└── MPreview.js
/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webjyh/MPreview/HEAD/images/loading.gif
--------------------------------------------------------------------------------
/images/media_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webjyh/MPreview/HEAD/images/media_icon.png
--------------------------------------------------------------------------------
/upload/MPreview_DOC_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webjyh/MPreview/HEAD/upload/MPreview_DOC_1.jpg
--------------------------------------------------------------------------------
/upload/MPreview_PPT_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webjyh/MPreview/HEAD/upload/MPreview_PPT_1.jpg
--------------------------------------------------------------------------------
/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 1,
3 | "imgs": [
4 | "./upload/1.png",
5 | "./upload/2.png",
6 | "./upload/3.png",
7 | "./upload/4.png",
8 | "./upload/5.png",
9 | "./upload/1.png?ver=1.0.0",
10 | "./upload/2.png?ver=1.0.0",
11 | "./upload/3.png?ver=1.0.0",
12 | "./upload/4.png?ver=1.0.0",
13 | "./upload/5.png?ver=1.0.0",
14 | "./upload/1.png?ver=2.0.0",
15 | "./upload/2.png?ver=2.0.0",
16 | "./upload/3.png?ver=2.0.0",
17 | "./upload/4.png?ver=2.0.0",
18 | "./upload/5.png?ver=2.0.0",
19 | "./upload/1.png?ver=3.0.0",
20 | "./upload/2.png?ver=3.0.0",
21 | "./upload/3.png?ver=3.0.0",
22 | ]
23 | }
--------------------------------------------------------------------------------
/PPT.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MPreview PPT格式预览
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MPreview Word格式预览
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/css/base.css:
--------------------------------------------------------------------------------
1 | /* reset */
2 | html, body, div, span, applet, object, iframe,
3 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
4 | a, abbr, acronym, address, big, cite, code,
5 | del, dfn, em, img, ins, kbd, q, s, samp,
6 | small, strike, strong, sub, sup, tt, var,
7 | b, u, i, center,
8 | dl, dt, dd, ol, ul, li,
9 | fieldset, form, label, legend,
10 | table, caption, tbody, tfoot, thead, tr, th, td,
11 | article, aside, canvas, details, embed,
12 | figure, figcaption, footer, header, hgroup,
13 | menu, nav, output, ruby, section, summary,
14 | time, mark, audio, video {
15 | margin: 0;
16 | padding: 0;
17 | border: 0;
18 | font-size: 100%;
19 | font: inherit;
20 | vertical-align: baseline;
21 | }
22 | /* HTML5 display-role reset for older browsers */
23 | article, aside, details, figcaption, figure,
24 | footer, header, hgroup, menu, nav, section {
25 | display: block;
26 | }
27 | body {
28 | line-height: 1;
29 | }
30 | ol, ul {
31 | list-style: none;
32 | }
33 | blockquote, q {
34 | quotes: none;
35 | }
36 | blockquote:before, blockquote:after,
37 | q:before, q:after {
38 | content: '';
39 | content: none;
40 | }
41 | table {
42 | border-collapse: collapse;
43 | border-spacing: 0;
44 | }
45 |
46 | /* common */
47 | body { font-size: 12px; line-height: 1.6; color: #333; font-family:"Microsoft Yahei", Arial; background: #F2F2F2; }
48 | .wrapper { width: 1000px; margin: 50px auto; }
49 | .doc { width: 1000px; height: 800px; margin: 0px auto; }
50 | .ppt { width: 1000px; height: 800px; margin: 0px auto; }
--------------------------------------------------------------------------------
/api.php:
--------------------------------------------------------------------------------
1 | 1,
8 | 'imgs' => array(
9 | './upload/MPreview_DOC_1.jpg?ver=1.0.0',
10 | './upload/MPreview_DOC_1.jpg?ver=2.0.0',
11 | './upload/MPreview_DOC_1.jpg?ver=3.0.0',
12 | './upload/MPreview_DOC_1.jpg?ver=4.0.0',
13 | './upload/MPreview_DOC_1.jpg?ver=5.0.0',
14 | './upload/MPreview_DOC_1.jpg?ver=6.0.0',
15 | './upload/MPreview_DOC_1.jpg?ver=7.0.0',
16 | './upload/MPreview_DOC_1.jpg?ver=8.0.0'
17 | )
18 | );
19 | } else {
20 | $JSON = array(
21 | 'code' => 1,
22 | 'imgs' => array(
23 | './upload/MPreview_PPT_1.jpg?ver=1.0.0',
24 | './upload/MPreview_PPT_1.jpg?ver=2.0.0',
25 | './upload/MPreview_PPT_1.jpg?ver=3.0.0',
26 | './upload/MPreview_PPT_1.jpg?ver=4.0.0',
27 | './upload/MPreview_PPT_1.jpg?ver=5.0.0',
28 | './upload/MPreview_PPT_1.jpg?ver=6.0.0',
29 | './upload/MPreview_PPT_1.jpg?ver=7.0.0',
30 | './upload/MPreview_PPT_1.jpg?ver=8.0.0',
31 | )
32 | );
33 | }
34 |
35 | header('Content-type: application/json');
36 | if ( !empty( $_GET['callback'] ) ){
37 | echo $callback.'('.json_encode($JSON).')';
38 | } else {
39 | echo json_encode($JSON);
40 | }
41 | ?>
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MPreview.js
2 |
3 | Word,PPT 文档预览组件(图片预览组件)
4 |
5 | 移动端请移步 [MPreview.mobile](https://github.com/webjyh/MPreview.mobile)
6 |
7 | ## Demo参考
8 |
9 |
10 |
11 | ### 特此说明
12 | 此插件是我在项目开发中而制作,其只适用于其项目,如须使用须注意,提供的图片须有较大的宽高。
13 |
14 | ### 插件说明
15 | 1. 此插件需要由服务端提供转换好的Word图片或PPT图片来进行预览。
16 | 2. 插件需要 jQuery1.9+ 库。支持IE7+,FireFox,Chrome。
17 | 3. 初始化调用插件的外容器,只需设置宽高样式即可,无需其它设置。
18 | 4. 因插件是刚开始阶段,一些功能并未能完善全,如:放大,缩小功能。
19 | 5. 插件中一些滚动的计算是硬算出来的(勿喷)。
20 |
21 | ### 插件特性
22 | 1. 服务端将全数据返回(图像地址的数组集合),由插件进行分割加载。
23 | 2. 支持滚动条拖拽滚动及全屏预览。
24 | 3. 支持上一页,下一页功能。
25 |
26 | ### 目录结构说明
27 | ```
28 | MPreview/
29 | ├── css/
30 | │ ├── base.css (重置样式)
31 | │ └── MPreview.css (插件所需样式)
32 | ├── images/
33 | │ ├── loading.gif (加载图片等待动画)
34 | │ └── media_icon.png (插件所需的icon)
35 | ├── js/
36 | │ ├── MPreview.js (Word版 js)
37 | │ └── MPreviewPPT.js (PPT版 js)
38 | ├── upload/
39 | │ ├── MPreview_DOC_1.jpg (测试图片)
40 | │ └── MPreview_PPT_1.jpg
41 | ├── api.php (数据请求的演示地址)
42 | ├── data.json (请求所返回的数据格式)
43 | ├── index.html (Word版 Demo)
44 | └── PPT.html (PPT版 Demo)
45 |
46 | PS: 务必一次性返回所有图片地址,插件将自动分割加载
47 | ```
48 |
49 | ### 如何使用
50 | ```html
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
63 | ```
64 |
65 | ### MPreview.js (Word 版) 参数说明
66 | ```javascript
67 | $('#doc').MPreview({
68 | url: 'api.php?action=doc&callback=?', //url中包含callback则表示跨越请求,具体可参考$.getJSON();
69 | data: null, //包含所有图片地址的数组,如填写则不发送Ajax。用于直接传入数据,方便调用。
70 | offset: 100, //每次滚动偏移多少像素,默认 100px
71 | loadSize: 5, //每次加载几张图片
72 | pageFix: 50, //当前页数判定的衡量标准
73 | scrollFix: 5, //当前默认滚动条距离外容器的边距
74 | minScrollHeight: 20 //当前滚动条按钮最小高度
75 | });
76 |
77 | //关于 data 参数的用法
78 | var data = ['upload/1.jpg','upload/2.jpg','upload/3.jpg'];
79 | $('#doc').MPreview({ data: data });
80 | ```
81 |
82 | ### MPreviewPPT.js (PPT 版) 参数说明
83 | ```javascript
84 | $('#ppt').MPreviewPPT({
85 | url: 'api.php?action=doc&callback=?', //url中包含callback则表示跨越请求,具体可参考$.getJSON();
86 | data: null, //包含所有图片地址的数组,如填写则不发送Ajax。用于直接传入数据,方便调用。
87 | loadSize: 5, //每次加载几张图片
88 | scrollFix: 5, //当前默认滚动条距离外容器的边距
89 | minScrollHeight: 20 //当前滚动条按钮最小高度
90 | });
91 |
92 | //关于 data 参数的用法
93 | var data = ['upload/1.jpg','upload/2.jpg','upload/3.jpg'];
94 | $('#ppt').MPreviewPPT({ data: data });
95 | ```
96 |
97 | ### 联系作者
98 | Blog:
99 | Weibo:
100 |
--------------------------------------------------------------------------------
/css/MPreview.css:
--------------------------------------------------------------------------------
1 | /* Media-box */
2 | .MPreview-box { position: relative; border: 1px solid #DDD; background: #FFF; height: 100%; }
3 | .MPreview-mediaPlay { position: absolute; top: 0; left: 0; right: 0; bottom: 31px; overflow: hidden; }
4 |
5 | /* Media-box common */
6 | .MPreview-box img { vertical-align: top; margin: 0; padding: 0; border: 0; }
7 |
8 | .MPreview-box .hidden { display:none; }
9 | .MPreview-box .invisible { visibility:hidden; }
10 |
11 | .MPreview-box .cle { display:block; height:0; overflow:hidden; clear:both; }
12 | .MPreview-box .clefix:after,
13 | .MPreview-ppt .MPreview-mediaView:after { content:'\20'; display:block; height:0; clear:both; }
14 | .MPreview-box .clefix,
15 | .MPreview-ppt .MPreview-mediaView { *zoom:1; }
16 |
17 | /* Media-box .tool-bar */
18 | .MPreview-box .tool-bar { position: absolute; width: 70px; height: 28px; padding-top: 10px; top: 0px; right: 0px; z-index: 28; -webkit-user-select: none; -moz-user-select: none; }
19 | .MPreview-box .MPreview-mediaPlay { width: 100%; overflow: hidden; -webkit-user-select: none; -moz-user-select: none; background:url(../images/loading.gif) no-repeat center center; }
20 | .MPreview-box .MPreview-mediaView { width: 100%; text-align: center; }
21 | .MPreview-box .MPreview-mediaView img { max-width: 100%; }
22 | .MPreview-box .tool-bar ul { padding-right: 20px; }
23 | .MPreview-box .tool-bar ul li { float: left; display: inline; margin: 0px 10px; }
24 | .MPreview-box .tool-bar ul li a { display: block; width: 26px; height: 26px; border: 1px solid transparent; border-radius: 3px; }
25 | .MPreview-box .tool-bar ul li a:hover { border-color: #DDD; }
26 | .MPreview-box .tool-bar ul li a span { position: relative; top:3px; left: 3px; display: block; overflow: hidden; width: 20px; height: 20px; text-indent: -9999px; font: 0 a; }
27 |
28 | /* Media-box => icon */
29 | .MPreview-box .MPreview-zoomBig span,
30 | .MPreview-box .MPreview-zoomSmall span,
31 | .MPreview-box .MPreview-viewOne span,
32 | .MPreview-box .MPreview-viewMulti span,
33 | .MPreview-box .MPreview-fullScreen span,
34 | .MPreview-box .MPreview-exit span,
35 | .MPreview-box .MPreview-pagePrev span,
36 | .MPreview-box .MPreview-pageNext span,
37 | .MPreview-box .MPreview-arrowTop span,
38 | .MPreview-box .MPreview-arrowBottom span { background: url(../images/media_icon.png) no-repeat -9999px -9999px; }
39 |
40 | .MPreview-box .MPreview-zoomBig span { background-position: 0px -78px; }
41 | .MPreview-box .MPreview-zoomSmall span { background-position: -23px -78px; }
42 | .MPreview-box .MPreview-viewOne span { background-position: 1px -23px; }
43 | .MPreview-box .MPreview-viewMulti span { background-position: -22px -23px; }
44 | .MPreview-box .MPreview-fullScreen span { background-position: -82px -27px; }
45 | .MPreview-box .MPreview-exit span { background-position: -55px -27px; }
46 | .MPreview-box .MPreview-pagePrev span { background-position: -82px -55px; }
47 | .MPreview-box .MPreview-pageNext span { background-position: -82px -80px; }
48 | .MPreview-box .MPreview-zoomBig.current span { background-position: 0px -50px; }
49 | .MPreview-box .MPreview-zoomSmall.current span { background-position: -23px -50px; }
50 | .MPreview-box .MPreview-viewOne.current span { background-position: 1px 2px; }
51 | .MPreview-box .MPreview-viewMulti.current span { background-position: -22px 3px; }
52 | .MPreview-box .MPreview-fullScreen:hover span,
53 | .MPreview-box .MPreview-fullScreen.current span { background-position: -82px 0px; }
54 | .MPreview-box .MPreview-exit:hover span,
55 | .MPreview-box .MPreview-exit.current span { background-position: -55px 0px; }
56 | .MPreview-box .MPreview-pagePrev.current span { background-position: -55px -55px; }
57 | .MPreview-box .MPreview-pageNext.current span { background-position: -55px -80px; }
58 | .MPreview-box .MPreview-arrowTop span { background-position: -122px -5px; }
59 | .MPreview-box .MPreview-arrowBottom span { background-position: -122px -48px; }
60 |
61 | /* Media-box => scroll-bar */
62 | .MPreview-box .MPreview-scrollBar { display: block; position: absolute; top: 0px; right: 0px; bottom: 31px; width: 15px; border-left: 1px solid #DDD; z-index: 30; }
63 | .MPreview-box .MPreview-scrollBar .MPreview-scrollBtn { z-index: 40; cursor: default; border-radius: 5px; position: absolute; top: 5px; left: -6px; width:9px; min-height: 20px; background: #DDD; border: 1px solid #ccc; }
64 | .MPreview-box .MPreview-scrollBar .MPreview-scrollBtn:active,
65 | .MPreview-box .MPreview-scrollBar .MPreview-scrollBtn.current { box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); }
66 |
67 | /* Media-box => page-bar */
68 | .MPreview-box .page-bar { position: absolute; z-index: 25; left: 0px; bottom: 0px; width: 100%; height: 30px; border-top: 1px solid #DDD; z-index: 25; -webkit-user-select: none; -moz-user-select: none; }
69 | .MPreview-box .page-bar .page-bar-inner { padding-top: 2px; margin: 0px auto; width: 160px; }
70 | .MPreview-box .page-bar .page-bar-inner a { float: left; display: inline; margin: 0px 10px; overflow: hidden; border: 1px solid #FFF; width: 16px; height: 14px; padding: 5px; border-radius: 3px; }
71 | .MPreview-box .page-bar .page-bar-inner a:hover { border: 1px solid #DDD; }
72 | .MPreview-box .page-bar .page-bar-inner a span { display: block; overflow: hidden; width: 16px; height: 14px; text-indent: -9999px; font: 0 a; }
73 | .MPreview-box .page-bar .MPreview-pageInput { float: left; background:#FFF; border: 1px solid #DDD; color: #666; border: 0; text-align: center; margin: 0px; width: 30px; height: 16px; line-height:16px; padding: 0px; padding-top: 4px; outline: 0; -webkit-user-select: none; -moz-user-select: none; }
74 | .MPreview-box .page-bar .MPreview-pageCount { float: left; width: 30px; height: 16px; text-align:center; padding-top: 3px; color: #666; font-size: 12px; }
75 | .MPreview-box .page-bar .MPreview-pageCount em { font-style: normal; color: #666; }
76 |
77 | /* Media-box => arrow */
78 | .MPreview-box .MPreview-arrowUp,
79 | .MPreview-box .MPreview-arrowDown { position: absolute; width: 100%; height: 30px; top: 10px; left: 0px; z-index: 25; *background:url(about:blank) no-repeat; }
80 | .MPreview-box .MPreview-arrowDown { top: auto; bottom: 40px; }
81 | .MPreview-box .MPreview-arrowUp div,
82 | .MPreview-box .MPreview-arrowDown div { display: none; margin: 0px auto; width: 61px; height: 30px; overflow: hidden; font: 0 a; text-indent: -9999px; width: 61px; height: 100%; margin: 0px auto; overflow: hidden; }
83 | .MPreview-box .MPreview-arrowUp span,
84 | .MPreview-box .MPreview-arrowDown span { cursor: pointer; display: block; width: 100%; height: 100%; }
85 | .MPreview-box .MPreview-arrowUp a:hover,
86 | .MPreview-box .MPreview-arrowDown a:hover, { opacity: 0.8; filter:alpha(opacity=80); }
87 | .MPreview-box .media-dual .view { float: left; width: 50%; }
88 |
89 | /* Media-PPT */
90 | .MPreview-ppt .MPreview-mediaPlay { bottom: 51px; }
91 | .MPreview-ppt .MPreview-mediaView { width: auto; height: 100%; text-align: left; -webkit-transition: all .5s; transition: all .5s; }
92 | .MPreview-ppt .MPreview-mediaView div { float: left; text-align: center; width: 100%; height: 100%; background: #FFF url(../images/loading.gif) no-repeat center center; }
93 | .MPreview-ppt .MPreview-mediaView img { max-width: 100%; max-height: 100%; }
94 | .MPreview-ppt .tool-bar { width: 50px; }
95 | .MPreview-ppt .MPreview-scrollBar { top: auto; bottom: 25px; width: 100%; height: 15px; border-left: 0 none; border-top: 1px solid #DDD; }
96 | .MPreview-ppt .MPreview-scrollBar .MPreview-scrollBtn { top: -6px; left: 5px; height: 9px; width: auto; min-width: 20px; min-height: 9px; }
97 | .MPreview-ppt .MPreview-arrowUp,
98 | .MPreview-ppt .MPreview-arrowDown { width: 30px; height: 100%; top: 0px; left: 10px; }
99 | .MPreview-ppt .MPreview-arrowDown { top: 0px; bottom: auto; left: auto; right: 10px; }
100 | .MPreview-ppt .MPreview-arrowUp div,
101 | .MPreview-ppt .MPreview-arrowDown div { position: absolute; top: 50%; margin-top: -30px; width: 30px; height: 61px; }
102 | .MPreview-ppt .MPreview-arrowUp span,
103 | .MPreview-ppt .MPreview-arrowDown span { width: 30px; height: 61px; }
104 | .MPreview-ppt .MPreview-arrowUp span { background-position: -206px 0px; }
105 | .MPreview-ppt .MPreview-arrowDown span { background-position: -249px 0px; }
--------------------------------------------------------------------------------
/js/MPreviewPPT.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @name MPreviewPPT.js
3 | * @desc 幻灯片预览。
4 | * @depend jQuery 1.7+, jQuery.MouseWheel.js
5 | * @author M.J
6 | * @date 2014-12-31
7 | * @URL http://webjyh.com
8 | * @reutn {jQuery}
9 | * @version 1.0.0
10 | *
11 | * @PS If you have any questions, please don't look for me, I don't know anything. thank you.
12 | */
13 | (function($) {
14 | var MPreviewPPT = function(elem, option) {
15 |
16 | this.config = $.extend({}, this.defaults, option);
17 |
18 | this.elem = $(elem); //绑定的元素
19 | this.page = 0; //当前页
20 | this.bout = 0; //当前滚动的总次数
21 | this.btnOffset = 0; //当前滚动按钮每次滚动的距离
22 | this.length = 0; //当前数据的总长度也是总页数
23 | this.data = []; //当前所有数据
24 | this.W = []; //存放所有图片容器距外容器左边的距离
25 | this.DOM = this.__createDOM(); //当前所有元素DOM
26 | this.S = { //存放当前容器的宽,高
27 | width: this.elem.width(),
28 | height: this.elem.height(),
29 | viewWidth: this.DOM.mediaPlay.width(),
30 | viewHeight: this.DOM.mediaPlay.height()
31 | };
32 |
33 | this.__init();
34 |
35 | };
36 |
37 |
38 | MPreviewPPT.prototype = {
39 | /**
40 | * 默认配置
41 | * @type {Object}
42 | */
43 | defaults: {
44 | url: null, //默认Ajax地址
45 | data: null, //默认JSON 格式的数据,如填写则不发送Ajax,默认为 {Array} 类型
46 | loadSize: 5, //默认先创建几页
47 | scrollFix: 5, //当前默认滚动条距离外容器的边距
48 | minScrollWidth: 20 //当前滚动条按钮最小高度
49 | },
50 |
51 | /**
52 | * @access private
53 | * @name 执行请求
54 | * @return {this}
55 | */
56 | __init: function() {
57 | var _this = this, DOM = this.DOM;
58 |
59 | if ( this.config.data && this.config.data.length ){
60 | this.__set(this.config.data).__create().__addEvent();
61 | } else {
62 | $.getJSON(this.config.url)
63 | .done(function(data) {
64 | if (data.code > 0 && data.imgs.length) {
65 | _this.__set(data.imgs).__create().__addEvent();
66 | }
67 | })
68 | .fail(function() {
69 | alert('\u83b7\u53d6\u6570\u636e\u5931\u8d25');
70 | });
71 | }
72 |
73 | return this;
74 | },
75 |
76 | /**
77 | * @access private
78 | * @name 首次数据进行设置
79 | * @return {Object}
80 | */
81 | __set: function(data) {
82 | var DOM = this.DOM;
83 |
84 | this.data = data;
85 | this.length = data.length;
86 |
87 | DOM.pageInput.val('01');
88 | DOM.pageCount.children('em').text(this.__formatNumber(this.length));
89 | if (this.length > 1) DOM.pageNext.addClass('current');
90 |
91 | return this;
92 | },
93 |
94 | /**
95 | * @access private
96 | * @name 创建list
97 | * @return {Object}
98 | */
99 | __create: function() {
100 | if (!this.data.length) return false;
101 | $(document).off('mousemove');
102 |
103 | var i = 0,
104 | tpl = '',
105 | len = this.data.length,
106 | count = len > this.config.loadSize ? this.config.loadSize : len,
107 | DOM = this.DOM,
108 | size = this.__getSize();
109 |
110 | // create TPL && delete array
111 | for (; i _this.bout) _this.page = _this.bout;
155 |
156 | var m = (typeof _this.W[_this.page-1] === 'undefined' ? 0 : _this.W[_this.page-1]),
157 | t = _this.page * _this.btnOffset;
158 |
159 | //设置滚动条
160 | DOM.mediaView.css('margin-left', -m);
161 | DOM.scrollBtn.css('left', t + (val == 'up' ? 0 : _this.config.scrollFix));
162 |
163 | //设置当前页
164 | DOM.pageInput.val(_this.__formatNumber(_this.page+1));
165 |
166 | //创建剩余数据
167 | _this.__createLastData();
168 |
169 | };
170 |
171 | //滚动事件绑定
172 | DOM.mediaPlay.off('mousewheel').on('mousewheel', function(event) {
173 | event.preventDefault();
174 | scroll(event.deltaY < 0 ? 'up' : 'down');
175 | });
176 |
177 | return this;
178 | },
179 |
180 | /**
181 | * @access private
182 | * @name 给元素绑定相应的事件
183 | * @return {Object}
184 | */
185 | __addEvent: function() {
186 | var DOM = this.DOM,
187 | _this = this;
188 |
189 | var arrowOver = function(){
190 | if (_this.page > 0) DOM.arrowTop.stop(true,true).fadeIn();
191 | if (_this.page < _this.length -1) DOM.arrowBottom.stop(true,true).fadeIn();
192 | };
193 |
194 | var arrowOut = function(){
195 | DOM.arrowTop.stop(true,true).fadeOut();
196 | DOM.arrowBottom.stop(true,true).fadeOut();
197 | };
198 |
199 | //拖拽事件
200 | DOM.scrollBtn.on('mousedown', function(event) { _this.__dragStart(event) });
201 |
202 | //页码按钮显示
203 | DOM.arrowUp.on('mouseover', arrowOver);
204 | DOM.arrowDown.on('mouseover', arrowOver);
205 | DOM.arrowUp.on('mouseout', arrowOut);
206 | DOM.arrowDown.on('mouseout', arrowOut);
207 |
208 | //上一页,下一页事件
209 | DOM.arrowTop.on('click', function() { _this.__pageJump('up') });
210 | DOM.pagePrev.on('click', function() { _this.__pageJump('up') });
211 | DOM.arrowBottom.on('click', function() { _this.__pageJump('down') });
212 | DOM.pageNext.on('click', function() { _this.__pageJump('down') });
213 |
214 | //全屏操作
215 | DOM.fullScreen.on('click', function() { _this.__full(); });
216 | DOM.mediaPlay.on('dblclick', function() { _this.__full(); });
217 |
218 | return this;
219 | },
220 |
221 | /**
222 | * @access private
223 | * @name 滚动条拖拽开始
224 | * @return {Object}
225 | */
226 | __dragStart: function(event) {
227 | var _this = this,
228 | DOM = this.DOM,
229 | fix = Math.floor(event.clientX - DOM.scrollBtn.offset().left);
230 |
231 | $(document).on('mousemove', function(event) { _this.__dragDrop(event, fix) });
232 | $(document).off('mouseup').on('mouseup', function() { $(this).off('mousemove') });
233 | },
234 |
235 | /**
236 | * @access private
237 | * @name 滚动条拖拽
238 | * @return {Object}
239 | */
240 | __dragDrop: function(event, fix) {
241 | var DOM = this.DOM,
242 | size = this.__getSize(),
243 | defaultLeft = parseInt(DOM.scrollBtn.css('left'), 10),
244 | W = Math.floor(event.clientX - DOM.scrollBtn.offset().left - fix + defaultLeft),
245 | minW = this.config.scrollFix,
246 | maxW = size.width - DOM.scrollBtn.outerWidth() - minW;
247 |
248 | if ( W < minW ) W = minW;
249 | if ( W > maxW ) W = maxW;
250 |
251 | //设置当前页
252 | var page = Math.floor(W / this.btnOffset), M;
253 | this.page = page > this.bout ? this.bout : page;
254 | M = (typeof this.W[this.page-1] === 'undefined' ? 0 : this.W[this.page-1]);
255 |
256 | DOM.mediaView.css('margin-left', -M );
257 | DOM.scrollBtn.css('left', W);
258 |
259 | //设置当前页
260 | DOM.pageInput.val(this.__formatNumber(this.page+1));
261 |
262 | //创建剩余数据
263 | this.__createLastData();
264 | },
265 |
266 | /**
267 | * @private private
268 | * @param 页码跳转
269 | * @return {null}
270 | */
271 | __pageJump: function(val) {
272 |
273 | //设置当前页码
274 | val == 'up' ? --this.page : ++this.page;
275 | if (this.page < 0) this.page = 0;
276 | if (this.page > this.length-1 ) this.page = this.length-1;
277 |
278 | //计算滚动值
279 | var DOM = this.DOM,
280 | size = this.__getSize(),
281 | M = typeof this.W[this.page-1] === 'undefined' ? 0 : this.W[this.page-1],
282 | btnL = this.page * this.btnOffset,
283 | minW = this.config.scrollFix,
284 | maxW = size.width - DOM.scrollBtn.outerWidth() - minW;
285 |
286 | if ( btnL < minW ) btnL = minW;
287 | if ( btnL > maxW ) btnL = maxW;
288 |
289 | //设置DOM
290 | DOM.pageInput.val(this.__formatNumber(this.page+1));
291 | DOM.mediaView.css('margin-left', -M);
292 | DOM.scrollBtn.css('left', btnL);
293 |
294 | //创建剩余数据
295 | this.__createLastData();
296 | },
297 |
298 | __full: function(bool) {
299 | var $elem = this.elem,
300 | DOM = this.DOM,
301 | _this = this,
302 | has = DOM.fullScreen.hasClass('MPreview-exit'),
303 | winH = $(window).outerHeight();
304 |
305 | //用于 resize 事件
306 | if ( bool ) has = false;
307 |
308 | // 全屏样式
309 | var css = {
310 | position: has ? 'static' : 'fixed',
311 | top: has ? 'auto' : 0,
312 | left: has ? 'auto' : 0,
313 | zIndex: has ? '0' : 9999,
314 | width: has ? this.S.width : '100%',
315 | height: has ? this.S.height : winH
316 | },
317 | bodyCss = {
318 | overflow: has ? 'auto' : 'hidden',
319 | width: has ? 'auto' : '100%',
320 | height: has ? 'auto': winH
321 | };
322 |
323 | //设置DOM样式
324 | DOM.fullScreen[has ? 'removeClass' : 'addClass']('MPreview-exit').attr('title', has ? '\u5168\u5c4f' : '\u53d6\u6d88\u5168\u5c4f');
325 | $('html').css(bodyCss);
326 | $elem.css(css);
327 |
328 | var winW = DOM.mediaPlay.width();
329 |
330 | //重新设置全局数据
331 | this.W = [];
332 | DOM.mediaView.children('div').each(function() {
333 | $(this).width(has ? _this.S.viewWidth : winW);
334 | $(this).children('img').height(has ? _this.S.viewHeight : winH);
335 | var W = (typeof _this.W[_this.W.length-1] === 'undefined' ? 0 : _this.W[_this.W.length-1]) + (has ? _this.S.viewWidth : winW);
336 | _this.W.push(W);
337 | });
338 |
339 | DOM.mediaView.css('width', this.W[this.W.length-1]);
340 | DOM.mediaView.css('margin-left', -(typeof this.W[this.page-1] === 'undefined' ? 0 : this.W[this.page-1]));
341 | this.__scrollBar();
342 |
343 | //绑定事件
344 | if ( has ){
345 | $(document).off('keyup');
346 | $(window).off('resize');
347 | } else {
348 | $(document).on('keyup', function(event){ if (event.which == 27) _this.__full(); });
349 | $(window).off('resize').on('resize', function(){ _this.__full(true); })
350 | }
351 |
352 | },
353 |
354 | /**
355 | * @private private
356 | * @param 给单数字自动补零
357 | * @return {String}
358 | */
359 | __formatNumber: function(val) {
360 | return val.toString().length < 2 ? '0' + val : val;
361 | },
362 |
363 | /**
364 | * @private private
365 | * @param 设置页码样式及判断是否创建剩余数据
366 | * @return {null}
367 | */
368 | __createLastData: function() {
369 | var DOM = this.DOM;
370 |
371 | DOM.pagePrev[this.page > 0 ? 'addClass' : 'removeClass']('current');
372 | DOM.pageNext[this.page < this.length - 1 ? 'addClass' : 'removeClass']('current');
373 |
374 | if ( this.page >= Math.floor( this.bout ) - 1) this.__create();
375 | },
376 |
377 | /**
378 | * @access private
379 | * @name 创建DOM,存储DOM
380 | * @return {Object}
381 | */
382 | __createDOM: function() {
383 | var $elem = this.elem, DOM = {}, elem;
384 |
385 | DOM['wrap'] = $(MPreviewPPT.template).appendTo($elem);
386 | DOM.wrap.find('*').each(function() {
387 | var className = $(this).attr('class');
388 | if ( className !== undefined && className.toString().indexOf('MPreview') > -1 ) {
389 | var name = className.replace(/icon /g, '').replace('MPreview-', '');
390 | DOM[name] = $(this);
391 | }
392 | });
393 |
394 | return DOM;
395 | },
396 |
397 | /**
398 | * @access private
399 | * @name 获取 DOM size
400 | * @return {Object}
401 | */
402 | __getSize: function() {
403 | var DOM = this.DOM;
404 | return {
405 | width: DOM.mediaPlay.width(),
406 | height: DOM.mediaPlay.height()
407 | };
408 | }
409 | };
410 |
411 | MPreviewPPT.tpl = '
'
412 |
413 | MPreviewPPT.template = '';
414 |
415 | $.fn.MPreviewPPT = function(option) {
416 | return this.each(function() {
417 | new MPreviewPPT(this, option);
418 | });
419 | };
420 |
421 | })(jQuery);
422 |
423 |
424 | /*!
425 | * jQuery Mousewheel 3.1.12
426 | *
427 | * Copyright 2014 jQuery Foundation and other contributors
428 | * Released under the MIT license.
429 | * http://jquery.org/license
430 | */
431 | (function (factory) {
432 | if ( typeof define === 'function' && define.amd ) {
433 | // AMD. Register as an anonymous module.
434 | define(['jquery'], factory);
435 | } else if (typeof exports === 'object') {
436 | // Node/CommonJS style for Browserify
437 | module.exports = factory;
438 | } else {
439 | // Browser globals
440 | factory(jQuery);
441 | }
442 | }(function ($) {
443 |
444 | var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
445 | toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
446 | ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
447 | slice = Array.prototype.slice,
448 | nullLowestDeltaTimeout, lowestDelta;
449 |
450 | if ( $.event.fixHooks ) {
451 | for ( var i = toFix.length; i; ) {
452 | $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
453 | }
454 | }
455 |
456 | var special = $.event.special.mousewheel = {
457 | version: '3.1.12',
458 |
459 | setup: function() {
460 | if ( this.addEventListener ) {
461 | for ( var i = toBind.length; i; ) {
462 | this.addEventListener( toBind[--i], handler, false );
463 | }
464 | } else {
465 | this.onmousewheel = handler;
466 | }
467 | // Store the line height and page height for this particular element
468 | $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
469 | $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
470 | },
471 |
472 | teardown: function() {
473 | if ( this.removeEventListener ) {
474 | for ( var i = toBind.length; i; ) {
475 | this.removeEventListener( toBind[--i], handler, false );
476 | }
477 | } else {
478 | this.onmousewheel = null;
479 | }
480 | // Clean up the data we added to the element
481 | $.removeData(this, 'mousewheel-line-height');
482 | $.removeData(this, 'mousewheel-page-height');
483 | },
484 |
485 | getLineHeight: function(elem) {
486 | var $elem = $(elem),
487 | $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
488 | if (!$parent.length) {
489 | $parent = $('body');
490 | }
491 | return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
492 | },
493 |
494 | getPageHeight: function(elem) {
495 | return $(elem).height();
496 | },
497 |
498 | settings: {
499 | adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
500 | normalizeOffset: true // calls getBoundingClientRect for each event
501 | }
502 | };
503 |
504 | $.fn.extend({
505 | mousewheel: function(fn) {
506 | return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
507 | },
508 |
509 | unmousewheel: function(fn) {
510 | return this.unbind('mousewheel', fn);
511 | }
512 | });
513 |
514 |
515 | function handler(event) {
516 | var orgEvent = event || window.event,
517 | args = slice.call(arguments, 1),
518 | delta = 0,
519 | deltaX = 0,
520 | deltaY = 0,
521 | absDelta = 0,
522 | offsetX = 0,
523 | offsetY = 0;
524 | event = $.event.fix(orgEvent);
525 | event.type = 'mousewheel';
526 |
527 | // Old school scrollwheel delta
528 | if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
529 | if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
530 | if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
531 | if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
532 |
533 | // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
534 | if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
535 | deltaX = deltaY * -1;
536 | deltaY = 0;
537 | }
538 |
539 | // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
540 | delta = deltaY === 0 ? deltaX : deltaY;
541 |
542 | // New school wheel delta (wheel event)
543 | if ( 'deltaY' in orgEvent ) {
544 | deltaY = orgEvent.deltaY * -1;
545 | delta = deltaY;
546 | }
547 | if ( 'deltaX' in orgEvent ) {
548 | deltaX = orgEvent.deltaX;
549 | if ( deltaY === 0 ) { delta = deltaX * -1; }
550 | }
551 |
552 | // No change actually happened, no reason to go any further
553 | if ( deltaY === 0 && deltaX === 0 ) { return; }
554 |
555 | // Need to convert lines and pages to pixels if we aren't already in pixels
556 | // There are three delta modes:
557 | // * deltaMode 0 is by pixels, nothing to do
558 | // * deltaMode 1 is by lines
559 | // * deltaMode 2 is by pages
560 | if ( orgEvent.deltaMode === 1 ) {
561 | var lineHeight = $.data(this, 'mousewheel-line-height');
562 | delta *= lineHeight;
563 | deltaY *= lineHeight;
564 | deltaX *= lineHeight;
565 | } else if ( orgEvent.deltaMode === 2 ) {
566 | var pageHeight = $.data(this, 'mousewheel-page-height');
567 | delta *= pageHeight;
568 | deltaY *= pageHeight;
569 | deltaX *= pageHeight;
570 | }
571 |
572 | // Store lowest absolute delta to normalize the delta values
573 | absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
574 |
575 | if ( !lowestDelta || absDelta < lowestDelta ) {
576 | lowestDelta = absDelta;
577 |
578 | // Adjust older deltas if necessary
579 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
580 | lowestDelta /= 40;
581 | }
582 | }
583 |
584 | // Adjust older deltas if necessary
585 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
586 | // Divide all the things by 40!
587 | delta /= 40;
588 | deltaX /= 40;
589 | deltaY /= 40;
590 | }
591 |
592 | // Get a whole, normalized value for the deltas
593 | delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
594 | deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
595 | deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
596 |
597 | // Normalise offsetX and offsetY properties
598 | if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
599 | var boundingRect = this.getBoundingClientRect();
600 | offsetX = event.clientX - boundingRect.left;
601 | offsetY = event.clientY - boundingRect.top;
602 | }
603 |
604 | // Add information to the event object
605 | event.deltaX = deltaX;
606 | event.deltaY = deltaY;
607 | event.deltaFactor = lowestDelta;
608 | event.offsetX = offsetX;
609 | event.offsetY = offsetY;
610 | // Go ahead and set deltaMode to 0 since we converted to pixels
611 | // Although this is a little odd since we overwrite the deltaX/Y
612 | // properties with normalized deltas.
613 | event.deltaMode = 0;
614 |
615 | // Add event and delta to the front of the arguments
616 | args.unshift(event, delta, deltaX, deltaY);
617 |
618 | // Clearout lowestDelta after sometime to better
619 | // handle multiple device types that give different
620 | // a different lowestDelta
621 | // Ex: trackpad = 3 and mouse wheel = 120
622 | if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
623 | nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
624 |
625 | return ($.event.dispatch || $.event.handle).apply(this, args);
626 | }
627 |
628 | function nullLowestDelta() {
629 | lowestDelta = null;
630 | }
631 |
632 | function shouldAdjustOldDeltas(orgEvent, absDelta) {
633 | // If this is an older event and the delta is divisable by 120,
634 | // then we are assuming that the browser is treating this as an
635 | // older mouse wheel event and that we should divide the deltas
636 | // by 40 to try and get a more usable deltaFactor.
637 | // Side note, this actually impacts the reported scroll distance
638 | // in older browsers and can cause scrolling to be slower than native.
639 | // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
640 | return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
641 | }
642 |
643 | }));
--------------------------------------------------------------------------------
/js/MPreview.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @name MPreview.js
3 | * @desc 文档预览。
4 | * @depend jQuery 1.7+, jQuery.MouseWheel.js
5 | * @author M.J
6 | * @date 2014-12-25
7 | * @URL http://webjyh.com
8 | * @reutn {jQuery}
9 | * @version 1.0.1
10 | *
11 | * @PS If you have any questions, please don't look for me, I don't know anything. thank you.
12 | */
13 | (function($) {
14 | var MPreview = function(elem, option) {
15 |
16 | this.config = $.extend({}, this.defaults, option);
17 |
18 | this.elem = $(elem); //绑定的元素
19 | this.page = 0; //当前页
20 | this.bout = 0; //当前要滚动总次数
21 | this.offset = 0; //当前已滚动次数
22 | this.btnOffset = 0; //当前滚动按钮每次滚动的距离
23 | this.length = 0; //当前数据的总长度也是总页数
24 | this.data = []; //当前所有数据
25 | this.H = []; //存放所有图片容器距外容器顶部的距离
26 | this.DOM = this.__createDOM(); //当前所有元素DOM
27 | this.S = { //存放当前容器的宽,高
28 | width: this.elem.width(),
29 | height: this.elem.height()
30 | };
31 |
32 | this.__init();
33 |
34 | };
35 |
36 |
37 | MPreview.prototype = {
38 | /**
39 | * 默认配置
40 | * @type {Object}
41 | */
42 | defaults: {
43 | url: null, //默认Ajax地址
44 | data: null, //默认JSON 格式的数据,如填写则不发送Ajax,默认为 {Array} 类型
45 | offset: 100, //每次滚动偏移多少像素
46 | loadSize: 5, //默认先创建几页
47 | pageFix: 50, //当前页码判定的衡量标准
48 | scrollFix: 5, //当前默认滚动条距离外容器的边距
49 | minScrollHeight: 20 //当前滚动条按钮最小高度
50 | },
51 |
52 | /**
53 | * @access private
54 | * @name 执行请求
55 | * @return {this}
56 | */
57 | __init: function() {
58 | var _this = this, DOM = this.DOM;
59 |
60 | if ( this.config.data && this.config.data.length ){
61 | this.__set(this.config.data).__create().__addEvent();
62 | } else {
63 | $.getJSON(this.config.url)
64 | .done(function(data) {
65 | if (data.code > 0 && data.imgs.length) {
66 | _this.__set(data.imgs).__create().__addEvent();
67 | }
68 | })
69 | .fail(function() {
70 | alert('\u83b7\u53d6\u6570\u636e\u5931\u8d25');
71 | });
72 | }
73 |
74 | return this;
75 | },
76 |
77 | /**
78 | * @access private
79 | * @name 首次数据进行设置
80 | * @return {Object}
81 | */
82 | __set: function(data) {
83 | var DOM = this.DOM;
84 |
85 | this.data = data;
86 | this.length = data.length;
87 |
88 | DOM.pageInput.val('01');
89 | DOM.pageCount.children('em').text(this.__formatNumber(this.length));
90 | if (this.length > 1) DOM.pageNext.addClass('current');
91 |
92 | return this;
93 | },
94 |
95 | /**
96 | * @access private
97 | * @name 创建list
98 | * @return {Object}
99 | */
100 | __create: function() {
101 | if (!this.data.length) return false;
102 | $(document).off('mousemove');
103 |
104 | var i = 0,
105 | tpl = '',
106 | len = this.data.length,
107 | count = len > this.config.loadSize ? this.config.loadSize : len,
108 | DOM = this.DOM,
109 | _this = this;
110 |
111 | // create TPL && delete array
112 | for (; i _this.bout) _this.offset = _this.bout;
167 | if (val == 'down' && _this.offset < 0) _this.offset = 0;
168 | setDOMStyle(val);
169 |
170 | //设置当前页
171 | if (val == 'up' && H + _this.config.pageFix > _this.H[_this.page]) DOM.pageInput.val(_this.__formatNumber(++_this.page+1));
172 | if (val == 'down' && H + _this.config.pageFix < _this.H[_this.page-1]) DOM.pageInput.val(_this.__formatNumber(--_this.page+1));
173 |
174 | //创建剩余数据
175 | _this.__createLastData();
176 |
177 | };
178 |
179 | //默认设置DOM
180 | DOM.scrollBtn.height(btnHeight <= this.config.minScrollHeight ? this.config.minScrollHeight : btnHeight);
181 | DOM.scrollBtn.css('top', _this.btnOffset * _this.offset + _this.config.scrollFix);
182 |
183 | //滚动事件绑定
184 | DOM.mediaPlay.off('mousewheel').on('mousewheel', function(event) {
185 | event.preventDefault();
186 | scroll(event.deltaY < 0 ? 'up' : 'down');
187 | });
188 |
189 | return this;
190 | },
191 |
192 | /**
193 | * @access private
194 | * @name 滚动按钮拖拽事件
195 | * @return {null}
196 | */
197 | __scrollDrag: {
198 | dragStart: function(event, _this){
199 | //滚动条偏差
200 | var DOM = _this.DOM,
201 | fix = (event.clientY - DOM.scrollBtn.offset().top).toFixed(0);
202 |
203 | //拖拽事件绑定
204 | $(document).on('mousemove', function(event) { _this.__scrollDrag.dragDrop(event, fix, _this) });
205 | $(document).off('mouseup').on('mouseup', function() { $(this).off('mousemove') });
206 | },
207 | dragDrop: function(event, fix, _this){
208 |
209 | //计算一些必要的值
210 | var DOM = _this.DOM,
211 | size = _this.__getSize(),
212 | defaultTop = parseInt(DOM.scrollBtn.css('top'), 10),
213 | offsetY = (event.clientY - DOM.scrollBtn.offset().top).toFixed(0) - fix,
214 | top = defaultTop + offsetY,
215 | minTop = _this.config.scrollFix,
216 | maxTop = size.height - _this.config.scrollFix - DOM.scrollBtn.outerHeight();
217 |
218 | //拖拽最小最大高度设置
219 | if ( top < minTop ) top = minTop;
220 | if ( top > maxTop ) top = maxTop;
221 |
222 | //设置当前分页,及滚动次数
223 | var offset = Math.floor(top / _this.btnOffset),
224 | marginTop = Math.floor( (size.viewHeight - _this.config.scrollFix * 2) / size.height) * (top == minTop ? 0 : top);
225 |
226 | //是否拖放到底部
227 | if ( top == maxTop ) marginTop = size.viewHeight - size.height;
228 |
229 | _this.offset = offset > _this.bout ? _this.bout: offset;
230 | if ( marginTop + _this.config.pageFix > _this.H[_this.page] ) DOM.pageInput.val(_this.__formatNumber(++_this.page+1));
231 | if ( marginTop + _this.config.pageFix < _this.H[_this.page-1] ) DOM.pageInput.val(_this.__formatNumber(--_this.page+1));
232 |
233 | //设置对应的DOM样式
234 | DOM.mediaView.css('margin-top', -marginTop);
235 | DOM.scrollBtn.css('top', top);
236 |
237 | //创建剩余数据 并卸载当前拖拽事件
238 | _this.__createLastData();
239 | }
240 | },
241 |
242 | /**
243 | * @access private
244 | * @name 给元素绑定相应的事件
245 | * @return {Object}
246 | */
247 | __addEvent: function() {
248 | var _this = this,
249 | DOM = this.DOM;
250 |
251 | var arrowOver = function(){
252 | if (_this.page > 0) DOM.arrowTop.stop(true,true).fadeIn();
253 | if (_this.page < _this.length -1) DOM.arrowBottom.stop(true,true).fadeIn();
254 | };
255 |
256 | var arrowOut = function(){
257 | DOM.arrowTop.stop(true,true).fadeOut();
258 | DOM.arrowBottom.stop(true,true).fadeOut();
259 | };
260 |
261 | //滚动条按钮拖拽事件
262 | DOM.scrollBtn.on('mousedown', function(event) { _this.__scrollDrag.dragStart(event, _this) });
263 |
264 | //页码按钮显示
265 | DOM.arrowUp.on('mouseover', arrowOver);
266 | DOM.arrowDown.on('mouseover', arrowOver);
267 | DOM.arrowUp.on('mouseout', arrowOut);
268 | DOM.arrowDown.on('mouseout', arrowOut);
269 |
270 | //上一页,下一页事件
271 | DOM.arrowTop.on('click', function() { _this.__pageJump('up') });
272 | DOM.pagePrev.on('click', function() { _this.__pageJump('up') });
273 | DOM.arrowBottom.on('click', function() { _this.__pageJump('down') });
274 | DOM.pageNext.on('click', function() { _this.__pageJump('down') });
275 |
276 | //全屏操作
277 | DOM.fullScreen.on('click', function() { _this.__full(); });
278 | DOM.mediaPlay.on('dblclick', function() { _this.__full(); });
279 |
280 | return this;
281 | },
282 |
283 | /**
284 | * @private private
285 | * @param 页码跳转
286 | * @return {null}
287 | */
288 | __pageJump: function(val) {
289 |
290 | //设置当前页码
291 | val == 'up' ? --this.page : ++this.page;
292 | if (this.page < 0) this.page = 0;
293 | if (this.page > this.length-1 ) this.page = this.length-1;
294 |
295 | //计算滚动值
296 | var DOM = this.DOM,
297 | size = this.__getSize(),
298 | H = typeof this.H[this.page-1] === 'undefined' ? 0 : this.H[this.page-1],
299 | minH = this.config.scrollFix,
300 | maxH = size.height - DOM.scrollBtn.outerHeight() - minH;
301 |
302 | //计算当前已滚动次数
303 | var btnT, offset = (H / this.config.offset == 0) ? 0 : Math.floor(H / this.config.offset);
304 | this.offset = offset > this.bout ? this.bout: offset;
305 | btnT = this.offset * this.btnOffset;
306 |
307 | //滚动条容错处理
308 | if (btnT < minH) btnT = minH;
309 | if (btnT > maxH) btnT = maxH;
310 |
311 | //设置DOM
312 | DOM.pageInput.val(this.__formatNumber(this.page+1));
313 | DOM.mediaView.css('margin-top', -H);
314 | DOM.scrollBtn.css('top', btnT);
315 |
316 | //创建剩余数据
317 | this.__createLastData();
318 | },
319 |
320 | /**
321 | * @private private
322 | * @param 全屏操作
323 | * @return {this}
324 | */
325 | __full: function(bool){
326 | var $elem = this.elem,
327 | DOM = this.DOM,
328 | _this = this,
329 | has = DOM.fullScreen.hasClass('MPreview-exit'),
330 | winHeight = $(window).outerHeight();
331 |
332 | //用于 resize 事件
333 | if ( bool ) has = false;
334 |
335 | // 全屏样式
336 | var css = {
337 | position: has ? 'static' : 'fixed',
338 | top: has ? 'auto' : 0,
339 | left: has ? 'auto' : 0,
340 | zIndex: has ? '0' : 9999,
341 | width: has ? this.S.width : '100%',
342 | height: has ? this.S.height : winHeight
343 | },
344 | bodyCss = {
345 | overflow: has ? 'auto' : 'hidden',
346 | width: has ? 'auto' : '100%',
347 | height: has ? 'auto': winHeight
348 | };
349 |
350 | //设置DOM样式
351 | DOM.fullScreen[has ? 'removeClass' : 'addClass']('MPreview-exit').attr('title', has ? '\u5168\u5c4f' : '\u53d6\u6d88\u5168\u5c4f');
352 | $('html').css(bodyCss);
353 | $elem.css(css);
354 |
355 | //保存原滚动次数
356 | var bout = function(){return _this.bout;}();
357 |
358 | //清空数组,重新计算
359 | this.H = [];
360 | DOM.mediaView.find('img').each(function(i) {
361 | var H = (typeof _this.H[_this.H.length-1] === 'undefined' ? 0 : _this.H[_this.H.length-1]) + $(this).parent().outerHeight();
362 | _this.H.push(H);
363 | });
364 | this.__scrollBar();
365 |
366 | //差值计算:新总滚动次数 - 原总滚动次数 * 每次滚动偏移量
367 | //得出与原滚动次数相差了多少差值
368 | //在 除此 原滚动的次数,得出每次滚动相差多少差值
369 | //在 乘以 当前已滚动的次数,得出总差值。在原基础上增加到预览页上。
370 | //由得出来的差值 得出偏移量的差值
371 | var fix = ((this.bout - bout) * this.config.offset / bout) * this.offset,
372 | offsetFix = fix / this.config.offset,
373 | top = parseInt(DOM.mediaView.css('margin-top'), 10);
374 |
375 | //重新计算浏览次数
376 | this.offset = this.offset+offsetFix;
377 | DOM.mediaView.css('margin-top', top+(-fix));
378 | DOM.scrollBtn.css('top', _this.btnOffset * _this.offset + _this.config.scrollFix);
379 |
380 | //绑定事件
381 | if ( has ){
382 | $(document).off('keyup');
383 | $(window).off('resize');
384 | } else {
385 | $(document).on('keyup', function(event){ if (event.which == 27) _this.__full(); });
386 | $(window).off('resize').on('resize', function(){ _this.__full(true); })
387 | }
388 | },
389 |
390 | /**
391 | * @private private
392 | * @param 给单数字自动补零
393 | * @return {String}
394 | */
395 | __formatNumber: function(val) {
396 | return val.toString().length < 2 ? '0' + val : val;
397 | },
398 |
399 | /**
400 | * @private private
401 | * @param 设置页码样式及判断是否创建剩余数据
402 | * @return {null}
403 | */
404 | __createLastData: function() {
405 | var DOM = this.DOM;
406 |
407 | DOM.pagePrev[this.page > 0 ? 'addClass' : 'removeClass']('current');
408 | DOM.pageNext[this.page < this.length - 1 ? 'addClass' : 'removeClass']('current');
409 |
410 | if ( this.offset >= Math.floor( this.bout ) - 1) this.__create();
411 | },
412 |
413 | /**
414 | * @access private
415 | * @name 创建DOM,存储DOM
416 | * @return {Object}
417 | */
418 | __createDOM: function() {
419 | var $elem = this.elem, DOM = {}, elem;
420 |
421 | DOM['wrap'] = $(MPreview.template).appendTo($elem);
422 | DOM.wrap.find('*').each(function() {
423 | var className = $(this).attr('class');
424 | if ( className !== undefined && className.toString().indexOf('MPreview') > -1 ) {
425 | var name = className.replace(/icon /g, '').replace('MPreview-', '');
426 | DOM[name] = $(this);
427 | }
428 | });
429 |
430 | return DOM;
431 | },
432 |
433 | /**
434 | * @access private
435 | * @name 获取 DOM size
436 | * @return {Object}
437 | */
438 | __getSize: function() {
439 | var DOM = this.DOM;
440 | return {
441 | width: DOM.mediaPlay.width(),
442 | height: DOM.mediaPlay.height(),
443 | viewWidth: DOM.mediaView.width(),
444 | viewHeight: DOM.mediaView.height()
445 | };
446 | }
447 | };
448 |
449 | MPreview.tpl = ''
450 |
451 | MPreview.template = '';
452 |
453 | $.fn.MPreview = function(option) {
454 | return this.each(function() {
455 | new MPreview(this, option);
456 | });
457 | };
458 |
459 | })(jQuery);
460 |
461 |
462 | /*!
463 | * jQuery Mousewheel 3.1.12
464 | *
465 | * Copyright 2014 jQuery Foundation and other contributors
466 | * Released under the MIT license.
467 | * http://jquery.org/license
468 | */
469 | (function (factory) {
470 | if ( typeof define === 'function' && define.amd ) {
471 | // AMD. Register as an anonymous module.
472 | define(['jquery'], factory);
473 | } else if (typeof exports === 'object') {
474 | // Node/CommonJS style for Browserify
475 | module.exports = factory;
476 | } else {
477 | // Browser globals
478 | factory(jQuery);
479 | }
480 | }(function ($) {
481 |
482 | var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
483 | toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
484 | ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
485 | slice = Array.prototype.slice,
486 | nullLowestDeltaTimeout, lowestDelta;
487 |
488 | if ( $.event.fixHooks ) {
489 | for ( var i = toFix.length; i; ) {
490 | $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
491 | }
492 | }
493 |
494 | var special = $.event.special.mousewheel = {
495 | version: '3.1.12',
496 |
497 | setup: function() {
498 | if ( this.addEventListener ) {
499 | for ( var i = toBind.length; i; ) {
500 | this.addEventListener( toBind[--i], handler, false );
501 | }
502 | } else {
503 | this.onmousewheel = handler;
504 | }
505 | // Store the line height and page height for this particular element
506 | $.data(this, 'mousewheel-line-height', special.getLineHeight(this));
507 | $.data(this, 'mousewheel-page-height', special.getPageHeight(this));
508 | },
509 |
510 | teardown: function() {
511 | if ( this.removeEventListener ) {
512 | for ( var i = toBind.length; i; ) {
513 | this.removeEventListener( toBind[--i], handler, false );
514 | }
515 | } else {
516 | this.onmousewheel = null;
517 | }
518 | // Clean up the data we added to the element
519 | $.removeData(this, 'mousewheel-line-height');
520 | $.removeData(this, 'mousewheel-page-height');
521 | },
522 |
523 | getLineHeight: function(elem) {
524 | var $elem = $(elem),
525 | $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
526 | if (!$parent.length) {
527 | $parent = $('body');
528 | }
529 | return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
530 | },
531 |
532 | getPageHeight: function(elem) {
533 | return $(elem).height();
534 | },
535 |
536 | settings: {
537 | adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
538 | normalizeOffset: true // calls getBoundingClientRect for each event
539 | }
540 | };
541 |
542 | $.fn.extend({
543 | mousewheel: function(fn) {
544 | return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
545 | },
546 |
547 | unmousewheel: function(fn) {
548 | return this.unbind('mousewheel', fn);
549 | }
550 | });
551 |
552 |
553 | function handler(event) {
554 | var orgEvent = event || window.event,
555 | args = slice.call(arguments, 1),
556 | delta = 0,
557 | deltaX = 0,
558 | deltaY = 0,
559 | absDelta = 0,
560 | offsetX = 0,
561 | offsetY = 0;
562 | event = $.event.fix(orgEvent);
563 | event.type = 'mousewheel';
564 |
565 | // Old school scrollwheel delta
566 | if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
567 | if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
568 | if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
569 | if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
570 |
571 | // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
572 | if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
573 | deltaX = deltaY * -1;
574 | deltaY = 0;
575 | }
576 |
577 | // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
578 | delta = deltaY === 0 ? deltaX : deltaY;
579 |
580 | // New school wheel delta (wheel event)
581 | if ( 'deltaY' in orgEvent ) {
582 | deltaY = orgEvent.deltaY * -1;
583 | delta = deltaY;
584 | }
585 | if ( 'deltaX' in orgEvent ) {
586 | deltaX = orgEvent.deltaX;
587 | if ( deltaY === 0 ) { delta = deltaX * -1; }
588 | }
589 |
590 | // No change actually happened, no reason to go any further
591 | if ( deltaY === 0 && deltaX === 0 ) { return; }
592 |
593 | // Need to convert lines and pages to pixels if we aren't already in pixels
594 | // There are three delta modes:
595 | // * deltaMode 0 is by pixels, nothing to do
596 | // * deltaMode 1 is by lines
597 | // * deltaMode 2 is by pages
598 | if ( orgEvent.deltaMode === 1 ) {
599 | var lineHeight = $.data(this, 'mousewheel-line-height');
600 | delta *= lineHeight;
601 | deltaY *= lineHeight;
602 | deltaX *= lineHeight;
603 | } else if ( orgEvent.deltaMode === 2 ) {
604 | var pageHeight = $.data(this, 'mousewheel-page-height');
605 | delta *= pageHeight;
606 | deltaY *= pageHeight;
607 | deltaX *= pageHeight;
608 | }
609 |
610 | // Store lowest absolute delta to normalize the delta values
611 | absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
612 |
613 | if ( !lowestDelta || absDelta < lowestDelta ) {
614 | lowestDelta = absDelta;
615 |
616 | // Adjust older deltas if necessary
617 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
618 | lowestDelta /= 40;
619 | }
620 | }
621 |
622 | // Adjust older deltas if necessary
623 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
624 | // Divide all the things by 40!
625 | delta /= 40;
626 | deltaX /= 40;
627 | deltaY /= 40;
628 | }
629 |
630 | // Get a whole, normalized value for the deltas
631 | delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
632 | deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
633 | deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
634 |
635 | // Normalise offsetX and offsetY properties
636 | if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
637 | var boundingRect = this.getBoundingClientRect();
638 | offsetX = event.clientX - boundingRect.left;
639 | offsetY = event.clientY - boundingRect.top;
640 | }
641 |
642 | // Add information to the event object
643 | event.deltaX = deltaX;
644 | event.deltaY = deltaY;
645 | event.deltaFactor = lowestDelta;
646 | event.offsetX = offsetX;
647 | event.offsetY = offsetY;
648 | // Go ahead and set deltaMode to 0 since we converted to pixels
649 | // Although this is a little odd since we overwrite the deltaX/Y
650 | // properties with normalized deltas.
651 | event.deltaMode = 0;
652 |
653 | // Add event and delta to the front of the arguments
654 | args.unshift(event, delta, deltaX, deltaY);
655 |
656 | // Clearout lowestDelta after sometime to better
657 | // handle multiple device types that give different
658 | // a different lowestDelta
659 | // Ex: trackpad = 3 and mouse wheel = 120
660 | if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
661 | nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
662 |
663 | return ($.event.dispatch || $.event.handle).apply(this, args);
664 | }
665 |
666 | function nullLowestDelta() {
667 | lowestDelta = null;
668 | }
669 |
670 | function shouldAdjustOldDeltas(orgEvent, absDelta) {
671 | // If this is an older event and the delta is divisable by 120,
672 | // then we are assuming that the browser is treating this as an
673 | // older mouse wheel event and that we should divide the deltas
674 | // by 40 to try and get a more usable deltaFactor.
675 | // Side note, this actually impacts the reported scroll distance
676 | // in older browsers and can cause scrolling to be slower than native.
677 | // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
678 | return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
679 | }
680 |
681 | }));
--------------------------------------------------------------------------------