OLD | NEW |
(Empty) | |
| 1 (function() { |
| 2 |
| 3 if (typeof self === 'undefined' || !self.Prism || !self.document) { |
| 4 return; |
| 5 } |
| 6 |
| 7 /** |
| 8 * Returns the absolute X, Y offsets for an element |
| 9 * @param {HTMLElement} element |
| 10 * @returns {{top: number, right: number, bottom: number, left: number}} |
| 11 */ |
| 12 var getOffset = function (element) { |
| 13 var left = 0, top = 0, el = element; |
| 14 |
| 15 if (el.parentNode) { |
| 16 do { |
| 17 left += el.offsetLeft; |
| 18 top += el.offsetTop; |
| 19 } while ((el = el.offsetParent) && el.nodeType < 9); |
| 20 |
| 21 el = element; |
| 22 |
| 23 do { |
| 24 left -= el.scrollLeft; |
| 25 top -= el.scrollTop; |
| 26 } while ((el = el.parentNode) && !/body/i.test(el.nodeNa
me)); |
| 27 } |
| 28 |
| 29 return { |
| 30 top: top, |
| 31 right: innerWidth - left - element.offsetWidth, |
| 32 bottom: innerHeight - top - element.offsetHeight, |
| 33 left: left |
| 34 }; |
| 35 }; |
| 36 |
| 37 var tokenRegexp = /(?:^|\s)token(?=$|\s)/; |
| 38 var activeRegexp = /(?:^|\s)active(?=$|\s)/g; |
| 39 var flippedRegexp = /(?:^|\s)flipped(?=$|\s)/g; |
| 40 |
| 41 /** |
| 42 * Previewer constructor |
| 43 * @param {string} type Unique previewer type |
| 44 * @param {function} updater Function that will be called on mouseover. |
| 45 * @param {string[]|string=} supportedLanguages Aliases of the languages
this previewer must be enabled for. Defaults to "*", all languages. |
| 46 * @constructor |
| 47 */ |
| 48 var Previewer = function (type, updater, supportedLanguages, initializer
) { |
| 49 this._elt = null; |
| 50 this._type = type; |
| 51 this._clsRegexp = RegExp('(?:^|\\s)' + type + '(?=$|\\s)'); |
| 52 this._token = null; |
| 53 this.updater = updater; |
| 54 this._mouseout = this.mouseout.bind(this); |
| 55 this.initializer = initializer; |
| 56 |
| 57 var self = this; |
| 58 |
| 59 if (!supportedLanguages) { |
| 60 supportedLanguages = ['*']; |
| 61 } |
| 62 if (Prism.util.type(supportedLanguages) !== 'Array') { |
| 63 supportedLanguages = [supportedLanguages]; |
| 64 } |
| 65 supportedLanguages.forEach(function (lang) { |
| 66 if (typeof lang !== 'string') { |
| 67 lang = lang.lang; |
| 68 } |
| 69 if (!Previewer.byLanguages[lang]) { |
| 70 Previewer.byLanguages[lang] = []; |
| 71 } |
| 72 if (Previewer.byLanguages[lang].indexOf(self) < 0) { |
| 73 Previewer.byLanguages[lang].push(self); |
| 74 } |
| 75 }); |
| 76 Previewer.byType[type] = this; |
| 77 }; |
| 78 |
| 79 /** |
| 80 * Creates the HTML element for the previewer. |
| 81 */ |
| 82 Previewer.prototype.init = function () { |
| 83 if (this._elt) { |
| 84 return; |
| 85 } |
| 86 this._elt = document.createElement('div'); |
| 87 this._elt.className = 'prism-previewer prism-previewer-' + this.
_type; |
| 88 document.body.appendChild(this._elt); |
| 89 if(this.initializer) { |
| 90 this.initializer(); |
| 91 } |
| 92 }; |
| 93 |
| 94 /** |
| 95 * Checks the class name of each hovered element |
| 96 * @param token |
| 97 */ |
| 98 Previewer.prototype.check = function (token) { |
| 99 do { |
| 100 if (tokenRegexp.test(token.className) && this._clsRegexp
.test(token.className)) { |
| 101 break; |
| 102 } |
| 103 } while(token = token.parentNode); |
| 104 |
| 105 if (token && token !== this._token) { |
| 106 this._token = token; |
| 107 this.show(); |
| 108 } |
| 109 }; |
| 110 |
| 111 /** |
| 112 * Called on mouseout |
| 113 */ |
| 114 Previewer.prototype.mouseout = function() { |
| 115 this._token.removeEventListener('mouseout', this._mouseout, fals
e); |
| 116 this._token = null; |
| 117 this.hide(); |
| 118 }; |
| 119 |
| 120 /** |
| 121 * Shows the previewer positioned properly for the current token. |
| 122 */ |
| 123 Previewer.prototype.show = function () { |
| 124 if (!this._elt) { |
| 125 this.init(); |
| 126 } |
| 127 if (!this._token) { |
| 128 return; |
| 129 } |
| 130 |
| 131 if (this.updater.call(this._elt, this._token.textContent)) { |
| 132 this._token.addEventListener('mouseout', this._mouseout,
false); |
| 133 |
| 134 var offset = getOffset(this._token); |
| 135 this._elt.className += ' active'; |
| 136 |
| 137 if (offset.top - this._elt.offsetHeight > 0) { |
| 138 this._elt.className = this._elt.className.replac
e(flippedRegexp, ''); |
| 139 this._elt.style.top = offset.top + 'px'; |
| 140 this._elt.style.bottom = ''; |
| 141 } else { |
| 142 this._elt.className += ' flipped'; |
| 143 this._elt.style.bottom = offset.bottom + 'px'; |
| 144 this._elt.style.top = ''; |
| 145 } |
| 146 |
| 147 this._elt.style.left = offset.left + Math.min(200, this.
_token.offsetWidth / 2) + 'px'; |
| 148 } else { |
| 149 this.hide(); |
| 150 } |
| 151 }; |
| 152 |
| 153 /** |
| 154 * Hides the previewer. |
| 155 */ |
| 156 Previewer.prototype.hide = function () { |
| 157 this._elt.className = this._elt.className.replace(activeRegexp,
''); |
| 158 }; |
| 159 |
| 160 /** |
| 161 * Map of all registered previewers by language |
| 162 * @type {{}} |
| 163 */ |
| 164 Previewer.byLanguages = {}; |
| 165 |
| 166 /** |
| 167 * Map of all registered previewers by type |
| 168 * @type {{}} |
| 169 */ |
| 170 Previewer.byType = {}; |
| 171 |
| 172 /** |
| 173 * Initializes the mouseover event on the code block. |
| 174 * @param {HTMLElement} elt The code block (env.element) |
| 175 * @param {string} lang The language (env.language) |
| 176 */ |
| 177 Previewer.initEvents = function (elt, lang) { |
| 178 var previewers = []; |
| 179 if (Previewer.byLanguages[lang]) { |
| 180 previewers = previewers.concat(Previewer.byLanguages[lan
g]); |
| 181 } |
| 182 if (Previewer.byLanguages['*']) { |
| 183 previewers = previewers.concat(Previewer.byLanguages['*'
]); |
| 184 } |
| 185 elt.addEventListener('mouseover', function (e) { |
| 186 var target = e.target; |
| 187 previewers.forEach(function (previewer) { |
| 188 previewer.check(target); |
| 189 }); |
| 190 }, false); |
| 191 }; |
| 192 Prism.plugins.Previewer = Previewer; |
| 193 |
| 194 // Initialize the previewers only when needed |
| 195 Prism.hooks.add('after-highlight', function (env) { |
| 196 if(Previewer.byLanguages['*'] || Previewer.byLanguages[env.langu
age]) { |
| 197 Previewer.initEvents(env.element, env.language); |
| 198 } |
| 199 }); |
| 200 |
| 201 }()); |
OLD | NEW |