Consider the following markup:
<p>spaceflight</p>
<p> </p>
<p> </p>
<p>spaceflight</p>
When user selects the whole block of text (e.g. using [Ctrl+A]) and applies font formatting in CKEditor the resulting markup is something like this:
<p><span style="font-family:comic sans ms,cursive">spaceflight</span></p>
<p> </p>
<p> </p>
<p><span style="font-family:comic sans ms,cursive">spaceflight</span></p>
i.e. font is not applied to the empty paragraphs.
Steps to reproduce the problem:
type a couple of lines of text, use [Enter] to insert empty paragraphs in between the lines
use [Ctrl+A] to select the whole block of text and apply "Comic Sans MS" font to the selection
use [Source] to check the resulting markup and see that the empty paragraphs are missing the font style
switch back to editing mode and type inside one of the empty paragraphs, the new text indeed uses default font
Is there any known workaround allowing to make CKEditor to apply formatting to empty paragraphs inside the current selection?
The problem here is after user has explicitly applied font to the whole block they expect the whole block to be in that font, but when they use cursor and navigate to one of the empty paragraphs and start typing there it's a different font altogether
So the problem is actually different - it's not related to data, but to these empty blocks not preserving styling inside the editor. There's a ticket for this somewhere, but the solution is not trivial. The problem is that when you apply style to an empty block this structure is created (inspect the DOM of the editor):
<p><strong></strong><br /></p>
The <br> there is for making the paragraph visible - it's so called bogus br. Otherwise, the paragraph would have 0 height.
Now, when you try to place your caret there (using mouse or keyboard) the browser finds an empty strong element, which is 0x0 and a paragraph which has non-zero width and height. Where the browser puts your caret? In the paragraph.
The same situation happens if you apply style on an empty selection and move your caret - there's still an empty inline element out there, but you won't be able to move your caret back to it.
It is possible to workaround this and there's even more than one way. Unfortunately, none is trivial.
If you want to attempt to implement a hack which should solve the most common cases, then it should work like this:
Watch the selection changes (editor#selectionChange).
If selection is collapsed and it is placed in an empty block (mind bogus brs) and there's an empty inline element, move caret there.
CKEditor's selection engine is able to place caret in an empty inline element (native implementations in Webkit and Blink are not able to do that).
Related
I've been working with contenteditable recently within a HTML5 page and encountering bugs when using it with certain elements, and I'd like to know where and how I can actually safely use it.
I've discovered that making a span element contenteditable results in some buggy behaviour in both Firefox1 and Chrome2. However, making a div or section contenteditable appears completely safe3.
A guideline a couple of people have mentioned is that only block-level elements should be made contenteditable. However, the Mozilla Developer Network lists the heading elements h1 through to h6 as block-level elements, and making a heading element contenteditable is buggy in Firefox4 and can crash the page in Chrome5.
I'd like to be able to use more than just divs and sections, but I'm not clear on what elements I can actually safely make contenteditable. By safely, I mean that using the element under normal conditions, I should be able to perform normal editing tasks without it doing unexpected or buggy things. I should be able to write in it, delete content, cut, copy, paste, and move my text cursor about and highlight text without unexpected or strange behaviour.
So, which elements can I really make contenteditable safely? Is there a specific category? Are there certain criteria the safely-contenteditable element must match?
Bug notes:
Firefox 21 w/ span: Element loses focus if the text cursor is brought to the beginning or end of the element, but not if it got there by deleting content. Highlighting part of the element, cutting and then pasting will split the element in two at that point then insert a blank element between the two parts - without actually putting the text you were trying to paste anywhere.
Chrome 27 w/ span: If the span covers multiple lines e.g. by being wordwrapped, cutting and pasting content will often insert a linebreak after the pasted content.
Unless you make the div display:inline, in which case it can still lose focus as in 1, but apparently only if you bring the text cursor to the end. I don't consider this "normal" usage of the element though.
Firefox 21 w/ heading: Selecting part of the content then cutting and pasting will, similarly to 1, split the heading element in half at that point, and insert a third heading element between the two halves. It will, at least, have your pasted content inside it, but now you have three heading elements where there was originally one.
Chrome 27 w/ heading: Select some content and cut and paste. The page crashes. You get an "Aw snap!" message. That's it.
Demo code
Here's a demo for reproducing the above. It's pretty simple, though at the moment the only thing it isn't reproducing is the lose-focus bug.
[contenteditable=true] {
border: 1px dotted #999;
}
<article style="width: 100px">
<h1 contenteditable="true">Heading</h1>
<p>
<strong>Some adjacent content</strong>
<span contenteditable="true">Span! This is long enough it will spread over multiple lines.</span>
</p>
<div style="display: inline" contenteditable="true">An inline div also with multiple lines.</div>
</article>
In my opinion, I'd say div is the safest bet across the board. Any element you wish to truly edit (be it a span, header, etc), you can place inside the div and edit as if it were just that element. Also, to account for the display:inline issue you mentioned, you could always use float:left or float:right on your editable div to give it an "inline feel" without having it actually be inline.
Hope that helps!
Since this is an evolving feature with, apparent, low priority from the browser vendors support has been sketchy and regressions not uncommon. The current state of affairs is evolving, so check the Googles, CanIUse etc and make sure support is there for your sites visitors, everything else is moot ...
Support in Firefox seems to be solid, at least for some elements, now https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content
It works well in Chrome as well as far as my testing goes.
And CanIUse looks good: http://caniuse.com/#feat=contenteditable
There are a number of different bugs related to the feature in the different browsers though, but for simple use cases it should be ok now, as of August 2016.
I'm having a problem finding out which css is actually applied to an element when using Firebug 1.11.2. I'm setting the paragraph font from my own css file (d.css), which is meant to over-ride 3 system css files (a.css, b.css, c.css).
I click on the html tab, and click on the <p> element that I'm
trying to debug.
The style window on the right now shows the applied styles from a.css, b.css, and c.css, but not d.css. No paragraph font is shown, but I can change the paragraph line-height, for example, from a.css.
If I click on the css tab, and find d.css, I can manually change the font and font size and see the changes applied to the <p> element in the main window. However, the style window on the right still shows no font.
Is there some magic to showing all the applied styles?
Try using another add-on for viewing your CSS code, for instance:
https://addons.mozilla.org/en-US/firefox/addon/web-developer
You can try other add-ons.
A bit dumb, but probably worth answering rather than withdrawing the question...
turns out that you have to be rather more careful when selecting the html element than I'd realised. My text was actually in a span:
<p>
<span class="foo">bar</span>
</p>
The problem was simply that selecting the <p> element or the bar text doesn't show the styles applied to bar - you actually have to select the entire span element by clicking on the span word.
Thanks.
I have the following HTML code:
this is just a <i>test sentence</i>
As you can see, I put in "white-space:nowrap" to ensure that the sentence stays on one line no matter the browser window size. However, it seems that italicizing some words in the sentence prevents this from happening. On smaller browser windows, the result is "this is just a" on one line and then "test sentence" on the next line. How do I make it so that the sentence always stay on one line?
Italic does not cause line wrapping. The problem is in some part of a style sheet that was not disclosed in the question (the code posted does not demonstrate the problem). It might be a “killer CSS reset”, which really tends to mess things up. It might be something like * { white-space: normal }, which naturally causes normal line wrapping inside the i element, instead of letting it inherit white-space from its parent.
So you should clean up your use of CSS, preferably getting rid of “CSS resets”. Reset just the properties that really need to be reset.
I've had this problem as well in FF - identical situation.
The quickest fix is to set the font size to be a bit smaller e.g 90%.
I don't have any css resets either.
You could try adding inline-block to the href which works at least in chrome
this here is a very long is just a<span style="font-style: italic"> test sentence</span>
I'm using CKEditor in OpenCart 1.4.9.3. My problem is with the paragraph tags it automatically add and how it handles applying header tags. Say I have this text:
Example text here
This is some example text.
CKEditor has them both in the same paragraph block even though they're on different lines. I highlight Example text here and select h1. It makes both lines h1 instead of just my selected line.
How can I fix this? I imported over 1000 products so I can't very well go through and replace every p with a br, especially since in any new product, the editor will add p tags anyway. I am aware I can add the header styles in Source, but my coworkers can not handle html. They need to be able to highlight a line and change it to h1 or h2 without hassle.
Thanks!
Are you sure that it works if there's a br to make a linefeed, but not when there's a paragraph?
As I've figured, the h1 would apply to the whole paragraph, ie change the p to h1.
Try the same in your Word Processor, with linefeed (ctrl+enter) or new paragraph (enter).
I'm working with an <input> field and I'd like to style part of the field as the user's typing in a different color. For example, let's say the <input> has a style declaration of color: red; and I want to change part of it to color: blue;. Is there any way this is possible?
If there isn't (as I suspect), any creative ideas on how I can simulate this effect while still preserving semantic mark-up?
Your suspicions are correct: styles will apply to the whole input only.
As styles can apply to the entirety of an element only, a solution will require at least one element per required colour.
Consider the division of the input field with respect to the point at which the user is making changes. There are three sections of the input:
that before the point at which changes are being applied
that after the point at which changes are being applied
that at the point the changes are being applied
You cannot achieve this with a single input element. And as the point at which the changes are being applied can change, the portions of the 'input' wrapped by the three elements will also change. JavaScript is required for a solution.
You should initially include a regular input element and forgo any of the required colouring. Use JavaScript to replace the input with a suitable container element. This can be styled to mimic an input element.
As changes occur, use JavaScript to identify the above-mentioned three divisions. Wrap them in suitable elements (spans would be ideal) and colour as needed.
Consider the following starting point for the generated replacement markup:
<div class="input">
<span class="nonEdited before">foo</span>
<span class="edited">fizz</span>
<span class="nonEdited after">bar</span>
</div>
Use click, keydown and keyup events to figure out the three divisions for the input and to apply wrap the three portions of the faked input as required.
As others have said, you can't do this with styles and static markup.
You could probably do it with a Flash-based form.
But, if I had to this, I'd use jQuery to overlay divs, with the colorized text, atop the <input>.
Algorithm:
Use a normal <input> with whatever default styles are desired. The contents of this input will never change except by user action.
jQuery monitors that <input>. When it detects trigger word(s), it adds a <div> after the input and fills it with the trigger word(s) -- styled as desired. Probably one <div> per word or phrase is best.
jQuery then positions the new <div>, absolutely, directly over the trigger word(s).
Getting the trigger word(s) offset within the <input> might not even be necessary, because the previous words could also be in the overlay <div> -- either styled defaultly or with visibility: hidden.
But, if only the trigger word(s) are desired in the overlay, then using a fixed-width font, like Courier, will help with the sub-positioning.
Take care that the overlay does not interfere with the user trying to mouse or key to certain parts of the <input>. IE, probably don't want to cover any more of the <input> than necessary, and set a click() handler to relay focus.
Alternate, user friendly and simpler approach:
Rather than try to do funky, non-user-expected things to the input, take a page from Jakob Nielsen and from sites like StackOverflow.
Just have a plain ol' <input>, but underneath it, show the formatted text as it comes in.
You can achieve this with (a lot of effort and) a div with the contentEditable attribute present. This is how most web-based WYSIWYG editors achieve rich formatting of inputs. See here for more info: http://ajaxian.com/archives/on-browser-wysiwyg
You can keep differently styled divs side by side in a container overlapped by a transparent input. Modify the widths of the styled divs on the basis of your input entry.
For example, to color input background for leading and trailing spaces:
<div class="bckg-container">
<div id="bckg-leading" class="bckg spaces">
</div>
<div id="bckg-middle" class="bckg">
</div>
<div id="bckg-trailing" class="bckg spaces">
</div>
<br style="clear: left;" />
</div>
<input id="inpt" type="text" placeholder="Add leading/trailing spaces" maxlength="20" />
The three divs inside the container will change their width with input change.
Check the working example in jsfiddle http://jsfiddle.net/TalhaAwan/ywyw4qq5/
You might be able to do it with some edit in place javascript (if it's not possible in pure html/css):
http://www.appelsiini.net/projects/jeditable/default.html
That jQuery plugin doesn't use html input fields so it could be possible to style different parts of the input. It has a couple of hooks for callbacks which you could use to style the input. Hope that helps as an idea.
You can have a label mocking that input and the real input to be hidden, then you can do a lot of things beteen label tags (e.g. colored spans).