diff --git a/plugins/toolbar/prism-toolbar.css b/plugins/toolbar/prism-toolbar.css index 2d0857178f..137284b9ef 100644 --- a/plugins/toolbar/prism-toolbar.css +++ b/plugins/toolbar/prism-toolbar.css @@ -2,7 +2,16 @@ div.code-toolbar { position: relative; } -div.code-toolbar > .toolbar { +div.code-toolbar > div.toolbar-positioner { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 0; + overflow: visible; +} + +div.toolbar-positioner > .toolbar { position: absolute; top: .3em; right: .2em; @@ -10,25 +19,25 @@ div.code-toolbar > .toolbar { opacity: 0; } -div.code-toolbar:hover > .toolbar { +div.code-toolbar:hover > div.toolbar-positioner > .toolbar { opacity: 1; } /* Separate line b/c rules are thrown out if selector is invalid. IE11 and old Edge versions don't support :focus-within. */ -div.code-toolbar:focus-within > .toolbar { +div.code-toolbar:focus-within > div.toolbar-positioner > .toolbar { opacity: 1; } -div.code-toolbar > .toolbar .toolbar-item { +div.toolbar-positioner > .toolbar .toolbar-item { display: inline-block; } -div.code-toolbar > .toolbar a { +div.toolbar-positioner > .toolbar a { cursor: pointer; } -div.code-toolbar > .toolbar button { +div.toolbar-positioner > .toolbar button { background: none; border: 0; color: inherit; @@ -41,9 +50,9 @@ div.code-toolbar > .toolbar button { -ms-user-select: none; } -div.code-toolbar > .toolbar a, -div.code-toolbar > .toolbar button, -div.code-toolbar > .toolbar span { +div.toolbar-positioner > .toolbar a, +div.toolbar-positioner > .toolbar button, +div.toolbar-positioner > .toolbar span { color: #bbb; font-size: .8em; padding: 0 .5em; @@ -53,12 +62,12 @@ div.code-toolbar > .toolbar span { border-radius: .5em; } -div.code-toolbar > .toolbar a:hover, -div.code-toolbar > .toolbar a:focus, -div.code-toolbar > .toolbar button:hover, -div.code-toolbar > .toolbar button:focus, -div.code-toolbar > .toolbar span:hover, -div.code-toolbar > .toolbar span:focus { +div.toolbar-positioner > .toolbar a:hover, +div.toolbar-positioner > .toolbar a:focus, +div.toolbar-positioner > .toolbar button:hover, +div.toolbar-positioner > .toolbar button:focus, +div.toolbar-positioner > .toolbar span:hover, +div.toolbar-positioner > .toolbar span:focus { color: inherit; text-decoration: none; } diff --git a/plugins/toolbar/prism-toolbar.js b/plugins/toolbar/prism-toolbar.js index 60be9ce4ba..c711fcc2dc 100644 --- a/plugins/toolbar/prism-toolbar.js +++ b/plugins/toolbar/prism-toolbar.js @@ -7,7 +7,25 @@ var map = {}; var noop = function() {}; - Prism.plugins.toolbar = {}; + Prism.plugins.toolbar = { + registerButton: registerButton, + hook: hook, + + /** + * Adjusts the layout of the toolbar of the given `pre` element. + * + * @param {HTMLElement} pre + */ + resize: function (pre) { + if (!pre || !/pre/i.test(pre.nodeName)) { + return; + } + var toolbar = pre.parentElement; + if (toolbar && toolbar.classList.contains('code-toolbar')) { + refreshLayout(toolbar); + } + } + }; /** * @typedef ButtonOptions @@ -23,7 +41,7 @@ * @param {string} key * @param {ButtonOptions|Function} opts */ - var registerButton = Prism.plugins.toolbar.registerButton = function (key, opts) { + function registerButton(key, opts) { var callback; if (typeof opts === 'function') { @@ -89,8 +107,9 @@ * * @param env */ - var hook = Prism.plugins.toolbar.hook = function (env) { + function hook(env) { // Check if inline or actual code block (credit to line-numbers plugin) + /** @type {HTMLPreElement} */ var pre = env.element.parentNode; if (!pre || !/pre/i.test(pre.nodeName)) { return; @@ -107,6 +126,12 @@ pre.parentNode.insertBefore(wrapper, pre); wrapper.appendChild(pre); + // Additional wrapper to align the toolbar properly + var toolbarPositioner = document.createElement('div'); + toolbarPositioner.classList.add('toolbar-positioner'); + wrapper.appendChild(toolbarPositioner); + + // Setup the toolbar var toolbar = document.createElement('div'); toolbar.classList.add('toolbar'); @@ -135,9 +160,33 @@ }); // Add our toolbar to the currently created wrapper of
 tag
-		wrapper.appendChild(toolbar);
+		toolbarPositioner.appendChild(toolbar);
+		refreshLayout(wrapper);
 	};
 
+
+	/**
+	 * This will adjust the width of the toolbar positioner on size changes.
+	 *
+	 * @param {HTMLElement} codeToolbar
+	 */
+	function refreshLayout(codeToolbar) {
+		/** @type {HTMLPreElement} */
+		var pre = codeToolbar.querySelector('div.code-toolbar > pre');
+		/** @type {HTMLDivElement} */
+		var toolbarWrapperElement = codeToolbar.querySelector('div.code-toolbar > div.toolbar-positioner');
+		if (toolbarWrapperElement) {
+			toolbarWrapperElement.style.marginRight = (codeToolbar.clientWidth - pre.clientWidth) + 'px';
+		}
+	}
+	window.addEventListener('resize', function () {
+		/** @type {NodeListOf} */
+		var codeToolbars = document.querySelectorAll('div.code-toolbar');
+		for (var i = 0; i < codeToolbars.length; i++) {
+			refreshLayout(codeToolbars[i]);
+		}
+	});
+
 	registerButton('label', function(env) {
 		var pre = env.element.parentNode;
 		if (!pre || !/pre/i.test(pre.nodeName)) {
diff --git a/plugins/toolbar/prism-toolbar.min.js b/plugins/toolbar/prism-toolbar.min.js
index e692394036..62d78cd628 100644
--- a/plugins/toolbar/prism-toolbar.min.js
+++ b/plugins/toolbar/prism-toolbar.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var i=[],l={},c=function(){};Prism.plugins.toolbar={};var e=Prism.plugins.toolbar.registerButton=function(e,n){var t;t="function"==typeof n?n:function(e){var t;return"function"==typeof n.onClick?((t=document.createElement("button")).type="button",t.addEventListener("click",function(){n.onClick.call(this,e)})):"string"==typeof n.url?(t=document.createElement("a")).href=n.url:t=document.createElement("span"),n.className&&t.classList.add(n.className),t.textContent=n.text,t},e in l?console.warn('There is a button with the key "'+e+'" registered already.'):i.push(l[e]=t)},t=Prism.plugins.toolbar.hook=function(a){var e=a.element.parentNode;if(e&&/pre/i.test(e.nodeName)&&!e.parentNode.classList.contains("code-toolbar")){var t=document.createElement("div");t.classList.add("code-toolbar"),e.parentNode.insertBefore(t,e),t.appendChild(e);var r=document.createElement("div");r.classList.add("toolbar");var n=i,o=function(e){for(;e;){var t=e.getAttribute("data-toolbar-order");if(null!=t)return(t=t.trim()).length?t.split(/\s*,\s*/g):[];e=e.parentElement}}(a.element);o&&(n=o.map(function(e){return l[e]||c})),n.forEach(function(e){var t=e(a);if(t){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(t),r.appendChild(n)}}),t.appendChild(r)}};e("label",function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-label")){var n,a,r=t.getAttribute("data-label");try{a=document.querySelector("template#"+r)}catch(e){}return a?n=a.content:(t.hasAttribute("data-url")?(n=document.createElement("a")).href=t.getAttribute("data-url"):n=document.createElement("span"),n.textContent=r),n}}),Prism.hooks.add("complete",t)}}();
\ No newline at end of file
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var l=[],d={},c=function(){};Prism.plugins.toolbar={registerButton:e,hook:t,resize:function(e){if(e&&/pre/i.test(e.nodeName)){var t=e.parentElement;t&&t.classList.contains("code-toolbar")&&s(t)}}},window.addEventListener("resize",function(){for(var e=document.querySelectorAll("div.code-toolbar"),t=0;t pre"),n=e.querySelector("div.code-toolbar > div.toolbar-positioner");n&&(n.style.marginRight=e.clientWidth-t.clientWidth+"px")}}();
\ No newline at end of file