After having created the needed folder and file structure for the module, you can start actually creating the module. Building the module code involves three different steps:
Creating the standard module functions - these functions must exist in every module you create; they are the way to interact with the KTML core.
Create the custom toolbar button which will display the available images and allow the user select one.
Create the main module functions that render the images and handle user events.
Each KTML module must implement two JavaScript functions that allow the module to interact with KTML. The function names are created from two parts:
A prefix which is the module name, identical to the folder name created earlier - in this case smileys.
The standard function names: runonce and runeach.
The final function names are: simleys_runonce() and simleys_runeach(k). The first function is only executed once per page, no matter how many KTML controls are applied. The second is executed by each KTML control individually, and gets as parameter the ID of the KTML instance that is running it.
To create these functions:
First open the <site_root>\includes\ktm\modules\smileys\scripts.js file with a text editor.
Add the following code (these are only function declarations, they do not perform any action):
function smileys_runonce() { }
function smileys_runeach(k) { }
Save the file. Do not close it, as you will add more code to it next.
To create a new toolbar button and assign it to one of the existing toolbars of the editor you will use existing methods of the ktml.toolbar object. The methods of this object you can use to add a button to a toolbar are:
insertButtonAfter(button,[ID],[toolbar_ID]) - as the name suggests, this method will insert a button in the specified toolbar after an existing and specified button.
insertButtonBefore(button,[toolbar_ID]) - this method will add a button in the specified toolbar before the specified button.
Both methods use the same parameters: an instance of the button object - the button we're trying to add, the ID of the button to add after or before and the ID of the toolbar to add the button in. The second and third parameters are optional, and if missing, the new button will be placed either as the first button of the first toolbar, or as the last button in the last toolbar.
Because each instance of the KTML control on page must display the new button, the code that defines a new button and uses one of the methods above to insert it into a toolbar will be placed inside the simleys_runeach() function.
The function declared above will become:
function smileys_runeach(k) {
var imgSrc = KtmlRoot + 'modules/smileys/img/';
var btn = new ToolbarButton({
'group': 'insert',
'command_type': $KT_JS_STRING,
'name': 'insert_smiley',
'help': 'insert_smiley',
'button_type': "combo",
'default_value': '<img width="16" height="16" src="' + imgSrc + '00.gif" border="0" align="center" />'
}, {
'command': insert_smiley_command,
'open': insert_smiley_open,
'paint': insert_smiley_paint
});
k.toolbar.insertButtonAfter(btn, '', 2);
};
Next you have to create the actual module. Before doing so, you must analyze the functionality it needs. As this module aims to be simple, it will only implement basic functionality:
Display the images in a pop-up table, and let the user hover and select one of them.
When the user clicks on one of these images, insert a string of HTML code in the source of the edit area ofKTML. In terms of code source, that string will roughly be saying something like: <img src=”/path/to/file.gif” width=”somevalue” height=”somevalue” title=”tooltip”>.
If you have worked with KTML a little, you will notice that the exact same functionality is already implemented by default in the Special Character Picker. The Special Character Picker allows the user to display a pop-up table with characters, and insert the HTML entity in the editor. You will build the module based on the existing code, by modifying it.
Before starting to add code, take a look at the Character Picker code. You can find it in the <site_root>\includes\ktm\core\js\lib\characterpicker.js file. Open it with a text editor. The code has mainly these sections:
Define the content and the shape of the character picker pop-up (lines 1-51).
Define the main object to represent the character picker pop-up in Javascript (lines 53-65).
Define the functions responsible with initialization/drawing the character picker pop-up (lines 67-118).
Define the user actions related functions - like over, click, etc.: (lines 120 to end).
To build the smiley module you will copy and paste the character picker code, and modify it to accommodate images, and to insert other types of code, section by section.
First, the section that defines the content and shape of the smiley picker:
You have to define the smiley descriptions which will be displayed as tool-tips. Because the file names have been set to use numeric, the script can automatically build the paths. The description will be stored as an array:
var Smileys = [
'smiling',
'sad',
'winking',
'big grin',
'confused',
'love struck',
'blushing',
'tongue',
'kiss',
'broken heart'
];
Next set the main outline of the picker. From the original code replace all charpalette with smileyspalette for all events . Also change the text in the <legend> tag.
var SmileysPaletteDivHead =
'<table border="0" style="border: solid 1px #000000" class="ktml_bg"'+
' id="ktml_@@ktml@@_mousecapture"'+
' onmouseover="window[\'ktml_@@ktml@@\'].smileyspalette.mOver(event)"'+
' onmouseout="window[\'ktml_@@ktml@@\'].smileyspalette.mOut(event)"'+
' onclick="window[\'ktml_@@ktml@@\'].smileyspalette.mClick(event)"'+
'>'+
' <tr class="ktml_bg">'+
' <td valign="top"><fieldset class="ktml_fieldset" style="height: ;">'+
'<legend class="ktml_legend">||Smileys Picker||</legend>'+
'<center>'+
' <table style="margin-top: 5px" cellspacing="4" cellpadding="1px" border="0">';
var SmileysPaletteDivFooter =' </table>'+'</center>'+'</fieldset>'+'</td>'+' </tr>'+'</table>';
Next you will modify the code that creates the picker object. From the original code you have to replace the CharacterPalette with SmileyPalette and change it a bit to suit the precise need:
function SmileyPalette(obj, cols) {
var d;
this.owner = obj;
this.cols = cols;
this.smilyesContainer = document.createElement("DIV");
if(is.mozilla && is.mac){
this.smilyesContainer.style.overflow = "auto";
this.smilyesContainer.style.width = "200px";
this.smilyesContainer.style.height = "85px";
}
this.smilyesContainer = this.owner.toolbar.base.appendChild(this.smilyesContainer);
this.smilyesContainer.style.position = 'absolute';
this.smilyesContainer.style.zIndex = 1000;
this.original = "";
this.preview = 'ktml_' + this.owner.name + '_smiley_preview';
this.isVisible = false;
this.isDrawn = false;
};
Modify the functions responsible with the initialization/drawing of the picker next:
First define the function that will retrieve images from the disk and generates the content for each <td> of the pop-up table:
SmileyPalette.prototype.writeColBtn = function(smileIndex) {
var imagesSrc = KtmlRoot + 'modules/smileys/img/';
var imgFileName = utility.math.zeroPad(smileIndex, Smileys.length.toString().length) + '.gif';
var toolTipText = Smileys[smileIndex];
var HTMLstring = '<td style="border:0px solid #08246B; width:12px;height:14px;cursor:default"><img style="margin:3px"
smiley="'+toolTipText+'" src="'+imagesSrc+imgFileName+'" title="'+toolTipText+'" alt="'+toolTipText+'" border="0" width="16" height="16"></td>';
return HTMLstring;
};
After the drwaing function, define the function that initializes the behavior. It is named initializeUI. The function calsl the “drawPicker()” function, saves the name of the ktml object, and sets the “isDrawn” flag after table generation completes:
SmileyPalette.prototype.initializeUI = function() {
this.drawPicker();
var oname = this.owner.name;
this.isDrawn = true;
};
Now define the method that generates the overall TABLE html layout. It will call the “drawPicker” function subsequently, for each cell. This function is almost identical to the one in the character picker code, having only the object name changed:
SmileyPalette.prototype.drawTable = function() {
var text = '';
var reminder = Smileys.length % this.cols;
var rows = parseInt(Smileys.length / this.cols, 10);
for (var i = 0; i<= rows; i++) {
text+="<tr>\n";
for ( var j=i*this.cols; j < Math.min((i+1)*this.cols, Smileys.length); j++ ) {
text += this.writeColBtn(j);
}
if (i==rows && ( (i+1)*this.cols > Smileys.length) ) {
text += '<td colspan="'+((i+1)*this.cols - Smileys.length) +'"></td>'
}
text+="</tr>\n";
}
return text;
};
The drawPicker function will add the “last touch” to the overall generated HTML code: routine translation, string placeholders replacing, and then will concatenate all and insert all HTML into your pop-up recipient (the one you created in the SmileyPalette object constructor, via document.createElement("DIV"); - see above:
SmileyPalette.prototype.drawPicker = function() {
var text = '';
var header = lang_translatepage(SmileysPaletteDivHead, this.owner.config.UILanguage, window);
header = header.replace(/@@ktml@@/g, this.owner.name);
var footer = SmileysPaletteDivFooter.replace(/@@ktml@@/g, this.owner.name);
footer = lang_translatepage(footer, this.owner.config.UILanguage, window);
text+=header;
text+=this.drawTable();
text+=footer;
this.smilyesContainer.innerHTML = text;
};
The only user interactions you need to worry about are: over, out, click. You'll copy the functionality from the original mdblClick function into mClick, that is, when user clicks a smiley, insert it in page, and close the pop-up:
SmileyPalette.prototype.mOver = function(e) {
var o = is.ie ? e.srcElement : e.target;
var current = o.getAttribute("smiley");
if(o.tagName.toLowerCase()=="img" && current){
o.parentNode.style.borderWidth = "1px";
o.parentNode.style.backgroundColor = "#D1D0E6";
o.style.margin = "2px";
}
};
SmileyPalette.prototype.mOut = function(e){
var o = is.ie ? e.srcElement : e.target;
var current = o.getAttribute("smiley");
if(o.tagName.toLowerCase() == "img" && current){
o.parentNode.style.borderWidth = "0px";
o.parentNode.style.backgroundColor = "transparent";
o.style.margin = "3px";
}
};
SileyPalette.prototype.mClick = function(e) {
utility.dom.stopEvent(is.ie ? event : e);
var o = is.ie ? e.srcElement : e.target;
var current = o.getAttribute("smiley");
var htmlToInsert = '<img src="'+o.src+'" border="0" width="16" height="16" alt="'+current+'" />';
if (!this.smilyesContainer.contains(o)) {
this.owner.util_restoreSelection();
}
if(o.tagName.toLowerCase() == "img" && current){
o.parentNode.style.borderColor = "buttonface";
this.setVisible(false);
this.pickColor(htmlToInsert);
}
};
Keep the pickColor and the setVisible functions unchanged, as they provide basic pop-up functionality for the picker (that is, pick, and show/hide, respectively). Only replace the original object name with the smiley one:
SmileyPalette.prototype.pickColor = function(selectedColor) {
utility.popup.force = true;
utility.popup.removeModal();
utility.popup.force = false;
};
You're almost done. You may now close the character_picker.js file you used as a model. The only things you need to do in order for the smileys module to function in your copy of KTML, is to add the standard functions for any combo button – see the API documentation for related in-depth information.
The button that inserts smileys is a combo box, so it will need the command, open, paint, and dispose functions. The actual names of the functions are those defined in the button constructor:
//...
'command': insert_smiley_command,
'open': insert_smiley_open,
'paint': insert_smiley_paint
//..
The following functions will close the file:
//the function that actually writes the string in the page:
function insert_smiley_command(new_value) {
var tlb = KTStorage.get(this.toolbar_button);
tlb.ktml.insertHTML(new_value, is.mozilla?"after":"");
};
//this function triggers the creation of the picker; note that you
//set the number of smileys per row in the “SmileyPalette” constructor;
function insert_smiley_open() {
var tlb = KTStorage.get(this.toolbar_button);
var cb = KTStorage.get(this.id);
if (typeof(tlb.ktml.smileyspalette) == "undefined") {
tlb.ktml.smileyspalette = new SmileyPalette(tlb.ktml, 5);
}
tlb.ktml.smileyspalette.onSelect = function (new_value) {
cb.setValue(new_value);
tlb.params.command.call(cb, cb.value);
};
tlb.ktml.logic_openSmileysPalette(cb.getElement("table"));
};
function insert_smiley_paint() {
var el = this.getElement("cell");
var tlb = KTStorage.get(this.toolbar_button);
//since there's no generated "ktml1_config['module_props']['smileys']"
//declaration within the page, i used some little hacks to get the path to smileys folder:
var imgSrc = KtmlRoot + 'modules/smileys/img/';
el.innerHTML = this.value.match(/^\<img/)? this.value: '<img width="16" height="16" src="' + imgSrc + this.value + '" border="0" align="center" />';
};
Save the file and upload the entire module folder to the server.
You have to make one more change in order for the module to be recognized and loaded by KTML:
Open the [site_root]\includes\ktm\core\modules.js file.
In this file you must add the name of the module you've created, as an array entry. By default, the KtmlUserModuleList is empty, similar to the code below:
KtmlUserModuleList = {
};
Each array entry has three parameters:
'module_name': ['main' , 'browser']
The three parameters are:
module_name - the name you have given to the module, at the beginning.
main - instructs KTML to load the main scripts.js file.
browser - optional parameter, instructs KTML to load the browser specific js file - scripts_ie.js or scripts_mozilla.js.
To make KTML load the smileys module, add it to the array. The new code should look like:
KtmlUserModuleList = {
'smileys': ['main']
};
Save the file.
Open the page which displays the KTML control. Check if a line like the one below exists in your file:
<script src="includes/ktm/core/modules.js" type="text/javascript"></script>
If it does not, you have to add it right after the line what looks like:
<script src="includes/resources/ktml.js" type="text/javascript"></script>
The new code in the page will have to contain the two lines:
<script src="includes/resources/ktml.js" type="text/javascript"></script>
<script src="includes/ktm/core/modules.js" type="text/javascript"></script>
Save the page to the server.
To test the smileys module, open a page containing the editor and you will notice the smiley button in the insert toolbar. Select one of the displayed images to insert it into the page: