ckeditor: should show empty spans, but not wrap in p - ckeditor

When I use an empty span, let's say
<span class="anchor" id="jumptome"></span>
ckeditor removes it.
To the config.js of ckeditor I added
CKEDITOR.editorConfig = function( config ) {
config.IgnoreEmptyParagraphValue = true;
};
CKEDITOR.dtd.$removeEmpty.span = 0;
Now ckeditor does not remove the spans, but they are wrapped in p's like
<p><span class="anchor" id="jumptome"></span></p>
Is there any configuration to remove the p's (I need the paragraphs for other elements, just want to avoid them for the spans).
Thanks in advance!

Why would you need the spans? If you need an anchor, why not use for example a DIV which can be styled to be a visible block in the Editor but an invisible ... anchor in the output content? I do this in my CKE app. Although I use widgets for anchors but same princible anyway.
I'm guessing the reason is because of caret positioning and user targeting - how would the user target that anchor? If it can't be targeted - why do you need it in the contents? Why not something targetable?

Related

How to indent the first line of a paragraph in CKEditor

I'm using CKEditor and I want to indent just the first line of the paragraph. What I've done before is click "Source" and edit the <p> style to include text-indent:12.7mm;, but when I click "Source" again to go back to the normal editor, my changes are gone and I have no idea why.
My preference would be to create a custom toolbar button, but I'm not sure how to do so or where to edit so that clicking a custom button would edit the <p> with the style attribute I want it to have.
Depending on which version of CKE you use, your changes most likely disappear because ether the style attribute or the text-indent style is not allowed in the content. This is due to the Allowed Content Filter feature of CKEditor, read more here: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
Like Ervald said in the comments, you can also use CSS to do this without adding the code manually - however, your targeting options are limited. Either you have to target all paragraphs or add an id or class property to your paragraph(s) and target that. Or if you use a selector like :first-child you are restricted to always having the first element indented only (which might be what you want, I don't know :D).
To use CSS like that, you have to add the relevant code to contents.css, which is the CSS file used in the Editor contents and also you have to include it wherever you output the Editor contents.
In my opinion the best solution would indeed be making a plugin that places an icon on the toolbar and that button, when clicked, would add or remove a class like "indentMePlease" to the currently active paragraph. Developing said plugin is quite simple and well documented, see the excellent example at http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1 - if you need more info or have questions about that, ask in the comments :)
If you do do that, you again need to add the "indentMePlease" style implementation in contents.css and the output page.
I've got a way to indent the first line without using style, because I'm using iReport to generate automatic reports. Jasper does not understand styles. So I assign by jQuery an onkeydown method to the main iframe of CKEditor 4.6 and I check the TAB and Shift key to do and undo the first line indentation.
// TAB
$(document).ready(function(){
startTab();
});
function startTab() {
setTimeout(function(){
var $iframe_document;
var $iframe;
$iframe_document = $('.cke_wysiwyg_frame').contents();
$iframe = $iframe_document.find('body');
$iframe.keydown(function(e){
event_onkeydown(e);
});
},300);
}
function event_onkeydown(event){
if(event.keyCode===9) { // key tab
event.preventDefault();
setTimeout(function(){
var editor = CKEDITOR.instances['editor1'], //get your CKEDITOR instance here
range = editor.getSelection().getRanges()[0],
startNode = range.startContainer,
element = startNode.$,
parent;
if(element.parentNode.tagName != 'BODY') // If you take an inner element of the paragraph, get the parentNode (P)
parent = element.parentNode;
else // If it takes BODY as parentNode, it updates the inner element
parent = element;
if(event.shiftKey) { // reverse tab
var res = parent.innerHTML.toString().split(' ');
var aux = [];
var count_space = 0;
for(var i=0;i<res.length;i++) {
// console.log(res[i]);
if(res[i] == "")
count_space++;
if(count_space > 8 || res[i] != "") {
if(!count_space > 8)
count_space = 9;
aux.push(res[i]);
}
}
parent.innerHTML = aux.join(' ');
}
else { // tab
var spaces = " ";
parent.innerHTML = spaces + parent.innerHTML;
}
},200);
}
}

jQuery UI Multiselect Widget With Images (Eric Hynds Version)

