Retrieving the selected HTML from a contenteditable div - html

I'm trying to get the selected HTML from a contenteditable div in a particular situation. First of all let me tell you that i read the questions from Get selected element's outer HTML and Get Selected HTML in browser via Javascript.
and that i am using Redactor http://imperavi.com/redactor/
So I tried the following function to retrieve the selected HTML:
function getSelectionHtml() {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}
Now the situation is this: i have something like an italic text, then i select it and i modify the DOM to make it look bolded too.
When i select the text and make it bolded, the HTML i get looks like this:
<span class="bold">​</span><strong><span class="bold" data-redactor="verified" data-redactor-inlineMethods="">fermentum</span><span></span></strong>
I click somewhere else within the page. The text is deselected.
When i select the text for the second time and i make it italic i get the following:
​fermentum
As you can see, the second time i don't get the elements which allow me to determine that it is bolded.
So, it DOESN'T WORK on Internet Explorer 10.
It WORKS on Firefox.
It DOESN'T WORK on Chrome.
Is there an effective way to get the selected HTML from a contenteditable div other than this one?

Related

Is there a way to select an HTML node and copy only the CSS for that node? [duplicate]

I often find nice stylings on the web. To copy the CSS of a DOM element, I inspect that element with Google Chrome Developer Tools, look at the various CSS properties, and copy those manually to my own stylesheets.
Is it possible to easily export all CSS properties of a given DOM element?
Here is the code for an exportStyles() method that should return a CSS string including all inline and external styles for a given element, except default values (which was the main difficulty).
For example: console.log(someElement.exportStyles());
Since you are using Chrome, I did not bother making it compatible with IE.
Actually it just needs that the browsers supports the getComputedStyle(element) method.
Element.prototype.exportStyles = (function () {
// Mapping between tag names and css default values lookup tables. This allows to exclude default values in the result.
var defaultStylesByTagName = {};
// Styles inherited from style sheets will not be rendered for elements with these tag names
var noStyleTags = {"BASE":true,"HEAD":true,"HTML":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true};
// This list determines which css default values lookup tables are precomputed at load time
// Lookup tables for other tag names will be automatically built at runtime if needed
var tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"];
// Precompute the lookup tables.
for (var i = 0; i < tagNames.length; i++) {
if(!noStyleTags[tagNames[i]]) {
defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]);
}
}
function computeDefaultStyleByTagName(tagName) {
var defaultStyle = {};
var element = document.body.appendChild(document.createElement(tagName));
var computedStyle = getComputedStyle(element);
for (var i = 0; i < computedStyle.length; i++) {
defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]];
}
document.body.removeChild(element);
return defaultStyle;
}
function getDefaultStyleByTagName(tagName) {
tagName = tagName.toUpperCase();
if (!defaultStylesByTagName[tagName]) {
defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName);
}
return defaultStylesByTagName[tagName];
}
return function exportStyles() {
if (this.nodeType !== Node.ELEMENT_NODE) {
throw new TypeError("The exportStyles method only works on elements, not on " + this.nodeType + " nodes.");
}
if (noStyleTags[this.tagName]) {
throw new TypeError("The exportStyles method does not work on " + this.tagName + " elements.");
}
var styles = {};
var computedStyle = getComputedStyle(this);
var defaultStyle = getDefaultStyleByTagName(this.tagName);
for (var i = 0; i < computedStyle.length; i++) {
var cssPropName = computedStyle[i];
if (computedStyle[cssPropName] !== defaultStyle[cssPropName]) {
styles[cssPropName] = computedStyle[cssPropName];
}
}
var a = ["{"];
for(var i in styles) {
a[a.length] = i + ": " + styles[i] + ";";
}
a[a.length] = "}"
return a.join("\r\n");
}
})();
This code is base on my answer for a slightly related question: Extract the current DOM and print it as a string, with styles intact
I'm quoting Doozer Blake's excellent answer, provided above as a comment. If you like this answer, please upvote his original comment above:
Not a direct answer, but with Chrome Developer Tools, you can click inside Styles or Computed Styles, hit Ctrl+A and then Ctrl+C to copy all the styles in those given areas. It's not perfect in the Style tab because it picks up some extra stuff. Better than selecting them one by one I guess. – Doozer Blake 3 hours ago
You can do the same using Firebug for Firefox, by using Firebug's "Computed" side panel.
There are a few ways to almost do this.
Have a look at FireDiff
Also have a look at cssUpdater This is for local CSS only]
And see this Q for more similar tools: Why can't I save CSS changes in Firebug?
Also this paid product claims to be able to do this: http://www.skybound.ca/

Is it possible to hide all the element tag by using only 1 id name?

I'm trying to hide certain tags by using one ID element, but seem like it only hide the first tag with the ID element that I used.
DEMO : http://jsfiddle.net/mgm3j5cd/
How can i solve this issue? I wanted to hide the tag only with the ID element that I've declared. Appreciated for helps
You have this tagged as CSS, so the following CSS in your page's stylesheet will work:
#hide {
display: none;
}
Edit:
If you must only use JavaScript, you can do the following. Keep in mind that your document is already technically invalid by having multiple elements with the same ID, so this approach may not work in every browser. (I tested with Firefox 32).
Working JSFiddle: http://jsfiddle.net/88yw7LL9/2/
function hideByID(string) {
var element = document.getElementById(string); // get first matching element
var array = [];
while(element) {
array.push(element);
element.id = string + '-processed'; // change ID so next call gets the next matching element
element = document.getElementById(string);
}
for(var i = 0; i < array.length; i++) {
array[i].id = string; // revert ID to previous state
array[i].style.display="none"; // hide
}
}
hideByID('hide');
The simplest solution should be to assign 'class' attribute to certain elements you want to hide, like :
.XXXX
{
display:none;
}
Perhaps, you want to specify some elements hidden with id, like :
#id1 , #id2
{
display:none;
}
or
div#id1 , div#id2 //more accurate
{
display:none;
}
but, unfortunately, you can't hide elements you want by using one ID.

How to make HTML5 contenteditable div allowing only text in firefox?

I want to make div with contentEditable attribute which is allowing only text. It's easily achievable in Chrome by using:
<div contenteditable="plaintext-only"></div>
However it doesn't work in Firefox. Is there a way how to make text-only contenteditable div in Firefox ? I know it is possible, because Google Plus has such div, but I don't know how they do it.
I ran into this problem myself. Here is my solution which I have tested in Firefox and Chrome:
Ensure the contenteditable div has the css white-space: pre, pre-line or pre-wrap so that it displays \n as new lines.
Override the "enter" key so that when we are typing, it does not create any <div> or <br> tags
myDiv.addEventListener("keydown", e => {
//override pressing enter in contenteditable
if (e.keyCode == 13)
{
//don't automatically put in divs
e.preventDefault();
e.stopPropagation();
//insert newline
insertTextAtSelection(myDiv, "\n");
}
});
Secondly, override the paste event to only ever fetch the plaintext
//override paste
myDiv.addEventListener("paste", e => {
//cancel paste
e.preventDefault();
//get plaintext from clipboard
let text = (e.originalEvent || e).clipboardData.getData('text/plain');
//insert text manually
insertTextAtSelection(myDiv, text);
});
And here is the supporting function which inserts text into the textContent of a div, and returns the cursor to the proper position afterwards.
function insertTextAtSelection(div, txt) {
//get selection area so we can position insert
let sel = window.getSelection();
let text = div.textContent;
let before = Math.min(sel.focusOffset, sel.anchorOffset);
let after = Math.max(sel.focusOffset, sel.anchorOffset);
//ensure string ends with \n so it displays properly
let afterStr = text.substring(after);
if (afterStr == "") afterStr = "\n";
//insert content
div.textContent = text.substring(0, before) + txt + afterStr;
//restore cursor at correct position
sel.removeAllRanges();
let range = document.createRange();
//childNodes[0] should be all the text
range.setStart(div.childNodes[0], before + txt.length);
range.setEnd(div.childNodes[0], before + txt.length);
sel.addRange(range);
}
https://jsfiddle.net/1te5hwv0/
Sadly, you can’t. As this answer points out the spec only specifies true, false and inherit as valid parameters. The subject seems to have been discussed but if I’m not mistaken only Webkit implements support for plaintext-only.

What is the best way to remove all tabindex attribute to html elements?

What is the best way to remove all tabindex attributes from html elements? GWt seems to put this attribute even it is not set anywhere in the code. It sets tabindex to -1.
I have the code below as working but it is tedious because I have to search every element according to its tag name and that slows the page loading. Any other suggestions? I'd prefer the solution not use javascript, as I am new to it.
NodeList<Element> input = this.getElement().getElementsByTagName("input");
if(input.getLength()>0)
{
for(int i=0; i<=input.getLength(); i++)
{
input.getItem(i).removeAttribute("tabIndex");
}
}
NodeList<Element> div = this.getElement().getElementsByTagName("div");
if(div.getLength()>0)
{
for(int i=0; i<=div.getLength(); i++)
{
div.getItem(i).removeAttribute("tabIndex");
}
}
I'm not entirely sure what you are asking then. You want to remove the tab index attribute. You either:
set the tabindex attribute to -1 manually in the HTML.
use the code you already have.
or use the simplified JQuery version in the other thread.
Perhaps I have misunderstood what you are trying to achieve?
EDIT
Okay perhaps this:
$(document).ready(function(){
$('input').removeAttr("tabindex");
});
This should remove it rather than set it to -1... hopefully. Sorry if I've misunderstood again!
JQuery removeAttr Link
Use querySelectorAll function which Returns a list of the elements within the document (using depth-first pre-order traversal of the document's nodes) that match the specified group of selectors.
function removeTagAttibute( attributeName ){
var allTags = '*';
var specificTags = ['ARTICLE', 'INPUT'];
var allelems = document.querySelectorAll( specificTags );
for(i = 0, j = 0; i < allelems.length; i++) {
allelems[i].removeAttribute( attributeName );
}
}
removeTagAttibute( 'tabindex' );
I finally figured it out.
I tried Javascirpt/jquery but they couldn't remove tabindexes because the page was not fully rendered yet - my panels are placed programmatically after window.load. What I did is make use of the RootPanel.class of gwt (which was being used already, but I didn't know).
The task: to get rid of all tabindex with -1 value, add type="tex/javascript" for all script tags, type="text/css" for style tags and out an alt to all img tags. These are all for the sake of html validation.
I am not sure this is the best way, it sure does add up to slow loading, but client is insisting that I do it. So here it is:
RootPanel mainPanel = RootPanel.get(Test_ROOT_PANEL_ID);
Widget widget = (Widget) getEntryView();
mainPanel.add((widget));
// Enable the view disable the loading view. There should always be
// the loading panel to disable.
Element mainPanelelement = DOM.getElementById(Test_ROOT_PANEL_ID);
Element loadingMessage = DOM.getElementById(LOADING_MESSAGE);
Element parent = loadingMessage.getParentElement();
if(parent!=null)
{
//i had to use prev sibling because it is the only way that I know of to access the body //tag that contains the scripts that are being generated by GWT ex.bigdecimal.js
Element body = parent.getPreviousSibling().getParentElement();
if(body!=null)
{
NodeList<Element> elms = body.getElementsByTagName("*");
if(elms.getLength()>0)
{
Element element=null;
for(int i=0; i<=elms.getLength(); i++)
{
if(elms.getItem(i)!=null)
{
element = elms.getItem(i);
if(element.getTagName().compareToIgnoreCase("script")==0)
element.setAttribute("type", "text/javascript");
else if(element.getTagName().compareToIgnoreCase("style")==0)
element.setAttribute("type", "text/css");
else if(element.getTagName().compareToIgnoreCase("img")==0)
{
if(element.getAttribute("alt")=="")
element.setAttribute("alt", element.getAttribute("title")!=" " ? element.getTitle() : " " );
}
else
{
if(element.getTabIndex()<=0)
element.removeAttribute("tabindex");
}
}
}
}
}
}
DOM.setStyleAttribute((com.google.gwt.user.client.Element) loadingMessage, "display", "none");
DOM.setStyleAttribute((com.google.gwt.user.client.Element) mainPanelelement, "display", "inline");
// Change cursor back to default.
RootPanel.getBodyElement().getStyle().setProperty("cursor", "default");
}

revealing text within a webpage on link

is there a simple way to reveal text within a webpage using a link without altering the web address or using an iframe? maybe with an 'onclick' function? im pretty new to new code so not sure where to start.. ive attached a picture of what exaclty im after, fairly simple. im already using an iframe as the main interface so another one would get messy in terms of a default menu. there must be a simple fix.. any help would be really appreciated.
thanks, Aaron
Put the text you want to hide until click inside hidden container, like this:
<div id="HiddenTextContainer" style="display: none;">
Hello, I will become visible when you click something else
</div>
Next step is add that JavaScript code to the page, for example inside the <head> section:
function ShowHiddenText() {
document.getElementById("HiddenTextContainer").style.display = "block";
}
And finally have such code:
<span onclick="ShowHiddenText();">click me to show hidden text</span>
Live test case.
Edit: in case you got more than one element to show, you can use the rel attribute:
<span rel="HiddenTextContainer2">click me to show second hidden text</span><br />
Then with pure JavaScript iterate over all elements with that attribute and assign their onclick programmatically:
window.onload = function() {
var elements = document.getElementsByTagName("span");
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
var id = element.getAttribute("rel") || "";
if (id.length > 0) {
element.onclick = function() {
var oToShow = document.getElementById(this.getAttribute("rel"));
if (oToShow)
oToShow.style.display = "block";
};
}
}
};
When clicked, element with ID the same as the rel value will be displayed.
Updated fiddle.
Edit: to show it in one single container, first have such container:
<div id="HiddenTextContainer"></div>
No need to have it hidden since it's initially empty, then change the code to:
window.onload = function() {
var elements = document.getElementsByTagName("span");
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
var id = element.getAttribute("rel") || "";
if (id.length > 0) {
element.onclick = function() {
var oToShow = document.getElementById(this.getAttribute("rel"));
if (oToShow)
document.getElementById("HiddenTextContainer").innerHTML = oToShow.innerHTML;
};
}
}
};
Instead of showing the related container, you copy its contents to the "main" container.
Updated jsFiddle.
You have 2 choices for this. The first is to preload everything on the page and then only set the visible property when you click the link. The second is to load it in using something like AJAX and then show it the same way as above.
To show these things look into JQuery: http://jquery.com/
A good tutorial for the second method is here: http://yensdesign.com/2008/12/how-to-load-content-via-ajax-in-jquery/