How to hide CKEditor widget content from source mode - javascript

I'm developing a new Widget for CKEditor 4 and some of its content is generated dynamically by a tool that parses CKEditor content window.
At first, the widget is simply a <span class="my-widget"></span> but then some content will be added on the fly.
When switching to CKEditor's source mode, then all the content inside span is visible and it gets really messy. Moreover, I don't want to save all that content in database but only the outer <span class="my-widget"></span>
I'm pretty sure this is feasible because this is how CKEditor's MathJax plugin works: when inserting a formula using TeX syntax, the plugin generates a <span class="math-tex">[formula here]</span>. Then, Mathjax runs and typesets the formula, producing the nice-looking LaTeX-like formula in CKEditor. However, when inspecting the code, it only shows the outer <span class="math-tex">[formula here]</span>.
I inspected their source code and I saw they were using an iframe inside the widget.
Can someone explain to me how it works and the way to do it without using an iframe if possible?
Thanks!

I actually achieved the desired result using the downcast property of a CKeditor widget. We can register a custom method that will be used to convert a widget into its text-based representation. Also, it is called both when switching from wysiwyg mode to source mode and when calling editor.getData().
Also, reading the docs, you get that:
The downcast function will be executed in the CKEDITOR.plugins.widget context
meaning that this is pointing to your widget. So, essentially, I replaced all my widget's children by a single text node:
downcast: function(element) {
element.children = [new CKEDITOR.htmlParser.text(CKEDITOR.tools.htmlEncode(this.data.text))];
return element;
}
And it does the trick!

Related

highlight.js: CSS styling absent after setting innerHTML

I am using highlight.js for syntax highlighting in a webpage.
When I change the content by setting the relevant innerHTML using JavaScript, the content output on the page updates as expected. However the changed content is not highlighted in the browser.
What is the correct way to deal with this situation, generally or with highlight.js using only JavaScript, HTML and CSS?
I found a solution thanks to #Afsar's insightful comment.
The function initHighlighting from highlight.js:
initHighlighting()
Applies highlighting to all <pre><code>...</code></pre> blocks on a page.
... contains an internal check to see whether it has already been run. Since I was attempting to run it more than once, highlighting was not working correctly.
So one possible solution to updating highlighting after updating content via JavaScript with no page reload is:
var element = document.querySelector(".class_that_contains_code_blocks");
var blocks = element.querySelectorAll('pre code');
blocks.forEach(hljs.highlightBlock);

How can I define a layout for Quill content?

How can you make an editor within editor with Quill? Imagine a scenario: there is some text with formating, then there is an embed (image/video/...) with some formated text on the right. And then there is some text again. So HTML would look like:
<editor>
<regular_quill_stuff></regular_quill_stuff>
<customEmbed> // some CSS flex here
<container contenteditable="false"><image></image></container>
<container><regular_quill_stuff_in></regular_quill_stuff_in></container>
</customEmbed>
<regular_quill_stuff></regular_quill_stuff>
</editor>
NOTES:
in 'regular_quill_stuff_in' user should be able too use the same toolbar but inserting embeds should be disabled.
when you remove embed blot from outside, 'regular_quill_stuff_in' contents should be moved to 'regular_quill_stuff'.
I've tried making some custom blot based on Block, Code and Scroll but I can't really understand how to make it work, and many low level stuff isn't documented very well. Then I tried to create another instance of Quill on a dom node, but it was very buggy becouse main quill was reciving events from within . I was able to fix it with auto-enabling/disabling Quills based on user focusing divs, but it still was buggy, not to mention passing information between two Quills and edit history and deltas were very incoistent.
Surely there has to be a way to make it easier.
Styling and organizing HTML elements on a page is done using CSS stylesheets. Basically, elements get values for their class and id attributes, so that they can be selected to have a desired stylization applied.
This same process is done with any WYSIWYG rich text editor. The buttons on the editor toolbar are responsible for not only adding new content, but also changing what is already present. For some, this involves changing or applying classes to the desired snippet.
We can see this happening in Quill using the alignment format. If you write the following line in Quill:
This is a simple test.
As a result, you will have the following HTML markup in the editor:
<p>This is a simple test.</p>
Selecting a portion of this text and using/applying the alignment format to, for example, center, will cause a class to be applied to the paragraph, and the result will be as follows:
<p class="ql-align-center">This is a simple test.</p>
So what does this mean? This means you can define your own formats to apply classes that are in charge of arranging the layout of Quill content the way you want.
Compared to what you said, the idea is not to add the content to a
container, but to add a CSS class capable of organizing the content.
You can choose to apply attributors, or define new elements for it. But this kind of process requires testing and more testing. I'm not sure how you want to organize things, or what features you want to add. Therefore, for this to be implemented correctly, you will need to test formats and styles for the different HTML elements present as the editor content.
I suggest you start with simple things, such as text, a paragraph. Try to create an attributor that can apply classes to paragraphs. When you can do that, try something else, such as images, videos, the embed elements. You will find varied results, and this will show that you have to test and test until the desired result is found.
As a help, copy the alignment code, but change it to a desired class. More information on this can be found at the following links:
Creating a custom class attributer in QuillJS
Using Quill.js To Build A WYSIWYG Editor For Your
Website
Example for custom class attributor
To learn how to define new formats through blots, see the following links:
Quill-Examples-and-FAQ
Quill GitHub - Parchment
Cloning Medium with
Parchment

