when setting data in CKEditor images disappear in the editor area. Links and other format is ok, so doesn't look like a double quote thing. Also, I tryed with absolute positioned and also external images, so it's not an image not found problem.
This is my code:
function getContent(id)
{
console.log($('#content-article-' + id).html());
return $('#content-article-' + id).html();
}
function enableEdition()
{
if (current_conclusion != 'NEW')
{
$('#titular-edit').val(getTitle(current_article));
//This setData() sets everthing but images
CKEDITOR.instances.editor.setData(getContent(current_article));
}
}
The image tag is substituted by a <br> tag inside the editor iframe
CKEditor 4.1 comes with Advanced Content Filter which is the root of your problem. Most likely you don't use the image plugin that adds <img> to allowedContent rules (don't you?). This is why editor discards those tags from your content and this is why you have to configure it manually.
See related answers: Stop CKEditor removing divs, CKEditor strips inline attributes
Related
I am trying to wrap some elements of TinyMCE with my custom HTML code.
For example, let us consider the user wants to add Media or Image element, the user will just click on Media or Image element icon, and he will be asked to enter the link, and TinyMCE will generate the required HTML code for that.
What I want to achieve is wrapping that generated HTML code with my custom code. I.e., so I will simply get this:
<div>
... What TinyMCE has generated for the image or media ...
</div>
For Media element, I tried using media_url_resolver, but that does not work for me, because this function does not give the ability to wrap the default behaviour, but only to rewrite the whole logic (which is a bad idea).
Could some one tell me if there is any TinyMCE native solution to get that (without any custom external JavaScript)?
There is no configuration option to do what you want but you can get notified when content is set into the editor and modify it before its inserted:
http://fiddle.tinymce.com/prgaab
The key code is here:
editor.on('BeforeSetContent', function (e) {
//Look at this object - it tells you a bunch of stuff about the insert activity
//such as was it via paste? Was there selected content in TinyMCE that will be overwritten?
//Using the browser tooling you can inspect the e object and learn a lot about the content that will be set.
console.log(e);
//Then you can modify that content if you want...for example:
if (e.content.startsWith("<a href=")) {
console.log('ADDING CONTENT');
e.content = '<p>BEFORE</p>' + e.content + '<p>AFTER</p>';
}
});
I designed my resume with bootstrap and material design lite, now I want to convert the html page to pdf file.
I tried some libraries (jsPdf) and some tools (html2pdf, princexml), it produces the pdf file but the problem is, that pdf is not what it looks in the html page.
There is no styles, the output i am getting is similar to pressing ctrl+p` in browser.
My question is,
Is there any tools or libraries for my problem ?
or
Is there any options in above mentioned tools that i can use?
pdf outputs
Try this converter WKHTMLTOPDF on your back-end. It outputs exactly what your see in you browser. It supports html, css and even js. Wkhtmltopdf based on webkit.
Using runtime it can be used like that
wkhtmltopdf http://google.com google.pdf
In your case, it seems that wkhtmltopdf can not load css. Check right css include path. Do not use relative path.
Your problem is the Bootstrap library, not any plugins or PDF tools you are using. It removes most styles when you "print" a web page, including print to PDF. My company, the DocRaptor HTML to PDF service, has a great blog post with a list of suggested fixes for getting Bootstrap styles to print correctly, but they could be summarized as:
Print using screen CSS mode/rules, not print. Otherwise, you have to a lot of overrides for Bootstrap to get it to work right. Much easier to just make the renderer use screen mode.
Bootstrap will think most PDFs are an extra small device, like a cell phone, so you have to either adjust your breakpoints or your in-code column definitions.
If your last column drops to a new row, this is because Bootstrap defines the width for many columns as XX.66666667%. The PDF engine adds all these up, and because of the 7 at the end, it is technically greater than 100%. Since the row width is over 100%, it bumps the last column to a new row. the fix is to override Bootstrap's column widths (handy Gist file for that).
jsPDF is able to use plugins. In order to enable it to print HTML, you have to include certain plugins and therefore have to do the following:
Go to https://github.com/MrRio/jsPDF and download the latest Version.
Include the following Scripts in your project:
jspdf.js
jspdf.plugin.from_html.js
jspdf.plugin.split_text_to_size.js
jspdf.plugin.standard_fonts_metrics.js
If you want to ignore certain elements, you have to mark them with an ID, which you can then ignore in a special element handler of jsPDF. Therefore your HTML should look like this:
<!DOCTYPE html>
<html>
<body>
<p id="ignorePDF">don't print this to pdf</p>
<div>
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
Then you use the following JavaScript code to open the created PDF in a PopUp:
var doc = new jsPDF();
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 180,'elementHandlers': elementHandler
});
doc.output("dataurlnewwindow");
For me this created a nice and tidy PDF that only included the line 'print this to pdf'.
Please note that the special element handlers only deal with IDs in the current version, which is also stated in a GitHub Issue. It states:
Because the matching is done against every element in the node tree, my desire was to make it as fast as possible. In that case, it meant "Only element IDs are matched" The element IDs are still done in jQuery style "#id", but it does not mean that all jQuery selectors are supported.
Therefore replacing '#ignorePDF' with class selectors like '.ignorePDF' did not work for me. Instead you will have to add the same handler for each and every element, which you want to ignore like:
var elementHandler = {
'#ignoreElement': function (element, renderer) {
return true;
},
'#anotherIdToBeIgnored': function (element, renderer) {
return true;
}
};
From the examples it is also stated that it is possible to select tags like 'a' or 'li'. That might be a little bit to unrestrictive for the most usecases though:
We support special element handlers. Register them with jQuery-style
ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
There is no support for any other type of selectors (class, of
compound) at this time.
One very important thing to add is that you lose all your style information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3 etc., which was enough for my purposes. Additionalyl it will only print text within text nodes, which means that it will not print the values of textareas and the like. Example:
<body>
<ul>
<!-- This is printed as the element contains a textnode -->
<li>Print me!</li>
</ul>
<div>
<!-- This is not printed because jsPDF doesn't deal with the value attribute -->
<input type="textarea" value="Please print me, too!">
</div>
</body>
In CKEditor I wants to differentiate between pasted content and the content added by the user. So, on paste event of ckeditor I am changing the p tags of copied content to div so that all new paragraphs are represented by div tags for copied code. Below is the code.
editor.on('paste', function(evt) {
evt.data.dataValue = data.replace(/(<p)/igm, '<div').replace(/<\/p>/igm, '</div>');
});
This works fine but after doing this when I am pressing enter and trying add any new content ckeditor is adding a new div tag to wrap the content whereas I have this declaration present in my config
config.enterMode = CKEDITOR.ENTER_P;
config.shiftEnterMode = CKEDITOR.ENTER_P;
I tried to change the enter mode in after paste event but didn't helped.
editor.on('afterPaste', function(evt) {
editor.setActiveEnterMode(null);
});
Any suggesttions?
You should not mix <div>s with paragraphs. The content inside the editor should be clean and by making it inconsistent you make it messy. This may cause more issues in the future.
Try the config.forceEnterMode option. By default CKEditor uses the block that you're currently in (to be consistent). With this option you are forcing it to use the block from the enter mode.
What's the best way to get usable DOM for an AJAX-requested page without loading any related images/scripts/etc?
Backstory:
I want to load a page in background, then perform a sort of data-mining on it (this is a browser extension, so I can't control the pages themselves). I do not want to spend time loading images and running scripts on the background page, since it is only page contents I need.
load data via ajax
strip all the tags containing src and href attributes, or simply change the value of those attributes with data:null. If data also contains inline style you should remove all statements containing a reference to external resources (e.g. background and border images, .htc components, xul bindings, .ico cursor)
append filtered data to the DOM and analyze it
step 2 could be achieved through a regular expression in javascript. e.g.
/* here we are in the ajax "success" callback */
...
data = data.replace(/(src|href|style)=['"]([^'"]+?)['"]/gi,
function(match, attribute) {
return (attribute.toLowerCase() === 'style')
? attribute + '=""' /* remove all inline style */
: attribute + '="data:null"'; /* href and src set to data:null */
})
/* append filtered data */
$(data).appendTo($('body_or_other_element'))
If possible, use jQuery, as I mentioned above. It makes it easy to select portions of the page DOM as needed.
Here are some examples:
You can grab tags href attribute like this: $("a", $(ajax_response)).attr("href");
Title's contents: $("title", $(ajax_response)).html();
You might have to test out the selectors to see which work best, but, I think this would be an easy way of going about this.
I'd like to use TinyMCE to WYSIWYG support inline editing of a page's body. The tricky thing is that my page body isn't necessarily rectangular or in the shape of a normal textarea.
Imagine a news article like this one. Could I make the entire story body an instance of TinyMCE so that my editor wraps above and below the lead image and the "don't miss" sections?
In other words, I'd to use TinyMCE (or other editor) to supports wrapping around existing page elements like images, navigation, etc. Since TinyMCE doesn't actually use a textarea for formatting, this should be possible, right?
If you know the dimensions of the image flowing in, you could use a bit of TinyMCE config to create a placeholder inside the TinyMCE editor to make it's content flow around, and at the same time lay the image above the editor window.
Like:
tinyMCE.init({
...
oninit : function () {
/* create '<div style="float:left;width:100px;height:100px"/>'
and insert it in front of the actual TinyMCE data.
*/
},
save_callback : function () {
/* remove the div created with oninit */
}
});
Then position the article image to flow above the editor area.
All in all not trivial, but neither is your problem :-)
Cheers,