Get ckeditor object from innerHTML - javascript

I have a situation where i have to take the CKeditor text from an iframe, in javascript, following some answers to similar problems (but not exactly the sames) i've arrived to get the inner html of the page and what i get is the textarea of the CKeditor.
To get what i've written above i've used this method:
document.getElementById(id).contentDocument.body
Now from here i would like to do one of those two things, but i don't know how or if it's possible:
1) First and more preferable, i would like to parse the body as a CKEDITOR instance, so that i can use the libray methods to get the text inside, is it possible?
2) Second (if the first option is not possible) i would like to navigate more inside but the only way that i have in mind is another getElementsById, but by reading some answer around i've seen that this is not a good practice to do what i need, why?
What's the best practice between the two? (Or if there is another way, what is it?)

Related

How do I know which JavaScript methods suit with which HTML-elements?

I want to understand which type of JavaScript functions/commands I need to use on which type of HTML-elements to make the intended action (say, print a value on that specific element).
For example, I have now faced the problem of having several different ways to implement the given value to the specific element in the HTML-page, but there is next to no explanations why it works on specific elements.
However, googling about this give me more information about frameworks and alternative workarounds rather how to do it with PLAIN JavaScript, which is what I am looking for.

Is calling a bunch of HTML in a JS function bad practice?

Here's what I'm trying to do:
I am doing a few things to my text input via "oninput=myFunction()"
When I start typing I wanted to do a few things:
I have the function removing a few elements and adding a textNode already, however, I need it to add 35-40 lines of HTML as well.
Would this be bad to do?
I'm not exactly sure how I should set it up to call this HTML through the function yet.
What's the best/cleanest way to go about doing this?
Should I just keep the HTML wrapped with a hidden display:none class, and have the function add a visible class?
I feel like that wouldn't be the best method, so that's why I'm here asking!
Any advice is appreciated. I'm typing on my phone so sorry if I wasn't very clear.
The better way in my opinion is have a script that will add your event handler after the element is ready (after page load). This function should take care of creating and removing any element that are part of the script on the fly.
Doing this will make sure your HTML is clean and that the JavaScript will do what it is responsible for. There are good ways to create HTML with JavaScript by using methods such as document.createElement and document.createTextNode. When your elements are created, you can append them in the right positions.
To help get the best rendering on all browsers, it is usually a good practice to make your elements display: none before everything is ready to display.

Is there a better way to do innerHTML?

I want to know if there is a better way to be doing innerHTML than what I do here. The way I am doing it is causing problems because of the fact that I can't have triple nested quotes. along side that, it is really hard to look at and manage. Thanks!
function buttonClicked(buttonValue)
{
switch (buttonValue)
{
case 1:
soundFolders.innerHTML = "<li onClick='buttonClicked(11);'>Thunder 1</li> <li onClick='buttonClicked(13);'>Light Rain 1</li> <li onClick='buttonClicked(0);'>Back</li>";
break;
case 11:
if(!thunder1Control)
{
thunder1.play();
var thunder1Control = document.createElement("li");
soundList.appendChild(thunder1Control);
thunder1Control.innerHTML = "<h3>Thunder 1</h3> <button class='stopSound' onClick='thunder1.pause(); thunder1.currentTime=0; thunder1Control.parentNode.removeChild(thunder1Control); '>X</button> <button class='volDown' onClick='thunder1.volume -= 0.25;'>-</button> <button class='volUp' onClick='thunder1.volume += 0.25;'>+</button>";
thunder1Control.setAttribute("class", "playingSound");
}
P.S. Do you guys know why the thunder1Control.parentNode.removeChild(thunder1Control) is not working?
To your first question about another way to approach this type of code, "best" is a matter of opinion so I won't really try to address what is best. But, I will give you some alternatives:
Avoid putting code into strings in your HTML. There are all sorts of limitations with that and you generally want to separate code from presentation anyway.
Install event handlers in your code with obj.addEventListener() instead of putting event handlers and code in your HTML.
Use classes and IDs or DOM queries from a particular point in the hierarchy to retrieve specific objects in your page rather than trying to save references to them in global variables. In plain javascript, element.querySelectorAll() is pretty powerful.
In many cases, it's much simpler to just hide and show blocks of HTML using obj.style.display = "none" and obj.style.display = "block" than it is to dynamically create and destroy HTML and this has the added advantage of the HTML is all specified in the page and doesn't have to be shoehorned into a javascript string.
For large blocks of dynamic HTML that wouldn't work well with hide/show for whatever reason, you can dynamically load snippets/templates of HTML from your server using ajax or you dynamically create the HTML using javascript. My first preference is generally hide/show and then if that isn't practical for some reason, it depends upon how much the HTML I want to insert varies based on the state for whether I'd rather load a template or create it dynamically using javascript. If you have large blocks of HTML you have to fit in your javascript, it is messy with quoting, etc... - no way around that if you go that route other than using one quoting scheme for the JS string delimiter and the other in your HTML.
In your particular case, it sure looks like the hide/show method would be simple.
To your second question, this line of code:
thunder1Control.parentNode.removeChild(thunder1Control)
does not work because the thunder1Control variable is long, long out of scope when your click handler is executed because it's a local variable in your buttonClicked() clicked function.
When you put code into a string as part of HTML, it is evaluated in the global scope only so any variables that it tries to reference, must themselves be global in scope.
I'd suggest that you NOT put code into strings in your HTML like that. Use references to actual javascript functions. In that particular case, I'd have to see your HTML to know how to best advise you. If there is only ever one thunder1Control, then I'd suggest you just put an id value on it and retrieve it with document.getElementBtId() when you need it rather than trying to save a reference to it in a variable.
There are essentially two other ways that I can see:
Use a framework that helps with this kind of things. Others have
mentioned jQuery. A commenter is arguing that it might be overkill
to include a framework for just this. I would argue that if you're
doing any javascript at all, you should be using a framework to
make it less terrible. But continue onto suggestion 2 if you
disagree!
You can create each of the elements via plain old javascript and append it to the elements that you need, instead of inserting it directly into innerHTML. ex.
var li = document.createElement("li");
soundFolders.appendChild(li);
etc...
But, honestly, use jQuery with some of the suggestions from others. It's pretty small, and it will heavily clean up all of your javascript. Include it via Google and it will likely already be cached in the users browser.
https://developers.google.com/speed/libraries/devguide#jquery
I think a better alternative is to use jQuery, and then instead of using .html() (equivalent of innerHTML in jQuery), you can create a template with your html and use .load() instead. Works nicer and it's cleaner. And you don't have to worry about triple nesting quotes as you said.
Edit: I'm not sure why I'm getting downvoted so much here... The poster doesn't want to worry about triple nesting quotes. A simple and, to me, elegant solution is to use .load() and to create a template, rather than a really long string of html...

How does one figure out what piece of JavaScript changes a given HTML tag?

I often want to change some releatively minor detail about how JS changes the DOM, but I can never figure out which function in what script changes a given tag. How does one do this?
For example, on this page, I want whatever JS is adding the "selected" class to various a tags to also add it to the enclosing li tags. However, I have no idea how to figure out where this is taking place.
Clarification: As much as I'd like an answer to my current, specific conundrum, I'd much rather be taught how to figure it out myself.
CLARIFICATION:Is there a way to point at a certain object in the DOM and find out what script(s) are/were accessing/modifying that object? In other words "watch" that object for JS access/modification.
What you need is DOM breakpoints in WebKit's Developer Tools.
They're designed for tracking DOM mutation events - such as change of an attribute of an element (which is your case), element removal, or addition of subelement. You can refer to tutorial in DevTools documentation.
In basic cases you might want to use grep for searching the strings such as "selected" in your code.
I’m not aware of any debugging tools that’ll tell you when a DOM element is being acted upon by a script.
(If anyone knows of any, dear lord please tell me about them — I’m a freelancer, so I spend most of my working days trying to figure out old, knotty DOM-manipulating JavaScript that someone else wrote.)
You basically have to search through every bit of JavaScript file included in the page, and identify lines that might be taking the action you’re seeing.
In the case of a class name being added to an element, an obvious search is for the class name itself, although that’s not guaranteed to work. E.g.
el.className = el.className + 'sel' + 'elected'
If jQuery is in use, I’d definitely search for addClass.
Once you think you’ve found the right line, then if you have access to the JavaScript code, you can change it and see if your change takes effect.
(And, because view source is still a part of the web, you can get access to the code by saving it all to your computer.)

What's the best method for creating a simple Rich-Text WYSIWYG editor?

I need to create a simple rich-text editor that saves its contents to an XML file using arbitrary markup to indicate special text styles (e.g: [b]...[/b] for bold and [i]...[/i] for italic). All the backend PHP stuff seems fairly straightforward, but the front-end WYSIWYG portion of the feature seems a bit more convoluted. I've been reticent to use one of the currently-available JavaScript-based WYSIWYG editors because the rich-text options I want to allow are so limited, and these applications are so fully-featured that it almost seems like more work to stip them down to the functions I need.
So, in setting out to create a bare-bones rich-text editor, I've encountered three approaches:
The first two approaches use the contentEditable or designMode properties to create an editable element, and the execCommand() method to apply new text styles to a selected range.
The first option uses a standard div element, executes all styling commands on that elements contents.
The second option uses the editible body of a window enclosed in an iframe, then passes any styling commands initiated from buttons in the parent document into its contentWindow to alter selected ranges in the contained body. This seems like several extra steps to accomplish the same effect as option one, but I suppose the isolation of the editable content in its own document has its advantages.
The third option uses a textarea overlaying a div, and uses the oninput JS event to update the background div's innerHTML to match the input textarea's value whenever it changes. Obviously, this requires some string finagling to to convert elements like newline characters in the textarea to <br/> in the div, but this would allow me to preserve the integrity of my [/] markup, while relegating the potentially-messy DOM manipulation to front-end display only.
I can see benefits and drawbacks for each method. the contentEditable solutions seem initially the simplest, but support for this features tends to vary across browsers, and each browser that DOES support it seems to manipulate the DOM differently when implementing execCommand(). As mentioned before, the textarea/div solution seems like the best way to preserve my arbitrary styling conventions, but the custom string-manipulation procedure to display rich text in the output div could get pretty hairy.
So, I submit to you my question: Given the development goals I've outlined, which method would you choose, and why? And of course, if there's another method I'm overlooking that might better serve my purpose, please enlighten me!
Thanks in advance!
Have you looked at http://php.net/manual/en/book.bbcode.php? This is your answer. If you are having doubts, then you are doing something wrong. :-)
Then use JS to track keyup event and simple AJAX to print preview of the input. Just like in stackoverflow.
NB It would be far more efficient to generate the preview using plain-js BBcode approach. However, do not overcomplicate stuff unless you necessary need it.
The problem with BBCode, Markdown, ... is that it's not that trivial for genpop. I suggest looking at widgEditor, it is by far the simplest WYSIWYG editor I've seen to date. It was developed some time ago, so I am not sure about compatibility, but it sure is an inspiration.
I would have included this only as a comment, since it does not directly answer your question, but I am fairly new to SA and could not find out how to do that. Sorry.

Categories

Resources