slide_hero 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +28 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +161 -0
  8. data/Rakefile +9 -0
  9. data/bin/slidehero +37 -0
  10. data/config.ru +14 -0
  11. data/lib/slide_hero/code.rb +16 -0
  12. data/lib/slide_hero/dsl.rb +10 -0
  13. data/lib/slide_hero/grouped_slides.rb +21 -0
  14. data/lib/slide_hero/list.rb +29 -0
  15. data/lib/slide_hero/list_point.rb +26 -0
  16. data/lib/slide_hero/point.rb +27 -0
  17. data/lib/slide_hero/presentation.rb +36 -0
  18. data/lib/slide_hero/slide.rb +47 -0
  19. data/lib/slide_hero/version.rb +3 -0
  20. data/lib/slide_hero/views/_footer.html.erb +0 -0
  21. data/lib/slide_hero/views/_header.html.erb +0 -0
  22. data/lib/slide_hero/views/code.html.erb +3 -0
  23. data/lib/slide_hero/views/empty.html +12 -0
  24. data/lib/slide_hero/views/grouped_slides.html.erb +5 -0
  25. data/lib/slide_hero/views/layout.html.erb +54 -0
  26. data/lib/slide_hero/views/ordered_list.html.erb +5 -0
  27. data/lib/slide_hero/views/slide.html.erb +6 -0
  28. data/lib/slide_hero/views/unordered_list.html.erb +5 -0
  29. data/lib/slide_hero.rb +15 -0
  30. data/slide_hero.gemspec +29 -0
  31. data/templates/new_presentation.tt +11 -0
  32. data/test/fixtures/testclass.rb +5 -0
  33. data/test/minitest_helper.rb +18 -0
  34. data/test/slide_hero/code_spec.rb +29 -0
  35. data/test/slide_hero/dsl_spec.rb +27 -0
  36. data/test/slide_hero/grouped_slides_spec.rb +29 -0
  37. data/test/slide_hero/list_point_spec.rb +34 -0
  38. data/test/slide_hero/list_spec.rb +49 -0
  39. data/test/slide_hero/point_spec.rb +25 -0
  40. data/test/slide_hero/presentation_spec.rb +56 -0
  41. data/test/slide_hero/slide_spec.rb +147 -0
  42. data/test/slide_hero_spec.rb +15 -0
  43. data/vendor/reveal.js/.gitignore +6 -0
  44. data/vendor/reveal.js/.travis.yml +5 -0
  45. data/vendor/reveal.js/Gruntfile.js +132 -0
  46. data/vendor/reveal.js/LICENSE +19 -0
  47. data/vendor/reveal.js/README.md +798 -0
  48. data/vendor/reveal.js/css/print/paper.css +176 -0
  49. data/vendor/reveal.js/css/print/pdf.css +190 -0
  50. data/vendor/reveal.js/css/reveal.css +1649 -0
  51. data/vendor/reveal.js/css/reveal.min.css +7 -0
  52. data/vendor/reveal.js/css/theme/README.md +23 -0
  53. data/vendor/reveal.js/css/theme/beige.css +142 -0
  54. data/vendor/reveal.js/css/theme/default.css +142 -0
  55. data/vendor/reveal.js/css/theme/moon.css +142 -0
  56. data/vendor/reveal.js/css/theme/night.css +130 -0
  57. data/vendor/reveal.js/css/theme/serif.css +132 -0
  58. data/vendor/reveal.js/css/theme/simple.css +132 -0
  59. data/vendor/reveal.js/css/theme/sky.css +139 -0
  60. data/vendor/reveal.js/css/theme/solarized.css +142 -0
  61. data/vendor/reveal.js/css/theme/source/beige.scss +50 -0
  62. data/vendor/reveal.js/css/theme/source/default.scss +42 -0
  63. data/vendor/reveal.js/css/theme/source/moon.scss +68 -0
  64. data/vendor/reveal.js/css/theme/source/night.scss +35 -0
  65. data/vendor/reveal.js/css/theme/source/serif.scss +35 -0
  66. data/vendor/reveal.js/css/theme/source/simple.scss +38 -0
  67. data/vendor/reveal.js/css/theme/source/sky.scss +46 -0
  68. data/vendor/reveal.js/css/theme/source/solarized.scss +74 -0
  69. data/vendor/reveal.js/css/theme/template/mixins.scss +29 -0
  70. data/vendor/reveal.js/css/theme/template/settings.scss +34 -0
  71. data/vendor/reveal.js/css/theme/template/theme.scss +163 -0
  72. data/vendor/reveal.js/examples/assets/image1.png +0 -0
  73. data/vendor/reveal.js/examples/assets/image2.png +0 -0
  74. data/vendor/reveal.js/examples/barebones.html +42 -0
  75. data/vendor/reveal.js/examples/embedded-media.html +49 -0
  76. data/vendor/reveal.js/examples/math.html +185 -0
  77. data/vendor/reveal.js/examples/slide-backgrounds.html +101 -0
  78. data/vendor/reveal.js/js/reveal.js +2788 -0
  79. data/vendor/reveal.js/js/reveal.min.js +8 -0
  80. data/vendor/reveal.js/lib/css/zenburn.css +115 -0
  81. data/vendor/reveal.js/lib/font/league_gothic-webfont.eot +0 -0
  82. data/vendor/reveal.js/lib/font/league_gothic-webfont.svg +230 -0
  83. data/vendor/reveal.js/lib/font/league_gothic-webfont.ttf +0 -0
  84. data/vendor/reveal.js/lib/font/league_gothic-webfont.woff +0 -0
  85. data/vendor/reveal.js/lib/font/league_gothic_license +2 -0
  86. data/vendor/reveal.js/lib/js/classList.js +2 -0
  87. data/vendor/reveal.js/lib/js/head.min.js +8 -0
  88. data/vendor/reveal.js/lib/js/html5shiv.js +7 -0
  89. data/vendor/reveal.js/package.json +45 -0
  90. data/vendor/reveal.js/plugin/highlight/highlight.js +31 -0
  91. data/vendor/reveal.js/plugin/leap/leap.js +157 -0
  92. data/vendor/reveal.js/plugin/markdown/example.html +98 -0
  93. data/vendor/reveal.js/plugin/markdown/example.md +31 -0
  94. data/vendor/reveal.js/plugin/markdown/markdown.js +220 -0
  95. data/vendor/reveal.js/plugin/markdown/marked.js +37 -0
  96. data/vendor/reveal.js/plugin/math/math.js +64 -0
  97. data/vendor/reveal.js/plugin/multiplex/client.js +13 -0
  98. data/vendor/reveal.js/plugin/multiplex/index.js +56 -0
  99. data/vendor/reveal.js/plugin/multiplex/master.js +50 -0
  100. data/vendor/reveal.js/plugin/notes/notes.html +259 -0
  101. data/vendor/reveal.js/plugin/notes/notes.js +78 -0
  102. data/vendor/reveal.js/plugin/notes-server/client.js +57 -0
  103. data/vendor/reveal.js/plugin/notes-server/index.js +59 -0
  104. data/vendor/reveal.js/plugin/notes-server/notes.html +142 -0
  105. data/vendor/reveal.js/plugin/postmessage/example.html +39 -0
  106. data/vendor/reveal.js/plugin/postmessage/postmessage.js +42 -0
  107. data/vendor/reveal.js/plugin/print-pdf/print-pdf.js +44 -0
  108. data/vendor/reveal.js/plugin/remotes/remotes.js +39 -0
  109. data/vendor/reveal.js/plugin/search/search.js +196 -0
  110. data/vendor/reveal.js/plugin/zoom-js/zoom.js +256 -0
  111. metadata +277 -0
