Created
March 28, 2014 05:16
-
-
Save twalker/9825891 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* edible adds contentEditable behavior to an element | |
* | |
* uses a subset of contenteditable API: | |
* https://developer.mozilla.org/en-US/docs/Rich-Text_Editing_in_Mozilla">content editable</a></p> | |
* | |
* inspired by | |
* https://github.com/mindmup/bootstrap-wysiwyg | |
* execCmd: | |
* https://developer.mozilla.org/en-US/docs/Rich-Text_Editing_in_Mozilla | |
* | |
* TODO: | |
* - clean and document | |
*/ | |
define([], function(){ | |
var proto = { | |
cleanHtml: function(){ | |
console.log('not yet implemented'); | |
}, | |
getHtml: function(){ | |
return this.el.innerHTML; | |
}, | |
replaceHtml: function(html){ | |
this.restoreSelection(); | |
this.cmd('selectAll'); | |
this.cmd('insertHTML', html); | |
window.getSelection().removeAllRanges(); | |
}, | |
insert: function(){}, | |
cmd: function(cmd, val){ | |
var success = document.execCommand(cmd, false, val || null); | |
console.log('command', cmd, val, success ? 'succeeded': 'failed'); | |
return success; | |
}, | |
getCurrentRange: function (){ | |
var sel = window.getSelection(); | |
if (sel.getRangeAt && sel.rangeCount) { | |
return sel.getRangeAt(0); | |
} | |
}, | |
closestElement: function(){ | |
var range = this.getCurrentRange(), | |
parent; | |
if(range){ | |
parent = range.commonAncestorContainer; | |
if(parent.nodeType !== 1) parent = parent.parentNode; | |
} | |
return parent; | |
}, | |
enable: function(enable){ | |
this.el.setAttribute('contenteditable', enable); | |
}, | |
focus: function(){ | |
this.el.focus(); | |
}, | |
saveSelection: function(){ | |
this.selectedRange = this.getCurrentRange(); | |
}, | |
restoreSelection: function(){ | |
var selection = window.getSelection(); | |
if (this.selectedRange) { | |
try { | |
selection.removeAllRanges(); | |
} catch (ex) { | |
document.body.createTextRange().select(); | |
document.selection.empty(); | |
} | |
selection.addRange(this.selectedRange); | |
} | |
}, | |
/* | |
markSelection: function(input, color){ | |
this.restoreSelection(); | |
if (document.queryCommandSupported('hiliteColor')) { | |
document.execCommand('hiliteColor', 0, color || 'transparent'); | |
} | |
this.saveSelection(); | |
//input.data(options.selectionMarker, color); | |
}, | |
*/ | |
// hierarchy of parent nodes of selection. | |
parents: function(){ | |
var current = this.getCurrentRange(); | |
var parents = []; | |
if(current){ | |
var parent = current.commonAncestorContainer; | |
// ensure we're starting with an ELEMENT_NODE | |
if(parent.nodeType !== 1) parent = parent.parentNode | |
while(parent && parent !== this.el && this.el.contains(parent)){ | |
parents.push(parent); | |
parent = parent.parentNode; | |
} | |
} | |
return parents; | |
}, | |
selectElement: function(el){ | |
var range = document.createRange(); | |
range.selectNode(el); | |
var sel = window.getSelection(); | |
sel.removeAllRanges(); | |
sel.addRange(range); | |
this.saveSelection(); | |
} | |
}; | |
// factory | |
var edible = function edible(el){ | |
var instance = Object.create(proto, { | |
el: {value: el} | |
}); | |
instance.enable(true); | |
//instance.cmd('styleWithCSS', true); | |
//instance.cmd('enableObjectResizing', false, false); | |
return instance; | |
}; | |
return edible; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment