Skip to content

Instantly share code, notes, and snippets.

@jrf0110
Last active January 28, 2017 06:57
Show Gist options
  • Save jrf0110/ac5add0e2b73dd527bf33b460bdf754c to your computer and use it in GitHub Desktop.
Save jrf0110/ac5add0e2b73dd527bf33b460bdf754c to your computer and use it in GitHub Desktop.
Gets line number of an HTML element.
/**
* Gets the line number of an element in an HTML element
* @return number -1 if not found
* @example
* getLineNo(document.body)
* @caveat
* This function assumes that <html>, </html>, and the DOCTYPE
* declaration are all on their own lines. If this isn't the case,
* you can adjust options.numLinesForHTMLElement. ALSO, I didn't
* make any concessions for browser support, but the general technique
* should across browsers. ALSO, this technique is totally useless if
* you want the ORIGINAL source line number and some other JS already
* messed with the DOM where the element lives
*/
function getLineNo(element, options = {}) {
for (const key in getLineNo.defaultOptions) {
if (!(key in options)) options[key] = getLineNo.defaultOptions[key]
}
const MAX_I = 100
let prev
let i = 0
let curr = element
// Get the root node for this element
while (curr.parentElement !== null && ++i < options.maxIterationsForRoot) {
curr = curr.parentElement
}
if (i === MAX_I) return -1
// Apply a unique identifier to the element that's very unlikely to
// have gotten here otherwise
const id = getLineNo.uuid()
const searchFor = `data-search-id="${id}"`
element.dataset.searchId = id
const lines = curr.innerHTML.split('\n')
// Find the line containing our id
for (let i = 0; i < lines.length; i++) {
if (lines[i].indexOf(searchFor) > -1) {
delete element.dataset.searchId
return i + options.numLinesForHTMLElement
}
}
delete element.dataset.searchId
return -1
}
getLineNo.defaultOptions = {
// This includes html open, close, and the doctype
numLinesForHTMLElement: 3,
// Maximum amount of times we check for parent before breaking
// the loop to avoid possible infinite loops
maxIterationsForRoot: 100,
}
// Credit: http://stackoverflow.com/a/2117523
getLineNo.uuid = function uuid(){
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8)
return v.toString(16)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment