jquery replaceWith not working on google chrome - javascript

I am facing a strange problem with dynamically replacing controls using javascript in Google Chrome. The replaced controls dont show up in UI but when i use developer tools i am able to locate the replaced element but it does not show up until i close the developer tools. once i open and close developer tools the issue is no longer replicatable until i refresh the page.
This happens only in cases where i am trying to replace outerHTML of an element.
I first tried using jquery's replaceWith api, that dint help so i switched to the following script -
function chromeOuterHTML(oldElem, outerhtml)
{
var el = document.createElement('div');
el.innerHTML = outerhtml;
var parentNode = oldElem.parentNode;
var range = document.createRange();
range.selectNodeContents(el);
var documentFragment = range.extractContents();
parentNode.insertBefore(documentFragment, oldElem);
parentNode.removeChild(oldElem);
}
I dont think that its a problem with my javascript since the problem is specific to chrome and also happens in only certain cases.
Any help would be greatly appreciated

More a diagnostic tool than a solution, but have you tried delaying your insertBefore?
function chromeOuterHTML(oldElem, outerhtml)
{
var el = document.createElement('div');
el.innerHTML = outerhtml;
var parentNode = oldElem.parentNode;
var range = document.createRange();
range.selectNodeContents(el);
var documentFragment = range.extractContents();
setTimeout(function () {
parentNode.insertBefore(documentFragment, oldElem);
parentNode.removeChild(oldElem);
}, 1);
}
In some situations (that I don't fully understand), DOM manipulations can fail if they happen in too quick a succession. This modification will delay (only by 1ms) the insert - it's possible that it will make a difference. It's also possible it'll do nothing!

Related

Dynamically created editable iframe not working in Firefox

I have an iframe that is generated in JavaScript with createElement() when a function is fired, which becomes a text editor. It works just fine in Chrome, Safari and Edge, but in Firefox, the innerHTML text, "Text Layer", will briefly flash within the iframe and then it disappears and the iframe doesn't seem to be editable. Upon inspection, the iframe's body tag is empty. If I set contentEditable to true on the iframe's body tag in the inspector it seems to work properly, but when I try to set this in my JS function, nothing happens in Firefox.
I'm guessing this has something to do with the iframe being created in JavaScript, since setting the designMode of an iframe already in the DOM to 'On' with JS seems to work properly. Wondering if there's a way to get this to work in Firefox, maybe another method of creating the iframe? I have seen some similar problems that were solved by putting some javascript in the iframe's src, as in the comments here, but that apparently causes problems in other browsers. Creating the iframe in JS is preferable to appending it from somewhere.
function text() {
var rtf = document.createElement("iframe");
rtf.name = "richTextField";
rtf.id = "richTextField";
rtf.className = "texteditor";
var dwrap = document.createElement("div");
dwrap.appendChild(rtf);
var tframe = document.getElementById("richTextField");
tframe.contentWindow.document.designMode = 'On';
tframe.contentWindow.document.body.innerHTML = "Text Layer";
tframe.contentWindow.document.getElementsByTagName('body')[0].focus();
tframe.onload = autosize();
};
Found this 15 year old bug report and was able to get it work by setting the contentWindow properties inside of a setTimeout function.
function text() {
var rtf = document.createElement("iframe");
rtf.name = "richTextField";
rtf.id = "richTextField";
rtf.className = "texteditor";
var dwrap = document.createElement("div");
dwrap.appendChild(rtf);
var tframe = document.getElementById("richTextField");
setTimeout(function(){
tframe.contentWindow.document.designMode = 'On';
tframe.contentWindow.document.body.innerHTML = "Text Layer";
tframe.contentWindow.document.getElementsByTagName('body')[0].focus();
}, 0);
tframe.onload = autosize();
};

Remove Html Element before it is rendered in page using javaScript?

I am working in very large project without Using any js Framework and Lib . I had a serious problem where I am looking for way to remove the HTML element before it is rendered in page. The code shown below is not actual problem but it helps me to find my actual solution . Please help me ?
code:-
var element = document.createElement('div');
element.innerHTML = 'This is Nirikshan Bhusal'
element.remove()
document.getElementById('root').appendChild(element);
I want logic something that above code shows.
I have 1 solution for this problem but this doesn't work for me
Codes That doesn't solve my problem :-
var element = document.createElement('div');
element.innerHTML = 'This is Nirikshan Bhusal';
element.style.display = 'none';
document.getElementById('root').appendChild(element);
element.remove();
Please help me ?
You cannot do that with native elements. But you could easily monkey patch it:
Element.prototype.remove = (old => function() {
this.dontAdd = true;
old.call(this);
})(Element.prototype.remove);
Element.prototype.appendChild = (old => function(el) {
if(!el.dontAdd) old.call(this, el);
})(Element.prototype.appendChild);
So now your first version works as expected. But this can cause side effects all over your code, so be careful with this.

iFrame Text Not showing up on Firefox but works on Chrome (document.body.innerHTML)

Fellow coders, I am running into this issue, I've a iframe with ID="graph", I am trying to output this html while page loads, but for some reason it's not working on firefox but works great on chrome.
<script language="javascript">
var text = "We are creating your Memory Performance Graph, Please hold.";
document.getElementById('graph').document.body.innerHTML = text;
</script>
Any recommendations on where it went wrong?
The DOM interface for an HTMLIFrameElement object specifies 'contentDocument' as the name of the IFrame document, not "document" by itself.
I was able to get a version of your message to appear in an iframe using
var text = "We are creating your Memory Performance Graph, Please hold.";
var iFrameObj = document.getElementById('graph');
var docObj = iFrameObj.contentDocument || iFrameObj.document;
docObj.body.innerHTML = text;
The only reason to include " || iFrameObj.document" was in case Chrome does not support the standard attribute name (untestested).
In testing I placed the code in a window onload event handler to avoid potential timing issues with accessing the iframe element before finalisation.

My script won't work in IE (even 9)? simple javascript to amend copy text

So I was browsing the internet one day, and copied a chunk of text "my cool text" and pasted it to facebook, only to see that it changed it to "my cool text - Read More at URL", I was in awe! That's awesome!
So I dove in a little and found some tutorials and such. I took to my own to convert it to a customizable plugin with dozens of options, and it outputs this (or similar based on options):
function copyCopyright() {
var theBody = document.getElementsByTagName("body")[0];
var selection;
selection = window.getSelection();
var copyrightLink = '<br /><br />Read more at: '+document.location.href+'<br /> ©2012 ';
var copytext = selection + copyrightLink;
var extraDiv = document.createElement("div");
extraDiv.style.position="absolute";
extraDiv.style.left="-99999px";
theBody.appendChild(extraDiv);
extraDiv.innerHTML = copytext;
selection.selectAllChildren(extraDiv);
window.setTimeout(function() {
theBody.removeChild(extraDiv);
},0);
}
document.oncopy = copyCopyright;​
works GREAT in Chrome and Firefox, etc. But of COURSE it doesn't work in IE (even IE9!). I'm fairly new to Javascript, especially hunting down IE problems with it.
Is there a function or method or something above that IE just won't recognize that I'll have to find an alternate way around?
IE needs
document.body.oncopy=copyCopyright
added to your onload event. (body doesn’t exist until loaded)

Copy / Put text on the clipboard with FireFox, Safari and Chrome

In Internet Explorer I can use the clipboardData object to access the clipboard. How can I do that in FireFox, Safari and/or Chrome?
For security reasons, Firefox doesn't allow you to place text on the clipboard. However, there is a workaround available using Flash.
function copyIntoClipboard(text) {
var flashId = 'flashId-HKxmj5';
/* Replace this with your clipboard.swf location */
var clipboardSWF = 'http://appengine.bravo9.com/copy-into-clipboard/clipboard.swf';
if(!document.getElementById(flashId)) {
var div = document.createElement('div');
div.id = flashId;
document.body.appendChild(div);
}
document.getElementById(flashId).innerHTML = '';
var content = '<embed src="' +
clipboardSWF +
'" FlashVars="clipboard=' + encodeURIComponent(text) +
'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
document.getElementById(flashId).innerHTML = content;
}
The only disadvantage is that this requires Flash to be enabled.
The source is currently dead: http://bravo9.com/journal/copying-text-into-the-clipboard-with-javascript-in-firefox-safari-ie-opera-292559a2-cc6c-4ebf-9724-d23e8bc5ad8a/ (and so is its Google cache)
There is now a way to easily do this in most modern browsers using
document.execCommand('copy');
This will copy currently selected text. You can select a textArea or input field using
document.getElementById('myText').select();
To invisibly copy text you can quickly generate a textArea, modify the text in the box, select it, copy it, and then delete the textArea. In most cases this textArea wont even flash onto the screen.
For security reasons, browsers will only allow you copy if a user takes some kind of action (ie. clicking a button). One way to do this would be to add an onClick event to a html button that calls a method which copies the text.
A full example:
function copier(){
document.getElementById('myText').select();
document.execCommand('copy');
}
<button onclick="copier()">Copy</button>
<textarea id="myText">Copy me PLEASE!!!</textarea>
Online spreadsheet applications hook Ctrl + C and Ctrl + V events and transfer focus to a hidden TextArea control and either set its contents to desired new clipboard contents for copy or read its contents after the event had finished for paste.
See also Is it possible to read the clipboard in Firefox, Safari and Chrome using JavaScript?.
It is summer 2015, and with so much turmoil surrounding Flash, here is how to avoid its use altogether.
clipboard.js is a nice utility that allows copying of text or html data to the clipboard. It's very easy to use, just include the .js and use something like this:
<button id='markup-copy'>Copy Button</button>
<script>
document.getElementById('markup-copy').addEventListener('click', function() {
clipboard.copy({
'text/plain': 'Markup text. Paste me into a rich text editor.',
'text/html': '<i>here</i> is some <b>rich text</b>'
}).then(
function(){console.log('success'); },
function(err){console.log('failure', err);
});
});
</script>
clipboard.js is also on GitHub.
As of 2017, you can do this:
function copyStringToClipboard (string) {
function handler (event){
event.clipboardData.setData('text/plain', string);
event.preventDefault();
document.removeEventListener('copy', handler, true);
}
document.addEventListener('copy', handler, true);
document.execCommand('copy');
}
And now to copy copyStringToClipboard('Hello, World!')
If you noticed the setData line, and wondered if you can set different data types, the answer is yes.
Firefox does allow you to store data in the clipboard, but due to security implications it is disabled by default. See how to enable it in "Granting JavaScript access to the clipboard" in the Mozilla Firefox knowledge base.
The solution offered by amdfan is the best if you are having a lot of users and configuring their browser isn't an option. Though you could test if the clipboard is available and provide a link for changing the settings, if the users are tech savvy. The JavaScript editor TinyMCE follows this approach.
The copyIntoClipboard() function works for Flash 9, but it appears to be broken by the release of Flash player 10. Here's a solution that does work with the new flash player:
http://bowser.macminicolo.net/~jhuckaby/zeroclipboard/
It's a complex solution, but it does work.
I have to say that none of these solutions really work. I have tried the clipboard solution from the accepted answer, and it does not work with Flash Player 10. I have also tried ZeroClipboard, and I was very happy with it for awhile.
I'm currently using it on my own site (http://www.blogtrog.com), but I've been noticing weird bugs with it. The way ZeroClipboard works is that it puts an invisible flash object over the top of an element on your page. I've found that if my element moves (like when the user resizes the window and i have things right aligned), the ZeroClipboard flash object gets out of whack and is no longer covering the object. I suspect it's probably still sitting where it was originally. They have code that's supposed to stop that, or restick it to the element, but it doesn't seem to work well.
So... in the next version of BlogTrog, I guess I'll follow suit with all the other code highlighters I've seen out in the wild and remove my Copy to Clipboard button. :-(
(I noticed that dp.syntaxhiglighter's Copy to Clipboard is broken now also.)
Check this link:
Granting JavaScript access to the clipboard
Like everybody said, for security reasons, it is by default disabled. The page above shows the instructions of how to enable it (by editing about:config in Firefox or the user.js file).
Fortunately, there is a plugin called "AllowClipboardHelper" which makes things easier with only a few clicks. however you still need to instruct your website's visitors on how to enable the access in Firefox.
Use the modern document.execCommand("copy") and jQuery. See this Stack Overflow answer.
var ClipboardHelper = { // As Object
copyElement: function ($element)
{
this.copyText($element.text())
},
copyText:function(text) // Linebreaks with \n
{
var $tempInput = $("<textarea>");
$("body").append($tempInput);
$tempInput.val(text).select();
document.execCommand("copy");
$tempInput.remove();
}
};
How to call it:
ClipboardHelper.copyText('Hello\nWorld');
ClipboardHelper.copyElement($('body h1').first());
// jQuery document
;(function ( $, window, document, undefined ) {
var ClipboardHelper = {
copyElement: function ($element)
{
this.copyText($element.text())
},
copyText:function(text) // Linebreaks with \n
{
var $tempInput = $("<textarea>");
$("body").append($tempInput);
//todo prepare Text: remove double whitespaces, trim
$tempInput.val(text).select();
document.execCommand("copy");
$tempInput.remove();
}
};
$(document).ready(function()
{
var $body = $('body');
$body.on('click', '*[data-copy-text-to-clipboard]', function(event)
{
var $btn = $(this);
var text = $btn.attr('data-copy-text-to-clipboard');
ClipboardHelper.copyText(text);
});
$body.on('click', '.js-copy-element-to-clipboard', function(event)
{
ClipboardHelper.copyElement($(this));
});
});
})( jQuery, window, document );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span data-copy-text-to-clipboard=
"Hello
World">
Copy Text
</span>
<br><br>
<span class="js-copy-element-to-clipboard">
Hello
World
Element
</span>
I've used GitHub's Clippy for my needs and is a simple Flash-based button. It works just fine if one doesn't need styling and is pleased with inserting what to paste on the server-side beforehand.
http://www.rodsdot.com/ee/cross_browser_clipboard_copy_with_pop_over_message.asp works with Flash 10 and all Flash enabled browsers.
Also ZeroClipboard has been updated to avoid the bug mentioned about page scrolling causing the Flash movie to no longer be in the correct place.
Since that method "Requires" the user to click a button to copy this is a convenience to the user and nothing nefarious is occurring.
A slight improvement on the Flash solution is to detect for Flash 10 using swfobject:
http://code.google.com/p/swfobject/
And then if it shows as Flash 10, try loading a Shockwave object using JavaScript. Shockwave can read/write to the clipboard (in all versions) as well using the copyToClipboard() command in Lingo.
Try creating a memory global variable storing the selection. Then the other function can access the variable and do a paste. For example,
var memory = ''; // Outside the functions but within the script tag.
function moz_stringCopy(DOMEle, firstPos, secondPos) {
var copiedString = DOMEle.value.slice(firstPos, secondPos);
memory = copiedString;
}
function moz_stringPaste(DOMEle, newpos) {
DOMEle.value = DOMEle.value.slice(0, newpos) + memory + DOMEle.value.slice(newpos);
}
If you support Flash, you can use https://everyplay.com/assets/clipboard.swf and use the flashvars text to set the text.
https://everyplay.com/assets/clipboard.swf?text=It%20Works
That’s the one I use to copy and you can set as extra if it doesn't support these options. You can use:
For Internet Explorer:
window.clipboardData.setData(DataFormat, Text) and window.clipboardData.getData(DataFormat)
You can use the DataFormat's Text and URL to getData and setData.
And to delete data:
You can use the DataFormat's File, HTML, Image, Text and URL. PS: You need to use window.clipboardData.clearData(DataFormat);.
And for other that’s not support window.clipboardData and swf Flash files you can also use Control + C button on your keyboard for Windows and for Mac its Command + C.
From addon code:
For how to do it from Chrome code, you can use the nsIClipboardHelper interface as described here: https://developer.mozilla.org/en-US/docs/Using_the_Clipboard
Use document.execCommand('copy'). It is supported in the latest versions of Chrome, Firefox, Edge, and Safari.
function copyText(text){
function selectElementText(element) {
if (document.selection) {
var range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection) {
var range = document.createRange();
range.selectNode(element);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
var element = document.createElement('DIV');
element.textContent = text;
document.body.appendChild(element);
selectElementText(element);
document.execCommand('copy');
element.remove();
}
var txt = document.getElementById('txt');
var btn = document.getElementById('btn');
btn.addEventListener('click', function(){
copyText(txt.value);
})
<input id="txt" value="Hello World!" />
<button id="btn">Copy To Clipboard</button>
Clipboard API is designed to supersede document.execCommand. Safari is still working on support, so you should provide a fallback until the specification settles and Safari finishes implementation.
const permalink = document.querySelector('[rel="bookmark"]');
const output = document.querySelector('output');
permalink.onclick = evt => {
evt.preventDefault();
window.navigator.clipboard.writeText(
permalink.href
).then(() => {
output.textContent = 'Copied';
}, () => {
output.textContent = 'Not copied';
});
};
Permalink
<output></output>
For security reasons clipboard Permissions may be necessary to read and write from the clipboard. If the snippet doesn't work on Stack Overflow give it a shot on localhost or an otherwise trusted domain.
Building off the excellent answer from David from Studio.201, this works in Safari, Firefox, and Chrome. It also ensures no flashing could occur from the textarea by placing it off-screen.
// ================================================================================
// ClipboardClass
// ================================================================================
var ClipboardClass = (function() {
function copyText(text) {
// Create temp element off-screen to hold text.
var tempElem = $('<textarea style="position: absolute; top: -8888px; left: -8888px">');
$("body").append(tempElem);
tempElem.val(text).select();
document.execCommand("copy");
tempElem.remove();
}
// ============================================================================
// Class API
// ============================================================================
return {
copyText: copyText
};
})();

Categories

Resources