_binary From 53999855c3f117659c9ce2ad02d10e30ec0ed3db Mon Sep 17 00:00:00 2001
From: Eswar Rajesh Pinapala <epinapala@live.com>
Date: Sat, 17 May 2014 21:10:28 -0700
Subject: [PATCH] Made all required changes suggested by Dr.Pollett - Added 
 localization constants. - Cleaned up JS function comments - Removed 
 unneccesary spaces - Removed unneeded comments - Removed unneeded new lines -
  Js Var changes, CS id,class name changes refactoring done > Added filter for
  buttons to include, exclude > if data-buttons starts with all, any comma 
 seperated button name that follows, WITH an exclamantion will be excluded 
 from buttons list. > if data-buttons starts with all, any comma seperated 
 button name that follows, WITHOUT an exclamantion will be ignored. > if 
 data-buttons does NOT start with all, any button name WITHOUT an exclamation 
 at the beginning will be added to inclusion list, and any button name WITH an
  exclamation will be ignored.

---
 css/editor.css                                     |  130 +++
 resources/wiki_button_images/empty.png             |  Bin 0 -> 20702 bytes
 resources/wiki_button_images/wikibtn-bold.png      |  Bin 0 -> 21067 bytes
 resources/wiki_button_images/wikibtn-bullets.png   |  Bin 0 -> 21705 bytes
 resources/wiki_button_images/wikibtn-hr.png        |  Bin 0 -> 20829 bytes
 resources/wiki_button_images/wikibtn-hyperlink.png |  Bin 0 -> 21045 bytes
 resources/wiki_button_images/wikibtn-italic.png    |  Bin 0 -> 20962 bytes
 resources/wiki_button_images/wikibtn-nowiki.png    |  Bin 0 -> 21602 bytes
 resources/wiki_button_images/wikibtn-numbers.png   |  Bin 0 -> 21508 bytes
 resources/wiki_button_images/wikibtn-strike.png    |  Bin 0 -> 21309 bytes
 resources/wiki_button_images/wikibtn-table.png     |  Bin 0 -> 20883 bytes
 resources/wiki_button_images/wikibtn-underline.png |  Bin 0 -> 21229 bytes
 .../wikibtn-yioop-search-widget.png                |  Bin 0 -> 21866 bytes
 scripts/wikify.js                                  | 1164 ++++++++++++++++++++
 views/layouts/web_layout.php                       |    3 +
 15 files changed, 1297 insertions(+)
 create mode 100755 css/editor.css
 create mode 100755 resources/wiki_button_images/empty.png
 create mode 100755 resources/wiki_button_images/wikibtn-bold.png
 create mode 100755 resources/wiki_button_images/wikibtn-bullets.png
 create mode 100755 resources/wiki_button_images/wikibtn-hr.png
 create mode 100755 resources/wiki_button_images/wikibtn-hyperlink.png
 create mode 100755 resources/wiki_button_images/wikibtn-italic.png
 create mode 100755 resources/wiki_button_images/wikibtn-nowiki.png
 create mode 100755 resources/wiki_button_images/wikibtn-numbers.png
 create mode 100755 resources/wiki_button_images/wikibtn-strike.png
 create mode 100755 resources/wiki_button_images/wikibtn-table.png
 create mode 100755 resources/wiki_button_images/wikibtn-underline.png
 create mode 100755 resources/wiki_button_images/wikibtn-yioop-search-widget.png
 create mode 100755 scripts/wikify.js

