CKEditor 4 shortcode replacement - javascript

I'm trying to make a shortcode "plugin" - similar to what Wordpress uses with TinyMce. I'd like user to be able to insert a shortcode (like [gallery id="3"] or [image id="9"]) via a button and then show a placeholder instead of the actual shortcode. I'll put all the code to github once I get it to work.
Current setup
I have a button which inserts html to the editor using insertHtml() like this:
// Custom button code
CKEDITOR.instances['editor_instance_name'].insertHtml '<div class="media-library-gallery">[gallery id=' + gallery_id + ']</div>'
and I've added extraAllowedContent to allow div with the classes I need:
// CKEditor configuration (config.js)
config.extraAllowedContent = 'div(media-library-image,media-library-gallery)';
I managed to replace div.media-library-gallery with an image using the code below:
(function() {
CKEDITOR.plugins.add('media_gallery', {
init: function(editor) {
CKEDITOR.addCss('.media_gallery{background: #f2f8ff url("/assets/gallery.png") no-repeat scroll center center; border: 1px dashed #888; display: block; width:100%; height: 250px;}');
},
afterInit: function( editor ) {
var dataProcessor = editor.dataProcessor;
var dataFilter = dataProcessor && dataProcessor.dataFilter;
dataFilter.addRules({
elements: {
'div': function(element) {
if (element.attributes.class == "media-library-gallery") {
var fakeElement = editor.createFakeParserElement(element, 'media_gallery', 'div', false);
return fakeElement;
}
}
}
})
}
})
})();
The problem
Currently the replacement nests a div inside the paragraph tag:
<p>
<div class="media-library-gallery">[gallery id="5"]</div>
</p>
I don't want to change the enterMode from the default CKEDITOR.ENTER_P but I want to get rid of the surrounding p. Can I do this using insertHtml or write a rule that would do that for me? Any other suggestions are welcome.
I've been digging around http://docs.ckeditor.com/ for a solution/inspiration but had little luck.

A bit late, but try to insert your div as an element:
var element = CKEDITOR.dom.element.createFromHtml('<div class="media-library-gallery">[gallery id=' + gallery_id + ']</div>');
CKEDITOR.instances['editor_instance_name'].insertElement(element);

Related

is there a simple way to replace a style by another in fullcalendar

