web - copy section to clipboard and remove certain elements - javascript

Ive got a method which will copy a section of html to the clipboard to allow pasting elsewhere.
It is usually a table of which will be the main content so it will be pasted into excel and keep its formatting, which is lovely.
What I want to do is remove certain elements from this section.
The main ones are checkboxes and textboxes - which cause excel to go really screwy, and for some reason you cannot delete them from excel - you just have to start a new sheet.
This is the method I am using to copy:
$('#CopyClipboard').click(function () {
var contentDiv = document.getElementById('copyablecontent');
var holdtext = document.getElementById('holdtext');
holdtext.innerText = contentDiv.innerHTML;
Copied = holdtext.createTextRange();
Copied.execCommand('Copy');
alert('Data copied to clipboard!');
});
(excuse the horrible mix of jquery and javascript).
So I have my 'contentDiv' variable, I want to parse that and remove all inputs, and possibly other elements too (I could give them all a css class 'doNotCopy' or something).
How can I do this?

you can use:
contentDiv.innerHTML.replace(/<input[^>]*>/g,"")
check the replace method here:
http://www.w3schools.com/jsref/jsref_replace.asp
you may have to adjust the regex for your needs

Related

Create clone of text selection without use of clipboard

For my application I need a kind of internal clipboard with history.
I can't use the clipboard api (as far as I can see) as this would need permission from the user which is not an option.
I wan't to preserve formatting like bold, italics and strikethrough.
I was thinking about getting the content from window.getSelection(), but there is no way of easily cloning all the html that is in the selection.
The contents would need to go into another container element to be shown somewhere in the app.
Any ideas of how to achieve this are highly appreciated.
Best
Matthias
EDIT: I'm already interrupting the copy event and replace it with custom function. What I need to do is start at the anchorNode, cut some possible offset and go forward to the focusNode (also with offset). Also all unknown/unwanted tags (span, h1, div etc need to be removed but the text content shall stay). I hoped that someone has already done this or a similar task so I can save some time :/
The copy event could help you, as it doesn't require any permission to work.
var clipHistory = [];
document.addEventListener('copy', (event) => {
const selection = document.getSelection();
clipHistory.push(selection.toString());
event.preventDefault(); // optional, it prevents to modify the user's clipboard
});
// other functions can access clipHistory
A nice thing is that the copy event is very well supported.
Unlcukly this solution remove the formatting, but on way to keep it is to use a <div contenteditable id="parse-div"></div> and fire the parse event manually.
I found an intersting class: the Range one, but it doesn't allow to set a start and an end offset of non #text elements, as far I can undertand it.

How can I make my Javascript code select all 'b' tags on a page instead of only the first one?

We have a very large website that is quite old and has a lot of 'b' tags. My boss wants to change them to 'strong' tags but this will require a lot of time to change manually so she was hoping we could change it with some code.
I had a nice bit of JQuery code that worked (intermittently), but I couldn't get it to work on the site as it uses JQuery 1.9.1 and cannot be upgraded.
I then found this piece of Javascript which does what I need but only works on the first 'b' tag on the page and all others stay as 'b' tags. I don't know enough about Javascript selectors to change the firstChild selector.
<script>
function replaceElement(source, newType) {
// Create the document fragment
const frag = document.createDocumentFragment();
// Fill it with what's in the source element
while (source.firstChild) {
frag.appendChild(source.firstChild);
}
// Create the new element
const newElem = document.createElement(newType);
// Empty the document fragment into it
newElem.appendChild(frag);
// Replace the source element with the new element on the page
source.parentNode.replaceChild(newElem, source);
}
// Replace the <b> with a <div>
replaceElement(document.querySelector('b'), 'strong');
</script>
You might use querySelectorAll:
Array.from(document.querySelectorAll('b')).forEach(e=>{
replaceElement(e, 'strong');
});
But this is really a xy question. You really should do the change server side, for example by using some search/replace (learn to use your code editor). You're adding to the code debt here.
Note also that there's no obvious reason to prefer strong over b in HTML5.
Use getElementsByTagName(). It's more efficient than querySelectorAll because it doesn't have to parse selectors, and it describes better what you are really trying to do - get elements by tag name.
var elements = document.getElementsByTagName("b");
replaceElement(elements[0], "strong");
replaceElement(elements[1], "strong");
replaceElement(elements[2], "strong");
You can also iterate over this collection by using Array.from().
You would be better off finding the source of the <b> tags and changing them there as Denys has mentioned.
Updating the DOM would have little benefit and would cause performance issues when there are many tags on a page.
Does this system use a CMS or database to store the content? I would look to use something like these 2 SQL queries to replace them across the site:
update content_table set content_column = replace(content_column, '<b>','<strong>');
update content_table set content_column = replace(content_column, '</b>','</strong>');

Converting table cells data to internal links in a separate .js file

Having an issue with a small project and I've been stuck for the past 3 days...
I have to convert data cells on a left column of a table in a html file into links (that will target other html files) using javascript & jquery in a separate js file. I am not able to edit the html file due to restrictions on the question.
I hope I understood your question correctly. You could access the cells with the selector .code and then use append() to put a link in there like so:
$(".code").each(function(i){ //find the right cells and for each one...
var text = $(this).text(); //...read the contents...
text = text.substring(3); //...remove the first 3 letters...
$(this).text(""); //...remove the text...
$(this).append("<a href='"+text+".html'>"+text+"</a>"); //...and replace with a link
});
Example: http://jsfiddle.net/7fawbkck/2/

Resizing a specific TinyMCE editor added by JS

I am adding/replacing two textareas with TinyMCE via two different javascript clicks/calls. They have different IDs and are being added correctly by the 'execCommand' call:
tinymce.execCommand('mceAddControl',true,'comment1');
However, I am having trouble resizing the objects when there are more than one on screen. If there is just one I am able to successfully call 'resizeTo' using the 'activeEditor' to resize the object, like this:
tinymce.execCommand('mceAddControl',true,'comment1');
var ed = tinymce.activeEditor;
ed.theme.resizeTo(400, 200);
But when there is more than one editor, I cannot use 'activeEditor' and I don't know how to select a specific editor to resize. I have tried the following, but it didn't work:
var edd = tinymce.get('comment2');
edd.theme.resizeTo(350,306);
Any help/suggestions? Thanks!
In order to have to working tinymce editors with textareas as source elements you have given each of those testareas a unique id. This id will help you to get the correct editor instance.
Use
var editor = tinymce.get('your_textarea_id');
to get the correct editor. That's all.

CKEditor: Apply removeFormat on paste

I have successfully managed to set up an on paste event to capture the HTML pasted into the text area as it is pasted.
I need to automatically apply the removeFormat command to that HTML before or at the time it is pasted into the text area, so that I can strip it of classes, various tags, and other attributes. Could somebody point me in the right direction to apply the removeFormat command correctly?
Here's my code so far:
$(function(){
$('textarea').ckeditor(
function( textarea ){
var editor = this;
editor.on('paste', function( e ) {
//alert(e.data.html); // This shows the HTML
editor.execCommand( 'removeFormat', e.data.html ); // Doesn't seem to do anything, HTML is pasted with the attributes intact
});
}
)
});
Thanks!
P.S. Force plain text option is not viable as there are some HTML elements I wish to keep (p,table and others).
You can use
config.forcePasteAsPlainText = true;
cf http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
You need to select the content before you can apply removeFormat to it.
You could try grabbing the range ( even if it's just the cursor sitting at the insertion point ) and saving a bookmark before you paste.
After you paste, use the bookmark to select that range again.
That should select everything that you pasted between the start and end of the range.
Then you can use removeFormat:
editor.execCommand( 'removeFormat', editor.selection );
Here are the links to the range and selection API pages:
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dom.range.html
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dom.selection.html
I've found it easier to work with ranges, the createBookmark method is good because it sets markers and you can grab the correct start and end points even if the DOM changes ( as it will when you paste in the new content ). You can use moveToBookmark() after the paste to select the range.
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dom.range.html#createBookmark
Because the documentation is sparse, I've found it helpful to search the source code for places where the methods are called. Looking at how they're used gives me a better idea of what kind of object I need to apply the methods to.
Be Well,
Joe
Starting from CKEditor 4.1 there is no need to do custom coding to define the list of elements that should be kept when pasting data into CKEditor, Advanced Content Filter should do the trick.
Either leave ACF enabled with the default configuration - CKEditor will accept all tags that can be created with it, or define your own set of rules with more or less strict set of allowed tags/attributes/styles. See documentation

Categories