diff --git a/css/editor.css b/css/editor.css
new file mode 100755
index 0000000..e6d8b76
--- /dev/null
+++ b/css/editor.css
@@ -0,0 +1,130 @@
+.wiki-editor
+{
+    display: block;
+    margin: 0 auto;
+}
+
+.wiki-editor div
+{
+    padding: 5px;
+}
+
+.wiki-editor textarea
+{
+    width: 500px; height: 300px; resize: none;
+}
+
+.wiki-buttons-div
+{
+    margin-bottom: -20px;
+}
+
+.wiki-buttons-div input
+{
+    cursor: pointer;
+    width: 36px;
+    height: 32px;
+    display: inline-block;
+    vertical-align: top;
+    border-style: solid;
+}
+.wiki-buttons-div select
+{
+    background: none repeat scroll 0 0 #FFFFFF;
+    border: 1px solid #E5E5E5;
+    border-radius: 5px 5px 5px 5px;
+    box-shadow: 0 0 10px #E8E8E8 inset;
+    height: 32px;
+    padding: 10px;
+    width: 100px;
+    background-color:lightgray;
+}
+
+div.wiki-overlay-div {
+    display: none;
+    z-index: 2;
+    background: #000;
+    position: fixed;
+    width: 100%;
+    height: 100%;
+    top: 0px;
+    left: 0px;
+    text-align: center;
+}
+div.wiki-popup-prompt {
+    display: none;
+    position: relative;
+    z-index: 3;
+    margin: 150px auto 0px auto;
+    width: 500px; 
+    height: 300px;
+    background: #FFF;
+    color: #000;
+}
+
+
+.wikibtn-bold
+{
+    background: url(../resources/wiki_button_images/wikibtn-bold.png) no-repeat;
+}
+.wikibtn-underline
+{
+    background: url(../resources/wiki_button_images/wikibtn-underline.png) no-repeat;
+}
+.wikibtn-bullets
+{
+    background: url(../resources/wiki_button_images/wikibtn-bullets.png) no-repeat;
+}
+.wikibtn-heading
+{
+    height: 50px;
+    background: url(../resources/wiki_button_images/wikibtn-heading.png) no-repeat;
+}
+.wikibtn-hr
+{
+    background: url(../resources/wiki_button_images/wikibtn-hr.png) no-repeat;
+}
+.wikibtn-hyperlink
+{
+    background: url(../resources/wiki_button_images/wikibtn-hyperlink.png) no-repeat;
+}
+.wikibtn-italic
+{
+    background: url(../resources/wiki_button_images/wikibtn-italic.png) no-repeat;
+}
+.wikibtn-nowiki
+{
+    background: url(../resources/wiki_button_images/wikibtn-nowiki.png) no-repeat;
+}
+.wikibtn-numbers
+{
+    background:url(../resources/wiki_button_images/wikibtn-numbers.png) no-repeat;
+}
+.wikibtn-strike
+{
+    background: url(../resources/wiki_button_images/wikibtn-strike.png) no-repeat;
+}
+.wikibtn-table
+{
+    background: url(../resources/wiki_button_images/wikibtn-table.png) no-repeat;
+}
+.wikibtn-yioop-search-widget
+{
+    background: url(../resources/wiki_button_images/wikibtn-yioop-search-widget.png) no-repeat;
+}
+
+.wikibtn-bold:hover,
+.wikibtn-bullets:hover,
+.wikibtn-heading:hover,
+.wikibtn-hr:hover,
+.wikibtn-hyperlink:hover,
+.wikibtn-italic:hover,
+.wikibtn-nowiki:hover,
+.wikibtn-numbers:hover,
+.wikibtn-strike:hover,
+.wikibtn-table:hover,
+.wikibtn-underline:hover,
+.wikibtn-yioop-search-widget:hover
+{
+    background-position: 0 -36px;
+}
\ No newline at end of file
diff --git a/resources/wiki_button_images/empty.png b/resources/wiki_button_images/empty.png
new file mode 100755
index 0000000000000000000000000000000000000000..6d9fabfbfe3a3c2b7276dabd752248136e7ecc7c
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-bold.png b/resources/wiki_button_images/wikibtn-bold.png
new file mode 100755
index 0000000000000000000000000000000000000000..49c14da327da6cc12f6d4d2dd7c68d26ada44f0c
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-bullets.png b/resources/wiki_button_images/wikibtn-bullets.png
new file mode 100755
index 0000000000000000000000000000000000000000..0915a682503ae762c5d94804f05086b7b3fccfeb
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-hr.png b/resources/wiki_button_images/wikibtn-hr.png
new file mode 100755
index 0000000000000000000000000000000000000000..fceb42c50eb96f749f9676fa03e675734942b610
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-hyperlink.png b/resources/wiki_button_images/wikibtn-hyperlink.png
new file mode 100755
index 0000000000000000000000000000000000000000..bc8ba8c325fa2d2c09efa3541f1cd18222fa0dce
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-italic.png b/resources/wiki_button_images/wikibtn-italic.png
new file mode 100755
index 0000000000000000000000000000000000000000..789b2873bfe671b834c158fb37ec6061bc2c269f
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-nowiki.png b/resources/wiki_button_images/wikibtn-nowiki.png
new file mode 100755
index 0000000000000000000000000000000000000000..3aeb3a72263cd16347fdbd4dfb14897855e325a8
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-numbers.png b/resources/wiki_button_images/wikibtn-numbers.png
new file mode 100755
index 0000000000000000000000000000000000000000..ed5434aac6ee782b2d01a37879b8b404d9fa5a99
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-strike.png b/resources/wiki_button_images/wikibtn-strike.png
new file mode 100755
index 0000000000000000000000000000000000000000..c4e0d3af3e516b4fb05e7a439ce6488aff5d484a
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-table.png b/resources/wiki_button_images/wikibtn-table.png
new file mode 100755
index 0000000000000000000000000000000000000000..cb4da2cf7cbe089fe6372d27ccf570a433f0a25a
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-underline.png b/resources/wiki_button_images/wikibtn-underline.png
new file mode 100755
index 0000000000000000000000000000000000000000..ce0191049410ce26f76dab0023deb673e0458ea0
GIT binary patch
diff --git a/resources/wiki_button_images/wikibtn-yioop-search-widget.png b/resources/wiki_button_images/wikibtn-yioop-search-widget.png
new file mode 100755
index 0000000000000000000000000000000000000000..47075d33ab8a6c8bb31c77da56405accff312ccf
GIT binary patch
diff --git a/scripts/wikify.js b/scripts/wikify.js
new file mode 100755
index 0000000..9eaa102
--- /dev/null
+++ b/scripts/wikify.js
@@ -0,0 +1,1164 @@
+/**
+ *  SeekQuarry/Yioop --
+ *  Open Source Pure PHP Search Engine, Crawler, and Indexer
+ *
+ *  Copyright (C) 2009 - 2014  Chris Pollett chris@pollett.org
+ *
+ *  LICENSE:
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  END LICENSE
+ *
+ * @author Eswara Rajesh Pinapala
+ * @package seek_quarry
+ * @subpackage javascript
+ * @license http://www.gnu.org/licenses/ GPL3
+ * @link http://www.seekquarry.com/
+ * @copyright 2014
+ * @filesource
+ */
+
+
+/* 
+ The editor automatically renders the 
+ editor buttons using this object as 
+ configuration data.
+ below is a valid list of button names
+ {
+ "wikibtn-bold"
+ "wikibtn-italic"
+ "wikibtn-underline"
+ "wikibtn-strike"
+ "wikibtn-nowiki"
+ "wikibtn-hyperlink"
+ "wikibtn-bullets"
+ "wikibtn-numbers"
+ "wikibtn-hr"
+ "wikibtn-heading"
+ "wikibtn-yioop"
+ "wikibtn-table" 
+ }
+ */
+
+/* 
+ global variable to store the wiki editor id 
+ */
+var wiki_editor = 'wiki-editor';
+
+
+/*
+ global flag variable to check if browser is Older MSIE.
+ */
+var is_msie = false;
+
+/*
+ global flag variable that holds the wiki_text_name. defults to wiki-text if 
+ data-wikitext is not set.
+ */
+var wiki_text_name = "wiki-text";
+
+/*
+ Arrays that store button configuration
+ */
+var all_buttons = {};
+var buttons = {};
+var buffer = {};
+
+if (!tl) {
+    var tl = [];
+}
+
+/**
+ On window load , Render the editor
+ and buttons.
+ */
+window.onload = function()
+{
+    /*
+     Create String.trim if it's not natively available.
+     */
+    if (!String.prototype.trim) {
+        String.prototype.trim = function() {
+            return this.replace(/^\s+|\s+$/g, '');
+        };
+    }
+
+    /*
+     check if the editor div exists.
+     */
+    var node = document.getElementById(wiki_editor);
+    if (node === null) {
+        /*
+         If the div to render wiki_editor is not found, do nothing.
+         */
+        return false;
+    }
+    if (document.selection) {
+        is_msie = true;
+        var button_string = "";
+
+        buttons = getStandardButtonsObject();
+        for (var prop in buttons) {
+            if (buttons.hasOwnProperty(prop)) {
+                button_string += '<input type="button" class="' + prop;
+                button_string += '" id="';
+                button_string += prop;
+                button_string += '" onmousedown="wikifySelection(\'';
+                button_string += prop + '\');">';
+            }
+        }
+        var editor_html = '<div id="wiki-buttons-div" ';
+        editor_html += 'class="wiki-buttons-div">';
+        editor_html += button_string;
+        editor_html += '<select class="heading" id="wikibtn-heading" ';
+        editor_html += ' value="heading" onchange="setHeading();">';
+        editor_html += '<option selected="" disabled="">Heading</option>';
+        editor_html += '<option value="1">H1</option>';
+        editor_html += '<option value="2">H2</option>';
+        editor_html += '<option value="3">H3</option>';
+        editor_html += '<option value="4">H4</option>';
+        editor_html += '</select>';
+        editor_html += '<input type="button" class="wikibtn-table" ';
+        editor_html += ' id="wikibtn-table" onmousedown="insertTable();">';
+        editor_html += '<input type="button" ';
+        editor_html += ' class="wikibtn-yioop-search-widget"';
+        editor_html += 'id="wikibtn-yioop-search-widget"';
+        editor_html += 'onmousedown="insertYioopSearch();">';
+        editor_html += '</div>';
+        editor_html += '<form action="" method="POST" name="">';
+        editor_html += '<textarea id="wiki-text" class="wiki-text"';
+        editor_html += 'style="width: 550px; height: 300px;';
+        editor_html += 'resize: none;">';
+        editor_html += '</textarea><p>';
+        editor_html += '<input type=SUBMIT value="' + tl['wiki_js_formbtn_submit'] + '" />';
+        editor_html += '</p></form>';
+        node.innerHTML = editor_html;
+
+        return;
+    } else {
+        if (filterButtons() === false) {
+            return;
+        } else {
+            renderWikiEditor(node);
+        }
+    }
+};
+
+
+/**
+ * Method to return standard buttons as an object.
+ * @param none
+ * @returns object
+ */
+function getStandardButtonsObject() {
+    return {
+        'wikibtn-bold': ['---', '--- \n'],
+        'wikibtn-italic': ['--', '-- \n'],
+        'wikibtn-underline': ['<u>', '</u> \n'],
+        'wikibtn-strike': ['<s>', '</s> \n'],
+        'wikibtn-nowiki': ['<nowiki>', '</nowiki> \n'],
+        'wikibtn-hyperlink': ['[', '] \n'],
+        'wikibtn-bullets': ['* ' + tl['wiki_js_bullet'] + ' \n'],
+        'wikibtn-numbers': ['# ' + tl['wiki_js_enum'] + ' \n'],
+        'wikibtn-hr': ['---- \n']
+    };
+}
+
+/**
+ * Filters the buttons according to exclusion/inclusion rules.
+ * If the 'data-buttons' attribute value starts with 'all' - Only the buttons 
+ * need to be excluded should be followed, with their name specified with a '!' 
+ * prefix. 
+ * Any buttons with no '!' prefix will eb ignored
+ * example : all,!bol,!italic will render editor with all buttns excluding bold 
+ * and italic
+ * 
+ * If the 'data-buttons' attribute value does not starts with 'all', any button 
+ * names followed will only be included in the editor. 
+ * Any buttons with '!' prefix will be ignored.
+ * example : bol,italic will render editor only with bold and italic buttons.
+ * 
+ * @param no params passed. Uses global vars.
+ * @return boolean
+ */
+function filterButtons()
+{
+    all_buttons = getStandardButtonsObject();
+    all_buttons['wikibtn-heading'] = '';
+    all_buttons['wikibtn-yioop'] = '';
+    all_buttons['wikibtn-table'] = '';
+
+    var wiki_text_div = document.getElementById(wiki_editor);
+    var wiki_buttons = wiki_text_div.getAttribute("data-buttons");
+    if (wiki_buttons) {
+        var wiki_buttons_array = wiki_buttons.split(',');
+        var buttons_array_length = wiki_buttons_array.length;
+        var included_buttons = new Array();
+        var excluded_buttons = new Array();
+        var exc = false;
+        if (wiki_buttons_array[0].trim() === 'all') {
+            exc = true;
+        }
+        for (var i = 0; i < buttons_array_length; i++) {
+            wiki_buttons_array[i] = wiki_buttons_array[i].trim();
+            var firstChar = wiki_buttons_array[i].charAt(0);
+
+            if (wiki_buttons_array[i] &&
+                    (exc === true) &&
+                    firstChar === '!') {
+                wiki_buttons_array[i] = wiki_buttons_array[i].substr(1);
+
+                if (all_buttons.hasOwnProperty(wiki_buttons_array[i])) {
+                    excluded_buttons.push(wiki_buttons_array[i]);
+                    delete all_buttons[wiki_buttons_array[i]];
+                }
+            } else if (wiki_buttons_array[i] &&
+                    (exc === false)) {
+                if (all_buttons.hasOwnProperty(wiki_buttons_array[i])) {
+                    included_buttons.push(wiki_buttons_array[i]);
+                    buttons[wiki_buttons_array[i]] =
+                            all_buttons[wiki_buttons_array[i]];
+                }
+            }
+        }
+    } else {
+        buttons = all_buttons;
+        return true;
+    }
+    if (Object.keys(buttons).length === 0) {
+        buttons = all_buttons;
+    }
+    return true;
+}
+
+/**
+ * This is a function for rendering the
+ * wiki editor using DOM manipulation.
+ * This is the core function that leverages
+ * teh cofigurations buttons object and builds
+ * the wiki editor buttons, textarea etc.
+ * 
+ * @param element wiki_editor_div is the reference to wiki editor 
+ * div element to render
+ * @return undefined
+ */
+function renderWikiEditor(wiki_editor_div)
+{
+    var wiki_overlay_div = createElement("div", {
+        "id": 'wiki-overlay-div',
+        "class": 'wiki-overlay-div'
+    });
+    wiki_editor_div.appendChild(wiki_overlay_div);
+
+    var wiki_popup = createElement("div", {
+        "id": 'wiki-popup-prompt',
+        "class": 'wiki-popup-prompt'
+    });
+
+    wiki_editor_div.appendChild(wiki_popup);
+
+    var wiki_buttons_div = createElement("div", {
+        "id": 'wiki-buttons-div',
+        "class": 'wiki-buttons-div'
+    });
+    /*
+     Insert Heading
+     */
+    if (buttons.hasOwnProperty('wikibtn-heading')) {
+        wiki_buttons_div.appendChild(createDropDown(
+                "wikibtn-heading",
+                "setHeading",
+                {
+                    "H1": "1",
+                    "H2": "2",
+                    "H3": "3",
+                    "H4": "4"
+                }
+        , tl['wiki_js_heading']));
+    }
+    /*
+     Using the buttons Object, populate the buttons.
+     */
+    for (var property in buttons) {
+        var obj = ['wikibtn-yioop', 'wikibtn-table', 'wikibtn-heading'];
+        if (buttons.hasOwnProperty(property)
+                && (obj.indexOf(property) === -1)
+                ) {
+            createButton(wiki_buttons_div, property);
+        }
+    }
+    if (buttons.hasOwnProperty('wikibtn-table')) {
+        /*
+         Insert button for insertTable
+         */
+        wiki_buttons_div.appendChild(createElement("input", {
+            "type": "button",
+            "class": 'wikibtn-table',
+            "id": 'wikibtn-table',
+            "onmousedown": "insertTable();"
+        }));
+    }
+    /*
+     Insert button for yioop-search-widget
+     */
+    if (buttons.hasOwnProperty('wikibtn-yioop')) {
+        wiki_buttons_div.appendChild(createElement("input", {
+            "type": "button",
+            "class": 'wikibtn-yioop-search-widget',
+            "id": 'wikibtn-yioop-search-widget',
+            "onmousedown": "insertYioopSearch();"
+        }));
+    }
+
+    wiki_editor_div.appendChild(wiki_buttons_div);
+
+    /*
+     Insert a couple of line breaks
+     */
+    wiki_editor_div.appendChild(document.createElement('br'));
+    /*
+     retreive data-* attributes for the wiki_editor.
+     */
+    var wiki_text_div = document.getElementById(wiki_editor);
+    var wiki_form_name = wiki_text_div.getAttribute("data-formname");
+    var wiki_form_action = wiki_text_div.getAttribute("data-formaction");
+    var wiki_form_method = wiki_text_div.getAttribute("data-formmethod");
+    /*
+     Check if the data-* attributes are set.
+     */
+    if (wiki_form_name && wiki_form_action && wiki_form_method) {
+        wiki_text_name = wiki_form_name;
+        /*
+         Create a FormElement 
+         */
+        var formElement = createElement("form", {
+            "name": wiki_text_name,
+            "action": wiki_form_action,
+            "method": wiki_form_method
+        });
+        /*
+         Insert a text area
+         */
+        formElement.appendChild(createElement("textarea", {
+            "id": wiki_text_name,
+            "class": wiki_form_name
+        }));
+        var pElement = createElement("p", {});
+        pElement.appendChild(createElement("input", {
+            "type": "SUBMIT",
+            "id": "Submit",
+            "value": tl['wiki_js_formbtn_submit']
+        }));
+        formElement.appendChild(pElement);
+        wiki_editor_div.appendChild(formElement);
+    } else {
+        /*
+         Insert a text area
+         */
+        wiki_editor_div.appendChild(createElement("textarea", {
+            "id": wiki_text_name,
+            "class": wiki_text_name
+        }));
+    }
+    /*
+     Finally another line break.
+     */
+    wiki_editor_div.appendChild(document.createElement('br'));
+}
+
+/**
+ * Util function to create a Dom element,
+ * given an element name and an object with
+ * attributes as key value pairs.
+ * 
+ * @param string element_name is the tagname of the element to be 
+ * created and returned.
+ * @param object attributes is a javascript object of attributes sent 
+ * as key value pairs.
+ * @return Element
+ */
+function createElement(element_name, attributes)
+{
+    var element_x = document.createElement(element_name);
+
+    for (var property in attributes) {
+        if (attributes.hasOwnProperty(property)) {
+            element_x.setAttribute(property, attributes[property]);
+        }
+    }
+    return element_x;
+}
+
+/**
+ * Given the parent element and
+ * name of the button, This util function
+ * created an editor button.
+ * 
+ * @param element context parent element to which the button will be added.
+ * @param string name this is the identifier to the button.
+ * @return element
+ */
+function createButton(context, name)
+{
+    context.appendChild(createElement("input", {
+        "type": "button",
+        "class": name,
+        "id": name,
+        "onmousedown": "wikifySelection('" + name + "');"
+    }));
+}
+
+
+/**
+ * creates a label element and returns it.
+ * 
+ * @param string for_att the attribute for value in the label.
+ * @param string label_name the value need to eb assigned.
+ * @returns Element label
+ */
+function createLabel(for_att, label_name)
+{
+    var label = createElement("label", {
+        "for": for_att
+    });
+
+    label.innerHTML = label_name;
+
+    return label;
+}
+
+/**
+ * This is a util function to
+ * create a dropdown element.
+ * 
+ * @param string name of the dropdown, used for class,id & value attributes.
+ * @param string function name to be called "onchange".
+ * @param object option parameters in the dropdown sent as a js object.
+ * @param string default_selected name of the default selected option. 
+ */
+function createDropDown(dropdown_name, action, options, default_selected)
+{
+    var select = createElement("select", {
+        "class": dropdown_name,
+        "id": dropdown_name,
+        "value": dropdown_name,
+        "onchange": action + "();"
+    });
+    var option = document.createElement("option");
+    if (default_selected) {
+        option.innerHTML = default_selected;
+    }
+    option.setAttribute("selected", "");
+    option.setAttribute("disabled", "");
+    select.add(option);
+    for (optionObj in options) {
+        if (options.hasOwnProperty(optionObj)) {
+            var option = document.createElement("option");
+            option.text = optionObj;
+            option.value = options[optionObj];
+            select.add(option);
+        }
+    }
+    return select;
+}
+
+/**
+ * This function returns the selection(from text_area)
+ * information in an object. The obejct contains 
+ * selected text, entre prefix and entire suffix strings to the
+ * selected text.
+ * 
+ * @param no params passed.
+ * @return object
+ */
+function getSelection()
+{
+    /*
+     Select the DOM element - wikiText
+     */
+    var text_area = document.getElementById(wiki_text_name);
+
+    /*
+     IE?
+     */
+    if (document.selection) {
+        var selection_bookmark = document.selection
+                .createRange()
+                .getBookmark();
+        var sel = text_area.createTextRange();
+        sel.moveToBookmark(selection_bookmark);
+        var sleft = text_area.createTextRange();
+        sleft.collapse(true);
+        sleft.setEndPoint("EndToStart", sel);
+        text_area.selectionStart = sleft.text.length;
+        text_area.selectionEnd = sleft.text.length + sel.text.length;
+        text_area.selectedText = sel.text;
+        var selected_text_prefix = text_area.value.substring(0,
+                text_area.selectionStart);
+        var selection = sel.text;
+        var selected_text_suffix = text_area.value.substring(
+                text_area.selectionEnd,
+                text_area.textLength);
+    }
+    /*
+     Mozilla?
+     */
+    else if (typeof (text_area.selectionStart) !== "undefined") {
+        /** 
+         Things are pretty straight forward in Mozilla based 
+         browsers & IE > 10. 
+         We can get the selectionStart & selectionEnd character 
+         position directly.
+         Then compute the prefix and suffix using substr method.
+         */
+        var selected_text_prefix = text_area.value.substr(0,
+                text_area.selectionStart);
+        var selection = text_area.value.substr(
+                text_area.selectionStart,
+                text_area.selectionEnd - text_area.selectionStart);
+        var selected_text_suffix = text_area.value.substr(
+                text_area.selectionEnd);
+    }
+    var obj = {};
+    obj.selection = selection;
+    obj.selected_text_prefix = selected_text_prefix;
+    obj.selected_text_suffix = selected_text_suffix;
+    setCaretPosition(text_area, text_area.selectionEnd);
+    return obj;
+}
+
+/**
+ * MSIE has a problem displaying \n as libe breaks
+ * we use this fucntions to normalise all the libebreaks
+ * to be backward compatible with MSIE.
+ * 
+ * @param string text to be normalized.
+ * @return string
+ */
+function normalizeNewlinesForMSIE(text)
+{
+    return text.replace(/(\r\n|\r|\n)/g, '\n\r');
+}
+
+
+/**
+ * This function can be used to set 
+ * the caret position in the ctrl object.
+ * 
+ * @param element ctrl element in which the caret has to be set.
+ * @param int pos position of the caret to be set.
+ * @return undefined
+ */
+function setCaretPosition(ctrl, pos)
+{
+    if (ctrl.setSelectionRange)
+    {
+        ctrl.focus();
+        ctrl.setSelectionRange(pos, pos);
+    }
+    else if (ctrl.createTextRange) {
+        var range = ctrl.createTextRange();
+        range.collapse(true);
+        range.moveEnd('character', pos);
+        range.moveStart('character', pos);
+        range.select();
+    }
+}
+
+/**
+ * This will check for type of the button to 
+ * render(looking at the array length, and renders the button 
+ * on the editor.
+ * 
+ * @param string name identifier to the wiki task to be performed.
+ * @return undefined
+ */
+function wikifySelection(name)
+{
+    var length = 0;
+    if (is_msie) {
+        for (var prop in buttons) {
+            if (buttons.hasOwnProperty(prop)) {
+                if (prop === name) {
+                    length = buttons[prop].length;
+                }
+            }
+        }
+    } else {
+        length = buttons[name].length;
+    }
+
+    if (length === 2) {
+        wikify(
+                buttons[name][0].replace(new RegExp('-', 'g'), "\'"),
+                buttons[name][1].replace(new RegExp('-', 'g'), "\'"),
+                name
+                );
+    } else if (length === 1) {
+        insertTextAtCursor(buttons[name][0]);
+    } else {
+        return;
+    }
+}
+
+/**
+ * This is the main function that takes
+ * prefix and suffix characters for wikifying 
+ * selected text. Selected text will be obtained using
+ * the function-getSelection();
+ * 
+ * @param string wiki_prefix prefix to be added to wikify the selected text.
+ * @param string wiki_suffix suffix to be added to wikify the selected text.
+ * @param string task_name name of the task to render default selection text.
+ * @return undefined
+ */
+function wikify(wiki_prefix, wiki_suffix, task_name)
+{
+    /*
+     Select the DOM element - wikiText
+     */
+    var text_area = document.getElementById(wiki_text_name);
+    
+    var obj = getSelection();
+    var selection = obj.selection;
+    var selected_text_prefix = obj.selected_text_prefix;
+    var selected_text_suffix = obj.selected_text_suffix;
+    if (!selection && wiki_prefix === '[') {
+        if (!is_msie) {
+            wiki_popup_prompt = document.getElementById('wiki-popup-prompt');
+            if (wiki_popup_prompt.hasChildNodes()) {
+                /*
+                 Remove childnodes, if any exist.
+                 */
+                while (wiki_popup_prompt.hasChildNodes()) {
+                    wiki_popup_prompt.removeChild(wiki_popup_prompt.lastChild);
+                }
+            }
+            wiki_popup_prompt.appendChild(createHyperlinkForm());
+            buffer = obj;
+            popupToggle();
+        } else {
+            requestHyperlinkInput();
+        }
+    }
+
+    if (!selection) {
+        selection = tl[task_name.replace('wikibtn-', 'wiki_js_')];
+    }
+
+    /*
+     Now Add the wrap the selected text between the wiki stuff, 
+     and then wrap the selected 
+     text between actual selected text's prefix and suffix. 
+     Replace the text_area contents with the result.
+     */
+    if(selection){
+    text_area.value = selected_text_prefix +
+            wiki_prefix +
+            selection +
+            wiki_suffix +
+            selected_text_suffix;   
+    }
+}
+
+/*
+ * This is a special fucntion for processing user input 
+ * when the user clicks on hyperlink, and inserts a hyper link.
+ * 
+ * @returns String
+ */
+function requestHyperlinkInput() {
+    if (!is_msie) {
+        popupToggle();
+
+        var title = document
+                .getElementById('wikify-enter-link-title-placeholder')
+                .value;
+        var link = document
+                .getElementById('wikify-enter-link-target-placeholder')
+                .value;
+        if (!title || !link) {
+            return false;
+        }
+        
+
+    } else {
+        var title = prompt(tl['wikify_link_title'],
+                tl['wikify_enter_link_title_placeholder']);
+        var link = prompt(tl['wikify_link'],
+                tl['wikify_enter_link_placeholder']);
+        if (!title || !link) {
+            return undefined;
+        }
+        
+    }
+    
+    insertTextAtCursor("[" + link + " "  + title + "]" + '\n');
+}
+
+/**
+ * This function takes in number of rows, columns and
+ * header_text(if desired) and constructs a table in wiki markup.
+ * 
+ * @param int rows number of rows intended in the table.
+ * @param int cols number of cols intended in the table.
+ * @param string example_text placeholder text to be inserted in each 
+ * table field.
+ * @param string header_text if header text is intended, placeholder 
+ * text for column header.
+ * @return string
+ */
+function createWikiTable(rows, cols, example_text, header_text)
+{
+    var br = "\n";
+    var table = "{|" + br;
+    for (i = 0; i < rows; i++) {
+        if (header_text && i === 0) {
+            table = table + "|- " + br;
+            table = table + "! ";
+            for (j = 0; j < cols; j++) {
+                table = table + header_text + " ";
+                if (j < (cols - 1)) {
+                    table = table + "!!" + " ";
+                } else {
+                    table = table + br;
+                }
+            }
+        }
+        table = table + "|- " + br;
+        table = table + "| ";
+
+        for (j = 0; j < cols; j++) {
+            table = table + example_text + " ";
+            if (j < (cols - 1)) {
+                table = table + "||" + " ";
+            } else {
+                table = table + br;
+            }
+        }
+    }
+    table = table + "|}";
+    return table;
+}
+
+/**
+ * function to insert
+ * yioop search widget.
+ * 
+ * @param no params passed.
+ * @return undefined
+ */
+function insertYioopSearch()
+{
+    if (!is_msie) {
+        wiki_popup_prompt = document.getElementById('wiki-popup-prompt');
+
+        if (wiki_popup_prompt.hasChildNodes()) {
+            /*
+             Remove childnodes, if any exist.
+             */
+            while (wiki_popup_prompt.hasChildNodes()) {
+                wiki_popup_prompt.removeChild(wiki_popup_prompt.lastChild);
+            }
+        }
+        wiki_popup_prompt.appendChild(createYioopWidgetInputForm());
+        popupToggle();
+    } else {
+        useInputForYioop();
+    }
+}
+
+/**
+ * For newer browsers , this uses overlay input form to get the 
+ * size of the Yioop widget to load.
+ * 
+ * @returns undefined
+ */
+function useInputForYioop() {
+    if (is_msie) {
+        var size = prompt(tl['wiki_js_prompt_search_size']);
+    } else {
+        popupToggle();
+        var element = document.getElementById("wikify-prompt-for-yioop-size");
+        var size = element.options[element.selectedIndex].text;
+    }
+    var widget_obj = {};
+    var yioop_obj = {};
+    yioop_obj.size = size;
+    widget_obj.search = objToString(yioop_obj);
+    if (size === tl['wiki_js_search_size_small'] ||
+            size === tl['wiki_js_search_size_medium'] ||
+            size === tl['wiki_js_search_size_large']) {
+        insertTextAtCursor("{" + objToString(widget_obj) + "}\n");
+    }
+
+}
+
+/**
+ * Util function to Stringify an JS Object
+ * 
+ * @param object js_object the javascript object to be converted to string.
+ * @return string
+ */
+function objToString(js_object)
+{
+    var json_string = [];
+    for (var property in js_object) {
+        if (js_object.hasOwnProperty(property)) {
+            json_string.push('"' +
+                    property +
+                    '"' +
+                    ':' +
+                    js_object[property]
+                    );
+        }
+    }
+    json_string.push();
+    return '{' + json_string.join(',') + '}';
+}
+
+/**
+ * This is invoked by the editor to insert a wiki table.
+ * This functions takes care okf the user input for rows/columns/etc
+ * and leverages createWikiTable function to construct the table.
+ * 
+ * @param no params passed
+ * @return undefined
+ */
+function insertTable()
+{
+    if (!is_msie) {
+        wiki_popup_prompt = document.getElementById('wiki-popup-prompt');
+
+        if (wiki_popup_prompt.hasChildNodes()) {
+            /*
+             Remove childnodes, if any exist.
+             */
+            while (wiki_popup_prompt.hasChildNodes()) {
+                wiki_popup_prompt.removeChild(wiki_popup_prompt.lastChild);
+            }
+        }
+
+        wiki_popup_prompt.appendChild(createTableCreationPromptElement());
+        popupToggle();
+    } else {
+        useInputForTable();
+    }
+
+}
+
+
+/**
+ * accepts input from user to create a table.
+ * For older MSIE browsers prompts are used and for newer browsers an overlay 
+ * popup is rendered to take input.
+ * @param none.
+ * @returns undefined
+ */
+function useInputForTable() {
+    if (is_msie) {
+        var cols = prompt(tl['wikify_prompt_for_table_cols']);
+        var rows = prompt(tl['wikify_prompt_for_table_rows']);
+        var headcheck = confirm(tl['wikify_prompt_heading']);
+
+    } else {
+        var rows = document
+                .getElementById('wiki-prompt-cols')
+                .value;
+        var cols = document
+                .getElementById('wiki-prompt-cols')
+                .value;
+        var headcheck = document
+                .getElementById('wiki-prompt-insert-heading')
+                .checked;
+    }
+    insertTableFromInput(rows, cols, headcheck);
+}
+
+/**
+ * Using the input from the user, like number of rows,cols etc.
+ * builds a table in wiki markup and inserts at cursor.
+ * @param int rows number of rows desired
+ * @param int cols number of cols desired
+ * @param boolean headcheck heading desired or not.
+ * @returns undefined
+ */
+function insertTableFromInput(rows, cols, headcheck)
+{
+    if (!is_msie) {
+        popupToggle();
+    }
+
+    if (!cols || !rows) {
+        return;
+    }
+
+    if (headcheck) {
+        var table = createWikiTable(
+                rows,
+                cols,
+                tl['wiki_js_example_placeholder'],
+                tl['wiki_js_table_title_placeholder']);
+    } else {
+        table = createWikiTable(
+                rows,
+                cols,
+                tl['wiki_js_example_placeholder']);
+    }
+    insertTextAtCursor(table + '\n');
+}
+
+/**
+ * Accepts text as parameter to be inserted at caret's 
+ * current position.
+ * 
+ * @param string text string that is intended to be placed at current cursor.
+ * @return undefined
+ */
+function insertTextAtCursor(text)
+{
+    var field = document.getElementById(wiki_text_name);
+    if (document.selection) {
+        var range = document.selection.createRange();
+        if (!range || range.parentElement() !== field) {
+            field.focus();
+            range = field.createTextRange();
+            range.collapse(false);
+        }
+        range.text = text;
+        range.collapse(false);
+        range.select();
+    } else {
+        field.focus();
+        var val = field.value;
+        var selStart = field.selectionStart;
+        var caretPos = selStart + text.length;
+        field.value = val.slice(0, selStart) +
+                text + val.slice(field.selectionEnd);
+        field.setSelectionRange(caretPos, caretPos);
+    }
+}
+
+/**
+ * Used to set the headings
+ * for selected text.
+ * 
+ * @param no params passed.
+ * @return undefined
+ */
+function setHeading()
+{
+    var markup_text = fillChars("=",
+            document.getElementById("wikibtn-heading").value);
+    document.getElementById("wikibtn-heading").selectedIndex = 0;
+    wikify(markup_text, markup_text, "wikibtn-heading");
+}
+
+/**
+ * This is a simple util
+ * function to fill a character 
+ * array and return as a string,
+ * given a character and array count.
+ * 
+ * @param string c caharacter to be filled into an array.
+ * @param int n number of times the character to eb repeated.
+ * @return string
+ */
+function fillChars(c, n)
+{
+    for (var e = ""; e.length < n; ) {
+        e += c;
+    }
+    return e;
+}
+
+/**
+ * This toggles the popup used for 
+ * prompting user input.
+ * @returns undefined
+ */
+function popupToggle() {
+    var wiki_overlay_div = document.getElementById('wiki-overlay-div');
+    var wiki_popup = document.getElementById('wiki-popup-prompt');
+
+    wiki_overlay_div.style.opacity = .8;
+    if (wiki_overlay_div.style.display === "block") {
+        /*
+         Hide the overlay popup
+         */
+        wiki_overlay_div.style.display = "none";
+        wiki_popup.style.display = "none";
+    } else {
+        /*
+         Show the overlay popup
+         */
+        wiki_overlay_div.style.display = "block";
+        wiki_popup.style.display = "block";
+    }
+}
+
+
+/**
+ * 
+ * Created an input prompt HTML elemtn with 2 text fields and a checkbox.
+ * @param no params passed
+ * @returns Element
+ */
+function createTableCreationPromptElement() {
+
+    var wiki_prompt_for_table = createElement("div", {
+        "id": 'wiki-prompt-for-table',
+        "class": 'wiki-prompt-for-table'
+    });
+
+    wiki_prompt_for_table.appendChild(
+            createLabel("rows", tl['wikify_prompt_for_table_rows'])
+            );
+
+    wiki_prompt_for_table.appendChild(createElement("input", {
+        "type": "text",
+        "name": 'wiki-prompt-rows',
+        "id": 'wiki-promt-rows'
+    }));
+
+    wiki_prompt_for_table.appendChild(document.createElement('br'));
+
+    wiki_prompt_for_table.appendChild(
+            createLabel("cols", tl['wikify_prompt_for_table_cols']
+                    ));
+
+    wiki_prompt_for_table.appendChild(createElement("input", {
+        "type": "text",
+        "name": 'wiki-prompt-cols',
+        "id": 'wiki-prompt-cols'
+    }));
+
+    wiki_prompt_for_table.appendChild(document.createElement('br'));
+
+    var checkbox = createElement("input", {
+        "type": "checkbox",
+        "name": 'wiki-prompt-insert-heading',
+        "id": 'wiki-prompt-insert-heading'
+    });
+    wiki_prompt_for_table.appendChild(
+            document.createTextNode(tl['wikify_prompt_heading']
+                    ));
+    wiki_prompt_for_table.appendChild(checkbox);
+    wiki_prompt_for_table.appendChild(document.createElement('br'));
+    var submitbtn = createElement("button", {
+        "name": 'submit',
+        "onmousedown": "useInputForTable()"
+    });
+    submitbtn.innerHTML = tl['wiki_js_formbtn_submit'];
+    wiki_prompt_for_table.appendChild(submitbtn);
+    var closebtn = createElement("button", {
+        "name": 'close',
+        "onmousedown": "popupToggle()"
+    });
+    closebtn.innerHTML = tl['wiki_js_formbtn_cancel'];
+    wiki_prompt_for_table.appendChild(closebtn);
+    return wiki_prompt_for_table;
+}
+
+/**
+ * Creates an input prompt HTML elemtn with 2 text fields for link title
+ * and link target.
+ * @param no params passed
+ * @returns Element
+ */
+function createHyperlinkForm() {
+    var wiki_prompt_for_hyperlink = createElement("div", {
+        "id": 'wiki-prompt-for-hyperlink',
+        "class": 'wiki-prompt-for-hyperlink'
+    });
+
+    wiki_prompt_for_hyperlink.appendChild(
+            createLabel(
+                    "wikify-enter-link-title-placeholder",
+                    tl['wikify_enter_link_title_placeholder']));
+    wiki_prompt_for_hyperlink.appendChild(createElement("input", {
+        "type": "text",
+        "name": 'wikify-enter-link-title-placeholder',
+        "id": 'wikify-enter-link-title-placeholder'
+    }));
+    wiki_prompt_for_hyperlink.appendChild(document.createElement('br'));
+    wiki_prompt_for_hyperlink.appendChild(
+            createLabel(
+                    "wikify-enter-link-target-placeholder",
+                    tl['wikify_enter_link_placeholder']));
+    wiki_prompt_for_hyperlink.appendChild(createElement("input", {
+        "type": "text",
+        "name": 'wikify-enter-link-target-placeholder',
+        "id": 'wikify-enter-link-target-placeholder'
+    }));
+    wiki_prompt_for_hyperlink.appendChild(document.createElement('br'));
+    var submitbtn = createElement("button", {
+        "name": 'submit',
+        "onmousedown": "requestHyperlinkInput()"
+    });
+    submitbtn.innerHTML = tl['wiki_js_formbtn_submit'];
+
+    wiki_prompt_for_hyperlink.appendChild(submitbtn);
+    var closebtn = createElement("button", {
+        "name": 'close',
+        "onmousedown": "popupToggle()"
+    });
+    closebtn.innerHTML = tl['wiki_js_formbtn_cancel'];
+    wiki_prompt_for_hyperlink.appendChild(closebtn);
+    return wiki_prompt_for_hyperlink;
+}
+
+/**
+ * Creates the input fields on a form for yioop search widget.
+ * @param none
+ * @returns undefined
+ */
+function createYioopWidgetInputForm() {
+    var wiki_prompt_for_yioop = createElement("div", {
+        "id": 'wiki-prompt-for-yioop',
+        "class": 'wiki-prompt-for-yioop'
+    });
+    wiki_prompt_for_yioop.appendChild(
+            document.createTextNode(
+                    tl['wiki_js_prompt_search_size']
+                    ));
+    wiki_prompt_for_yioop.appendChild(document.createElement('br'));
+    
+    var options = {};
+    options[tl['wiki_js_search_size_small']] = 1;
+    options[tl['wiki_js_search_size_medium']] = 2;
+    options[tl['wiki_js_search_size_large']] = 3;
+
+    wiki_prompt_for_yioop.appendChild(createDropDown(
+            "wiki_js_prompt_search_size",
+            tl['wiki_js_prompt_search_size'],
+            options
+    , tl['wiki_js_search_size']));
+    wiki_prompt_for_yioop.appendChild(document.createElement('br'));
+    var submitbtn = createElement("button", {
+        "name": 'submit',
+        "onmousedown": "useInputForYioop()"
+    });
+    submitbtn.innerHTML = tl['wiki_js_formbtn_submit'];
+
+    wiki_prompt_for_yioop.appendChild(submitbtn);
+    var closebtn = createElement("button", {
+        "name": 'close',
+        "onmousedown": "popupToggle()"
+    });
+    closebtn.innerHTML = tl['wiki_js_formbtn_cancel'];
+    wiki_prompt_for_yioop.appendChild(closebtn);
+    return wiki_prompt_for_yioop;
+}
\ No newline at end of file
diff --git a/views/layouts/web_layout.php b/views/layouts/web_layout.php
index 74d79e3..370c977 100755
--- a/views/layouts/web_layout.php
+++ b/views/layouts/web_layout.php
@@ -91,6 +91,8 @@ class WebLayout extends Layout
             href="<?php e($path_info); ?>favicon.ico" />
         <link rel="stylesheet" type="text/css"
             href="<?php e($path_info); ?>/css/search.css" />
+        <link rel="stylesheet" type="text/css"
+            href="<?php e($path_info); ?>/css/editor.css" />
         <link rel="search" type="application/opensearchdescription+xml"
             href="<?php e(NAME_SERVER."yioopbar.xml");?>"
             title="Content search" />
@@ -128,6 +130,7 @@ class WebLayout extends Layout
         } ?>
 
         <script type="text/javascript" src="./scripts/basic.js" ></script>
+        <script type="text/javascript" src="./scripts/wikify.js" ></script>
         <?php
         if(isset($data['INCLUDE_SCRIPTS'])) {
             foreach($data['INCLUDE_SCRIPTS'] as $script_name) {
-- 
1.8.5.2 (Apple Git-48)

