Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
my-cucumbers-ru-github-io
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Лотуга Данила Сергеевич
my-cucumbers-ru-github-io
Commits
b8e67a43
Commit
b8e67a43
authored
Mar 01, 2021
by
Vadim Makeev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updates
parent
6841741a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
252 additions
and
216 deletions
+252
-216
index.html
index.html
+3
-3
presentation.zip
presentation.zip
+0
-0
shower.js
shower/shower.js
+244
-210
README.md
shower/themes/material/README.md
+1
-1
shower-full.css
shower/themes/material/styles/shower/shower-full.css
+1
-0
columns.css
shower/themes/material/styles/slide/elements/columns.css
+1
-1
README.md
shower/themes/ribbon/README.md
+1
-1
shower-full.css
shower/themes/ribbon/styles/shower/shower-full.css
+1
-0
No files found.
index.html
View file @
b8e67a43
...
...
@@ -20,11 +20,11 @@
<section
class=
"slide"
id=
"cover"
>
<h2>
Shower Presentation Engine
</h2>
<p>
Brought to you by
<a
href=
"http://pepelsbey.net"
>
Vadim Makeev
</a></p>
<p>
Brought to you by
<a
href=
"http
s
://pepelsbey.net"
>
Vadim Makeev
</a></p>
<figure>
<img
class=
"cover"
src=
"pictures/cover.jpg"
alt=
"Hands on the orange typewriter in a park"
>
<figcaption
class=
"copyright right white"
>
<a
href=
"http
://fiftyfootshadows.net/
"
>
© John Carey
</a>
<a
href=
"http
s://fiftyfootshadows.net
"
>
© John Carey
</a>
</figcaption>
</figure>
<style>
...
...
@@ -155,7 +155,7 @@
<figure>
<img
class=
"cover"
src=
"pictures/picture.jpg"
alt=
"Orange typewriter on a wooden table close-up"
>
<figcaption
class=
"copyright right white"
>
<a
href=
"http
://fiftyfootshadows.net/
"
>
© John Carey
</a>
<a
href=
"http
s://fiftyfootshadows.net
"
>
© John Carey
</a>
</figcaption>
</figure>
<style>
...
...
presentation.zip
View file @
b8e67a43
No preview for this file type
shower/shower.js
View file @
b8e67a43
/**
* Core for Shower HTML presentation engine
* @shower/core v3.0.0
-2
, https://github.com/shower/core
* @copyright 2010–202
0
Vadim Makeev, https://pepelsbey.net
* @shower/core v3.0.0, https://github.com/shower/core
* @copyright 2010–202
1
Vadim Makeev, https://pepelsbey.net
* @license MIT
*/
(
function
()
{
'use strict'
;
const
EVENT_TARGET
=
Symbol
(
'EventTarget'
);
class
EventTarget
{
constructor
()
{
this
[
EVENT_TARGET
]
=
document
.
createElement
(
'div'
);
}
addEventListener
(...
args
)
{
this
[
EVENT_TARGET
].
addEventListener
(...
args
);
}
removeEventListener
(...
args
)
{
this
[
EVENT_TARGET
].
removeEventListener
(...
args
);
}
dispatchEvent
(
event
)
{
Object
.
defineProperties
(
event
,
{
target
:
{
value
:
this
},
currentTarget
:
{
value
:
this
},
});
return
this
[
EVENT_TARGET
].
dispatchEvent
(
event
);
}
}
const
isInteractiveElement
=
(
element
)
=>
element
.
tabIndex
!==
-
1
;
const
freezeHistory
=
(
callback
)
=>
{
history
.
pushState
=
()
=>
{};
history
.
replaceState
=
()
=>
{};
try
{
callback
();
}
finally
{
delete
history
.
pushState
;
delete
history
.
replaceState
;
}
};
const
contentLoaded
=
(
callback
)
=>
{
if
(
document
.
currentScript
.
async
)
{
...
...
@@ -53,6 +17,19 @@
}
};
const
defineReadOnly
=
(
target
,
props
)
=>
{
for
(
const
[
key
,
value
]
of
Object
.
entries
(
props
))
{
Object
.
defineProperty
(
target
,
key
,
{
value
,
writable
:
false
,
enumerable
:
true
,
configurable
:
true
,
});
}
};
class
ShowerError
extends
Error
{}
var
defaultOptions
=
{
containerSelector
:
'.shower'
,
progressSelector
:
'.progress'
,
...
...
@@ -66,22 +43,32 @@
visitedSlideClass
:
'visited'
,
};
/**
* @param {HTMLElement} element
* @param {object} options
*/
class
Slide
extends
EventTarget
{
constructor
(
element
,
options
)
{
/**
* @param {Shower} shower
* @param {HTMLElement} element
*/
constructor
(
shower
,
element
)
{
super
();
this
.
element
=
element
;
this
.
options
=
options
;
defineReadOnly
(
this
,
{
shower
,
element
,
state
:
{
visitCount
:
0
,
innerStepCount
:
0
,
},
});
this
.
_isActive
=
false
;
this
.
state
=
{
visitsCount
:
0
,
innerStepsCount
:
0
,
};
this
.
_options
=
this
.
shower
.
options
;
this
.
element
.
addEventListener
(
'click'
,
(
event
)
=>
{
if
(
event
.
defaultPrevented
)
return
;
this
.
activate
();
this
.
shower
.
enterFullMode
();
});
}
get
isActive
()
{
...
...
@@ -89,7 +76,7 @@
}
get
isVisited
()
{
return
this
.
state
.
visit
s
Count
>
0
;
return
this
.
state
.
visitCount
>
0
;
}
get
id
()
{
...
...
@@ -97,27 +84,57 @@
}
get
title
()
{
const
titleElement
=
this
.
element
.
querySelector
(
this
.
options
.
slideTitleSelector
);
const
titleElement
=
this
.
element
.
querySelector
(
this
.
_
options
.
slideTitleSelector
);
return
titleElement
?
titleElement
.
innerText
:
''
;
}
/**
* Deactivates currently active slide (if any) and activates itself.
* @emits Slide#deactivate
* @emits Slide#activate
* @emits Shower#slidechange
*/
activate
()
{
if
(
this
.
_isActive
)
return
;
const
prev
=
this
.
shower
.
activeSlide
;
if
(
prev
)
{
prev
.
_deactivate
();
}
this
.
state
.
visitCount
++
;
this
.
element
.
classList
.
add
(
this
.
_options
.
activeSlideClass
);
this
.
_isActive
=
true
;
this
.
state
.
visitsCount
++
;
this
.
element
.
classList
.
add
(
this
.
options
.
activeSlideClass
);
this
.
dispatchEvent
(
new
Event
(
'activate'
));
this
.
shower
.
dispatchEvent
(
new
CustomEvent
(
'slidechange'
,
{
detail
:
{
prev
},
}),
);
}
/**
* @throws {ShowerError}
* @emits Slide#deactivate
*/
deactivate
()
{
if
(
!
this
.
_isActive
)
return
;
if
(
this
.
shower
.
isFullMode
)
{
throw
new
ShowerError
(
'In full mode, another slide should be activated instead.'
);
}
this
.
_isActive
=
false
;
if
(
this
.
_isActive
)
{
this
.
_deactivate
();
}
}
_deactivate
()
{
this
.
element
.
classList
.
replace
(
this
.
options
.
activeSlideClass
,
this
.
options
.
visitedSlideClass
,
this
.
_
options
.
activeSlideClass
,
this
.
_
options
.
visitedSlideClass
,
);
this
.
_isActive
=
false
;
this
.
dispatchEvent
(
new
Event
(
'deactivate'
));
}
}
...
...
@@ -152,6 +169,11 @@
}
};
shower
.
addEventListener
(
'start'
,
()
=>
{
updateDocumentRole
();
updateLiveRegion
();
});
shower
.
addEventListener
(
'modechange'
,
updateDocumentRole
);
shower
.
addEventListener
(
'slidechange'
,
updateLiveRegion
);
};
...
...
@@ -179,6 +201,7 @@
}
break
;
case
'BACKSPACE'
:
case
'PAGEUP'
:
case
'ARROWUP'
:
case
'ARROWLEFT'
:
...
...
@@ -277,15 +300,12 @@
};
const
applyURLMode
=
()
=>
{
const
isFull
=
new
URL
(
location
).
searchParams
.
has
(
'full'
);
freezeHistory
(()
=>
{
if
(
isFull
)
{
shower
.
enterFullMode
();
}
else
{
shower
.
exitFullMode
();
}
});
const
isFull
=
new
URLSearchParams
(
location
.
search
).
has
(
'full'
);
if
(
isFull
)
{
shower
.
enterFullMode
();
}
else
{
shower
.
exitFullMode
();
}
};
const
applyURLSlide
=
()
=>
{
...
...
@@ -294,9 +314,7 @@
const
target
=
shower
.
slides
.
find
((
slide
)
=>
slide
.
id
===
id
);
if
(
target
)
{
freezeHistory
(()
=>
{
target
.
activate
();
});
target
.
activate
();
}
else
if
(
!
shower
.
activeSlide
)
{
shower
.
first
();
// invalid hash
}
...
...
@@ -307,65 +325,77 @@
applyURLSlide
();
};
applyURL
();
window
.
addEventListener
(
'popstate'
,
applyURL
);
shower
.
addEventListener
(
'start'
,
()
=>
{
history
.
replaceState
(
null
,
document
.
title
,
composeURL
());
});
shower
.
addEventListener
(
'modechange'
,
()
=>
{
history
.
replaceState
(
null
,
document
.
title
,
composeURL
());
});
shower
.
addEventListener
(
'slidechange'
,
()
=>
{
history
.
pushState
(
null
,
document
.
title
,
composeURL
());
const
url
=
composeURL
();
if
(
!
location
.
href
.
endsWith
(
url
))
{
history
.
pushState
(
null
,
document
.
title
,
url
);
}
});
shower
.
addEventListener
(
'start'
,
applyURL
);
window
.
addEventListener
(
'popstate'
,
applyURL
);
};
var
next
=
(
shower
)
=>
{
const
{
stepSelector
,
activeSlideClass
}
=
shower
.
options
;
const
{
stepSelector
,
activeSlideClass
,
visitedSlideClass
}
=
shower
.
options
;
let
innerSteps
;
let
innerAt
;
let
activeIndex
;
const
getInnerSteps
=
()
=>
{
const
{
element
}
=
shower
.
activeSlide
;
return
[...
element
.
querySelectorAll
(
stepSelector
)];
};
const
isActive
=
(
step
)
=>
step
.
classList
.
contains
(
activeSlideClass
);
const
isVisited
=
(
step
)
=>
step
.
classList
.
contains
(
visitedSlideClass
);
const
getInnerAt
=
()
=>
{
return
innerSteps
.
filter
((
step
)
=>
{
return
step
.
classList
.
contains
(
activeSlideClass
);
}).
length
;
};
const
setInnerStepsState
=
()
=>
{
if
(
shower
.
isListMode
)
return
;
const
toggleActive
=
()
=>
{
innerSteps
.
forEach
((
step
,
index
)
=>
{
step
.
classList
.
toggle
(
activeSlideClass
,
index
<
innerAt
);
});
};
const
slide
=
shower
.
activeSlide
;
shower
.
addEventListener
(
'slidechange'
,
()
=>
{
innerSteps
=
getInnerSteps
();
innerAt
=
getInnerAt
();
innerSteps
=
[...
slide
.
element
.
querySelectorAll
(
stepSelector
)];
activeIndex
=
innerSteps
.
length
&&
innerSteps
.
every
(
isVisited
)
?
innerSteps
.
length
:
innerSteps
.
filter
(
isActive
).
length
-
1
;
const
slide
=
shower
.
activeSlide
;
slide
.
state
.
innerStepsCount
=
innerSteps
.
length
;
});
slide
.
state
.
innerStepCount
=
innerSteps
.
length
;
};
shower
.
addEventListener
(
'start'
,
setInnerStepsState
);
shower
.
addEventListener
(
'modechange'
,
setInnerStepsState
);
shower
.
addEventListener
(
'slidechange'
,
setInnerStepsState
);
shower
.
addEventListener
(
'next'
,
(
event
)
=>
{
if
(
event
.
defaultPrevented
||
!
event
.
cancelable
)
return
;
if
(
shower
.
isListMode
||
innerAt
===
innerSteps
.
length
)
return
;
if
(
shower
.
isListMode
||
event
.
defaultPrevented
||
!
event
.
cancelable
)
return
;
event
.
preventDefault
();
innerAt
++
;
toggleActive
();
activeIndex
++
;
innerSteps
.
forEach
((
step
,
index
)
=>
{
step
.
classList
.
toggle
(
visitedSlideClass
,
index
<
activeIndex
);
step
.
classList
.
toggle
(
activeSlideClass
,
index
===
activeIndex
);
});
if
(
activeIndex
<
innerSteps
.
length
)
{
event
.
preventDefault
();
}
});
shower
.
addEventListener
(
'prev'
,
(
event
)
=>
{
if
(
event
.
defaultPrevented
||
!
event
.
cancelable
)
return
;
if
(
shower
.
isListMode
||
innerAt
===
innerSteps
.
length
||
!
innerAt
)
return
;
if
(
shower
.
isListMode
||
event
.
defaultPrevented
||
!
event
.
cancelable
)
return
;
if
(
activeIndex
===
-
1
||
activeIndex
===
innerSteps
.
length
)
return
;
activeIndex
--
;
innerSteps
.
forEach
((
step
,
index
)
=>
{
step
.
classList
.
toggle
(
visitedSlideClass
,
index
<
activeIndex
+
1
);
step
.
classList
.
toggle
(
activeSlideClass
,
index
===
activeIndex
);
});
event
.
preventDefault
();
innerAt
--
;
toggleActive
();
});
};
...
...
@@ -388,29 +418,10 @@
bar
.
setAttribute
(
'aria-valuetext'
,
`Slideshow progress:
${
progress
}
%`
);
};
shower
.
addEventListener
(
'start'
,
updateProgress
);
shower
.
addEventListener
(
'slidechange'
,
updateProgress
);
};
var
scale
=
(
shower
)
=>
{
const
{
container
}
=
shower
;
const
getScale
=
()
=>
{
const
maxRatio
=
Math
.
max
(
container
.
offsetWidth
/
window
.
innerWidth
,
container
.
offsetHeight
/
window
.
innerHeight
,
);
return
`scale(
${
1
/
maxRatio
}
)`
;
};
const
updateStyle
=
()
=>
{
container
.
style
.
transform
=
shower
.
isFullMode
?
getScale
()
:
''
;
};
shower
.
addEventListener
(
'modechange'
,
updateStyle
);
window
.
addEventListener
(
'resize'
,
updateStyle
);
window
.
addEventListener
(
'load'
,
updateStyle
);
};
const
units
=
[
's'
,
'm'
,
'h'
];
const
hasUnits
=
(
timing
)
=>
{
return
units
.
some
((
unit
)
=>
timing
.
includes
(
unit
));
...
...
@@ -443,27 +454,28 @@
var
timer
=
(
shower
)
=>
{
let
id
;
const
setTimer
=
()
=>
{
const
re
setTimer
=
()
=>
{
clearTimeout
(
id
);
if
(
shower
.
isListMode
)
return
;
const
slide
=
shower
.
activeSlide
;
const
{
visit
sCount
,
innerSteps
Count
}
=
slide
.
state
;
if
(
visit
s
Count
>
1
)
return
;
const
{
visit
Count
,
innerStep
Count
}
=
slide
.
state
;
if
(
visitCount
>
1
)
return
;
const
timing
=
parseTiming
(
slide
.
element
.
dataset
.
timing
);
if
(
!
timing
)
return
;
if
(
innerStep
s
Count
)
{
const
stepTiming
=
timing
/
(
innerStep
s
Count
+
1
);
if
(
innerStepCount
)
{
const
stepTiming
=
timing
/
(
innerStepCount
+
1
);
id
=
setInterval
(()
=>
shower
.
next
(),
stepTiming
);
}
else
{
id
=
setTimeout
(()
=>
shower
.
next
(),
timing
);
}
};
shower
.
addEventListener
(
'modechange'
,
setTimer
);
shower
.
addEventListener
(
'slidechange'
,
setTimer
);
shower
.
addEventListener
(
'start'
,
resetTimer
);
shower
.
addEventListener
(
'modechange'
,
resetTimer
);
shower
.
addEventListener
(
'slidechange'
,
resetTimer
);
shower
.
container
.
addEventListener
(
'keydown'
,
(
event
)
=>
{
if
(
!
event
.
defaultPrevented
)
{
...
...
@@ -489,6 +501,7 @@
document
.
title
=
title
;
};
shower
.
addEventListener
(
'start'
,
updateTitle
);
shower
.
addEventListener
(
'modechange'
,
updateTitle
);
shower
.
addEventListener
(
'slidechange'
,
updateTitle
);
};
...
...
@@ -497,131 +510,154 @@
const
{
container
}
=
shower
;
const
{
fullModeClass
,
listModeClass
}
=
shower
.
options
;
shower
.
addEventListener
(
'modechange'
,
()
=>
{
if
(
container
.
classList
.
contains
(
fullModeClass
))
{
shower
.
enterFullMode
();
}
else
{
container
.
classList
.
add
(
listModeClass
);
}
const
updateScale
=
()
=>
{
const
firstSlide
=
shower
.
slides
[
0
];
if
(
!
firstSlide
)
return
;
const
{
innerWidth
,
innerHeight
}
=
window
;
const
{
offsetWidth
,
offsetHeight
}
=
firstSlide
.
element
;
const
listScale
=
1
/
(
offsetWidth
/
innerWidth
);
const
fullScale
=
1
/
Math
.
max
(
offsetWidth
/
innerWidth
,
offsetHeight
/
innerHeight
);
container
.
style
.
setProperty
(
'--shower-list-scale'
,
listScale
);
container
.
style
.
setProperty
(
'--shower-full-scale'
,
fullScale
);
};
const
updateModeView
=
()
=>
{
if
(
shower
.
isFullMode
)
{
container
.
classList
.
remove
(
listModeClass
);
container
.
classList
.
add
(
fullModeClass
);
return
;
}
else
{
container
.
classList
.
remove
(
fullModeClass
);
container
.
classList
.
add
(
listModeClass
);
}
container
.
classList
.
remove
(
fullModeClass
);
container
.
classList
.
add
(
listModeClass
);
updateScale
();
if
(
shower
.
isFullMode
)
return
;
const
slide
=
shower
.
activeSlide
;
if
(
slide
)
{
slide
.
element
.
scrollIntoView
({
block
:
'center'
});
}
}
)
;
};
shower
.
addEventListener
(
'start'
,
updateModeView
);
shower
.
addEventListener
(
'modechange'
,
updateModeView
);
shower
.
addEventListener
(
'slidechange'
,
()
=>
{
if
(
shower
.
isFullMode
)
return
;
const
slide
=
shower
.
activeSlide
;
slide
.
element
.
scrollIntoView
({
block
:
'nearest'
});
});
shower
.
addEventListener
(
'start'
,
()
=>
{
if
(
container
.
classList
.
contains
(
fullModeClass
))
{
shower
.
enterFullMode
();
}
else
{
container
.
classList
.
add
(
listModeClass
);
}
});
window
.
addEventListener
(
'resize'
,
updateScale
);
};
var
installModules
=
(
shower
)
=>
{
a11y
(
shower
);
keys
(
shower
);
// should come before `timer`
progress
(
shower
);
next
(
shower
);
// should come before `timer`
timer
(
shower
);
title
(
shower
);
// should come before `location`
location$1
(
shower
);
keys
(
shower
);
next
(
shower
);
timer
(
shower
);
// should come after `keys` and `next`
title
(
shower
);
location$1
(
shower
);
// should come after `title`
view
(
shower
);
scale
(
shower
);
};
const
ensureSlideId
=
(
slideElement
,
index
)
=>
{
if
(
!
slideElement
.
id
)
{
s
lideElement
.
id
=
index
+
1
;
// maintains invariant: active slide always exists in `full` mode
if
(
shower
.
isFullMode
&&
!
shower
.
activeSlide
)
{
s
hower
.
first
()
;
}
};
class
Shower
extends
EventTarget
{
/**
* @param {object=} options
*/
constructor
(
options
)
{
super
();
defineReadOnly
(
this
,
{
options
:
{
...
defaultOptions
,
...
options
},
});
this
.
_mode
=
'list'
;
this
.
_isStarted
=
false
;
this
.
options
=
{
...
defaultOptions
,
...
options
}
;
this
.
_container
=
null
;
}
/**
* @param {object} options
* @param {object=} options
* @throws {ShowerError}
*/
configure
(
options
)
{
if
(
this
.
_isStarted
)
{
throw
new
ShowerError
(
'Shower should be configured before it is started.'
);
}
Object
.
assign
(
this
.
options
,
options
);
}
/**
* @throws {ShowerError}
* @emits Shower#start
*/
start
()
{
if
(
this
.
_isStarted
)
return
;
const
{
containerSelector
}
=
this
.
options
;
this
.
container
=
document
.
querySelector
(
containerSelector
);
if
(
!
this
.
container
)
{
throw
new
Error
(
`Shower container with selector '
${
containerSelector
}
' not found.`
);
this
.
_container
=
document
.
querySelector
(
containerSelector
);
if
(
!
this
.
_container
)
{
throw
new
ShowerError
(
`Shower container with selector '
${
containerSelector
}
' was not found.`
,
);
}
this
.
_isStarted
=
true
;
this
.
_initSlides
();
// maintains invariant: active slide always exists in `full` mode
this
.
addEventListener
(
'modechange'
,
()
=>
{
if
(
this
.
isFullMode
&&
!
this
.
activeSlide
)
{
this
.
first
();
}
});
installModules
(
this
);
this
.
_isStarted
=
true
;
this
.
dispatchEvent
(
new
Event
(
'start'
));
}
_initSlides
()
{
const
slideElements
=
[
...
this
.
container
.
querySelectorAll
(
this
.
options
.
slideSelector
),
].
filter
((
slideElement
)
=>
!
slideElement
.
hidden
);
slideElements
.
forEach
(
ensureSlideId
);
this
.
slides
=
slideElements
.
map
((
slideElement
)
=>
{
const
slide
=
new
Slide
(
slideElement
,
this
.
options
);
slide
.
addEventListener
(
'activate'
,
()
=>
{
this
.
_changeActiveSlide
(
slide
);
});
slide
.
element
.
addEventListener
(
'click'
,
()
=>
{
if
(
this
.
isListMode
)
{
this
.
enterFullMode
();
slide
.
activate
();
}
});
const
visibleSlideSelector
=
`
${
this
.
options
.
slideSelector
}
:not([hidden])`
;
const
visibleSlideElements
=
this
.
_container
.
querySelectorAll
(
visibleSlideSelector
);
return
slide
;
this
.
slides
=
Array
.
from
(
visibleSlideElements
,
(
slideElement
,
index
)
=>
{
if
(
!
slideElement
.
id
)
{
slideElement
.
id
=
index
+
1
;
}
return
new
Slide
(
this
,
slideElement
);
});
}
_changeActiveSlide
(
next
)
{
const
prev
=
this
.
slides
.
find
((
slide
)
=>
{
return
slide
.
isActive
&&
slide
!==
next
;
});
_setMode
(
mode
)
{
if
(
mode
===
this
.
_mode
)
return
;
if
(
prev
)
{
prev
.
deactivate
(
);
}
this
.
_mode
=
mode
;
this
.
dispatchEvent
(
new
Event
(
'modechange'
)
);
}
const
event
=
new
CustomEvent
(
'slidechange'
,
{
detail
:
{
prev
},
});
/**
* @param {Event} event
*/
dispatchEvent
(
event
)
{
if
(
!
this
.
_isStarted
)
return
false
;
this
.
dispatchEvent
(
event
);
return
super
.
dispatchEvent
(
event
);
}
get
container
()
{
return
this
.
_container
;
}
get
isFullMode
()
{
...
...
@@ -642,22 +678,18 @@
/**
* Slide fills the maximum area.
* @emits Shower#modechange
*/
enterFullMode
()
{
if
(
!
this
.
isFullMode
)
{
this
.
_mode
=
'full'
;
this
.
dispatchEvent
(
new
Event
(
'modechange'
));
}
this
.
_setMode
(
'full'
);
}
/**
* Shower returns into list mode.
* @emits Shower#modechange
*/
exitFullMode
()
{
if
(
!
this
.
isListMode
)
{
this
.
_mode
=
'list'
;
this
.
dispatchEvent
(
new
Event
(
'modechange'
));
}
this
.
_setMode
(
'list'
);
}
/**
...
...
@@ -673,27 +705,29 @@
/**
* @param {number} delta
*/
go
(
delta
)
{
go
By
(
delta
)
{
this
.
goTo
(
this
.
activeSlideIndex
+
delta
);
}
/**
* @param {boolean=} isForce
* @param {boolean} [isForce=false]
* @emits Shower#prev
*/
prev
(
isForce
)
{
const
prev
=
new
Event
(
'prev'
,
{
cancelable
:
!
isForce
});
if
(
this
.
dispatchEvent
(
prev
))
{
this
.
go
(
-
1
);
this
.
go
By
(
-
1
);
}
}
/**
* @param {boolean=} isForce
* @param {boolean} [isForce=false]
* @emits Shower#next
*/
next
(
isForce
)
{
const
next
=
new
Event
(
'next'
,
{
cancelable
:
!
isForce
});
if
(
this
.
dispatchEvent
(
next
))
{
this
.
go
(
1
);
this
.
go
By
(
1
);
}
}
...
...
shower/themes/material/README.md
View file @
b8e67a43
...
...
@@ -8,7 +8,7 @@ Default theme for the [Shower](https://github.com/shower/shower/) presentation e
Get the Shower template where Material is already included. Download the
[
template archive
](
https://shwr.me/shower.zip
)
or install the package:
npm install shower
npm install
@shower/
shower
If you want to install Material separately you can install the package:
...
...
shower/themes/material/styles/shower/shower-full.css
View file @
b8e67a43
...
...
@@ -10,4 +10,5 @@
width
:
var
(
--slide-width
);
height
:
var
(
--slide-height
);
background-color
:
black
;
transform
:
scale
(
var
(
--shower-full-scale
));
}
shower/themes/material/styles/slide/elements/columns.css
View file @
b8e67a43
...
...
@@ -3,7 +3,7 @@
.columns
{
display
:
grid
;
width
:
100%
;
grid-column-gap
:
75
px
;
grid-column-gap
:
48
px
;
}
.columns.two
{
...
...
shower/themes/ribbon/README.md
View file @
b8e67a43
...
...
@@ -8,7 +8,7 @@ Default theme for the [Shower](https://github.com/shower/shower/) presentation e
Get the Shower template where Ribbon is already included. Download the
[
template archive
](
https://shwr.me/shower.zip
)
or install the package:
npm install shower
npm install
@shower/
shower
If you want to install Ribbon separately you can install the package:
...
...
shower/themes/ribbon/styles/shower/shower-full.css
View file @
b8e67a43
...
...
@@ -14,4 +14,5 @@
width
:
var
(
--slide-width
);
height
:
var
(
--slide-height
);
background-color
:
black
;
transform
:
scale
(
var
(
--shower-full-scale
));
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment