| 1 |
/** |
| 2 |
* Provides reusable UI components for the Plugin's administration screens: |
| 3 |
* - inline tabs |
| 4 |
* - copy to clipboard buttons on code blocks |
| 5 |
* |
| 6 |
* @since 3.4.1 |
| 7 |
* |
| 8 |
* @author ConvertKit |
| 9 |
*/ |
| 10 |
|
| 11 |
document.addEventListener('DOMContentLoaded', function () { |
| 12 |
convertKitInlineTabsInit(); |
| 13 |
convertKitCopyButtonsInit(); |
| 14 |
}); |
| 15 |
|
| 16 |
/** |
| 17 |
* Displays the panel belonging to the inline tab that is clicked, hiding all |
| 18 |
* other panels in the same tabbed interface. |
| 19 |
* |
| 20 |
* @since 3.4.1 |
| 21 |
*/ |
| 22 |
function convertKitInlineTabsInit() { |
| 23 |
document.querySelectorAll('.kit-inline-tabs').forEach(function (container) { |
| 24 |
const tabs = container.querySelectorAll('button.kit-inline-tab'); |
| 25 |
const panels = container.querySelectorAll('.kit-inline-tab-panel'); |
| 26 |
|
| 27 |
tabs.forEach(function (tab) { |
| 28 |
tab.addEventListener('click', function () { |
| 29 |
const activeTab = tab.dataset.tab; |
| 30 |
|
| 31 |
// Activate the clicked tab, deactivating all other tabs. |
| 32 |
tabs.forEach(function (item) { |
| 33 |
item.classList.toggle( |
| 34 |
'is-active', |
| 35 |
item.dataset.tab === activeTab |
| 36 |
); |
| 37 |
}); |
| 38 |
|
| 39 |
// Display the clicked tab's panel, hiding all other panels. |
| 40 |
panels.forEach(function (panel) { |
| 41 |
panel.classList.toggle( |
| 42 |
'is-active', |
| 43 |
panel.dataset.tab === activeTab |
| 44 |
); |
| 45 |
}); |
| 46 |
}); |
| 47 |
}); |
| 48 |
}); |
| 49 |
} |
| 50 |
|
| 51 |
/** |
| 52 |
* Copies a code block's contents to the clipboard when its Copy button is clicked. |
| 53 |
* |
| 54 |
* @since 3.4.1 |
| 55 |
*/ |
| 56 |
function convertKitCopyButtonsInit() { |
| 57 |
document |
| 58 |
.querySelectorAll('button.kit-code-copy') |
| 59 |
.forEach(function (button) { |
| 60 |
button.addEventListener('click', function () { |
| 61 |
const code = button.parentNode.querySelector('pre code'); |
| 62 |
|
| 63 |
// Bail if the button isn't in a code block. |
| 64 |
if (!code) { |
| 65 |
return; |
| 66 |
} |
| 67 |
|
| 68 |
convertKitCopyToClipboard(code.textContent, button); |
| 69 |
}); |
| 70 |
}); |
| 71 |
} |
| 72 |
|
| 73 |
/** |
| 74 |
* Copies the given text to the clipboard, updating the button to tell the user |
| 75 |
* whether copying succeeded. |
| 76 |
* |
| 77 |
* @since 3.4.1 |
| 78 |
* |
| 79 |
* @param {string} text Text to copy to the clipboard. |
| 80 |
* @param {Object} button Button element clicked. |
| 81 |
*/ |
| 82 |
function convertKitCopyToClipboard(text, button) { |
| 83 |
// Use the Clipboard API where it's available. It requires a secure context, |
| 84 |
// which isn't guaranteed on e.g. a development site served over HTTP. |
| 85 |
if (navigator.clipboard && window.isSecureContext) { |
| 86 |
navigator.clipboard.writeText(text).then( |
| 87 |
function () { |
| 88 |
convertKitCopyButtonFeedback(button, convertkit_ui.copied); |
| 89 |
}, |
| 90 |
function () { |
| 91 |
convertKitCopyButtonFeedback(button, convertkit_ui.failed); |
| 92 |
} |
| 93 |
); |
| 94 |
return; |
| 95 |
} |
| 96 |
|
| 97 |
// Fall back to copying from a temporary, off screen textarea. |
| 98 |
const textarea = document.createElement('textarea'); |
| 99 |
textarea.value = text; |
| 100 |
textarea.setAttribute('readonly', ''); |
| 101 |
textarea.style.position = 'absolute'; |
| 102 |
textarea.style.left = '-9999px'; |
| 103 |
document.body.appendChild(textarea); |
| 104 |
textarea.select(); |
| 105 |
|
| 106 |
let copied = false; |
| 107 |
try { |
| 108 |
copied = document.execCommand('copy'); |
| 109 |
} catch { |
| 110 |
// Copying isn't supported; the button tells the user to copy manually. |
| 111 |
} |
| 112 |
|
| 113 |
document.body.removeChild(textarea); |
| 114 |
|
| 115 |
convertKitCopyButtonFeedback( |
| 116 |
button, |
| 117 |
copied ? convertkit_ui.copied : convertkit_ui.failed |
| 118 |
); |
| 119 |
} |
| 120 |
|
| 121 |
/** |
| 122 |
* Displays the given label on the button for a couple of seconds, before |
| 123 |
* restoring the button's original label. |
| 124 |
* |
| 125 |
* @since 3.4.1 |
| 126 |
* |
| 127 |
* @param {Object} button Button element clicked. |
| 128 |
* @param {string} label Label to display on the button. |
| 129 |
*/ |
| 130 |
function convertKitCopyButtonFeedback(button, label) { |
| 131 |
button.textContent = label; |
| 132 |
|
| 133 |
setTimeout(function () { |
| 134 |
button.textContent = convertkit_ui.copy; |
| 135 |
}, 2000); |
| 136 |
} |
| 137 |
|