I am trying to figure out a way to remove style properties from pasted HTML content into a CKEditor instance. I used the following to remove style attributes completely, but I actually want to keep the margin-left property.
CKEDITOR.on('instanceReady', function(ev) {
ev.editor.on('paste', function(evt) {
if (evt.data.type == 'html') {
evt.data.dataValue = evt.data.dataValue.replace(/ style=".*?"/g, '');
}
}, null, null, 9);
});
The issue is, sometimes margin-left is just switched to the margin shorthand and extra data that I do not want is added to that.
I am looking into jQuery and Javascript methods to try and accomplish this, but I haven't had any success yet.
You can apply properly configured Allowed Content Filter to the pasted data. See this answer to learn how to apply it to a string: Apply CKEditor Advanced Content Filter to a string
The only problem which you may have is that you cannot tell ACF to allow all elements and their attributes, you have to specify the elements. So the filter may look like this:
var filter = new CKEDITOR.filter(
'p h1 h2 h3 img strong em ul ol li[*](*){margin-left}'
);
It will allow all attributes and classes, but only margin-left on these elements.
EDIT
There's an easy way to list all elements:
var filter = new CKEDITOR.filter( {
'$1': {
// Use the hash containing all correct HTML elements
// (plus some more things, but we can ignore them in this case).
elements: CKEDITOR.dtd,
attributes: true,
classes: true,
styles: 'margin-left'
}
} );
Related
Is there a way to define own list styles for ckeditor. I have found the plugin http://ckeditor.com/addon/liststyle but it lets me choose only things like circle or square.
I want to define own css classes for ol or ul in my application that i can use. For example a class to define more space between list elements. the users of the editor should pick the list class via a context menu like in the nice "liststyle" plugin.
Is there a way to do this?
Confirmed the approach mentioned above works, I am using Drupal, Ckeditor List Style (plugin) and the Ckeditor List Style module (Drupal module).
I needed to make a change to the lang > en.js file to add the appropriate Title in instead of the function as the OP.
cute: 'Cute',
Once that was done, inside the liststyle.js file I updated the existing code to this:
Existing code in liststyle.js file:
commit: function(element) {
var value = this.getValue();
if (value)
element.setStyle('list-style-type', value);
else
element.removeStyle('list-style-type');
}
New code:
commit: function(element) {
var value = this.getValue();
if (value) {
if (value == 'cute') {
element.setAttribute("class", 'cute');
element.removeStyle('list-style-type');
} else {
element.setStyle('list-style-type', value);
}
} else {
element.removeStyle('list-style-type');
}
}
I am dealing with CKEditor to add custom list styling to the liststyle plugin.
I added one new style (you can add more if you like) using the CSS class.
Here's how: in liststyle.js (after de-obfuscating) I insert my .logo class:
..........
function e(c,e){
c.lang.liststyle.logo="My bullet"; // BBoyanov - adding 'My bullet' as title in dropdown list (in current language), otherwise it stay "empty" title
var b=c.lang.liststyle;
........
style:"width:150px",
items:[[b.notset,""],[b.circle,"circle"],[b.disc,"disc"],[b.square,"square"],
[b.logo,"logo"]],//BBoyanov - css class 'logo' as Bullet \,[b.logo,"logo"]\
........
commit:function(a){
var b=this.getValue();b?a.setStyle("list-style-type",b):a.removeStyle("list-style-type");
"logo"==b?a.setAttribute("class",'logo'):a.removeAttribute("class");//BBoyanv set 'logo' as CSS class
........
h={a:"lower-alpha",A:"upper-alpha",i:"lower-roman",I:"upper-roman",
1:"decimal", disc:"disc", circle:"circle", square:"square",logo:"logo"};//BBoyanov \,logo:"logo"\
........
You define the CSS class in ckeditor.css (to be visualised in CKEditor) and in your own CSS file.
If you prefer different titles for different languages, you must put translation in the corresponding language .js file of CKEditor.
It worked for me.
However, probably this is injection because it takes over the allowedContent - need tests and confirmation.
I'm trying to search a page for all numbers, and selectively increase the font size only on numbers. So for the header "Over $3000" only '3000' should increase size. So far I have tried this, and a few other permutations on the same theme, but no dice. Any ideas?
$(function () {
function replaceText(i,el) {
var regex = /(\d+)/g;
if (el.nodeType === 3) {
if (regex.test(el.data)) {
$(el).css('font-size', '30px');
}
} else {
$(el).css('font-size', '30px');
}
}
$('body').each( replaceText );
});
What you could use is the .html() method. You can access the HTML of the element in a function as the second argument. However, using body as a selector is dangerously broad—narrowing down your range of selectors will also help greatly with performance.
Mistake: using .html() is extremely risky because you might end up replacing numerical attributes in HTML elements/tags. A better solution would be to fetch the text nodes in all children of the <body> element (although changing the selector to be more specific will help), using a previously published method, will work.
The code consist of two loops:
The first loop iterates through all descendents of the <body> element, i.e. using $('body').find('*').each(function() {...});—this is very costly. You should narrow down your selectors to achieve better performance.
The second loop occurs after retrieving the content of each child, using .contents(), and then filtering based on node type using .filter(). This gives us all text nodes in the body element. We simply replace these text nodes with the regex you have defined.
p/s: It's a good idea to separate the styling from your JS code, unless it has to be specific depending on context. Otherwise, simply declare an appropriate class and style it any way you desire:
$('body').find('*').each(function() {
$(this).contents().filter(function () {
return this.nodeType === 3;
}).each(function () {
$(this).replaceWith($(this).text().replace(/(\d+)/g, '<span class="number">$1</span>'));
});
});
span.number {
font-size: 30px;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Over $2000.</p>
<div><p>Over $3000.</p></div>
I'm currently making a google chrome extension and am using this javascript to change dynamically the background color of the hovered element:
var bindEvent = function(elem ,evt,cb) {
//see if the addEventListener function exists on the element
if ( elem.addEventListener ) {
elem.addEventListener(evt,cb,false);
//if addEventListener is not present, see if this is an IE browser
} else if ( elem.attachEvent ) {
//prefix the event type with "on"
elem.attachEvent('on' + evt, function(){
/* use call to simulate addEventListener
* This will make sure the callback gets the element for "this"
* and will ensure the function's first argument is the event object
*/
cb.call(event.srcElement,event);
});
}
};
bindEvent(document,'mouseover', function(event)
{ var target = event.target || event.srcElement;
/* getting target.style.background and inversing it */
});
bindEvent(document,'mouseout', function(event)
{ var target = event.target || event.srcElement;
/* getting target.style.background and inversing it */
});
and when used with static values, like target.style.background = #FFFFFF; when the cursor hover an element and target.style.background = #00000; when the cursor leave the element, it works perfectly. However, when I try to get the value of target.style.background or even target.style.backgroundColor, I always get rgb(255,255,255), no matter what the background color of the element is.
I know how to convert rgb to hexa and how to inverse it, but if I can't get the initial value of the background, it's useless.
So, my question is: why do var foo = target.style.backgroundColor; always return rgb(255, 255, 255) and how do I get the correct value?
Additional notes: the extension will be ported to other browsers later, so a cross-browser solution would be nice if it is possible.
In my experience, target.style is only populated with inline styling. To get style including css definitions just use the getComputedStyle method. For example
//instead of this
target.style.backgroundColor
//try this
getComputedStyle(target).backgroundColor
*Note that using the getComputedStyle method returns a read-only object, and target.style should still be used to set the background color.
You can't use .style to get settings that haven't been defined using .style or style="". Most browsers implement other ways for getting at current style calculations, these are a minefield of oddities however.
Internet explorer has .currentStyle, whereas the rest tend to implement .getComputedStyle. It would be a good idea to read up on these two subjects, to see their implementation — however, as I have said retrieving style settings is a much more complicated process than it first seems.
Even jQuery's css method only returns settings that have been specifically determined on that element i.e. no inheritance.
The following could be of use however:
http://upshots.org/javascript/jquery-get-currentstylecomputedstyle
The only reliable way I know of is to associate a CSS class or ID with a colour, then extract that from an anchor in a hidden element, or simply from empty anchor tag with the class applied. Otherwise it really is about knowing what that colour is and having it already stored as a value somewhere. My HTML would be the following for this solution:
<style>
a:hover,
a#yourChosenIdName {
background-color:#00FF00;
}
</style>
<!-- -->
<script>
var el = document.getElementById('yourChosenIdName'),
getStyle = el.currentStyle ? el.currentStyle : getComputedStyle(el),
hoverBackgroundColor = getStyle.backgroundColor;
//do something with background-color
</script>
I'm looking for a way to add a inline span element with attributes to a selection.
The hard part of this is getting it working with selections that pass over multiple block level elements.
I was looking in the sourcecode of the StyleCombobox and found this line.
var style = styles[ value ],
elementPath = editor.elementPath();
editor[ style.checkActive( elementPath ) ? 'removeStyle' : 'applyStyle' ]( style );
This way it already works on multiple block level elements.
The only thing is that i would like to apply attributes to the span that is made around the multiple selections for different block level elements instead of applying a style element.
Does anyone know how this can be done?
I used this as solution.
It is indeed possible to set attributes and element type.
this wasn't defined in the api. I found this in the CKEditor 3.0 api (older version)
var style = new CKEDITOR.style({attributes: {name:"changed"}});
editor.applyStyle(style);
The latest Solution for your Problem.
Get Selected Text:
editor.getSelection().getSelectedText();
Put tags and attributes
editor.applyStyle(new CKEDITOR.style({
element : 'span',
attributes : {'class':'YourClass','data-Otherattr':'otherattrvalue'},
style : {'background-color':'gray'}
});
);
Alrite, I have seen other Questions with similar titles but they don't do exactly what Im asking.
I have 2 x HTML documents, one containing my page, one containing a element with a paragraph of text in it. As-well as a separate .js file
what I want to do is extract this text, store it as a JS variable and then use jQuery to edit the contents of an element within the main page. This is the conclusion I came to but it didnt work as expected, im not sure if it is me making a syntax error or if i am using the wrong code completely:
$(document).ready(function(){
var c1=(#homec.substring(0))
// #homec is the container of the text i need
$(".nav_btn #1").click(function(c1){
$(".pcontent span p") .html(+c1)}
);
});
i know +c1 is most probably wrong, but i have been struggling to find the syntax on this one. thankyou in advance :D
var c1=(#homec.substring(0)) will throw an error because #homec is not a valid variable name, is undefined, and does not have a property function called substring. To get the html of an element with an id of homec, use the html method:
var c1 = $("#homec").html();
c1 should not be an argument of the click function because it is defined in the parent scope. +c1 is unnecessary because you do not need to coerce c1 to a number.
If you are trying to add content to the end of the paragraph, use the append method:
$(".pcontent span p").append(c1)
That means you should use this code instead:
$(document).ready(function() {
var c1 = $("#homec").html();
$(".nav_btn #1").click(function() {
$(".pcontent span p").append(c1)
});
});
P.S. Numbers are not valid ID attributes in HTML. Browsers support it, so it won't make anything go awry, but your pages won't validate.
Try this:
$(".nav_btn #1").click(function(c1){
var para = $(".pcontent span p");
para.html(para.html() + c1);
});
The JQuery text() function will allow you to get the combined text contents of each element in the set of matched elements, including their descendants. You can then use the text(value) function to set the text content of your target paragraph element. Something like this should suffice:
$(document).ready(function() {
var c1 = $("homec").text();
$(".nav_btn #1").click(function() {
$(".pcontent span p").text(c1);
});
});
See the JQuery documentation for more details on the text() function. If you need to capture the full structure of the other document, then try the html() function instead.