From: Bryan Braun Date: Fri, 15 May 2015 04:37:07 +0000 (-0400) Subject: Update Anchor.js and port over the existing styles. X-Git-Tag: v3.3.5~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dec2faec3d1ebdf0f72d5814e570ebc453346cde;p=thirdparty%2Fbootstrap.git Update Anchor.js and port over the existing styles. Anchor.js 1.0.0 drops the need to use anchor.css, so we remove it from the codebase and move any leftover styles over to docs.css. Closes #16488 by merging it. --- diff --git a/Gruntfile.js b/Gruntfile.js index f6cae30e31..32cc83fdfa 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -195,7 +195,7 @@ module.exports = function (grunt) { src: 'dist/css/<%= pkg.name %>-theme.css' }, docs: { - src: ['docs/assets/css/anchor.css', 'docs/assets/css/src/docs.css'] + src: ['docs/assets/css/src/docs.css'] }, examples: { expand: true, @@ -244,9 +244,7 @@ module.exports = function (grunt) { docs: { src: [ 'docs/assets/css/src/pygments-manni.css', - 'docs/assets/css/src/anchor.css', 'docs/assets/css/src/docs.css' - ], dest: 'docs/assets/css/docs.min.css' } diff --git a/docs/_includes/header.html b/docs/_includes/header.html index 06c4ab02fe..176f45fc01 100644 --- a/docs/_includes/header.html +++ b/docs/_includes/header.html @@ -33,7 +33,6 @@ {% else %} - {% endif %} diff --git a/docs/assets/css/src/anchor.css b/docs/assets/css/src/anchor.css deleted file mode 100644 index 69c6f5dcd1..0000000000 --- a/docs/assets/css/src/anchor.css +++ /dev/null @@ -1,60 +0,0 @@ -/** -* Store the link icon as a base64 embedded icon font. -*/ -@font-face { - font-family: 'anchorjs-link'; - src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg6v8yoAAAC8AAAAYGNtYXDL8RqdAAABHAAAADxnYXNwAAAAEAAAAVgAAAAIZ2x5Zkm2oNUAAAFgAAABWGhlYWQAHd4cAAACuAAAADZoaGVhB3sECwAAAvAAAAAkaG10eAYAAEcAAAMUAAAADGxvY2EACgCsAAADIAAAAAhtYXhwAAYAcAAAAygAAAAgbmFtZUQXtNYAAANIAAABOXBvc3QAAwAAAAAEhAAAACAAAwQAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAACDmAAPA/8D/wAPAAEAAAAAAAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEACgAAAAGAAQAAQACACDmAP//AAAAIOYA////4RoCAAEAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAIARwAHA7kDeQA2AG0AAAEnLgEiBg8BDgEUFh8BHgMXNy4DLwEuATQ2PwE+ATIWHwEeARQGDwEeAxU3PgE0JicBLgMnBx4DHwEeARQGDwEOASImLwEuATQ2PwEuAzUHDgEUFh8BHgEyNj8BPgE0Ji8BA7kEI1ldWiPaIyQkIwQDBgYGBFAEBwYHAwQTExMT2xMwMjETBBMTExNjBwkGA5gkIyMk/r4DBgYGBFAEBwYHAwQTExMT2xMwMjETBBMTExNjBwkGA5gkIyMkBCNZXVoj2iMkJCMEA3UEJCMjJNojWV1aIwQDBgUFA1ACBQUFAwQUMDIxE9oTExMTBBMxMjATYxAhISIRmSNaXVkj/sYDBgUFA1ACBQUFAwQUMDIxE9oTExMTBBMxMjATYxAhISIRmSNaXVkjBCQjIyTaI1ldWiMEAAEAAAABAABR/4xQXw889QALBAAAAAAAzqNM0wAAAADOo0zTAAAAAAO5A3kAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAABHA7kAAQAAAAAAAAAAAAAAAAAAAAMAAAAAAgAAAAQAAEcAAAAAAAoArAABAAAAAwBuAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADgAAAAEAAAAAAAIADgBHAAEAAAAAAAMADgAkAAEAAAAAAAQADgBVAAEAAAAAAAUAFgAOAAEAAAAAAAYABwAyAAEAAAAAAAoAKABjAAMAAQQJAAEADgAAAAMAAQQJAAIADgBHAAMAAQQJAAMADgAkAAMAAQQJAAQADgBVAAMAAQQJAAUAFgAOAAMAAQQJAAYADgA5AAMAAQQJAAoAKABjAGkAYwBvAG0AbwBvAG4AVgBlAHIAcwBpAG8AbgAgADAALgAwAGkAYwBvAG0AbwBvAG5pY29tb29uAGkAYwBvAG0AbwBvAG4AUgBlAGcAdQBsAGEAcgBpAGMAbwBtAG8AbwBuAEcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype'), - url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAATwAAsAAAAABKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDq/zKmNtYXAAAAFoAAAAPAAAADzL8RqdZ2FzcAAAAaQAAAAIAAAACAAAABBnbHlmAAABrAAAAVgAAAFYSbag1WhlYWQAAAMEAAAANgAAADYAHd4caGhlYQAAAzwAAAAkAAAAJAd7BAtobXR4AAADYAAAAAwAAAAMBgAAR2xvY2EAAANsAAAACAAAAAgACgCsbWF4cAAAA3QAAAAgAAAAIAAGAHBuYW1lAAADlAAAATkAAAE5RBe01nBvc3QAAATQAAAAIAAAACAAAwAAAAMEAAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAg5gADwP/A/8ADwABAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAgAAAAMAAAAUAAMAAQAAABQABAAoAAAABgAEAAEAAgAg5gD//wAAACDmAP///+EaAgABAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAACAEcABwO5A3kANgBtAAABJy4BIgYPAQ4BFBYfAR4DFzcuAy8BLgE0Nj8BPgEyFh8BHgEUBg8BHgMVNz4BNCYnAS4DJwceAx8BHgEUBg8BDgEiJi8BLgE0Nj8BLgM1Bw4BFBYfAR4BMjY/AT4BNCYvAQO5BCNZXVoj2iMkJCMEAwYGBgRQBAcGBwMEExMTE9sTMDIxEwQTExMTYwcJBgOYJCMjJP6+AwYGBgRQBAcGBwMEExMTE9sTMDIxEwQTExMTYwcJBgOYJCMjJAQjWV1aI9ojJCQjBAN1BCQjIyTaI1ldWiMEAwYFBQNQAgUFBQMEFDAyMRPaExMTEwQTMTIwE2MQISEiEZkjWl1ZI/7GAwYFBQNQAgUFBQMEFDAyMRPaExMTEwQTMTIwE2MQISEiEZkjWl1ZIwQkIyMk2iNZXVojBAABAAAAAQAAUf+MUF8PPPUACwQAAAAAAM6jTNMAAAAAzqNM0wAAAAADuQN5AAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAARwO5AAEAAAAAAAAAAAAAAAAAAAADAAAAAAIAAAAEAABHAAAAAAAKAKwAAQAAAAMAbgACAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAA4AAAABAAAAAAACAA4ARwABAAAAAAADAA4AJAABAAAAAAAEAA4AVQABAAAAAAAFABYADgABAAAAAAAGAAcAMgABAAAAAAAKACgAYwADAAEECQABAA4AAAADAAEECQACAA4ARwADAAEECQADAA4AJAADAAEECQAEAA4AVQADAAEECQAFABYADgADAAEECQAGAA4AOQADAAEECQAKACgAYwBpAGMAbwBtAG8AbwBuAFYAZQByAHMAaQBvAG4AIAAwAC4AMABpAGMAbwBtAG8AbwBuaWNvbW9vbgBpAGMAbwBtAG8AbwBuAFIAZQBnAHUAbABhAHIAaQBjAG8AbQBvAG8AbgBHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4AAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('woff'); - font-weight: normal; - font-style: normal; -} - -.anchorjs-icon { - font-family: 'anchorjs-link'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Icon Rendering */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -/** -* Link placement and hover behavior. -*/ -.anchorjs-link { - float: left; - width: 1em; - height: 1em; - margin-left: -1.2em; - opacity: 0; - color: inherit; - text-align: center; -} - -@media (max-width: 480px) { - .anchorjs-link { - display: none; - } -} - -*:hover > .anchorjs-link, -.anchorjs-link:focus { - opacity: .75; - transition: color .16s linear; -} -*:hover > .anchorjs-link:hover { - opacity: 1; - text-decoration: none; -} -.anchorjs-icon { - font-size: 60%; - vertical-align: .2em; -} -.anchorjs-icon:before { - content: "\e600"; -} diff --git a/docs/assets/css/src/docs.css b/docs/assets/css/src/docs.css index 2bdaaa0d81..28d92d73d4 100644 --- a/docs/assets/css/src/docs.css +++ b/docs/assets/css/src/docs.css @@ -1595,6 +1595,31 @@ h1[id] { } } +/* + * AnchorJS Styles + */ +.anchorjs-link { + color: inherit; +} + +@media (max-width: 480px) { + .anchorjs-link { + display: none; + } +} + +*:hover > .anchorjs-link { + opacity: .75; + -webkit-transition: color .16s linear; + -o-transition: color .16s linear; + transition: color .16s linear; +} + +*:hover > .anchorjs-link:hover, +.anchorjs-link:focus { + text-decoration: none; + opacity: 1; +} /* * Miscellaneous diff --git a/docs/assets/js/src/application.js b/docs/assets/js/src/application.js index 35f39f6f03..51f42cd05a 100644 --- a/docs/assets/js/src/application.js +++ b/docs/assets/js/src/application.js @@ -9,7 +9,7 @@ * details, see http://creativecommons.org/licenses/by/3.0/. */ -/* global ZeroClipboard, addAnchors */ +/* global ZeroClipboard, anchors */ !function ($) { 'use strict'; @@ -178,5 +178,6 @@ ;(function () { 'use strict'; - addAnchors('.bs-docs-section > h1, .bs-docs-section > h2, .bs-docs-section > h3, .bs-docs-section > h4, .bs-docs-section > h5') + anchors.options.placement = 'left'; + anchors.add('.bs-docs-section > h1, .bs-docs-section > h2, .bs-docs-section > h3, .bs-docs-section > h4, .bs-docs-section > h5') })(); diff --git a/docs/assets/js/vendor/anchor.js b/docs/assets/js/vendor/anchor.js index e5ddfa7256..248821fc4a 100644 --- a/docs/assets/js/vendor/anchor.js +++ b/docs/assets/js/vendor/anchor.js @@ -1,48 +1,196 @@ /*! - * AnchorJS - v0.1.0 - 2014-08-17 + * AnchorJS - v1.0.1 - 2015-05-15 * https://github.com/bryanbraun/anchorjs - * Copyright (c) 2014 Bryan Braun; Licensed MIT + * Copyright (c) 2015 Bryan Braun; Licensed MIT */ -function addAnchors(selector) { +function AnchorJS(options) { 'use strict'; - // Sensible default selector, if none is provided. - if (!selector) { - selector = 'h1, h2, h3, h4, h5, h6'; - } else if (typeof selector !== 'string') { - throw new Error('AnchorJS accepts only strings; you used a ' + typeof selector); - } + this.options = options || {}; - // Select any elements that match the provided selector. - var elements = document.querySelectorAll(selector); + this._applyRemainingDefaultOptions = function(opts) { + this.options.icon = this.options.hasOwnProperty('icon') ? opts.icon : ''; // Accepts characters (and also URLs?), like '#', '¶', '❡', or '§'. + this.options.visible = this.options.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always' + this.options.placement = this.options.hasOwnProperty('placement') ? opts.placement : 'right'; // Also accepts 'left' + this.options.class = this.options.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name. + }; - // Loop through the selected elements. - for (var i = 0; i < elements.length; i++) { - var elementID; + this._applyRemainingDefaultOptions(options); - if (elements[i].hasAttribute('id')) { - elementID = elements[i].getAttribute('id'); - } else { - // We need to create an ID on our element. First, we find which text selection method is available to the browser. - var textMethod = document.body.textContent ? 'textContent' : 'innerText'; + this.add = function(selector) { + var elements, + elsWithIds, + idList, + elementID, + i, + roughText, + tidyText, + index, + count, + newTidyText, + readableID, + anchor, + div, + anchorNodes; + + this._applyRemainingDefaultOptions(this.options); + + // Provide a sensible default selector, if none is given. + if (!selector) { + selector = 'h1, h2, h3, h4, h5, h6'; + } else if (typeof selector !== 'string') { + throw new Error('The selector provided to AnchorJS was invalid.'); + } + + elements = document.querySelectorAll(selector); + if (elements.length === 0) { + return false; + } + + this._addBaselineStyles(); + + // We produce a list of existing IDs so we don't generate a duplicate. + elsWithIds = document.querySelectorAll('[id]'); + idList = [].map.call(elsWithIds, function assign(el) { + return el.id; + }); + + for (i = 0; i < elements.length; i++) { + + if (elements[i].hasAttribute('id')) { + elementID = elements[i].getAttribute('id'); + } else { + roughText = elements[i].textContent; + + // Refine it so it makes a good ID. Strip out non-safe characters, replace + // spaces with hyphens, truncate to 32 characters, and make toLowerCase. + // + // Example string: // '⚡⚡⚡ Unicode icons are cool--but don't belong in a URL.' + tidyText = roughText.replace(/[^\w\s-]/gi, '') // ' Unicode icons are cool--but dont belong in a URL' + .replace(/\s+/g, '-') // '-Unicode-icons-are-cool--but-dont-belong-in-a-URL' + .replace(/-{2,}/g, '-') // '-Unicode-icons-are-cool-but-dont-belong-in-a-URL' + .substring(0, 32) // '-Unicode-icons-are-cool-but-dont' + .replace(/^-+|-+$/gm, '') // 'Unicode-icons-are-cool-but-dont' + .toLowerCase(); // 'unicode-icons-are-cool-but-dont' + + // Compare our generated ID to existing IDs (and increment it if needed) + // before we add it to the page. + newTidyText = tidyText; + count = 0; + do { + if (index !== undefined) { + newTidyText = tidyText + '-' + count; + } + // .indexOf is supported in IE9+. + index = idList.indexOf(newTidyText); + count += 1; + } while (index !== -1); + index = undefined; + idList.push(newTidyText); + + // Assign it to our element. + // Currently the setAttribute element is only supported in IE9 and above. + elements[i].setAttribute('id', newTidyText); + + elementID = newTidyText; + } - // Get the text inside our element - var roughText = elements[i][textMethod]; + readableID = elementID.replace(/-/g, ' '); - // Refine it so it makes a good ID. Makes all lowercase and hyphen separated. - // Ex. Hello World > hello-world - var tidyText = roughText.replace(/\s+/g, '-').toLowerCase(); + anchor = ''; - // Assign it to our element. - // Currently the setAttribute element is only supported in IE9 and above. - elements[i].setAttribute('id', tidyText); + div = document.createElement('div'); + div.innerHTML = anchor; + anchorNodes = div.childNodes; - // Grab it for use in our anchor. - elementID = tidyText; + if (this.options.visible === 'always') { + anchorNodes[0].style.opacity = '1'; + } + + if (this.options.icon === '') { + anchorNodes[0].style.fontFamily = 'anchorjs-icons'; + anchorNodes[0].style.fontStyle = 'normal'; + anchorNodes[0].style.fontVariant = 'normal'; + anchorNodes[0].style.fontWeight = 'normal'; + } + + if (this.options.placement === 'left') { + anchorNodes[0].style.position = 'absolute'; + anchorNodes[0].style.marginLeft = '-1em'; + anchorNodes[0].style.paddingRight = '0.5em'; + elements[i].insertBefore(anchorNodes[0], elements[i].firstChild); + } else { // if the option provided is `right` (or anything else). + anchorNodes[0].style.paddingLeft = '0.375em'; + elements[i].appendChild(anchorNodes[0]); + } + } + + return this; + }; + + this.remove = function(selector) { + var domAnchor, + elements = document.querySelectorAll(selector); + for (var i = 0; i < elements.length; i++) { + domAnchor = elements[i].querySelector('.anchorjs-link'); + if (domAnchor) { + elements[i].removeChild(domAnchor); + } + } + return this; + }; + + this._addBaselineStyles = function() { + // We don't want to add global baseline styles if they've been added before. + if (document.head.querySelector('style.anchorjs') !== null) { + return; } - var anchor = ''; - elements[i].innerHTML += anchor; - } + var style = document.createElement('style'), + linkRule = + ' .anchorjs-link {' + + ' opacity: 0;' + + ' text-decoration: none;' + + ' -webkit-font-smoothing: antialiased;' + + ' -moz-osx-font-smoothing: grayscale;' + + ' }', + hoverRule = + ' *:hover > .anchorjs-link,' + + ' .anchorjs-link:focus {' + + ' opacity: 1;' + + ' }', + anchorjsLinkFontFace = + ' @font-face {' + + ' font-family: "anchorjs-icons";' + + ' font-style: normal;' + + ' font-weight: normal;' + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above + ' src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBTUAAAC8AAAAYGNtYXAWi9QdAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zgq29TcAAAF4AAABNGhlYWQEZM3pAAACrAAAADZoaGVhBhUDxgAAAuQAAAAkaG10eASAADEAAAMIAAAAFGxvY2EAKACuAAADHAAAAAxtYXhwAAgAVwAAAygAAAAgbmFtZQ5yJ3cAAANIAAAB2nBvc3QAAwAAAAAFJAAAACAAAwJAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpywPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6cv//f//AAAAAAAg6cv//f//AAH/4xY5AAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAACADEARAJTAsAAKwBUAAABIiYnJjQ/AT4BMzIWFxYUDwEGIicmND8BNjQnLgEjIgYPAQYUFxYUBw4BIwciJicmND8BNjIXFhQPAQYUFx4BMzI2PwE2NCcmNDc2MhcWFA8BDgEjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAEAAAABAACiToc1Xw889QALBAAAAAAA0XnFFgAAAADRecUWAAAAAAJTAsAAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAAAlMAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAACAAAAAoAAMQAAAAAACgAUAB4AmgABAAAABQBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADgAAAAEAAAAAAAIABwCfAAEAAAAAAAMADgBLAAEAAAAAAAQADgC0AAEAAAAAAAUACwAqAAEAAAAAAAYADgB1AAEAAAAAAAoAGgDeAAMAAQQJAAEAHAAOAAMAAQQJAAIADgCmAAMAAQQJAAMAHABZAAMAAQQJAAQAHADCAAMAAQQJAAUAFgA1AAMAAQQJAAYAHACDAAMAAQQJAAoANAD4YW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzUmVndWxhcgBSAGUAZwB1AGwAYQByYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format("truetype");' + + ' }', + pseudoElContent = + ' [data-anchorjs-icon]::after {' + + ' content: attr(data-anchorjs-icon);' + + ' }', + firstStyleEl; + + style.className = 'anchorjs'; + style.appendChild(document.createTextNode('')); // Necessary for Webkit. + + // We place it in the head with the other style tags, if possible, so as to + // not look out of place. We insert before the others so these styles can be + // overridden if necessary. + firstStyleEl = document.head.querySelector('[rel="stylesheet"], style'); + if (firstStyleEl === undefined) { + document.head.appendChild(style); + } else { + document.head.insertBefore(style, firstStyleEl); + } + + style.sheet.insertRule(linkRule, style.sheet.cssRules.length); + style.sheet.insertRule(hoverRule, style.sheet.cssRules.length); + style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length); + style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length); + }; } + +var anchors = new AnchorJS();