passing css to new page using javascript not working

I am building a string comparer using diffjs library and want to display the resultant table in a new page using javascript.
Although I can see the table on a new window and also able to passed the css and js script on the new window (as they are there in the inspect element tab of the browser) but till css is not working and I see only plain text.
I have used w.document.getElementsByTagName("head")[0].appendChild(cssNode);to pass css and respective javascripts to pass js and css to new window
I'm not sure,but maybe wrap it into style tags.
w.document.getElementsByTagName("head")[0].appendChild("<style>"+cssNode+"</style>");

Building a Windows 8 Metro app with jQuery

I am just starting out with Windows 8 development using HTML/JS. I've spent the last few months immersed in jQuery development for apps targeting vehicle head-units and televisions.
Jumping into this, I thought the transition would be simple. I have the design and structure of my site all figured out for the most part and was hoping to follow some of the practices I had been using for my previous work.
That is, I want to essentially create a single page app. The main default.html file will house the top navigation/title and one other div. The other div will be used to load in all the other pages, all separate HTML files within the project.
All of the global functions and major functionality will reside in a javascript file, application.js. Then any page-specific javascript will reside at the top of each HTML file.
I'm quickly realizing that this is a problem. Using jQuery.load() to load in my pages causes security errors in my app.
JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement.
I was really hoping to avoid having to learn a bunch of Microsoft-specific stuff. I think it's great that they've provided a lot of tools and what not, and maybe I just haven't used them enough, but everything just feels too rigid for me and for what I'm trying to do or can already be accomplished with jQuery. I'm one who likes to know EXACTLY what is happening and have full control over it.
Also looking through the templates and sample projects, I really don't like all the repeated code. For instance, every single HTML file declaring all the same references. I want to write my references and sections like my title bar just once, and not have to copy/paste that code all over my project.
Is there a way to do things the way I was hoping, and create a single page app? Do they have their own substitute for jQuery's .load()?
Any help pointing me in the right direction would be much appreciated!
EDIT 8/14/2012:
I have tried using the fix from this question:
Using jQuery with Windows 8 Metro JavaScript App causes security error
This gets rid of the security warning and I can load in HTML using jQuery.load(). However, looking at DOM explorer, my HTML is being stripped of my scripts.
I have also tried wrapping my .load() call inside of MSApp.execUnsafeLocalFunction(), but yet again my file still gets stripped of all scripts. What gives?
I fixed by simply changing the line of jQuery that was causing the error.
jQuery-1.8.0, line 5566:
append: function () {
return this.domManip(arguments, true, function (elem) {
if (this.nodeType === 1 || this.nodeType === 11) {
self.appendChild(elem); // problem line
}
});
},
Changed to:
append: function () {
return this.domManip(arguments, true, function (elem) {
if (this.nodeType === 1 || this.nodeType === 11) {
var self = this;
MSApp.execUnsafeLocalFunction(function () {
self.appendChild(elem);
});
}
});
},
There is a "formal" way to do what you are seeking.
WinJS.Navigation is provided to support "single page apps". For example, the default.html would contain a markup that would represent where the dynamically loaded page content would go:
<div id="contenthost"
data-win-control="Application.PageControlNavigator"
data-win-options="{home: '/pages/home/home.html'}">
</div>
In the example above, the actual content page loaded is at /pages/home/home.html
In event handlers, you can simply do the following to load or navigate to another page:
WinJS.Navigation.nav("/pages/other/page.html");
True, it is not jQuery, but it works great :)
Depending on your app, if you are not intending to access any WinRT components, you can navigate your page to ms-appx-web which will change the security policy around the page, but you can't specify this from start up. You would have to do a navigate, and leverage that new securyt context.
The other option you have it to wrap the calls to JQuery with msWWA.execUnsafeLocalFunction function, which will enable all that unsafe code be pushed into the DOM

