Skip to content

Commit 6f7988b

Browse files
author
markzegarelli
authored
Merge pull request #2167 from segmentio/copy-code-samples
one click code-sample copy
2 parents 0906892 + a05c51c commit 6f7988b

File tree

5 files changed

+117
-2
lines changed

5 files changed

+117
-2
lines changed

js/code-copy/index.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import tippy from 'tippy.js'
2+
3+
export default function () {
4+
5+
// get the list of all highlight code blocks
6+
const highlights = document.querySelectorAll("div.highlighter-rouge")
7+
8+
9+
10+
11+
highlights.forEach(div => {
12+
// create the copy button
13+
const copy = document.createElement("button")
14+
copy.innerHTML = "<img src='/docs/images/duplicate.svg' />"
15+
// add the event listener to each click
16+
copy.addEventListener("click", handleCopyClick)
17+
// append the copy button to each code block
18+
div.append(copy)
19+
20+
})
21+
22+
23+
24+
25+
26+
const copyToClipboard = str => {
27+
const el = document.createElement("textarea") // Create a <textarea> element
28+
el.value = str // Set its value to the string that you want copied
29+
el.setAttribute("readonly", "") // Make it readonly to be tamper-proof
30+
el.style.position = "absolute"
31+
el.style.left = "-9999px" // Move outside the screen to make it invisible
32+
document.body.appendChild(el) // Append the <textarea> element to the HTML document
33+
const selected =
34+
document.getSelection().rangeCount > 0 // Check if there is any content selected previously
35+
?
36+
document.getSelection().getRangeAt(0) // Store selection if found
37+
:
38+
false // Mark as false to know no selection existed before
39+
el.select() // Select the <textarea> content
40+
document.execCommand("copy") // Copy - only works as a result of a user action (e.g. click events)
41+
document.body.removeChild(el) // Remove the <textarea> element
42+
if (selected) {
43+
// If a selection existed before copying
44+
document.getSelection().removeAllRanges() // Unselect everything on the HTML document
45+
document.getSelection().addRange(selected) // Restore the original selection
46+
}
47+
}
48+
49+
50+
51+
function handleCopyClick(evt) {
52+
// get the children of the parent element
53+
const {
54+
children
55+
} = evt.target.parentElement.parentElement
56+
// grab the first element (we append the copy button on afterwards, so the first will be the code element)
57+
// destructure the innerText from the code block
58+
const {
59+
innerText
60+
} = Array.from(children)[0]
61+
// copy all of the code to the clipboard
62+
copyToClipboard(innerText)
63+
// alert to show it worked, but you can put any kind of tooltip/popup to notify it worked
64+
const alert = children[1]
65+
alert.classList.add("green")
66+
setTimeout(() => {
67+
alert.classList.remove("green")
68+
}, 700)
69+
}
70+
}

js/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import glightbox from './glightbox'
2222
import autocomplete from './algolia'
2323
import mapTable from './map-table'
2424
import expando from './expando'
25+
import codeCopy from './code-copy'
2526
feedback()
2627
accordion()
2728
accordionGroup()
@@ -44,4 +45,5 @@ tracking()
4445
searchBar()
4546
glightbox()
4647
mapTable()
47-
expando()
48+
expando()
49+
codeCopy()

src/_includes/content/snippet-helper.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{% codeexample %}
22
{% codeexampletab Minified %}
3-
```js
3+
```html
44
<script>
55
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.src="https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};analytics._writeKey="YOUR_WRITE_KEY";analytics.SNIPPET_VERSION="4.15.2";
66
analytics.load("YOUR_WRITE_KEY");

src/_sass/components/_markdown.scss

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
}
147147
div.highlighter-rouge {
148148
margin: 15px auto;
149+
position: relative;
149150
}
150151
table {
151152
margin: 15px auto;
@@ -378,4 +379,43 @@ tr.show {
378379
max-height: 100%;
379380
transition: max-height .5s ease-in-out;
380381
}
382+
381383
}
384+
385+
div.highlighter-rouge {
386+
position: relative;
387+
388+
button {
389+
color: #adb5bd;
390+
box-sizing: border-box;
391+
transition: 0.2s ease-out;
392+
cursor: pointer;
393+
user-select: none;
394+
padding: 8px 10px;
395+
font-size: 0.8em;
396+
position: absolute;
397+
top: 0;
398+
right: 0;
399+
border-radius: 0 0.15rem;
400+
width: 40px;
401+
img {
402+
width: 16px;
403+
margin: 0;
404+
border: none;
405+
border-radius: 0px;
406+
}
407+
img:hover {
408+
filter: invert(65%) sepia(9%) saturate(784%) hue-rotate(192deg) brightness(91%) contrast(87%);
409+
transition: 0.2s ease-out;
410+
}
411+
412+
img:active {
413+
filter: invert(65%) sepia(9%) saturate(784%) hue-rotate(192deg) brightness(91%) contrast(87%);
414+
}
415+
}
416+
417+
.green{
418+
background-color: #BAE5D5;
419+
content: "copied!";
420+
}
421+
}

src/images/duplicate.svg

Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)