Force CKEditor to add a class to Image2 widget - javascript

I want to configure CKEditor (version 4.3.2) to add a class-attribute to every Image2 widget figure tag in the content. I use the following code (based on How to add CSS classes and an ID to paragraphs in CKEditor?):
CKEDITOR.on("instanceReady", function(e)
{
var editor = e.editor;
pClass = 'additional_class',
pClassRegexp = new RegExp(pClass, 'g');
editor.dataProcessor.htmlFilter.addRules(
{
elements:
{
figure: function(element)
{
// If there's no class, assign the custom one:
if (!element.attributes['class'])
element.attributes['class'] = pClass;
// It there's some other class, append the custom one:
else if (!element.attributes['class'].match(pClassRegexp))
element.attributes['class'] += ' ' + pClass;
}
}
});
});
Unfortunately, I can add class only for the figure elements having no class 'caption' but then it is not a widget any more.

You can do this with CKEditor 4.4 and above, using some configuration options. Here's the relevant instructions from CKEditor's image2 documentation:
Thanks to the CKEDITOR.config.image2_alignClasses option introduced in CKEditor 4.4 you can use CSS classes for setting image alignment. Additionally, the CKEDITOR.config.image2_captionedClass option allows you to assign a custom class to the element of a captioned image....
config.image2_alignClasses = [ 'image-left', 'image-center', 'image-right' ];
config.image2_captionedClass = 'image-captioned';
will produce class-driven, stylable markup that lets you avoid inflexible and non-semantic inline CSS code:
<figure class="image-captioned image-right">
<img alt="MyImage" src="myimage.png" />
<figcaption>MyCaption</figcaption>
</figure>

Related

Class styles are applied when attribute set manually but not dynamically

I want to change the class name of a canvas dynamically (after a click) using javascript in my AngularJS application, for this I tried the following code :
submit.addEventListener("click", function() {
var cc = angular.element(document.querySelector('[ng-controller="DashboardController"]')).scope().canvas;
cc = "chart chart-"+cc;
document.getElementById('mycanvas').className = cc;
},false);
The first query is to get the "cc" value, the second is to change the class name.
"mycanvas" 's class name is changed to the "cc" value (I checked that by inspecting the element) but the styles aren't applied !
For example, when I set the class manually to "chart chart-line", the chart appears, but it doesn't work dynamically.
Any ideas why and how ?
You can do this with an ng-click and append the new class you want.
HTML:
<button ng-click="Controller.changeClass"></button>
Javascript:
vm.changeClass = function () {
document.getElementById("mycanvas").className += "whateverClass";
};

Toggling Background Color on Click with Javascript

I am working on a class project and need to be able to toggle the background color of a transparent png on click. I have been working through a number of examples from the site, but I can't get it working. I am a total novice at Javascript and haven't had luck trying to plug in jQuery code either.
Here is the targeted section:
<div class="expenseIcon"><a href="#">
<img src="images/mortgage.png"></a><br/>
<p>Rent or Mortgage</p>
</div>
On clicking the linked image, the goal is for the background on the image to change to green. Clicking it again would change it back to the default, white. Here's the CSS I'd like to toggle on/off with click.
.colorToggle {
background: #A6D785;
}
I had tried adding class="iconLink" to the href and class="iconBox" to the image with the following Javascript adapted from another post, but it didn't work.
var obj = {};
$(document).ready(function () {
$(".iconLink").click(function () {
var text = $(this).find(".iconBox");
obj.var1 = text;
//alert(obj.var1);
//return false;
$('.iconBox').removeClass('colorToggle');
$(this).addClass('colorToggle')
});
});
Any advice would be greatly appreciated!
Let's break down what is happening with your current code when you click the link.
var obj = {};
$(document).ready(function () {
$(".iconLink").click(function () {
var text = $(this).find(".iconBox");
obj.var1 = text;
$('.iconBox').removeClass('colorToggle');
$(this).addClass('colorToggle')
});
});
JQuery finds all elements with the classname "iconBox". In your case, this is the img element. The reference to that element is then saved in "obj.var1". You do not end up doing anything with this reference, so these two lines can be removed.
All elements with the class "iconBox" have the class "colorToggle" removed. Your img element didn't have this class on it, so nothing happens.
The class "colorToggle" is added to the anchor element. Yes! Now the element wrapping the img has a background color.
Unfortunately, clicking the anchor tag again won't do anything, since the anchor tag will already have the "colorToggle" class and all we would be doing would be trying to add it again. Hmm. Let's try changing addClass to toggleClass. Here's our new code:
$(document).ready(function () {
$(".iconLink").click(function () {
$(this).toggleClass('colorToggle');
}
});
Also, note that because we're working with the anchor element, the p element won't be affected by this change. If you want the entire div to change background colors, use this line instead:
$(".expenseIcon").toggleClass('colorToggle');
Using the given markup:
<!-- to toggle the bg-color onClick of anchor tag -->
<div class="expenseIcon">
<a href="#">
<img src="images/mortgage.png">
</a>
<br/>
<p>Rent or Mortgage</p>
</div>
since the question asks for javascript, heres an option for updating the background-color of an element using the built-in js.style method
//get a handle on the link
//only one element w/ className 'expenseIcon'
//first child of 'expenseIcon' is the anchor tag
var link = document.getElementsByClassName('expenseIcon')[0].children[0];
//get a handle on the image
var image = link.children[0];
//listen for click on link & call bgUpdate()
link.addEventListener('click', bgUpdate, false);
function bgUpdate() {
if(image.style.backgroundColor === 'lightgoldenrodyellow'){
image.style.backgroundColor = 'aliceblue';
} else if (image.style.backgroundColor === 'aliceblue') {
image.style.backgroundColor = 'lightgoldenrodyellow';
}
else console.log('image bgColor: ' + image.style.backgroundColor);
}
a similar example
css
.expenseIcon{
background: red;
}
.colorToggle {
background: blue;
}
jquery
$(".expenseIcon").click(function () {
$('.expenseIcon').toggleClass('colorToggle');
});
By default, the div will have expenseIcon background. ToggleClass will toggle the div class with colorToggle so will override the previous color.
You don't need an hyperlink tag A to manage clicks, just put it on the DIV.

using jQuery, how can I remove a dynamically added class to the head of a page

I use an inline editor to edit css classes, when a change is made I wish to remove the class definition and add it again, also user has option to delete the element using it so I need to delete the definition.
Adding works using this code:
$("<style>").prop("type", "text/css").html( "#my_element_"+MaxElements+" {"+ xCSSCode +"}").appendTo("head");
however I can't seem to remove this class which is inserted into the head of the page as follows:
<style type="text/css">#my_element_1 {border-radius: 12.5px;
...
}</style>
create a style tag:
var style = $("<style />", {
id : 'myStyleTag',
type: 'text/css',
html: "#my_element_"+MaxElements+" {"+ xCSSCode +"}"
}).appendTo("head");
to remove
style.remove();
// or
$('#myStyleTag').remove();
I would store the elements in an object:
var styles = {};
...
styles[some_identifier] = $("<style>", {
type: "text/css",
html: "#my_element_"+MaxElements+" {"+ xCSSCode +"}"
}).appendTo("head");
You can remove the style tag easily:
styles[some_identifier].remove();
$('#my_element').removeClass('hidden');
// also
$('#my_element').addClass('hidden');

CKEditor default style for styleCommand (format styles with buttons)

I have created a CKEditor plugin which does the base p, h2, h3, h4 formatting with custom buttons (instead of the stylescombo). It works great, but if I uncheck an element (ex. 'h2'), sets the 'div' tag as parent element for the row. I want to be the 'p' as the default element and also the 'p' button can't be unchecked (unless I clicking on another, ex. 'h2' button). How is this possible?
The plugin looks like:
CKEDITOR.plugins.add('stylesbuttons_custom',{
lang:'en',
icons:'p,h2,h3,h4',
init:function(editor){
var order=0;
var addButtonCommand=function(buttonName,buttonLabel,commandName,styleDefiniton){
if (!styleDefiniton)
return;
var style=new CKEDITOR.style(styleDefiniton);
editor.attachStyleStateChange(style,function(state){
!editor.readOnly && editor.getCommand(commandName).setState(state);
});
editor.addCommand(commandName,new CKEDITOR.styleCommand(style));
if (editor.ui.addButton){
editor.ui.addButton(buttonName,{
label:buttonLabel,
command:commandName,
toolbar:'basicstyles,'+(order+=10)
});
}
};
var lang=editor.lang.stylesbuttons_custom;
addButtonCommand('P',lang.p,'p',{element:'p'});
addButtonCommand('H2',lang.h2,'h2',{element:'h2'});
addButtonCommand('H3',lang.h3,'h3',{element:'h3'});
addButtonCommand('H4',lang.h4,'h4',{element:'h4'});
}
});
I load the plugin like:
config.extraPlugins='stylesbuttons_custom';
I put buttons to toolbar like:
config.toolbar:[['P','H2','H3','H4','Pre']];
Here is a screenshot about the problem:
Cross posting my answer from CKEditor forum.
I think that you need to write your own command instead of using CKEDITOR.styleCommand.
It should work exactly like CKEDITOR.styleCommand when style is not yet applied on current selection.
But when clicked again it should apply the paragraph style, not remove the previously applied style. E.g:
styleCommand.prototype.exec = function( editor ) {
editor.focus();
if ( this.state == CKEDITOR.TRISTATE_OFF )
editor.applyStyle( this.style );
else if ( this.state == CKEDITOR.TRISTATE_ON )
editor.applyStyle( paragraphStyle );
};
PS. I created a ticket: http://dev.ckeditor.com/ticket/10190 because I think that removing block style should revert back to paragraph (in enterMode=P). For now use the above workaround.
Yes, #Reinmar notifies that there is an error in the CKEditor's style.js where the this._.enterMode is not defined.
Doing this on style.js, resolve the problem:
this._ = {
definition: styleDefinition,
enterMode: CKEDITOR.config.enterMode
};
And from now on when a style button is unchecked the block changes to the default 'p' element.
Now my complete working plugin looks like:
(function(){
CKEDITOR.plugins.add('custombuttons',{
lang:'hu,en,de,ro',
init:function(editor){
var order=0,t=this,lang=editor.lang.custombuttons;
// addButtonCommand helper
var addButtonCommand=function(buttonName,buttonLabel,commandName,styleDefiniton){
var style=new CKEDITOR.style(styleDefiniton);
var styleCommand=function(style){
this.style=style;
this.allowedContent=style;
this.requiredContent=style;
this.contextSensitive=true;
};
styleCommand.prototype={
exec:function(editor){
editor.focus();
if (this.state==CKEDITOR.TRISTATE_OFF)
editor.applyStyle(this.style);
else if (this.state==CKEDITOR.TRISTATE_ON)
editor.removeStyle(this.style);
if(commandName!='fakecommand'){editor.execCommand('fakecommand');editor.execCommand('fakecommand');} /* hack to change button state properly */
},
refresh:function(editor,path){
this.setState(path&&this.style.checkApplicable(path)?(this.style.checkActive(path)?CKEDITOR.TRISTATE_ON:CKEDITOR.TRISTATE_OFF):CKEDITOR.TRISTATE_DISABLED);
}
};
editor.addCommand(commandName,new styleCommand(style));
if(editor.ui.addButton){editor.ui.addButton(buttonName,{label:buttonLabel,command:commandName,toolbar:'basicstyles,'+(order+=10),icon:t.path+'images/'+commandName+'.png'});}
};
// _fakebutton (hack)
addButtonCommand('_fakebutton','','fakecommand',{element:'span'});
// style buttons
addButtonCommand('P',lang.p,'p',{element:'p'});
addButtonCommand('H2',lang.h2,'h2',{element:'h2'});
addButtonCommand('H3',lang.h3,'h3',{element:'h3'});
addButtonCommand('H4',lang.h4,'h4',{element:'h4'});
addButtonCommand('Pre',lang.pre,'pre',{element:'pre'});
addButtonCommand('Mini',lang.mini,'mini',{element:'p',attributes:{class:'mini'}});
addButtonCommand('Important',lang.important,'important',{element:'span',attributes:{class:'important'}});
addButtonCommand('Comment',lang.comment,'comment',{element:'span',attributes:{class:'comment'}});
addButtonCommand('Mark',lang.mark,'mark',{element:'mark'});
addButtonCommand('ImgLeft',lang.imgLeft,'imgLeft',{element:'img',attributes:{class:'imgleft'}});
addButtonCommand('ImgRight',lang.imgRight,'imgRight',{element:'img',attributes:{class:'imgright'}});
addButtonCommand('ImgCenter',lang.imgCenter,'imgCenter',{element:'img',attributes:{class:'imgcenter'}});
// button shortcut keys
editor.setKeystroke(
[
[CKEDITOR.CTRL+48,'p'], // Ctrl+0
[CKEDITOR.CTRL+49,'h2'], // Ctrl+1
[CKEDITOR.CTRL+50,'h3'], // Ctrl+2
[CKEDITOR.CTRL+51,'h4'], // Ctrl+3
]);
}
});
})();
There is still a hack in the code. I needed to run a 'fakecommand' to really update (refilter?) the changed tags and all its parent tags. For example the 'p.mini' button caused problems (the state was not updated) when clicked multiple time. So there is still an unelegant solution. Any idea how to force to update or refilter the code after a style is applied?

adding css to custom reusable function

i created a function in jQuery which lets me create a lightbox as following:
var lightbox = create_lightbox(params);
I would like to expand this function so i can add custom css to it and make it look like a feel in any given circumstance. I would prefer to be able to do the folowing:
lightbox.css = {
"background-color" : "red",
etc...
}
What would be the best way to do this and how would i iterate over the css elements inside my function?
tyvm
Create your function to take an object with all the values you want to add to your lightbox's css property, then add in your defaults with jQuery's extend.
function create_lightbox(params, css){
css = $.extend({ "background-color": "default val"}, css);
lightbox.css = css;
}
If you really want to loop over all the properties in css, you could use a for in loop
function create_lightbox (params, css) {
css = $.extend({ "background-color": "default val"}, css);
for (cssKey in css)
lightbox.css[cssKey] = css[cssKey];
}
Just use CSS as CSS should be used: In a <style>-tag or a linked .css-file. The lightbox plugin uses the following dom tree;
<div id="jquery-lightbox">
<div id="lightbox-container-image-box">
<div id="lightbox-container-image">
<img id="lightbox-image" />
<div id="lightbox-nav">...</div>
</div>
</div>
</div>
So then style what you want to style. I guess you dpn't want to use different styles on each of your boxes?
You can add an element property to the lightbox class so you can modify value out of the constructor:
function lightbox() {
this.element = document.ccreateElement("div")
this.light = "light";
this.box = "box";
}
var newLightBox = new lightbox();
newLightBox.element.style.background = "#000";

Categories

Resources