Inserting "placeholders" with an FCKeditor plugin to be later replaced with dynamic content

I'm writing a plugin for FCKeditor that's meant to insert placeholders for dynamic content into the HTML. The interface look like this:
Currently, the plugin inserts the following HTML:
<div title="Dynamic Element: E-Cards (sidebar)" class="dynamicelement ecards-sidebar"> </div>
The snippet of Javascript in my plugin that accomplishes the actual insertion of these placeholders is this:
function insertNewDiv() {
var divNode = oEditor.FCK.EditorDocument.createElement('div');
oEditor.FCK.InsertElement(divNode);
oEditor.FCK.Focus();
oEditor.FCK.Events.FireEvent('OnSelectionChange');
return divNode;
}
To make it look nice in the FCKeditor window, I'm applying some CSS to the FCKeditor window, including the following, that writes the title in there:
.dynamicelement:before {
content: attr(title);
}
Anyway, other than the styling, FCKeditor treats these div elements no differently than any other div element in its window. This is not good for me.
I need these placeholders to have the following traits:
Insertion of content into the placeholder is not allowed.
Clicking it should select it as a whole.
Tapping the delete key when it's selected should delete it.
The only way to edit it (apart from deleting it) is to select it, then click the toolbar button to open an edit dialog.
It should always be considered a block-level element
It doesn't matter if the HTML output uses a custom tag name or not (<dynamicelement> instead of <div class="dynamicelement">).
Does the FCKeditor API provide a way to give it command like, "Treat every element that matches the selector 'div.dynamicelement' the following way: ..." ?
Also, is there another FCKeditor plugin that does a similar thing that I can refer to that I might have overlooked in my research?
EDIT: By the way, I already know about CKeditor. I'm using FCKeditor for a couple of reasons: it's working for my CMS, the configuration options I'm using are perfect for my clients (except, obviously, for the placeholder thing), etc..
I solved this by duplicating the code that makes the "Page Break" button work.
While wading through the source code, I learned that FCKeditor has a native method for inserting placeholders.
Create a "fake image" and insert it into the editor DOM. You can style the image however you want.
Using Javascript, connect it to the div in question.
Hide the div (it still appears in the source and in your output though).
While in WYSIWYG mode, you're playing with this fake image, and the changes are being carried over to the div.
There a few bits and pieces that need to be in the plugin to make this work. If you grep for FCK__PageBreak, you will find them all in the source, ready to be copied into your plugin. FCK__PageBreak is the class name of the Page Break's fake image.
You might be able to use ProtectedSource to get what you want:
The editor offers a way to "protect" part of the source to remain untouched while editing or changing views. Just use the "FCKConfig.ProtectedSource.Add" function in the configuration file.
But:
Note that there currently isn't any way to "lock" displayed content in the editor. The content protected with ProtectedSource will actually be invisible during editing. It may be used instead, for example, to protect custom non standard tags or server side scripts. By default, FCKeditor uses it to protect <script> tags from activation during editing.
You might be able to use this together with a placeholder image:
Your plugin adds both the "real" protect tags and the placeholder.
The server strips out the placeholder and does things to the real tag; however, if the placeholder isn't there but the "real" stuff is then delete the "real" stuff.
When editing, the server inserts the placeholder image before sending things off to the browser.
All this seems a little convoluted so you might be better off with a simpler kludge:
Plugin just inserts a placeholder image with a specific class or a fake attribute of your choosing.
Tweak the image plugin to ignore your placeholder.
Replace the placeholder image with the real stuff on the server.
Replace the real stuff with a placeholder image when sending it back to the browser when they're editing the content.
Or, you could use your own custom tag (i.e. <dynamicelement>) and then use ProtectedTags:
In many situations, it is important to be able to switch to the source view in FCKeditor and add a few custom tags, needed for custom processing, or whatever. The problem is that browsers don't know how to handle non standard HTML tags, and usually break the DOM tree when finding them (specially IE).
That combined with some CSS to display <dynamicelement> nicely (say some dimensions and a background image) might do the trick without too much dirty kludging.

Categories