Refactored clipboard integration, not finished

This commit is contained in:
squidfunk 2017-05-31 15:22:59 +02:00
parent c07ef90f0e
commit 670ae4a44c
18 changed files with 161 additions and 108 deletions

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2016-2017 Martin Donath <martin.donath@squidfunk.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* ----------------------------------------------------------------------------
* Declarations
* ------------------------------------------------------------------------- */
declare module "clipboard" {
/* Class: Clipboard */
declare class Clipboard {
static isSupported(): boolean,
on(event: string, cb: Function): void
}
/* Exports */
declare export default typeof Clipboard
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -35,10 +35,10 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block libs %} {% block libs %}
<script src="{{ base_url }}/assets/javascripts/modernizr-56ade86843.js"></script> <script src="{{ base_url }}/assets/javascripts/modernizr-1df76c4e58.js"></script>
{% endblock %} {% endblock %}
{% block styles %} {% block styles %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-99e13a48f0.css"> <link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-9749f36cad.css">
{% if config.extra.palette %} {% if config.extra.palette %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-0a3e9e1c07.palette.css"> <link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-0a3e9e1c07.palette.css">
{% endif %} {% endif %}
@ -149,7 +149,7 @@
{% endblock %} {% endblock %}
</div> </div>
{% block scripts %} {% block scripts %}
<script src="{{ base_url }}/assets/javascripts/application-6b4ff16fa7.js"></script> <script src="{{ base_url }}/assets/javascripts/application-1a4408fe3b.js"></script>
<script>app.initialize({url:{base:"{{ base_url }}"}})</script> <script>app.initialize({url:{base:"{{ base_url }}"}})</script>
{% for path in extra_javascript %} {% for path in extra_javascript %}
<script src="{{ path }}"></script> <script src="{{ path }}"></script>

View File

@ -34,9 +34,7 @@
"test:visual:session": "scripts/test/visual/session", "test:visual:session": "scripts/test/visual/session",
"travis": "scripts/travis" "travis": "scripts/travis"
}, },
"dependencies": { "dependencies": {},
"escape-string-regexp": "^1.0.5"
},
"devDependencies": { "devDependencies": {
"autoprefixer": "^7.0.1", "autoprefixer": "^7.0.1",
"babel-core": "^6.23.0", "babel-core": "^6.23.0",
@ -49,10 +47,12 @@
"babel-register": "^6.23.0", "babel-register": "^6.23.0",
"babel-root-import": "^4.1.5", "babel-root-import": "^4.1.5",
"chalk": "^1.1.3", "chalk": "^1.1.3",
"clipboard": "^1.7.1",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"css-mqpacker": "^6.0.0", "css-mqpacker": "^6.0.0",
"custom-event-polyfill": "^0.3.0", "custom-event-polyfill": "^0.3.0",
"del": "^2.2.2", "del": "^2.2.2",
"escape-string-regexp": "^1.0.5",
"eslint": "^3.16.0", "eslint": "^3.16.0",
"fastclick": "^1.0.6", "fastclick": "^1.0.6",
"flow-bin": "^0.46.0", "flow-bin": "^0.46.0",

View File

@ -20,7 +20,9 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
import Clipboard from "clipboard"
import FastClick from "fastclick" import FastClick from "fastclick"
import Material from "./components/Material" import Material from "./components/Material"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
@ -48,7 +50,7 @@ function initialize(config) { // eslint-disable-line func-style
}) })
/* Wrap all data tables for better overflow scrolling */ /* Wrap all data tables for better overflow scrolling */
const tables = document.querySelectorAll("table:not([class])") const tables = document.querySelectorAll("table:not([class])") // TODO: this is JSX
Array.prototype.forEach.call(tables, table => { Array.prototype.forEach.call(tables, table => {
const wrap = ( const wrap = (
<div class="md-typeset__scrollwrap"> <div class="md-typeset__scrollwrap">
@ -85,7 +87,6 @@ function initialize(config) { // eslint-disable-line func-style
/* If Clipboard.js is available, inject "copy to clipboard" overlays /* If Clipboard.js is available, inject "copy to clipboard" overlays
and attach Clipboard to copy the code. and attach Clipboard to copy the code.
Handle both div.codehilite>pre and pre>code. */ Handle both div.codehilite>pre and pre>code. */
// $FlowFixMe
if (typeof Clipboard !== "undefined" && if (typeof Clipboard !== "undefined" &&
Clipboard.isSupported()) { // eslint-disable-line no-undef Clipboard.isSupported()) { // eslint-disable-line no-undef
const blocks = document.querySelectorAll( const blocks = document.querySelectorAll(
@ -95,31 +96,35 @@ function initialize(config) { // eslint-disable-line func-style
const parent = code.parentNode const parent = code.parentNode
const codeId = `hl_code${i}` const codeId = `hl_code${i}`
const btn = document.createElement("button") const btn = document.createElement("button")
const icon = document.createElement("i") // const icon = document.createElement("i")
parent.id = codeId parent.id = codeId
icon.setAttribute("class", "md-icon md-icon--clipboard") // icon.setAttribute("class", "md-icon md-icon--clipboard")
btn.appendChild(icon) // btn.appendChild(icon)
btn.setAttribute("class", "clip-btn") btn.setAttribute("class", "md-clipboard")
btn.setAttribute("data-clipboard-target", btn.setAttribute("data-clipboard-target",
`#${codeId} pre, #${codeId} code`) `#${codeId} pre, #${codeId} code`)
btn.setAttribute("aria-label", "Copy to Clipboard.") btn.setAttribute("aria-label", "Copy to Clipboard.")
new Material.Event.Listener(btn, "mouseleave", e => { // new Material.Event.Listener(btn, "mouseleave", e => {
e.currentTarget.setAttribute("class","clip-btn") // e.currentTarget.classList.remove("md-clipboard__snackbar")
e.currentTarget.setAttribute("aria-label", "Copy to Clipboard.") // e.currentTarget.setAttribute("aria-label", "Copy to Clipboard.")
}).listen() // }).listen()
parent.insertBefore(btn, parent.childNodes[0]) parent.insertBefore(btn, parent.childNodes[0])
i += 1 i += 1
}) })
const cBoard = new Clipboard(".clip-btn") // eslint-disable-line no-undef const cBoard = new Clipboard(".md-clipboard")
cBoard.on("success", e => { cBoard.on("success", e => {
e.clearSelection() e.clearSelection()
e.trigger.setAttribute("aria-label", "Copied!") const foo = document.createElement("span")
e.trigger.setAttribute("class", "clip-btn clip-tip") foo.classList.add("md-clipboard__message")
// foo.textContent = "Copied to clipboard"
foo.setAttribute("aria-label", "Copied to clipboard")
e.trigger.appendChild(foo)
// e.trigger.classList.add("md-clipboard--tip")
}) })
cBoard.on("error", e => { cBoard.on("error", e => {
e.clearSelection() e.clearSelection()
e.trigger.setAttribute("aria-label", "Copy Failed!") e.trigger.setAttribute("aria-label", "Copy Failed!")
e.trigger.setAttribute("class", "clip-btn clip-tip") // e.trigger.classList.add("md-clipboard--tip")
}) })
} }
}).listen() }).listen()

View File

@ -42,6 +42,7 @@
@import "base/typeset"; @import "base/typeset";
@import "layout/base"; @import "layout/base";
@import "layout/clipboard";
@import "layout/content"; @import "layout/content";
@import "layout/header"; @import "layout/header";
@import "layout/footer"; @import "layout/footer";
@ -56,8 +57,6 @@
@import "extensions/footnotes"; @import "extensions/footnotes";
@import "extensions/permalinks"; @import "extensions/permalinks";
@import "clipboardjs/clipboardjs";
@import "extensions/pymdown/arithmatex"; @import "extensions/pymdown/arithmatex";
@import "extensions/pymdown/critic"; @import "extensions/pymdown/critic";
@import "extensions/pymdown/emoji"; @import "extensions/pymdown/emoji";

View File

@ -57,8 +57,7 @@
"arrow_forward": "arrow-forward", "arrow_forward": "arrow-forward",
"menu": "menu", "menu": "menu",
"search": "search", "search": "search",
"school": "home", "school": "home"
"assignment": "clipboard"
) { ) {
&--#{$name}::before { &--#{$name}::before {
content: $ligature; content: $ligature;

View File

@ -230,7 +230,7 @@ kbd {
> code { > code {
display: block; display: block;
margin: 0; margin: 0;
padding: 1rem 1.2rem; padding: 1.05rem 1.2rem;
background-color: transparent; background-color: transparent;
font-size: inherit; font-size: inherit;
box-shadow: none; box-shadow: none;
@ -239,7 +239,7 @@ kbd {
// [mobile -]: Increase padding to match text // [mobile -]: Increase padding to match text
@include break-to-device(mobile) { @include break-to-device(mobile) {
padding: 1rem 1.6rem; padding: 1.05rem 1.6rem;
} }
// Override native scrollbar styles // Override native scrollbar styles

View File

@ -230,7 +230,7 @@ $codehilite-whitespace: transparent;
code { code {
display: block; display: block;
margin: 0; margin: 0;
padding: 1rem 1.2rem 0.8rem; padding: 1.05rem 1.2rem;
background-color: transparent; background-color: transparent;
overflow: auto; overflow: auto;
vertical-align: top; vertical-align: top;
@ -257,9 +257,10 @@ $codehilite-whitespace: transparent;
pre.codehilite { pre.codehilite {
overflow: visible; overflow: visible;
// Actual container with code, overflowing
code { code {
display: block; display: block;
padding: 1rem 1.2rem 0.8rem; padding: 1.05rem 1.2rem;
overflow: auto; overflow: auto;
} }
} }
@ -296,7 +297,7 @@ $codehilite-whitespace: transparent;
// Add spacing to line number container // Add spacing to line number container
.linenodiv { .linenodiv {
padding: 1rem 1.2rem 0.8rem; padding: 1.05rem 1.2rem;
// Stretch the line number container vertically, so it always aligns with // Stretch the line number container vertically, so it always aligns with
// the code container, even when there's a scrollbar. // the code container, even when there's a scrollbar.
@ -342,7 +343,7 @@ $codehilite-whitespace: transparent;
// Actual container with code, overflowing // Actual container with code, overflowing
pre, pre,
code { code {
padding: 1rem 1.6rem 0.8rem; padding: 1.05rem 1.6rem;
} }
} }
} }

View File

@ -20,85 +20,99 @@
/// DEALINGS /// DEALINGS
//// ////
$clip-btn-background: #C4C4C4; // ----------------------------------------------------------------------------
$clip-tip-background: #404040; // Keyframes
// ----------------------------------------------------------------------------
// Show snackbar
@keyframes md-clipboard__snackbar--appear {
0% {
transform: translateX(0.8rem);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Rules // Rules
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
.md-typeset {
// Render muted when hovering over code and // Copy to clipboard
// render fully when hovering over the button. .md-clipboard {
.codehilite { position: absolute;
&:hover { top: 0.6rem;
.clip-btn { right: 0.6rem;
transition: opacity 0.3s; width: 2.8rem;
opacity: 0.4; height: 2.8rem;
border-radius: 0.2rem;
font-size: 1.6rem;
cursor: pointer;
z-index: 1;
// Hack: put everything on the GPU to omit flickering
backface-visibility: hidden;
&:hover { // Icon
transition: opacity 0.1s; &::before {
background-color: $md-color-primary; @extend %md-icon;
opacity: 1;
}
}
}
}
// Clipboard button object. transition:
.clip-btn { color 0.25s,
@include z-depth(2); opacity 0.25s;
color: $md-color-black--light;
content: "content_copy";
opacity: 0.25;
display: inline-block; // Show on container hover
position: absolute; .codehilite:hover &,
top: 0.2rem; .highlight:hover & {
right: 0.2rem;
width: 3.2rem;
height: 3.2rem;
transition: opacity 0.3s;
border-radius: 50%;
background-color: $clip-btn-background;
color: $md-color-white;
cursor: pointer;
opacity: 0;
overflow: visible;
.md-icon--clipboard {
position: relative;
top: 0.1rem;
font-size: 1.8rem;
}
}
// Tooltips for messages when a copy is successful or fails.
// Render it to the left as somtimes it is in a code table which
// cuts off the right, or on the edge of the screen with mobile.
.clip-tip {
&::after {
position: absolute;
top: 0.3rem;
left: 0;
padding: 0.6rem 1rem;
transform: translateX(-112%) translateY(0);
transition: opacity 0.2s;
border-radius: 0.2rem;
background: $clip-tip-background;
color: $md-color-white;
font-size: ms(-1);
font-weight: 700;
white-space: nowrap;
content: attr(aria-label);
opacity: 1; opacity: 1;
visibility: hidden; }
}
// Hovered and active icon
&:hover::before,
&:active::before {
color: $md-color-accent;
}
// Message
&__message {
display: block;
position: absolute;
top: 0;
right: 3.4rem;
padding: 0.6rem 1rem;
animation:
md-clipboard__snackbar--appear
0.25s cubic-bezier(0.4, 0, 0.2, 1);
border-radius: 0.2rem;
background: $md-color-black--light;
color: $md-color-white;
font-size: ms(-1);
white-space: nowrap;
opacity: 1;
// Inject content from ARIA label
&::before {
content: attr(aria-label);
} }
&:hover { // Paint a nice speech bubble
&::after { &::after {
display: block; display: block;
transform: translateX(-110%) translateY(0); position: absolute;
opacity: 0.9; top: 50%;
visibility: visible; right: -0.4rem;
} width: 0;
margin-top: -0.4rem;
border-width: 0.4rem 0 0.4rem 0.4rem;
border-style: solid;
border-color: transparent $md-color-black--light;
content: "";
} }
} }
} }

View File

@ -36,7 +36,7 @@
transition: background-color 0.25s; transition: background-color 0.25s;
background-color: $md-color-primary; background-color: $md-color-primary;
color: $md-color-white; color: $md-color-white;
z-index: 1; z-index: 2;
// Hack: putting the header on the GPU avoids unnecessary repaints // Hack: putting the header on the GPU avoids unnecessary repaints
backface-visibility: hidden; backface-visibility: hidden;

View File

@ -21,7 +21,7 @@
//// ////
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Rules // Keyframes
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Show source facts // Show source facts