The excellent dropdown jQuery UI Multiselect widget that supports styling via jQuery UI Themeroller still doesn't have support for including images within the drop down rows.
I didn't see any answers to this problem within Stackoverflow yet it seems to be asked regularly in various areas of the internet, so I am giving the answer to this question below..
(ALSO See my FIDDLE Example to see this in action,)
The following is based on an initial idea by 'pdlove' for introducing the use of images within this excellent UI Multiselect for jQuery.
Adding Image support for line items in check box text area is achieved by setting out the selector option rows html like this:
<option value="somevalue" image="yourimage.jpg" class="multSelktrImg">
normal visible text
</option>
I would also add a class control to your style sheet css file to set the image size being rendered in the option line items of the drop down, along with a couple of position settings for the image, label and span text.
In this example I use the class name 'multSelktrImg', so within the css file it would look something like this:
.multSelktrImg span{position: relative;top: 10px;vertical-align: middle;
display: inline-flex;}
.multSelktrImg input {vertical-align: -2px;}
.multSelktrImg img {position: relative;height: 30px;margin: 2px 6px;top: -10px;}
Now for the change in the src/jquery.multiselect.js file
Search for the following matching code around line 130 (depending on what version id of the script you are using):
// build items
el.find('option').each(function( i ){
var $this = $(this),
parent = this.parentNode,
title = this.innerHTML,
description = this.title,
....
ADD the following line above "title = this.innerHTML,":
image = this.getAttribute("image");
so that it looks like this:
// build items
el.find('option').each(function( i ){
var $this = $(this),
parent = this.parentNode,
image = this.getAttribute("image");
title = this.innerHTML,
description = this.title,
Now Search for the following matching code around line 180:
// add the title and close everything off
html += ' /><span>' + title + '</span></label></li>';
....
Replace the code line with the following to allow for rendering of your images:
// add the title and close everything off
html += ' /><span>';
if (image != null) {
html += '<img src="'+image+'" class="multSelktrImg">';
}
html += title + '</span></label></li>';
save the new version of the script src/jquery.multiselect.js file and now the images will appear in the multiselect drop down. Use the 'multSelktrImg' class value to control the size of the image displayed by altering the pixel size for the class in your css file.
In the FIDDLE version, I have altered the minimized version of the jQuery script, and created an initialisation of the Select object.

CKEDITOR 4 Inline mode Toolbar in LI contenteditable

In CKEDITOR 4 I'm using the inline mode
I have a BulletedList with <ul contenteditable="true">
and when I press ENTER I can't not create a new LI with a <P contentenditable="true"> children to have the toolbar for format text options.
Here the JSFIDDLE
And here the list plugin source
You cannot build your editor on <ul> element because CKEditor wasn't designed to work like that. You can find the list of editable elements by calling CKEDITOR.dtd.$editable in your console:
CKEDITOR.dtd.$editable
>>> Object {address: 1, article: 1, aside: 1, blockquote: 1, body: 1…}
You can wrap your list in div element, make it editable and strip out when retrieving data. There's a simple example of how to modify elements on editor output. You'll need to return false when your div is processed. This is it.
You can also do this with RegExp but I don't find it gentle ;)

Only set a marker if content is there

I'm currently adding a custom marker to tt_news. I want to keep the design in the template. But if the markers are empty I get <br /><h2></h2> and so on. This only makes sense if there is a content. Currently I have the logic and the formatting in class.tx_tt_news.php. Is there another way?
From what I read you put <h2>###GENERIC_MARKER###</h2> into the template. You better wrap the content in typoscript an set required=1. In this case the wrap will only be rendered when there is content. Example:
marker = TEXT
marker.field = title
marker.wrap = <h2>|</h2>
marker.required = 1

Templating issues with Backbone.js views : this.el attributes

I'm trying to find the best way to render a li-element :
I've read that i should never replace this.el
So it seems that i have to unwrap my template in my LiView render() function :
// replace element content with html generated from template
var $rendered = $.tmpl(this.template, this.model.toJSON());
this.el.html($rendered.unwrap().html());
I just get the contents inside the $rendered li, since i should not replace it.
But how should i transfer attributes ?
I tried :
this.el.attr('class', $rendered.attr('class'));
this.el.attr('title', $rendered.attr('title'));
But it replaces attributes... And some (like jQuery ui ui-draggable) could be lost.
All this seems a bit clunky...
Thanks !
I'm not sure I fully grasp what you're trying to do Olouv, but I'll have a stab at answering your question regardless :)
You have an liView that corresponds to an li dom element
So you need to specify
el: "li"
Do not have an li in your template. Then the result of your render will be
<li>
contents of template
</li>
Now you want to add attributes to this li element?
Class names are pretty simple, just add the className attribute to your view
className: "ui-draggable myGreatClass ui-corner-all"
If you need to add additional attributes to your root (li) element
$(el).attr("title","your title")
If that doesn't work for you, and you want to put the li attributes in your template perhaps consider some form of the following:
Tolerating HTML of the form:
Instead of an liView (list item view), just have a ulView (List view), and put a loop construct in your template

Resources