i would like to change all the occurrence style="width: 1px;" by style="width: 41px;" in fullcalendar agendaWeek after it render,
for that i used eventAfterRender
and my code is
eventAfterRender: function(event, $el, view) {
if( 'agendaWeek' === view.name ) {
var r = new RegExp(style="width: 1px;", "g");
var txtWith = 'style="width: 41px;"';
$el.find(".fc-body").val().replace(r,
txtWith).
replace(/\</g, "<").replace(/\>/g,
">").replace(/\&/g, "&");
}
Instead of trying to change the inline style attribute, I would assign a CSS class which overrides the inline styling.
$el.addClass('wideCell');
The class .wideCell would be something like this:
.wideCell {
width: 41px !important;
}
If you absolutely want to go with the replacement strategy, I would advise to use the following regex:
function replaceInlineWidth(element) {
// When the element has no style attribute, skip it.
if (!element.hasAttribute('style')) {
return;
}
// Get the style attribute from the element
var inlineStyle = element.getAttribute('style'),
regex = /width\s?:\s?\d+px(?:;|$)/g;
// Replace the inline width declaration with 41px
inlineStyle = inlineStyle.replace(regex, 'width: 41px;');
// Set the modified style attribute back on the element.
element.setAttribute('style', inlineStyle);
}
// Create a test element.
var
element = document.createElement('div');
// Give the test element some inline style.
element.setAttribute('style', 'background-color: #000; width: 1px; margin: 1em;');
// Run the replacement method.
replaceInlineWidth(element);
// Log the inline style, the width should be 41px.
console.log(element.getAttribute('style'));
It will match things like width:1px, width :1px, and width: 1px. It also matches width: 30px. It will be a bit more resilient. If you really only want to replace width: 1px change the regex to width\s?:\s?1px(?:;|$).
to change fc-axis style,
First solution,
#Thijs idea
add to your css file,
.wideCell {
width: 41px !important;
}
go to fullcalendar.js and add wideCell to any class that contain fc-axis, EXP
'<td class="fc-axis fc-time '
become
'<td class="fc-axis fc-time wideCell '
without it i would have
fullcalendar weekview not showing correctly
but it should be like this fullcalendar weekview showing correctly
Second solution
open fullcalendar.js and change
var maxInnerWidth = 0; to var maxInnerWidth = 40;\\40 or what ever feet your need,

Disable/Enable CSS on webpage using Javascript

According to This page I was able to remove all the CSS preloaded and added on the webpage using that. I wanted to implement a button system where "onclick" = enable/disable webpage CSS even the ones pre-loaded by my web-host. I would like to eliminate the style tags to prevent lags for my website users. I prefer using the script that I have linked above unless there is another alternative that works better. Is it possible to enable CSS onclick the same button to disable? If not is it possible, can it be done with this quick? example with the preferred script below:
if (disable) {
style = "disable";
} else {
location.reload();
}
PREFERRED SCRIPT:
function removeStyles(el) {
el.removeAttribute('style');
if(el.childNodes.length > 0) {
for(var child in el.childNodes) {
/* filter element nodes only */
if(el.childNodes[child].nodeType == 1)
removeStyles(el.childNodes[child]);
}
}
}
removeStyles(document.body);
What about a different aproach?
Add initially a class to a body called 'styled' for example
<body class="styled">
use it as a main selector in your css definitions
<style>
.styled a { ... }
.styled h1 { .... }
</style>
then an example jquery script to toggle the class:
<script>
$(function() {
$('#myswitch').click(function() {
$('body').toggleClass('styled');
});
});
</script>
when class is present, the page will be styled, when absent there will be no styling.
Of coures there could be better aproach, but this is the first thing which pops up in my mind
To remove all style on an element, you could do
function removeStyles(el) {
el.style = {};
}
If you want to enable/disable the CSS on the page, then the goal is not to merely remove all the styles on the page, but you will need to save them somewhere also so they can be recalled when the user re-clicks the button. I would recommend having jQuery to help you with this, and it could be done the following way:
var style_nodes = $('link[rel="stylesheet"], style');
style_nodes.remove();
$('*').each(function(num, obj) {
var style_string = $(obj).attr("style");
if (style_string) {
$(obj).data("style-string", style_string);
$(obj).attr("style", "");
}
});
Now you've saved the stylesheets and style DOM nodes inside of style_nodes, and the actual style attribute inside of a jQuery data attribute for that specific DOM node. When you click to add the CSS back to the page, you can do the following:
$('head').append(style_nodes);
$('*').each(function(num, obj) {
if ($(obj).data("style-string"))
$(obj).attr("style", $(obj).data("style-string"));
});
Check out this JS Fiddle I put together to demonstrate it:
https://jsfiddle.net/5krLn3w1/
Uses JQuery, but I'm sure most frameworks should give you similar functionality.
HTML:
<h1>Hello World</h1>
Turn off CSS
Turn on CSS
JS:
$(document).ready(function() {
$('a#turn_off').click(function(evt) {
evt.preventDefault();
var css = $('head').find('style[type="text/css"]').add('link[rel="stylesheet"]');
$('head').data('css', css);
css.remove();
});
$('a#turn_on').click(function(evt) {
evt.preventDefault();
var css = $('head').data('css');
console.info(css);
if (css) {
$('head').append(css);
}
});
});
CSS:
body {
color: #00F;
}
h1 {
font-size: 50px;
}

Apply CSS Repeatedly to Specific Words

I'm trying to apply CSS repeatedly and automatically to specific words.
For example, for the word "Twitter" I want the colour of the text to be #00ACED.
At present I am manually applying these colours around specific brand terms using span classes:
<span class="twitter">Twitter</span>
With the CSS:
.twitter {
color: #00ACED;
}
However, this is a process and I would prefer a method which completes this styling automatically. I have about 20 brand words with an associated colour styling.
Can anyone assist me with this problem. I am using WordPress if that makes any difference.
I think the most straight-forward way to do it is by using a smart jQuery highlight plugin I came across. After applying it, you'll be able to do what you're after. Below is an example, with a link to a live fiddle at the end:
HTML
<p>Some examples of how to highlight words with the jQuery Highlight plugin. First an example to demonstrate the default behavior and then others to demonstrate how to highlight the words Facebook and Twitter with their own class names. Words will be highlighted anywhere in the DOM, one needs only to be specific on where the script should look for the words. It supports case-sensitivity and other options, like in the case of YouTube.</p>
CSS
p { line-height: 30px; }
span { padding: 4px; }
.highlight { background-color: yellow; }
.facebook { background-color: #3c528f; color: white; }
.twitter { background-color: #1e9ae9; color: white; }
.youtube { background-color: #be0017; color: white; }
Highlight Plugin (needs to be loaded after jQuery and before the JavaScript below)
<script type="text/javascript" src="http://github.com/bartaz/sandbox.js/raw/master/jquery.highlight.js"></script>
JS
// default
$("body p").highlight("default");
// specify class name (not case sensitive)
$("body p").highlight("twitter", { className: 'twitter' });
$("body p").highlight("facebook", { className: 'facebook' });
// specify class name (case sensitive)
$("body p").highlight("YouTube", { className: 'youtube', caseSensitive: true });
Include this JavaScript at the bottom of the page (before the body closing tag so that you don't need to use the function below:
$(document).ready(function() {
// unnecessary if you load all your scripts at the bottom of your page
});
Fiddle for the win! :)
Something like this may work. You would have to loop through your search terms and this might not be the most effective way to do it.
function add_class (search, replacement) {
var all = document.getElementsByTagName("*");
for (var i=0, max=all.length; i < max; i++) {
var text = all[i].textContent || all[i].innerText;
if (text.indexOf(search) !== -1 && ! all[i].hasChildNodes()) {
all[i].className = all[i].className + " " + replacement;
}
}
}
var replacements = [
["Twitter","twitter"],
//
]
for (var i = replacements.length - 1; i >= 0; i--) {
add_class(replacements[i][0],replacements[i][1]);
};
Note: I didn't test this at all.
If you know minimum among of JavaScript, this JavaScript library can make your life much easier. it will convert all the letter in the string into a span tag. http://daverupert.com/2010/09/lettering-js/
For those of you interested in the answer, I've created a solution using WordPress functionality:
function replace_custom_word($text){
$replace = array(
'Twitter' => '<span class="twitter"><a title="Twitter" target="_blank" href="http://www.twitter.com/">Twitter</a></span>',
'Facebook' => '<span class="facebook"><a title="Facebook" target="_blank" href="http://www.facebook.com/">Facebook</a></span>'
);
$text = str_replace(array_keys($replace), $replace, $text);
return $text;}

Need help about a function

I am new at Javascript and jQuery. I need help with something like:
<script type="text/javascript">
$(window).load(function(){
$('#createDiv').click(function (){
$("<div/>").html("<span id='myInstance2' style='display: block;'>New Folder</span>").css("display", "none").appendTo("#results").fadeIn();
});
});
</script>
I have this function to click and create a new <span> tag with a text. You can see I have an ID myInstance2. So what I am trying to do is when I click and the span is created, I would like to make this span live-editable. Like I can rename this "New folder" into whatever I want.
If anyone can help it would be great. Thanks in advance and sorry for my bad English :)
If I catch what I think you're trying to do, it's not quite feasable the way you imagine. However, there are tricks. The following is one of them. The idea is to insert a "hidden" input where the span is, then create functions to show the input and hide span when needed (like when user clicks on span. Something like so:
jsFiddle
HTML
<button id="createDiv">Start</button>
<div id="results"></div>
CSS
#createDiv, #results span { cursor: pointer; }
#results div {
background: #FFA;
border: 1px solid;
margin: 1em;
padding: 1em 1em 2em;
}
#results input[type=text] {
border: none;
display: none;
outline: none;
}
JavaScript
// Call for document .onload event
$(function() {
// Normal Click event asignement, same as $("#createDiv").click(function
$("#createDiv").on("click", function(e) {
// Simply creating the elements one by one to remove confusion
var newDiv = $("<div />", { class: "new-folder" }), // Notice, each child variable is appended to parent
newInp = $("<input />", { type: "text", value: "New Folder", class: "title-inp" }).appendTo(newDiv),
newSpan = $("<span />", { id: "myInstance2", text: "New Folder", class: "title-span" }).appendTo(newDiv);
// Everything created and seated, let's append this new div to it's parent
$("#results").append(newDiv);
});
// the following use the ".delegate" side of .on
// This means that ALL future created elements with the same classname,
// inside the same parent will have this same event function added
$("#results").on("click", ".new-folder .title-span", function(e) {
// This hides our span as it was clicked on and shows our trick input,
// also places focus on input
$(this).hide().prev().show().focus();
});
$("#results").on("blur", ".new-folder .title-inp", function(e) {
// tells the browser, when user clicks away from input, hide input and show span
// also replaces text in span with new text in input
$(this).hide().next().text($(this).val()).show();
});
// The following sures we get the same functionality from blur on Enter key being pressed
$("#results").on("keyup", ".new-folder .title-inp", function(e) {
// Here we grab the key code for the "Enter" key
var eKey = e.which || e.keyCode;
if (eKey == 13) { // if enter key was pressed then hide input, show span, replace text
$(this).hide().next().text($(this).val()).show();
}
});
})
what you can do is put a delegated event handler on the enclosing, static element where span will reside #results. The handler will hide the span and reveal an input. I don't know your code well enough but you likely want the id on the input instead of the span. You did not say you wanted to go from editable back to "read-only" so I did not do that.
DEMO
$('#createDiv').on('click', function () {
var str = "Click here to edit it"; // New Folder
$("<div/>").html("<span id='myInstance2' class='editToggler' style='display: block;'>" + str + "</span><input class='editToggler' style='display: none' value='" + str + "'/>").appendTo("#results").fadeIn();
$(this).off('click');
});
$('#results').on('click', 'span', function () {
$('.editToggler').toggle();
});
This should work and is much simpler than other answers (imo):
<script type="text/javascript">
$(window).load(function(){
$('#createDiv').click(function (){
$("<div />").html("<span onclick='$(this).html(prompt(\"Rename \"+$(this).html()))' id='myInstance2' style='display: block; cursor:pointer;'>New Folder</span>").css("display", "none").appendTo("#results").fadeIn();
});
});
</script>
When you click your span, you will be prompted for its new name. To visual represent that your created the span is clickable, I also added cursor:pointer to the style for the span.
Demo: http://jsfiddle.net/XJ6Cn/
Edit: P.S: Do you create more than one spanusing this method? If so, you should create the ids dynamically, because ids are meant to be unique. If you want a string to be the same for all spans, you can set it as a class instead.

jQuery Font Selector: show&hide with focus

I'm trying to implement a jQuery Font Selector in my project but I have some troubles to achieve it. I'm using the source code I found here jQuery Font Selector
You can see the demo here
Everything is working great, except the author of this code hasn't included a function that close the "scrolling menu" if we clicked anywhere else on the screen. You're forced to choose something inside that list for this list to close.
I'm going to paste the code here so it'll be easier to explain.
/**
* Font selector plugin
*/
jQuery.fn.fontSelector = function() {
var fonts = new Array(
'Arial,Arial,Helvetica,sans-serif',
'Arial Black,Arial Black,Gadget,sans-serif',
/* other fonts */);
return this.each(function(){
// Get input field
var sel = this;
// Add a ul to hold fonts
var ul = $('<ul class="fontselector"></ul>');
$('body').prepend(ul);
$(ul).hide();
jQuery.each(fonts, function(i, item) {
$(ul).append('<li>' + item.split(',')[0] + '</li>');
// Prevent real select from working
$(sel).focus(function(ev) {
ev.preventDefault();
// Show font list
$(ul).show();
// Position font list
$(ul).css({ top: $(sel).offset().top + $(sel).height() + 4,
left: $(sel).offset().left});
// Blur field
$(this).blur();
return false;
});
$(ul).find('a').click(function() {
var font = fonts[$(this).attr('class').split('_')[1]];
$(sel).val(font);
$(ul).hide();
return false;
});
});
});
}
From here I tried to modify the code, like adding $(ul).hide(); inside the blur function... Works BUT that i don't want the input to be manually editable. I don't want the user to be able to modify the content of the input except by selecting a font.
I hope you're not to confused with what I'm asking !
Thanks for your help
EDIT: Some changes after discussion:
http://jsfiddle.net/ahkEv/4/
Add the following inside jQuery.fn.fontSelector = function() {
$("body").click(function(){
$(".fontselector").hide();
});
Change $(sel).focus to
$(sel).click(function(ev) {
and add the following to $(ul).find('a').click(function(ev) {
ev.stopPropagation();

Categories

Resources