@@ -0,0 +1,44 @@
1
+ /**
2
+ * phantomjs script for printing presentations to PDF.
3
+ *
4
+ * Example:
5
+ * phantomjs print-pdf.js "http://lab.hakim.se/reveal-js?print-pdf" reveal-demo.pdf
6
+ *
7
+ * By Manuel Bieh (https://github.com/manuelbieh)
8
+ */
9
+
10
+ // html2pdf.js
11
+ var page = new WebPage();
12
+ var system = require( 'system' );
13
+
14
+ page.viewportSize = {
15
+ width: 1024,
16
+ height: 768
17
+ };
18
+
19
+ page.paperSize = {
20
+ format: 'letter',
21
+ orientation: 'landscape',
22
+ margin: {
23
+ left: '0',
24
+ right: '0',
25
+ top: '0',
26
+ bottom: '0'
27
+ }
28
+ };
29
+
30
+ var revealFile = system.args[1] || 'index.html?print-pdf';
31
+ var slideFile = system.args[2] || 'slides.pdf';
32
+
33
+ if( slideFile.match( /\.pdf$/gi ) === null ) {
34
+ slideFile += '.pdf';
35
+ }
36
+
37
+ console.log( 'Printing PDF...' );
38
+
39
+ page.open( revealFile, function( status ) {
40
+ console.log( 'Printed succesfully' );
41
+ page.render( slideFile );
42
+ phantom.exit();
43
+ } );
44
+
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Touch-based remote controller for your presentation courtesy
3
+ * of the folks at http://remotes.io
4
+ */
5
+
6
+ (function(window){
7
+
8
+ /**
9
+ * Detects if we are dealing with a touch enabled device (with some false positives)
10
+ * Borrowed from modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touch.js
11
+ */
12
+ var hasTouch = (function(){
13
+ return ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
14
+ })();
15
+
16
+ /**
17
+ * Detects if notes are enable and the current page is opened inside an /iframe
18
+ * this prevents loading Remotes.io several times
19
+ */
20
+ var remotesAndIsNotes = (function(){
21
+ return !(window.RevealNotes && self == top);
22
+ })();
23
+
24
+ if(!hasTouch && !remotesAndIsNotes){
25
+ head.ready( 'remotes.ne.min.js', function() {
26
+ new Remotes("preview")
27
+ .on("swipe-left", function(e){ Reveal.right(); })
28
+ .on("swipe-right", function(e){ Reveal.left(); })
29
+ .on("swipe-up", function(e){ Reveal.down(); })
30
+ .on("swipe-down", function(e){ Reveal.up(); })
31
+ .on("tap", function(e){ Reveal.next(); })
32
+ .on("zoom-out", function(e){ Reveal.toggleOverview(true); })
33
+ .on("zoom-in", function(e){ Reveal.toggleOverview(false); })
34
+ ;
35
+ } );
36
+
37
+ head.js('https://raw.github.com/Remotes/Remotes/master/dist/remotes.ne.min.js');
38
+ }
39
+ })(window);
@@ -0,0 +1,196 @@
1
+ /*
2
+ * Handles finding a text string anywhere in the slides and showing the next occurrence to the user
3
+ * by navigatating to that slide and highlighting it.
4
+ *
5
+ * By Jon Snyder <snyder.jon@gmail.com>, February 2013
6
+ */
7
+
8
+ var RevealSearch = (function() {
9
+
10
+ var matchedSlides;
11
+ var currentMatchedIndex;
12
+ var searchboxDirty;
13
+ var myHilitor;
14
+
15
+ // Original JavaScript code by Chirp Internet: www.chirp.com.au
16
+ // Please acknowledge use of this code by including this header.
17
+ // 2/2013 jon: modified regex to display any match, not restricted to word boundaries.
18
+
19
+ function Hilitor(id, tag)
20
+ {
21
+
22
+ var targetNode = document.getElementById(id) || document.body;
23
+ var hiliteTag = tag || "EM";
24
+ var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM|SPAN)$");
25
+ var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"];
26
+ var wordColor = [];
27
+ var colorIdx = 0;
28
+ var matchRegex = "";
29
+ var matchingSlides = [];
30
+
31
+ this.setRegex = function(input)
32
+ {
33
+ input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|");
34
+ matchRegex = new RegExp("(" + input + ")","i");
35
+ }
36
+
37
+ this.getRegex = function()
38
+ {
39
+ return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " ");
40
+ }
41
+
42
+ // recursively apply word highlighting
43
+ this.hiliteWords = function(node)
44
+ {
45
+ if(node == undefined || !node) return;
46
+ if(!matchRegex) return;
47
+ if(skipTags.test(node.nodeName)) return;
48
+
49
+ if(node.hasChildNodes()) {
50
+ for(var i=0; i < node.childNodes.length; i++)
51
+ this.hiliteWords(node.childNodes[i]);
52
+ }
53
+ if(node.nodeType == 3) { // NODE_TEXT
54
+ if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) {
55
+ //find the slide's section element and save it in our list of matching slides
56
+ var secnode = node.parentNode;
57
+ while (secnode.nodeName != 'SECTION') {
58
+ secnode = secnode.parentNode;
59
+ }
60
+
61
+ var slideIndex = Reveal.getIndices(secnode);
62
+ var slidelen = matchingSlides.length;
63
+ var alreadyAdded = false;
64
+ for (var i=0; i < slidelen; i++) {
65
+ if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) {
66
+ alreadyAdded = true;
67
+ }
68
+ }
69
+ if (! alreadyAdded) {
70
+ matchingSlides.push(slideIndex);
71
+ }
72
+
73
+ if(!wordColor[regs[0].toLowerCase()]) {
74
+ wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length];
75
+ }
76
+
77
+ var match = document.createElement(hiliteTag);
78
+ match.appendChild(document.createTextNode(regs[0]));
79
+ match.style.backgroundColor = wordColor[regs[0].toLowerCase()];
80
+ match.style.fontStyle = "inherit";
81
+ match.style.color = "#000";
82
+
83
+ var after = node.splitText(regs.index);
84
+ after.nodeValue = after.nodeValue.substring(regs[0].length);
85
+ node.parentNode.insertBefore(match, after);
86
+ }
87
+ }
88
+ };
89
+
90
+ // remove highlighting
91
+ this.remove = function()
92
+ {
93
+ var arr = document.getElementsByTagName(hiliteTag);
94
+ while(arr.length && (el = arr[0])) {
95
+ el.parentNode.replaceChild(el.firstChild, el);
96
+ }
97
+ };
98
+
99
+ // start highlighting at target node
100
+ this.apply = function(input)
101
+ {
102
+ if(input == undefined || !input) return;
103
+ this.remove();
104
+ this.setRegex(input);
105
+ this.hiliteWords(targetNode);
106
+ return matchingSlides;
107
+ };
108
+
109
+ }
110
+
111
+ function openSearch() {
112
+ //ensure the search term input dialog is visible and has focus:
113
+ var inputbox = document.getElementById("searchinput");
114
+ inputbox.style.display = "inline";
115
+ inputbox.focus();
116
+ inputbox.select();
117
+ }
118
+
119
+ function toggleSearch() {
120
+ var inputbox = document.getElementById("searchinput");
121
+ if (inputbox.style.display !== "inline") {
122
+ openSearch();
123
+ }
124
+ else {
125
+ inputbox.style.display = "none";
126
+ myHilitor.remove();
127
+ }
128
+ }
129
+
130
+ function doSearch() {
131
+ //if there's been a change in the search term, perform a new search:
132
+ if (searchboxDirty) {
133
+ var searchstring = document.getElementById("searchinput").value;
134
+
135
+ //find the keyword amongst the slides
136
+ myHilitor = new Hilitor("slidecontent");
137
+ matchedSlides = myHilitor.apply(searchstring);
138
+ currentMatchedIndex = 0;
139
+ }
140
+
141
+ //navigate to the next slide that has the keyword, wrapping to the first if necessary
142
+ if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) {
143
+ currentMatchedIndex = 0;
144
+ }
145
+ if (matchedSlides.length > currentMatchedIndex) {
146
+ Reveal.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v);
147
+ currentMatchedIndex++;
148
+ }
149
+ }
150
+
151
+ var dom = {};
152
+ dom.wrapper = document.querySelector( '.reveal' );
153
+
154
+ if( !dom.wrapper.querySelector( '.searchbox' ) ) {
155
+ var searchElement = document.createElement( 'div' );
156
+ searchElement.id = "searchinputdiv";
157
+ searchElement.classList.add( 'searchdiv' );
158
+ searchElement.style.position = 'absolute';
159
+ searchElement.style.top = '10px';
160
+ searchElement.style.left = '10px';
161
+ //embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/:
162
+ searchElement.innerHTML = '<span><input type="search" id="searchinput" class="searchinput" style="vertical-align: top;"/><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJiSURBVHjatFZNaxNBGH5md+Mmu92NVdKDRipSAyqCghgQD4L4cRe86UUtAQ+eFCxoa4/25EXBFi8eBE+eRPoDhB6KgiiixdAPCEkx2pjvTXadd9yNsflwuyUDD/O+u8PzzDPvzOwyx3EwyCZhwG3gAkp7MnpjgbopjsltcD4gjuXZZKeAR348MYLYTm3LzOs/y3j3JTfZxgXWXmTuwPHIc4VmoOmv5IrI53+AO2DdHLjkDWQ3GoEEVFXtXQOvkSnPWcyUceviLhwbDYv8/XIVj97kse7TodLvZXxYxrPUHkQ1ufXs3FEdybEIxucySOesoNvUgWU1cP3MkCBfTFdw9fGaAMVmRELq7LBw2Q3/FaAxxWIRpw+ZIr/7IouPqzUBiqmdHAv7EuhRAwf1er2Vy4x1jW3b2d5Jfvu5IPp7l2LYbcgCFFNb+FoJ7oBqEAqFMPNqFcmEgVMJDfMT+1tvN0pNjERlMS6QA5pFOKxiKVPFhakPeL3It+WGJUDxt2wFR+JhzI7v5ctkd8DXOZAkCYYxhO+lKm4+Xfqz/rIixBuNBl7eOYzkQQNzqX249mRl6zUgEcYkaJrGhUwBinVdh6IouPzwE6/DL5w4oLkH8y981aDf+uq6hlKpJESiUdNfDZi7/ehG9K6KfiA3pml0PLcsq+cSMTj2NL9ukc4UOmz7AZ3+crkC4mHujFvXNaMFB3bEr8xPS6p5O+jXxq4VZtaen7/PwzrntjcLUE0iHPS1Ud1cdiEJl/8WivZk0wXd7zWOMkeF8s0CcAmkNrC2nvXZDbbbN73ccYnZoH9bfgswAFzAe9/h3dbKAAAAAElFTkSuQmCC" id="searchbutton" class="searchicon" style="vertical-align: top; margin-top: -1px;"/></span>';
163
+ dom.wrapper.appendChild( searchElement );
164
+ }
165
+
166
+ document.getElementById("searchbutton").addEventListener( 'click', function(event) {
167
+ doSearch();
168
+ }, false );
169
+
170
+ document.getElementById("searchinput").addEventListener( 'keyup', function( event ) {
171
+ switch (event.keyCode) {
172
+ case 13:
173
+ event.preventDefault();
174
+ doSearch();
175
+ searchboxDirty = false;
176
+ break;
177
+ default:
178
+ searchboxDirty = true;
179
+ }
180
+ }, false );
181
+
182
+ // Open the search when the 's' key is hit (yes, this conflicts with the notes plugin, disabling for now)
183
+ /*
184
+ document.addEventListener( 'keydown', function( event ) {
185
+ // Disregard the event if the target is editable or a
186
+ // modifier is present
187
+ if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
188
+
189
+ if( event.keyCode === 83 ) {
190
+ event.preventDefault();
191
+ openSearch();
192
+ }
193
+ }, false );
194
+ */
195
+ return { open: openSearch };
196
+ })();
@@ -0,0 +1,256 @@
1
+ // Custom reveal.js integration
2
+ (function(){
3
+ var isEnabled = true;
4
+
5
+ document.querySelector( '.reveal' ).addEventListener( 'mousedown', function( event ) {
6
+ if( event.altKey && isEnabled ) {
7
+ event.preventDefault();
8
+ zoom.to({ element: event.target, pan: false });
9
+ }
10
+ } );
11
+
12
+ Reveal.addEventListener( 'overviewshown', function() { isEnabled = false; } );
13
+ Reveal.addEventListener( 'overviewhidden', function() { isEnabled = true; } );
14
+ })();
15
+
16
+ /*!
17
+ * zoom.js 0.2 (modified version for use with reveal.js)
18
+ * http://lab.hakim.se/zoom-js
19
+ * MIT licensed
20
+ *
21
+ * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
22
+ */
23
+ var zoom = (function(){
24
+
25
+ // The current zoom level (scale)
26
+ var level = 1;
27
+
28
+ // The current mouse position, used for panning
29
+ var mouseX = 0,
30
+ mouseY = 0;
31
+
32
+ // Timeout before pan is activated
33
+ var panEngageTimeout = -1,
34
+ panUpdateInterval = -1;
35
+
36
+ var currentOptions = null;
37
+
38
+ // Check for transform support so that we can fallback otherwise
39
+ var supportsTransforms = 'WebkitTransform' in document.body.style ||
40
+ 'MozTransform' in document.body.style ||
41
+ 'msTransform' in document.body.style ||
42
+ 'OTransform' in document.body.style ||
43
+ 'transform' in document.body.style;
44
+
45
+ if( supportsTransforms ) {
46
+ // The easing that will be applied when we zoom in/out
47
+ document.body.style.transition = 'transform 0.8s ease';
48
+ document.body.style.OTransition = '-o-transform 0.8s ease';
49
+ document.body.style.msTransition = '-ms-transform 0.8s ease';
50
+ document.body.style.MozTransition = '-moz-transform 0.8s ease';
51
+ document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
52
+ }
53
+
54
+ // Zoom out if the user hits escape
55
+ document.addEventListener( 'keyup', function( event ) {
56
+ if( level !== 1 && event.keyCode === 27 ) {
57
+ zoom.out();
58
+ }
59
+ }, false );
60
+
61
+ // Monitor mouse movement for panning
62
+ document.addEventListener( 'mousemove', function( event ) {
63
+ if( level !== 1 ) {
64
+ mouseX = event.clientX;
65
+ mouseY = event.clientY;
66
+ }
67
+ }, false );
68
+
69
+ /**
70
+ * Applies the CSS required to zoom in, prioritizes use of CSS3
71
+ * transforms but falls back on zoom for IE.
72
+ *
73
+ * @param {Number} pageOffsetX
74
+ * @param {Number} pageOffsetY
75
+ * @param {Number} elementOffsetX
76
+ * @param {Number} elementOffsetY
77
+ * @param {Number} scale
78
+ */
79
+ function magnify( pageOffsetX, pageOffsetY, elementOffsetX, elementOffsetY, scale ) {
80
+
81
+ if( supportsTransforms ) {
82
+ var origin = pageOffsetX +'px '+ pageOffsetY +'px',
83
+ transform = 'translate('+ -elementOffsetX +'px,'+ -elementOffsetY +'px) scale('+ scale +')';
84
+
85
+ document.body.style.transformOrigin = origin;
86
+ document.body.style.OTransformOrigin = origin;
87
+ document.body.style.msTransformOrigin = origin;
88
+ document.body.style.MozTransformOrigin = origin;
89
+ document.body.style.WebkitTransformOrigin = origin;
90
+
91
+ document.body.style.transform = transform;
92
+ document.body.style.OTransform = transform;
93
+ document.body.style.msTransform = transform;
94
+ document.body.style.MozTransform = transform;
95
+ document.body.style.WebkitTransform = transform;
96
+ }
97
+ else {
98
+ // Reset all values
99
+ if( scale === 1 ) {
100
+ document.body.style.position = '';
101
+ document.body.style.left = '';
102
+ document.body.style.top = '';
103
+ document.body.style.width = '';
104
+ document.body.style.height = '';
105
+ document.body.style.zoom = '';
106
+ }
107
+ // Apply scale
108
+ else {
109
+ document.body.style.position = 'relative';
110
+ document.body.style.left = ( - ( pageOffsetX + elementOffsetX ) / scale ) + 'px';
111
+ document.body.style.top = ( - ( pageOffsetY + elementOffsetY ) / scale ) + 'px';
112
+ document.body.style.width = ( scale * 100 ) + '%';
113
+ document.body.style.height = ( scale * 100 ) + '%';
114
+ document.body.style.zoom = scale;
115
+ }
116
+ }
117
+
118
+ level = scale;
119
+
120
+ if( level !== 1 && document.documentElement.classList ) {
121
+ document.documentElement.classList.add( 'zoomed' );
122
+ }
123
+ else {
124
+ document.documentElement.classList.remove( 'zoomed' );
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Pan the document when the mosue cursor approaches the edges
130
+ * of the window.
131
+ */
132
+ function pan() {
133
+ var range = 0.12,
134
+ rangeX = window.innerWidth * range,
135
+ rangeY = window.innerHeight * range,
136
+ scrollOffset = getScrollOffset();
137
+
138
+ // Up
139
+ if( mouseY < rangeY ) {
140
+ window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
141
+ }
142
+ // Down
143
+ else if( mouseY > window.innerHeight - rangeY ) {
144
+ window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
145
+ }
146
+
147
+ // Left
148
+ if( mouseX < rangeX ) {
149
+ window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
150
+ }
151
+ // Right
152
+ else if( mouseX > window.innerWidth - rangeX ) {
153
+ window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
154
+ }
155
+ }
156
+
157
+ function getScrollOffset() {
158
+ return {
159
+ x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
160
+ y: window.scrollY !== undefined ? window.scrollY : window.pageXYffset
161
+ }
162
+ }
163
+
164
+ return {
165
+ /**
166
+ * Zooms in on either a rectangle or HTML element.
167
+ *
168
+ * @param {Object} options
169
+ * - element: HTML element to zoom in on
170
+ * OR
171
+ * - x/y: coordinates in non-transformed space to zoom in on
172
+ * - width/height: the portion of the screen to zoom in on
173
+ * - scale: can be used instead of width/height to explicitly set scale
174
+ */
175
+ to: function( options ) {
176
+ // Due to an implementation limitation we can't zoom in
177
+ // to another element without zooming out first
178
+ if( level !== 1 ) {
179
+ zoom.out();
180
+ }
181
+ else {
182
+ options.x = options.x || 0;
183
+ options.y = options.y || 0;
184
+
185
+ // If an element is set, that takes precedence
186
+ if( !!options.element ) {
187
+ // Space around the zoomed in element to leave on screen
188
+ var padding = 20;
189
+
190
+ options.width = options.element.getBoundingClientRect().width + ( padding * 2 );
191
+ options.height = options.element.getBoundingClientRect().height + ( padding * 2 );
192
+ options.x = options.element.getBoundingClientRect().left - padding;
193
+ options.y = options.element.getBoundingClientRect().top - padding;
194
+ }
195
+
196
+ // If width/height values are set, calculate scale from those values
197
+ if( options.width !== undefined && options.height !== undefined ) {
198
+ options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
199
+ }
200
+
201
+ if( options.scale > 1 ) {
202
+ options.x *= options.scale;
203
+ options.y *= options.scale;
204
+
205
+ var scrollOffset = getScrollOffset();
206
+
207
+ if( options.element ) {
208
+ scrollOffset.x -= ( window.innerWidth - ( options.width * options.scale ) ) / 2;
209
+ }
210
+
211
+ magnify( scrollOffset.x, scrollOffset.y, options.x, options.y, options.scale );
212
+
213
+ if( options.pan !== false ) {
214
+
215
+ // Wait with engaging panning as it may conflict with the
216
+ // zoom transition
217
+ panEngageTimeout = setTimeout( function() {
218
+ panUpdateInterval = setInterval( pan, 1000 / 60 );
219
+ }, 800 );
220
+
221
+ }
222
+ }
223
+
224
+ currentOptions = options;
225
+ }
226
+ },
227
+
228
+ /**
229
+ * Resets the document zoom state to its default.
230
+ */
231
+ out: function() {
232
+ clearTimeout( panEngageTimeout );
233
+ clearInterval( panUpdateInterval );
234
+
235
+ var scrollOffset = getScrollOffset();
236
+
237
+ if( currentOptions && currentOptions.element ) {
238
+ scrollOffset.x -= ( window.innerWidth - ( currentOptions.width * currentOptions.scale ) ) / 2;
239
+ }
240
+
241
+ magnify( scrollOffset.x, scrollOffset.y, 0, 0, 1 );
242
+
243
+ level = 1;
244
+ },
245
+
246
+ // Alias
247
+ magnify: function( options ) { this.to( options ) },
248
+ reset: function() { this.out() },
249
+
250
+ zoomLevel: function() {
251
+ return level;
252
+ }
253
+ }
254
+
255
+ })();
256
+