https://github.com/gamell/atom-markpress
Markpress wrapper for atom.io editor
https://github.com/gamell/atom-markpress
Last synced: 3 months ago
JSON representation
Markpress wrapper for atom.io editor
- Host: GitHub
- URL: https://github.com/gamell/atom-markpress
- Owner: gamell
- License: mit
- Created: 2016-08-28T22:30:27.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2016-09-06T02:22:39.000Z (almost 9 years ago)
- Last Synced: 2025-01-14T19:09:11.102Z (5 months ago)
- Language: JavaScript
- Size: 17.6 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.html
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
README
atom-text-editor,
:host {
background-color: white;
color: #555;
}
atom-text-editor .invisible-character,
:host .invisible-character {
color: rgba(85, 85, 85, 0.2);
}
atom-text-editor .indent-guide,
:host .indent-guide {
color: rgba(85, 85, 85, 0.2);
}
atom-text-editor .wrap-guide,
:host .wrap-guide {
background-color: rgba(85, 85, 85, 0.2);
}
atom-text-editor .gutter,
:host .gutter {
color: #555;
background: white;
}
atom-text-editor .gutter .line-number.folded,
:host .gutter .line-number.folded,
atom-text-editor .gutter .line-number:after,
:host .gutter .line-number:after,
atom-text-editor .fold-marker:after,
:host .fold-marker:after {
color: #e87b00;
}
atom-text-editor .invisible,
:host .invisible {
color: #555;
}
atom-text-editor .selection .region,
:host .selection .region {
background-color: #e1e1e1;
}
atom-text-editor.is-focused .cursor,
:host.is-focused .cursor {
border-color: black;
}
atom-text-editor.is-focused .selection .region,
:host.is-focused .selection .region {
background-color: #afc4da;
}
atom-text-editor.is-focused .line-number.cursor-line-no-selection,
:host.is-focused .line-number.cursor-line-no-selection,
atom-text-editor.is-focused .line.cursor-line,
:host.is-focused .line.cursor-line {
background-color: rgba(255, 255, 134, 0.34);
}
atom-text-editor .source.gfm,
:host .source.gfm {
color: #444;
}
atom-text-editor .gfm .markup.heading,
:host .gfm .markup.heading {
color: #111;
}
atom-text-editor .gfm .link,
:host .gfm .link {
color: #888;
}
atom-text-editor .gfm .variable.list,
:host .gfm .variable.list {
color: #888;
}
atom-text-editor .markdown .paragraph,
:host .markdown .paragraph {
color: #444;
}
atom-text-editor .markdown .heading,
:host .markdown .heading {
color: #111;
}
atom-text-editor .markdown .link,
:host .markdown .link {
color: #888;
}
atom-text-editor .markdown .link .string,
:host .markdown .link .string {
color: #888;
}
:host(.is-focused) .cursor {
border-color: black;
}
:host(.is-focused) .selection .region {
background-color: #afc4da;
}
:host(.is-focused) .line-number.cursor-line-no-selection,
:host(.is-focused) .line.cursor-line {
background-color: rgba(255, 255, 134, 0.34);
}
.comment {
color: #999988;
font-style: italic;
}
.string {
color: #D14;
}
.string .source,
.string .meta.embedded.line {
color: #5A5A5A;
}
.string .punctuation.section.embedded {
color: #920B2D;
}
.string .punctuation.section.embedded .source {
color: #920B2D;
}
.constant.numeric {
color: #D14;
}
.constant.language {
color: #606aa1;
}
.constant.character,
.constant.other {
color: #606aa1;
}
.constant.symbol {
color: #990073;
}
.constant.numeric.line-number.find-in-files .match {
color: rgba(143, 190, 0, 0.63);
}
.variable {
color: #008080;
}
.variable.parameter {
color: #606aa1;
}
.keyword {
color: #222;
font-weight: bold;
}
.keyword.unit {
color: #445588;
}
.keyword.special-method {
color: #0086B3;
}
.storage {
color: #222;
}
.storage.type {
color: #222;
}
.entity.name.class {
text-decoration: underline;
color: #606aa1;
}
.entity.other.inherited-class {
text-decoration: underline;
color: #606aa1;
}
.entity.name.function {
color: #900;
}
.entity.name.tag {
color: #008080;
}
.entity.other.attribute-name {
color: #458;
font-weight: bold;
}
.entity.name.filename.find-in-files {
color: #E6DB74;
}
.support.constant,
.support.function,
.support.type {
color: #458;
}
.support.class {
color: #008080;
}
.invalid {
color: #F8F8F0;
background-color: #00A8C6;
}
.invalid.deprecated {
color: #F8F8F0;
background-color: #8FBE00;
}
.meta.structure.dictionary.json > .string.quoted.double.json,
.meta.structure.dictionary.json > .string.quoted.double.json .punctuation.string {
color: #000080;
}
.meta.structure.dictionary.value.json > .string.quoted.double.json {
color: #d14;
}
.meta.diff,
.meta.diff.header {
color: #75715E;
}
.css.support.property-name {
font-weight: bold;
color: #333;
}
.css.constant {
color: #099;
}
.bracket-matcher .region {
background-color: #C9C9C9;
opacity: .7;
border-bottom: 0 none;
}
body {
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
color: #333;
font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 16px;
line-height: 1.6;
word-wrap: break-word;
}
a {
background-color: transparent;
}
a:active,
a:hover {
outline: 0;
}
strong {
font-weight: bold;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
img {
border: 0;
}
hr {
box-sizing: content-box;
height: 0;
}
pre {
overflow: auto;
}
code,
kbd,
pre {
font-family: monospace, monospace;
font-size: 1em;
}
input {
color: inherit;
font: inherit;
margin: 0;
}
html input[disabled] {
cursor: default;
}
input {
line-height: normal;
}
input[type="checkbox"] {
box-sizing: border-box;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}
* {
box-sizing: border-box;
}
input {
font: 13px / 1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
a {
color: #4078c0;
text-decoration: none;
}
a:hover,
a:active {
text-decoration: underline;
}
hr {
height: 0;
margin: 15px 0;
overflow: hidden;
background: transparent;
border: 0;
border-bottom: 1px solid #ddd;
}
hr:before {
display: table;
content: "";
}
hr:after {
display: table;
clear: both;
content: "";
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 15px;
margin-bottom: 15px;
line-height: 1.1;
}
h1 {
font-size: 30px;
}
h2 {
font-size: 21px;
}
h3 {
font-size: 16px;
}
h4 {
font-size: 14px;
}
h5 {
font-size: 12px;
}
h6 {
font-size: 11px;
}
blockquote {
margin: 0;
}
ul,
ol {
padding: 0;
margin-top: 0;
margin-bottom: 0;
}
ol ol,
ul ol {
list-style-type: lower-roman;
}
ul ul ol,
ul ol ol,
ol ul ol,
ol ol ol {
list-style-type: lower-alpha;
}
dd {
margin-left: 0;
}
code {
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 12px;
}
pre {
margin-top: 0;
margin-bottom: 0;
font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
}
.select::-ms-expand {
opacity: 0;
}
.octicon {
font: normal normal normal 16px/1 octicons-link;
display: inline-block;
text-decoration: none;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.octicon-link:before {
content: '\f05c';
}
.markdown-body:before {
display: table;
content: "";
}
.markdown-body:after {
display: table;
clear: both;
content: "";
}
.markdown-body > *:first-child {
margin-top: 0 !important;
}
.markdown-body > *:last-child {
margin-bottom: 0 !important;
}
a:not([href]) {
color: inherit;
text-decoration: none;
}
.anchor {
display: inline-block;
padding-right: 2px;
margin-left: -18px;
}
.anchor:focus {
outline: none;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 1em;
margin-bottom: 16px;
font-weight: bold;
line-height: 1.4;
}
h1 .octicon-link,
h2 .octicon-link,
h3 .octicon-link,
h4 .octicon-link,
h5 .octicon-link,
h6 .octicon-link {
color: #000;
vertical-align: middle;
visibility: hidden;
}
h1:hover .anchor,
h2:hover .anchor,
h3:hover .anchor,
h4:hover .anchor,
h5:hover .anchor,
h6:hover .anchor {
text-decoration: none;
}
h1:hover .anchor .octicon-link,
h2:hover .anchor .octicon-link,
h3:hover .anchor .octicon-link,
h4:hover .anchor .octicon-link,
h5:hover .anchor .octicon-link,
h6:hover .anchor .octicon-link {
visibility: visible;
}
h1 {
padding-bottom: 0.3em;
font-size: 2.25em;
line-height: 1.2;
border-bottom: 1px solid #eee;
}
h1 .anchor {
line-height: 1;
}
h2 {
padding-bottom: 0.3em;
font-size: 1.75em;
line-height: 1.225;
border-bottom: 1px solid #eee;
}
h2 .anchor {
line-height: 1;
}
h3 {
font-size: 1.5em;
line-height: 1.43;
}
h3 .anchor {
line-height: 1.2;
}
h4 {
font-size: 1.25em;
}
h4 .anchor {
line-height: 1.2;
}
h5 {
font-size: 1em;
}
h5 .anchor {
line-height: 1.1;
}
h6 {
font-size: 1em;
color: #777;
}
h6 .anchor {
line-height: 1.1;
}
p,
blockquote,
ul,
ol,
dl,
table,
pre {
margin-top: 0;
margin-bottom: 16px;
}
hr {
height: 4px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
}
ul,
ol {
padding-left: 2em;
}
ul ul,
ul ol,
ol ol,
ol ul {
margin-top: 0;
margin-bottom: 0;
}
li > p {
margin-top: 16px;
}
dl {
padding: 0;
}
dl dt {
padding: 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: bold;
}
dl dd {
padding: 0 16px;
margin-bottom: 16px;
}
blockquote {
padding: 0 15px;
color: #777;
border-left: 4px solid #ddd;
}
blockquote > :first-child {
margin-top: 0;
}
blockquote > :last-child {
margin-bottom: 0;
}
table {
display: block;
width: 100%;
overflow: auto;
word-break: normal;
word-break: keep-all;
}
table th {
font-weight: bold;
}
table th,
table td {
padding: 6px 13px;
border: 0.1em solid #ccc;
}
table tr {
background-color: #eee;
border-top: 1px solid #ccc;
}
table tr:nth-child(2n) {
background-color: #dcdcdc;
}
img {
max-width: 100%;
box-sizing: content-box;
}
code {
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
margin: 0;
font-size: 85%;
background-color: rgba(0, 0, 0, 0.06);
border-radius: 0.2em;
}
code:before,
code:after {
letter-spacing: -0.2em;
content: "\00a0";
}
pre > code {
padding: 0;
margin: 0;
font-size: 100%;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.highlight {
margin-bottom: 16px;
}
.highlight pre,
pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f7f7f7;
border-radius: 0.2em;
}
.highlight pre {
margin-bottom: 0;
word-break: normal;
}
pre {
word-wrap: normal;
}
pre code {
display: inline;
max-width: initial;
padding: 0;
margin: 0;
overflow: initial;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
pre code:before,
pre code:after {
content: normal;
}
kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #fcfcfc;
border: solid 1px #ccc;
border-bottom-color: #bbb;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #bbb;
}
.pl-c {
color: #969896;
}
.pl-c1,
.pl-s .pl-v {
color: #0086b3;
}
.pl-e,
.pl-en {
color: #795da3;
}
.pl-s .pl-s1,
.pl-smi {
color: #333;
}
.pl-ent {
color: #63a35c;
}
.pl-k {
color: #a71d5d;
}
.pl-pds,
.pl-s,
.pl-s .pl-pse .pl-s1,
.pl-sr,
.pl-sr .pl-cce,
.pl-sr .pl-sra,
.pl-sr .pl-sre {
color: #183691;
}
.pl-v {
color: #ed6a43;
}
.pl-id {
color: #b52a1d;
}
.pl-ii {
background-color: #b52a1d;
color: #f8f8f8;
}
.pl-sr .pl-cce {
color: #63a35c;
font-weight: bold;
}
.pl-ml {
color: #693a17;
}
.pl-mh,
.pl-mh .pl-en,
.pl-ms {
color: #1d3e81;
font-weight: bold;
}
.pl-mq {
color: #008080;
}
.pl-mi {
color: #333;
font-style: italic;
}
.pl-mb {
color: #333;
font-weight: bold;
}
.pl-md {
background-color: #ffecec;
color: #bd2c00;
}
.pl-mi1 {
background-color: #eaffea;
color: #55a532;
}
.pl-mdr {
color: #795da3;
font-weight: bold;
}
.pl-mo {
color: #1d3e81;
}
kbd {
display: inline-block;
padding: 3px 5px;
font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #fcfcfc;
border: solid 1px #ccc;
border-bottom-color: #bbb;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #bbb;
}
.task-list-item {
list-style-type: none;
}
.task-list-item + .task-list-item {
margin-top: 3px;
}
.task-list-item input {
margin: 0 0.35em 0.25em -1.6em;
vertical-align: middle;
}
:checked + .radio-label {
z-index: 1;
position: relative;
border-color: #4078c0;
}
body {
font-size: 100%;
font-size: 2.9vmin;
}
h1,
h2,
h3,
h4,
h5,
h6 {
border-bottom: 0;
}
h1 {
font-size: 6em;
font-size: 6.09vmin;
text-align: center;
margin-top: 0;
}
h2 {
font-size: 4em;
font-size: 4.06vmin;
margin-top: 2.9vmin;
}
h3 {
font-size: 3em;
font-size: 3.19vmin;
margin-top: 2.9vmin;
}
h4,
h5,
h6 {
font-size: 2.9vmin;
}
body {
line-height: 1;
min-height: 740px;
color: #0f0f0f;
background: #f0f0f0;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(#f0f0f0), to(#bebebe));
background: -webkit-radial-gradient(#f0f0f0, #bebebe);
background: -moz-radial-gradient(#f0f0f0, #bebebe);
background: -ms-radial-gradient(#f0f0f0, #bebebe);
background: -o-radial-gradient(#f0f0f0, #bebebe);
background: radial-gradient(#f0f0f0, #bebebe);
}
blockquote {
color: #5c5c5c;
border-color: #353535;
}
p,
li {
margin-bottom: 1em;
}
.highlight pre,
pre {
background-color: #f0f0f0;
}
a {
color: #000;
text-decoration: underline;
padding: 0.1em;
}
a:hover {
color: #4d4d4d;
}
.step {
position: relative;
width: 85vw;
max-height: 100vh;
padding: 40px;
margin: 20px auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
line-height: 1.5;
opacity: 0.3;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
-ms-transition: opacity 1s;
-o-transition: opacity 1s;
transition: opacity 1s;
}
.step.past {
opacity: 0.3;
}
.step.active {
opacity: 1;
}
kbd {
font-size: 2.9vmin;
display: inline-block;
padding: 0.435vmin 1.015vmin;
font: Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 2.9vmin;
color: #555;
vertical-align: middle;
background-color: #fcfcfc;
border: solid 1px #ccc;
border-bottom-color: #bbb;
border-radius: 0.4vmax;
box-shadow: inset 0 -0.1vmax 0 #bbb;
}* {
/*CSS transitions*/
-o-transition-property: none !important;
-moz-transition-property: none !important;
-ms-transition-property: none !important;
-webkit-transition-property: none !important;
transition-property: none !important;
/*CSS transforms*/
-o-transform: none !important;
-moz-transform: none !important;
-ms-transform: none !important;
-webkit-transform: none !important;
transform: none !important;
/*CSS animations*/
-webkit-animation: none !important;
-moz-animation: none !important;
-o-animation: none !important;
-ms-animation: none !important;
animation: none !important;
}
body {
color: black !important;
}
#impress {
position: relative !important;
top: auto !important;
left: auto !important;
transform-origin: none !important;
transform: none !important;
}
#impress div {
transform: none !important;
position: relative !important;
}
.step {
padding: 10px !important;
break-after: always !important;
page-break-after: always !important;
position: relative !important;
opacity: 1 !important;
}
.step h1 {
text-align: left;
}
atom-markpress package
A short description of your package.
/**
* impress.js
*
* impress.js is a presentation tool based on the power of CSS3 transforms and transitions
* in modern browsers and inspired by the idea behind prezi.com.
*
*
* Copyright 2011-2012 Bartek Szopka (@bartaz)
*
* Released under the MIT and GPL Licenses.
*
* ------------------------------------------------
* author: Bartek Szopka
* version: 0.5.3
* url: http://bartaz.github.com/impress.js/
* source: http://github.com/bartaz/impress.js/
*//*jshint bitwise:true, curly:true, eqeqeq:true, forin:true, latedef:true, newcap:true,
noarg:true, noempty:true, undef:true, strict:true, browser:true */// You are one of those who like to know how things work inside?
// Let me show you the cogs that make impress.js run...
( function( document, window ) {
"use strict";// HELPER FUNCTIONS
// `pfx` is a function that takes a standard CSS property name as a parameter
// and returns it's prefixed version valid for current browser it runs in.
// The code is heavily inspired by Modernizr http://www.modernizr.com/
var pfx = ( function() {var style = document.createElement( "dummy" ).style,
prefixes = "Webkit Moz O ms Khtml".split( " " ),
memory = {};return function( prop ) {
if ( typeof memory[ prop ] === "undefined" ) {var ucProp = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),
props = ( prop + " " + prefixes.join( ucProp + " " ) + ucProp ).split( " " );memory[ prop ] = null;
for ( var i in props ) {
if ( style[ props[ i ] ] !== undefined ) {
memory[ prop ] = props[ i ];
break;
}
}}
return memory[ prop ];
};} )();
// `arraify` takes an array-like object and turns it into real Array
// to make all the Array.prototype goodness available.
var arrayify = function( a ) {
return [].slice.call( a );
};// `css` function applies the styles given in `props` object to the element
// given as `el`. It runs all property names through `pfx` function to make
// sure proper prefixed version of the property is used.
var css = function( el, props ) {
var key, pkey;
for ( key in props ) {
if ( props.hasOwnProperty( key ) ) {
pkey = pfx( key );
if ( pkey !== null ) {
el.style[ pkey ] = props[ key ];
}
}
}
return el;
};// `toNumber` takes a value given as `numeric` parameter and tries to turn
// it into a number. If it is not possible it returns 0 (or other value
// given as `fallback`).
var toNumber = function( numeric, fallback ) {
return isNaN( numeric ) ? ( fallback || 0 ) : Number( numeric );
};// `byId` returns element with given `id` - you probably have guessed that ;)
var byId = function( id ) {
return document.getElementById( id );
};// `$` returns first element for given CSS `selector` in the `context` of
// the given element or whole document.
var $ = function( selector, context ) {
context = context || document;
return context.querySelector( selector );
};// `$$` return an array of elements for given CSS `selector` in the `context` of
// the given element or whole document.
var $$ = function( selector, context ) {
context = context || document;
return arrayify( context.querySelectorAll( selector ) );
};// `triggerEvent` builds a custom DOM event with given `eventName` and `detail` data
// and triggers it on element given as `el`.
var triggerEvent = function( el, eventName, detail ) {
var event = document.createEvent( "CustomEvent" );
event.initCustomEvent( eventName, true, true, detail );
el.dispatchEvent( event );
};// `translate` builds a translate transform string for given data.
var translate = function( t ) {
return " translate3d(" + t.x + "px," + t.y + "px," + t.z + "px) ";
};// `rotate` builds a rotate transform string for given data.
// By default the rotations are in X Y Z order that can be reverted by passing `true`
// as second parameter.
var rotate = function( r, revert ) {
var rX = " rotateX(" + r.x + "deg) ",
rY = " rotateY(" + r.y + "deg) ",
rZ = " rotateZ(" + r.z + "deg) ";return revert ? rZ + rY + rX : rX + rY + rZ;
};// `scale` builds a scale transform string for given data.
var scale = function( s ) {
return " scale(" + s + ") ";
};// `perspective` builds a perspective transform string for given data.
var perspective = function( p ) {
return " perspective(" + p + "px) ";
};// `getElementFromHash` returns an element located by id from hash part of
// window location.
var getElementFromHash = function() {// Get id from url # by removing `#` or `#/` from the beginning,
// so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work
return byId( window.location.hash.replace( /^#\/?/, "" ) );
};// `computeWindowScale` counts the scale factor between window size and size
// defined for the presentation in the config.
var computeWindowScale = function( config ) {
var hScale = window.innerHeight / config.height,
wScale = window.innerWidth / config.width,
scale = hScale > wScale ? wScale : hScale;if ( config.maxScale && scale > config.maxScale ) {
scale = config.maxScale;
}if ( config.minScale && scale < config.minScale ) {
scale = config.minScale;
}return scale;
};// CHECK SUPPORT
var body = document.body;var ua = navigator.userAgent.toLowerCase();
var impressSupported =// Browser should support CSS 3D transtorms
( pfx( "perspective" ) !== null ) &&// Browser should support `classList` and `dataset` APIs
( body.classList ) &&
( body.dataset )// &&
// But some mobile devices need to be blacklisted,
// because their CSS 3D support or hardware is not
// good enough to run impress.js properly, sorry...
// ( ua.search( /(iphone)|(ipod)|(android)/ ) === -1 );if ( !impressSupported ) {
// We can't be sure that `classList` is supported
body.className += " impress-not-supported ";
} else {
body.classList.remove( "impress-not-supported" );
body.classList.add( "impress-supported" );
}// GLOBALS AND DEFAULTS
// This is where the root elements of all impress.js instances will be kept.
// Yes, this means you can have more than one instance on a page, but I'm not
// sure if it makes any sense in practice ;)
var roots = {};// Some default config values.
var defaults = {
width: 1024,
height: 768,
maxScale: 1,
minScale: 0,perspective: 1000,
transitionDuration: 1000
};// It's just an empty function ... and a useless comment.
var empty = function() { return false; };// IMPRESS.JS API
// And that's where interesting things will start to happen.
// It's the core `impress` function that returns the impress.js API
// for a presentation based on the element with given id ('impress'
// by default).
var impress = window.impress = function( rootId ) {// If impress.js is not supported by the browser return a dummy API
// it may not be a perfect solution but we return early and avoid
// running code that may use features not implemented in the browser.
if ( !impressSupported ) {
return {
init: empty,
goto: empty,
prev: empty,
next: empty
};
}rootId = rootId || "impress";
// If given root is already initialized just return the API
if ( roots[ "impress-root-" + rootId ] ) {
return roots[ "impress-root-" + rootId ];
}// Data of all presentation steps
var stepsData = {};// Element of currently active step
var activeStep = null;// Current state (position, rotation and scale) of the presentation
var currentState = null;// Array of step elements
var steps = null;// Configuration options
var config = null;// Scale factor of the browser window
var windowScale = null;// Root presentation elements
var root = byId( rootId );
var canvas = document.createElement( "div" );var initialized = false;
// STEP EVENTS
//
// There are currently two step events triggered by impress.js
// `impress:stepenter` is triggered when the step is shown on the
// screen (the transition from the previous one is finished) and
// `impress:stepleave` is triggered when the step is left (the
// transition to next step just starts).// Reference to last entered step
var lastEntered = null;// `onStepEnter` is called whenever the step element is entered
// but the event is triggered only if the step is different than
// last entered step.
var onStepEnter = function( step ) {
if ( lastEntered !== step ) {
triggerEvent( step, "impress:stepenter" );
lastEntered = step;
}
};// `onStepLeave` is called whenever the step element is left
// but the event is triggered only if the step is the same as
// last entered step.
var onStepLeave = function( step ) {
if ( lastEntered === step ) {
triggerEvent( step, "impress:stepleave" );
lastEntered = null;
}
};// `initStep` initializes given step element by reading data from its
// data attributes and setting correct styles.
var initStep = function( el, idx ) {
var data = el.dataset,
step = {
translate: {
x: toNumber( data.x ),
y: toNumber( data.y ),
z: toNumber( data.z )
},
rotate: {
x: toNumber( data.rotateX ),
y: toNumber( data.rotateY ),
z: toNumber( data.rotateZ || data.rotate )
},
scale: toNumber( data.scale, 1 ),
el: el
};if ( !el.id ) {
el.id = "step-" + ( idx + 1 );
}stepsData[ "impress-" + el.id ] = step;
css( el, {
position: "absolute",
transform: "translate(-50%,-50%)" +
translate( step.translate ) +
rotate( step.rotate ) +
scale( step.scale ),
transformStyle: "preserve-3d"
} );
};// `init` API function that initializes (and runs) the presentation.
var init = function() {
if ( initialized ) { return; }// First we set up the viewport for mobile devices.
// For some reason iPad goes nuts when it is not done properly.
var meta = $( "meta[name='viewport']" ) || document.createElement( "meta" );
meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no";
if ( meta.parentNode !== document.head ) {
meta.name = "viewport";
document.head.appendChild( meta );
}// Initialize configuration object
var rootData = root.dataset;
config = {
width: toNumber( rootData.width, defaults.width ),
height: toNumber( rootData.height, defaults.height ),
maxScale: toNumber( rootData.maxScale, defaults.maxScale ),
minScale: toNumber( rootData.minScale, defaults.minScale ),
perspective: toNumber( rootData.perspective, defaults.perspective ),
transitionDuration: toNumber(
rootData.transitionDuration, defaults.transitionDuration
)
};windowScale = computeWindowScale( config );
// Wrap steps with "canvas" element
arrayify( root.childNodes ).forEach( function( el ) {
canvas.appendChild( el );
} );
root.appendChild( canvas );// Set initial styles
document.documentElement.style.height = "100%";css( body, {
height: "100%",
overflow: "hidden"
} );var rootStyles = {
position: "absolute",
transformOrigin: "top left",
transition: "all 0s ease-in-out",
transformStyle: "preserve-3d"
};css( root, rootStyles );
css( root, {
top: "50%",
left: "50%",
transform: perspective( config.perspective / windowScale ) + scale( windowScale )
} );
css( canvas, rootStyles );body.classList.remove( "impress-disabled" );
body.classList.add( "impress-enabled" );// Get and init steps
steps = $$( ".step", root );
steps.forEach( initStep );// Set a default initial state of the canvas
currentState = {
translate: { x: 0, y: 0, z: 0 },
rotate: { x: 0, y: 0, z: 0 },
scale: 1
};initialized = true;
triggerEvent( root, "impress:init", { api: roots[ "impress-root-" + rootId ] } );
};// `getStep` is a helper function that returns a step element defined by parameter.
// If a number is given, step with index given by the number is returned, if a string
// is given step element with such id is returned, if DOM element is given it is returned
// if it is a correct step element.
var getStep = function( step ) {
if ( typeof step === "number" ) {
step = step < 0 ? steps[ steps.length + step ] : steps[ step ];
} else if ( typeof step === "string" ) {
step = byId( step );
}
return ( step && step.id && stepsData[ "impress-" + step.id ] ) ? step : null;
};// Used to reset timeout for `impress:stepenter` event
var stepEnterTimeout = null;// `goto` API function that moves to step given with `el` parameter
// (by index, id or element), with a transition `duration` optionally
// given as second parameter.
var goto = function( el, duration ) {if ( !initialized || !( el = getStep( el ) ) ) {
// Presentation not initialized or given element is not a step
return false;
}// Sometimes it's possible to trigger focus on first link with some keyboard action.
// Browser in such a case tries to scroll the page to make this element visible
// (even that body overflow is set to hidden) and it breaks our careful positioning.
//
// So, as a lousy (and lazy) workaround we will make the page scroll back to the top
// whenever slide is selected
//
// If you are reading this and know any better way to handle it, I'll be glad to hear
// about it!
window.scrollTo( 0, 0 );var step = stepsData[ "impress-" + el.id ];
if ( activeStep ) {
activeStep.classList.remove( "active" );
body.classList.remove( "impress-on-" + activeStep.id );
}
el.classList.add( "active" );body.classList.add( "impress-on-" + el.id );
// Compute target state of the canvas based on given step
var target = {
rotate: {
x: -step.rotate.x,
y: -step.rotate.y,
z: -step.rotate.z
},
translate: {
x: -step.translate.x,
y: -step.translate.y,
z: -step.translate.z
},
scale: 1 / step.scale
};// Check if the transition is zooming in or not.
//
// This information is used to alter the transition style:
// when we are zooming in - we start with move and rotate transition
// and the scaling is delayed, but when we are zooming out we start
// with scaling down and move and rotation are delayed.
var zoomin = target.scale >= currentState.scale;duration = toNumber( duration, config.transitionDuration );
var delay = ( duration / 2 );// If the same step is re-selected, force computing window scaling,
// because it is likely to be caused by window resize
if ( el === activeStep ) {
windowScale = computeWindowScale( config );
}var targetScale = target.scale * windowScale;
// Trigger leave of currently active element (if it's not the same step again)
if ( activeStep && activeStep !== el ) {
onStepLeave( activeStep );
}// Now we alter transforms of `root` and `canvas` to trigger transitions.
//
// And here is why there are two elements: `root` and `canvas` - they are
// being animated separately:
// `root` is used for scaling and `canvas` for translate and rotations.
// Transitions on them are triggered with different delays (to make
// visually nice and 'natural' looking transitions), so we need to know
// that both of them are finished.
css( root, {// To keep the perspective look similar for different scales
// we need to 'scale' the perspective, too
transform: perspective( config.perspective / targetScale ) + scale( targetScale ),
transitionDuration: duration + "ms",
transitionDelay: ( zoomin ? delay : 0 ) + "ms"
} );css( canvas, {
transform: rotate( target.rotate, true ) + translate( target.translate ),
transitionDuration: duration + "ms",
transitionDelay: ( zoomin ? 0 : delay ) + "ms"
} );// Here is a tricky part...
//
// If there is no change in scale or no change in rotation and translation, it means
// there was actually no delay - because there was no transition on `root` or `canvas`
// elements. We want to trigger `impress:stepenter` event in the correct moment, so
// here we compare the current and target values to check if delay should be taken into
// account.
//
// I know that this `if` statement looks scary, but it's pretty simple when you know
// what is going on
// - it's simply comparing all the values.
if ( currentState.scale === target.scale ||
( currentState.rotate.x === target.rotate.x &&
currentState.rotate.y === target.rotate.y &&
currentState.rotate.z === target.rotate.z &&
currentState.translate.x === target.translate.x &&
currentState.translate.y === target.translate.y &&
currentState.translate.z === target.translate.z ) ) {
delay = 0;
}// Store current state
currentState = target;
activeStep = el;// And here is where we trigger `impress:stepenter` event.
// We simply set up a timeout to fire it taking transition duration
// (and possible delay) into account.
//
// I really wanted to make it in more elegant way. The `transitionend` event seemed to
// be the best way to do it, but the fact that I'm using transitions on two separate
// elements and that the `transitionend` event is only triggered when there was a
// transition (change in the values) caused some bugs and made the code really
// complicated, cause I had to handle all the conditions separately. And it still
// needed a `setTimeout` fallback for the situations when there is no transition at
// all.
// So I decided that I'd rather make the code simpler than use shiny new
// `transitionend`.
//
// If you want learn something interesting and see how it was done with `transitionend`
// go back to
// version 0.5.2 of impress.js:
// http://github.com/bartaz/impress.js/blob/0.5.2/js/impress.js
window.clearTimeout( stepEnterTimeout );
stepEnterTimeout = window.setTimeout( function() {
onStepEnter( activeStep );
}, duration + delay );return el;
};// `prev` API function goes to previous step (in document order)
var prev = function() {
var prev = steps.indexOf( activeStep ) - 1;
prev = prev >= 0 ? steps[ prev ] : steps[ steps.length - 1 ];return goto( prev );
};// `next` API function goes to next step (in document order)
var next = function() {
var next = steps.indexOf( activeStep ) + 1;
next = next < steps.length ? steps[ next ] : steps[ 0 ];return goto( next );
};// Adding some useful classes to step elements.
//
// All the steps that have not been shown yet are given `future` class.
// When the step is entered the `future` class is removed and the `present`
// class is given. When the step is left `present` class is replaced with
// `past` class.
//
// So every step element is always in one of three possible states:
// `future`, `present` and `past`.
//
// There classes can be used in CSS to style different types of steps.
// For example the `present` class can be used to trigger some custom
// animations when step is shown.
root.addEventListener( "impress:init", function() {// STEP CLASSES
steps.forEach( function( step ) {
step.classList.add( "future" );
} );root.addEventListener( "impress:stepenter", function( event ) {
event.target.classList.remove( "past" );
event.target.classList.remove( "future" );
event.target.classList.add( "present" );
}, false );root.addEventListener( "impress:stepleave", function( event ) {
event.target.classList.remove( "present" );
event.target.classList.add( "past" );
}, false );}, false );
// Adding hash change support.
root.addEventListener( "impress:init", function() {// Last hash detected
var lastHash = "";// `#/step-id` is used instead of `#step-id` to prevent default browser
// scrolling to element in hash.
//
// And it has to be set after animation finishes, because in Chrome it
// makes transtion laggy.
// BUG: http://code.google.com/p/chromium/issues/detail?id=62820
root.addEventListener( "impress:stepenter", function( event ) {
window.location.hash = lastHash = "#/" + event.target.id;
}, false );window.addEventListener( "hashchange", function() {
// When the step is entered hash in the location is updated
// (just few lines above from here), so the hash change is
// triggered and we would call `goto` again on the same element.
//
// To avoid this we store last entered hash and compare.
if ( window.location.hash !== lastHash ) {
goto( getElementFromHash() );
}
}, false );// START
// by selecting step defined in url or first step of the presentation
goto( getElementFromHash() || steps[ 0 ], 0 );
}, false );body.classList.add( "impress-disabled" );
// Store and return API for given impress.js root element
return ( roots[ "impress-root-" + rootId ] = {
init: init,
goto: goto,
next: next,
prev: prev
} );};
// Flag that can be used in JS to check if browser have passed the support test
impress.supported = impressSupported;} )( document, window );
// NAVIGATION EVENTS
// As you can see this part is separate from the impress.js core code.
// It's because these navigation actions only need what impress.js provides with
// its simple API.
//
// In future I think about moving it to make them optional, move to separate files
// and treat more like a 'plugins'.
( function( document, window ) {
"use strict";// Throttling function calls, by Remy Sharp
// http://remysharp.com/2010/07/21/throttling-function-calls/
var throttle = function( fn, delay ) {
var timer = null;
return function() {
var context = this, args = arguments;
clearTimeout( timer );
timer = setTimeout( function() {
fn.apply( context, args );
}, delay );
};
};// Wait for impress.js to be initialized
document.addEventListener( "impress:init", function( event ) {// Getting API from event data.
// So you don't event need to know what is the id of the root element
// or anything. `impress:init` event data gives you everything you
// need to control the presentation that was just initialized.
var api = event.detail.api;// KEYBOARD NAVIGATION HANDLERS
// Prevent default keydown action when one of supported key is pressed.
document.addEventListener( "keydown", function( event ) {
if ( event.keyCode === 9 ||
( event.keyCode >= 32 && event.keyCode <= 34 ) ||
( event.keyCode >= 37 && event.keyCode <= 40 ) ) {
event.preventDefault();
}
}, false );// Trigger impress action (next or prev) on keyup.
// Supported keys are:
// [space] - quite common in presentation software to move forward
// [up] [right] / [down] [left] - again common and natural addition,
// [pgdown] / [pgup] - often triggered by remote controllers,
// [tab] - this one is quite controversial, but the reason it ended up on
// this list is quite an interesting story... Remember that strange part
// in the impress.js code where window is scrolled to 0,0 on every presentation
// step, because sometimes browser scrolls viewport because of the focused element?
// Well, the [tab] key by default navigates around focusable elements, so clicking
// it very often caused scrolling to focused element and breaking impress.js
// positioning. I didn't want to just prevent this default action, so I used [tab]
// as another way to moving to next step... And yes, I know that for the sake of
// consistency I should add [shift+tab] as opposite action...
document.addEventListener( "keyup", function( event ) {if ( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) {
return;
}if ( event.keyCode === 9 ||
( event.keyCode >= 32 && event.keyCode <= 34 ) ||
( event.keyCode >= 37 && event.keyCode <= 40 ) ) {
switch ( event.keyCode ) {
case 33: // Page up
case 37: // Left
case 38: // Up
api.prev();
break;
case 9: // Tab
case 32: // Space
case 34: // Page down
case 39: // Right
case 40: // Down
api.next();
break;
}event.preventDefault();
}
}, false );// Delegated handler for clicking on the links to presentation steps
document.addEventListener( "click", function( event ) {// Event delegation with "bubbling"
// Check if event target (or any of its parents is a link)
var target = event.target;
while ( ( target.tagName !== "A" ) &&
( target !== document.documentElement ) ) {
target = target.parentNode;
}if ( target.tagName === "A" ) {
var href = target.getAttribute( "href" );// If it's a link to presentation step, target this step
if ( href && href[ 0 ] === "#" ) {
target = document.getElementById( href.slice( 1 ) );
}
}if ( api.goto( target ) ) {
event.stopImmediatePropagation();
event.preventDefault();
}
}, false );// Delegated handler for clicking on step elements
document.addEventListener( "click", function( event ) {
var target = event.target;// Find closest step element that is not active
while ( !( target.classList.contains( "step" ) &&
!target.classList.contains( "active" ) ) &&
( target !== document.documentElement ) ) {
target = target.parentNode;
}if ( api.goto( target ) ) {
event.preventDefault();
}
}, false );// Touch handler to detect taps on the left and right side of the screen
// based on awesome work of @hakimel: https://github.com/hakimel/reveal.js
document.addEventListener( "touchstart", function( event ) {
if ( event.touches.length === 1 ) {
var x = event.touches[ 0 ].clientX,
width = window.innerWidth * 0.3,
result = null;if ( x < width ) {
result = api.prev();
} else if ( x > window.innerWidth - width ) {
result = api.next();
}if ( result ) {
event.preventDefault();
}
}
}, false );// Rescale presentation when window is resized
window.addEventListener( "resize", throttle( function() {// Force going to active step again, to trigger rescaling
api.goto( document.querySelector( ".step.active" ), 500 );
}, 250 ), false );}, false );
} )( document, window );
// THAT'S ALL FOLKS!
//
// Thanks for reading it all.
// Or thanks for scrolling down and reading the last part.
//
// I've learnt a lot when building impress.js and I hope this code and comments
// will help somebody learn at least some part of it.impress().init();