_binary From 9c602707e1b0dbcea04d4d22a2aa9dda650cc656 Mon Sep 17 00:00:00 2001
From: Eswar Rajesh Pinapala <epinapala@live.com>
Date: Fri, 16 May 2014 02:24:04 -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                     | 106 ++++++
 resources/wikiedit/Bold.png        | Bin 0 -> 23068 bytes
 resources/wikiedit/Hyperlink.png   | Bin 0 -> 23980 bytes
 resources/wikiedit/Italic.png      | Bin 0 -> 22773 bytes
 resources/wikiedit/No-Wiki.png     | Bin 0 -> 23588 bytes
 resources/wikiedit/Strike.png      | Bin 0 -> 23717 bytes
 resources/wikiedit/Underline.png   | Bin 0 -> 23171 bytes
 resources/wikiedit/bullets.png     | Bin 0 -> 23394 bytes
 resources/wikiedit/button.psd      | Bin 0 -> 89306 bytes
 resources/wikiedit/empty.png       | Bin 0 -> 21979 bytes
 resources/wikiedit/heading.png     | Bin 0 -> 22663 bytes
 resources/wikiedit/hr.png          | Bin 0 -> 22174 bytes
 resources/wikiedit/numbers.png     | Bin 0 -> 23336 bytes
 resources/wikiedit/table.png       | Bin 0 -> 23545 bytes
 resources/wikiedit/yioopSearch.png | Bin 0 -> 23742 bytes
 scripts/wikify.js                  | 693 +++++++++++++++++++++++++++++++++++++
 views/layouts/web_layout.php       |   3 +
 17 files changed, 802 insertions(+)
 create mode 100755 css/editor.css
 create mode 100644 resources/wikiedit/Bold.png
 create mode 100644 resources/wikiedit/Hyperlink.png
 create mode 100644 resources/wikiedit/Italic.png
 create mode 100644 resources/wikiedit/No-Wiki.png
 create mode 100644 resources/wikiedit/Strike.png
 create mode 100644 resources/wikiedit/Underline.png
 create mode 100644 resources/wikiedit/bullets.png
 create mode 100755 resources/wikiedit/button.psd
 create mode 100644 resources/wikiedit/empty.png
 create mode 100644 resources/wikiedit/heading.png
 create mode 100644 resources/wikiedit/hr.png
 create mode 100644 resources/wikiedit/numbers.png
 create mode 100644 resources/wikiedit/table.png
 create mode 100755 resources/wikiedit/yioopSearch.png
 create mode 100755 scripts/wikify.js

diff --git a/css/editor.css b/css/editor.css
new file mode 100755
index 0000000..c0d09ad
--- /dev/null
+++ b/css/editor.css
@@ -0,0 +1,106 @@
+#wiki-editor
+{
+    display: block;
+    margin: 0 auto;
+}
+
+#wiki-editor div
+{
+    padding: 5px;
+}
+
+div.wiki-editor input
+{
+    cursor: pointer;
+    width: 46px;
+    height: 50px;
+    display: inline-block;
+    vertical-align: top;
+    border-style: solid;
+}
+div.wiki-editor select
+{
+    cursor: pointer;
+    width: 46px;
+    height: 50px;
+    border: 1px;
+}
+
+#bold
+{
+    background: url(../resources/wikiedit/Bold.png) no-repeat;
+}
+
+
+#underline
+{
+    background: url(../resources/wikiedit/Underline.png) no-repeat;
+}
+
+#bullets
+{
+    background: url(../resources/wikiedit/bullets.png) no-repeat;
+}
+
+#heading
+{
+    height: 50px;
+    background: url(../resources/wikiedit/heading.png) no-repeat;
+}
+
+#hr
+{
+    background: url(../resources/wikiedit/hr.png) no-repeat;
+}
+
+#hyperlink
+{
+    background: url(../resources/wikiedit/Hyperlink.png) no-repeat;
+}
+
+
+#italic
+{
+    background: url(../resources/wikiedit/Italic.png) no-repeat;
+}
+
+#nowiki
+{
+    background: url(../resources/wikiedit/No-Wiki.png) no-repeat;
+}
+
+#numbers
+{
+    background:url(../resources/wikiedit/numbers.png) no-repeat;
+}
+
+#strike
+{
+    background: url(../resources/wikiedit/Strike.png) no-repeat;
+}
+
+#table
+{
+    background: url(../resources/wikiedit/table.png) no-repeat;
+}
+
+#yioop-search-widget
+{
+    background: url(../resources/wikiedit/yioopSearch.png) no-repeat;
+}
+
+#bold:hover,
+#bullets:hover,
+#heading:hover,
+#hr:hover,
+#hyperlink:hover,
+#italic:hover,
+#nowiki:hover,
+#numbers:hover,
+#strike:hover,
+#table:hover,
+#underline:hover,
+#yioop-search-widget:hover
+{
+    background-position: 0 -50px;
+}
\ No newline at end of file
diff --git a/resources/wikiedit/Bold.png b/resources/wikiedit/Bold.png
new file mode 100644
index 0000000000000000000000000000000000000000..c77f5d7395f95837dad94de87d22c50cb6df50ce
GIT binary patch
diff --git a/resources/wikiedit/Hyperlink.png b/resources/wikiedit/Hyperlink.png
new file mode 100644
index 0000000000000000000000000000000000000000..b703fae35ccd0e1fbfefd7308cbd61d9cfd20e8d
GIT binary patch
diff --git a/resources/wikiedit/Italic.png b/resources/wikiedit/Italic.png
new file mode 100644
index 0000000000000000000000000000000000000000..b8e92c0db0f9393fcff495a4c981949ff6e29485
GIT binary patch
diff --git a/resources/wikiedit/No-Wiki.png b/resources/wikiedit/No-Wiki.png
new file mode 100644
index 0000000000000000000000000000000000000000..e96c6137da344ed109f903519a65d09500a1237a
GIT binary patch
diff --git a/resources/wikiedit/Strike.png b/resources/wikiedit/Strike.png
new file mode 100644
index 0000000000000000000000000000000000000000..7a5159b280ff29d7e4170ee1450c353ee9d7ef06
GIT binary patch
diff --git a/resources/wikiedit/Underline.png b/resources/wikiedit/Underline.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa5f509edf020d2ee655cf278f6984ddcf7fa56a
GIT binary patch
diff --git a/resources/wikiedit/bullets.png b/resources/wikiedit/bullets.png
new file mode 100644
index 0000000000000000000000000000000000000000..79bc7fd5d07459e7ba9509eddca5df81d9ac150d
GIT binary patch
diff --git a/resources/wikiedit/button.psd b/resources/wikiedit/button.psd
new file mode 100755
index 0000000000000000000000000000000000000000..0ee1deacd8c0495c7af904733aba4ade3c3758af
GIT binary patch
diff --git a/resources/wikiedit/empty.png b/resources/wikiedit/empty.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0a72bc4b5a697f1b49a8736570e519083d0056f
GIT binary patch
diff --git a/resources/wikiedit/heading.png b/resources/wikiedit/heading.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b2c5be4ae2269704cce671acd593348ffea06fd
GIT binary patch
diff --git a/resources/wikiedit/hr.png b/resources/wikiedit/hr.png
new file mode 100644
index 0000000000000000000000000000000000000000..0f72892893450b8f0994ee91f915e37ff0c33166
GIT binary patch
diff --git a/resources/wikiedit/numbers.png b/resources/wikiedit/numbers.png
new file mode 100644
index 0000000000000000000000000000000000000000..2de3b1790757c8bc6fe83902ab67ff75baf7fa39
GIT binary patch
diff --git a/resources/wikiedit/table.png b/resources/wikiedit/table.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5719cf93998cf854274a9f2547c478a25b7e9db
GIT binary patch
diff --git a/resources/wikiedit/yioopSearch.png b/resources/wikiedit/yioopSearch.png
new file mode 100755
index 0000000000000000000000000000000000000000..1664f842b979d2e7b723cf07a3319fb9875fc57e
GIT binary patch
diff --git a/scripts/wikify.js b/scripts/wikify.js
new file mode 100755
index 0000000..2b96b3f
--- /dev/null
+++ b/scripts/wikify.js
@@ -0,0 +1,693 @@
+/**
+ *  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.
+ */
+
+/* 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 wikiText if data-wikiText is not set.
+ */
+var wiki_text_name = "wiki-text";
+
+/*
+ * 
+ * Arrays that store button configuration
+ */
+var all_buttons = {};
+var buttons = {};
+
+/**
+ * 
+ * Localization string constants
+ * 
+ */
+
+var bullet_entry = "Bulleted list item";
+var enum_list_entry = "Numbered list item";
+var insert_nonformatted_text = "Insert non-formatted text here";
+var prompt_for_yioop_height = "Enter the width of the widget";
+var prompt_for_yioop_width = "Enter the height of the widget";
+var prompt_for_table_cols = "Enter the number of columns";
+var prompt_for_table_rows = "Enter the number of rows";
+var enter_link_title_placeholder = "Enter Link title";
+var link_title = "Link Title";
+var enter_link_placeholder = "Enter link startng with http:// or https://";
+var prompt_heading = "Insert heading too?";
+var table_example_placeholder = "Example";
+var table_title_placeholder = "Title";
+
+/**
+ * On window load , Render the editor
+ * and buttons.
+ */
+window.onload = function()
+{
+    /*
+     * 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 = {
+            'bold': ['---', '---'],
+            'italic': ['--', '--'],
+            'underline': ['<u>', '</u>'],
+            'strike': ['<s>', '</s>'],
+            'nowiki': ['<nowiki>', '</nowiki>'],
+            'hyperlink': ['[', ']'],
+            'bullets': ['* ' + bullet_entry + ' \n'],
+            'numbers': ['# ' + enum_list_entry + ' \n'],
+            'hr': ['---- \n']
+        };
+        for (var prop in buttons) {
+            if (buttons.hasOwnProperty(prop)) {
+                button_string += '<input type="button" class="button" id="' + prop + '" onmousedown="wikifySelection(\'' + prop + '\');">';
+            }
+        }
+        node.innerHTML =
+                button_string +
+                '<select class="heading" id="heading" value="heading" onchange="setHeading();">\n\
+                <option selected="" disabled="">Heading\n\
+                </option><option value="1">H1</option>\n\
+                <option value="2">H2</option>\n\
+                <option value="3">H3</option>\n\
+                <option value="4">H4</option>\n\
+                </select>\n\
+                <input type="button" class="button" id="table" onmousedown="insertTable();">' +
+                '<input type="button" class="button" id="yioop-search-widget" onmousedown="insertYioopSearch();">' +
+                '<form action="" method="POST" name="">' +
+                '<textarea id="wiki-text" class="wiki-text" style="width: 550px; height: 300px; resize: none;"></textarea><p>' +
+                '<input type=SUBMIT value="submit" />\n\
+                </p></form>';
+        return;
+    } else {
+        if (filterButtons() === false) {
+            return;
+        } else {
+            renderWikiEditor(node);
+        }
+    }
+};
+
+/**
+ * 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.
+ * 
+ */
+function filterButtons()
+{
+    all_buttons = {
+        'bold': ['---', '---'],
+        'italic': ['--', '--'],
+        'underline': ['<u>', '</u>'],
+        'strike': ['<s>', '</s>'],
+        'nowiki': ['<nowiki>', '</nowiki>'],
+        'hyperlink': ['[', ']'],
+        'bullets': ['* Bulleted list item \n'],
+        'numbers': ['# Numbered list item \n'],
+        'hr': ['---- \n'],
+        'heading': '',
+        'yioop': '',
+        '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 (trimString(wiki_buttons_array[0]) === 'all') {
+            exc = true;
+        }
+        for (var i = 0; i < buttons_array_length; i++) {
+            wiki_buttons_array[i] = trimString(wiki_buttons_array[i]);
+            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.
+ * 
+ */
+function renderWikiEditor(wiki_editor_div)
+{
+    /*
+     * Insert Heading
+     */
+    if (buttons.hasOwnProperty('heading')) {
+        wiki_editor_div.appendChild(createDropDown(
+                "heading",
+                "setHeading",
+                {
+                    "H1": "1",
+                    "H2": "2",
+                    "H3": "3",
+                    "H4": "4"
+                }
+        ));
+    }
+    /*
+     * 
+     * Using the buttons Object, populate the buttons.
+     */
+    for (var property in buttons) {
+        var obj = ['yioop', 'table', 'heading'];
+        if (buttons.hasOwnProperty(property) && (obj.indexOf(property) === -1)) {
+            createButton(wiki_editor_div, property);
+        }
+    }
+    if (buttons.hasOwnProperty('table')) {
+        /*
+         * Insert button for insertTable
+         */
+        wiki_editor_div.appendChild(createElement("input", {
+            "type": "button",
+            "class": 'button',
+            "id": 'table',
+            "onmousedown": "insertTable();"
+        }));
+    }
+    /*
+     * Insert button for yioop-search-widget
+     */
+    if (buttons.hasOwnProperty('yioop')) {
+        wiki_editor_div.appendChild(createElement("input", {
+            "type": "button",
+            "class": 'button',
+            "id": 'yioop-search-widget',
+            "onmousedown": "insertYioopSearch();"
+        }));
+    }
+    /*
+     * 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,
+            "style": 'width: 550px; height: 300px; resize: none;'
+        }));
+        var pElement = createElement("p", {});
+        pElement.appendChild(createElement("input", {
+            "type": "SUBMIT",
+            "id": "Submit",
+            "value": "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,
+            "style": 'width: 550px; height: 300px; resize: none;'
+        }));
+    }
+    /*
+     * 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.
+ * 
+ */
+function createElement(element_name, attributes)
+{
+    var elementx = document.createElement(element_name);
+
+    for (var property in attributes) {
+        if (attributes.hasOwnProperty(property)) {
+            elementx.setAttribute(property, attributes[property]);
+        }
+    }
+    return elementx;
+}
+
+/**
+ * Given the parent element and
+ * name of the button, This util function
+ * created an editor button.
+ * 
+ */
+function createButton(context, name)
+{
+    context.appendChild(createElement("input", {
+        "type": "button",
+        "class": 'button',
+        "id": name,
+        "onmousedown": "wikifySelection('" + name + "');"
+    }));
+}
+
+/**
+ * This is a util function to
+ * create a dropdown element.
+ * 
+ */
+function createDropDown(dropdown_name, action, options)
+{
+    var select = createElement("select", {
+        "class": dropdown_name,
+        "id": dropdown_name,
+        "value": dropdown_name,
+        "onchange": action + "();"
+    });
+    var option = document.createElement("option");
+    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.
+ */
+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 {type} text
+ * @returns {unresolved}
+ */
+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.
+ * 
+ */
+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.
+ */
+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'), "\'")
+                );
+    } 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();
+ * 
+ */
+function wikify(wiki_prefix, wiki_suffix)
+{
+    /*
+     * 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 === '[') {
+        var title = prompt(link_title, enter_link_title_placeholder);
+        var link = prompt("Link", enter_link_placeholder);
+        if (!title || !link) {
+            return;
+        }
+        selection = link + " " + title;
+    } else if (!selection && wiki_prefix === '<nowiki>') {
+        selection = insert_nonformatted_text;
+    }
+    /*
+     *  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.
+     */
+    text_area.value = selected_text_prefix + wiki_prefix + selection + wiki_suffix + selected_text_suffix;
+}
+
+/**
+ * This function takes in number of rows, columns and
+ * header_text(if desired) and constructs a table in wiki markup.
+ * 
+ */
+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.
+ */
+function insertYioopSearch()
+{
+    var width = prompt(prompt_for_yioop_height);
+    var height = prompt(prompt_for_yioop_width);
+    var widget_obj = {};
+    var yioop_obj = {};
+    yioop_obj.width = width;
+    yioop_obj.height = height;
+    widget_obj.yioop_search = objToString(yioop_obj);
+    insertTextAtCursor("[" + objToString(widget_obj) + "]");
+}
+
+/**
+ * Util function to Stringify an JS Object
+ */
+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.
+ * 
+ */
+function insertTable()
+{
+    var cols = prompt(prompt_for_table_cols);
+    var rows = prompt(prompt_for_table_rows);
+    if (!cols || !rows) {
+        return;
+    }
+    var retVal = confirm(prompt_heading);
+    if (retVal) {
+        var table = createWikiTable(rows, cols, table_example_placeholder, table_title_placeholder);
+    } else {
+        table = createWikiTable(rows, cols, table_example_placeholder);
+    }
+    insertTextAtCursor(table);
+}
+
+/**
+ * Accepts text as parameter to be inserted at caret's current position.
+ */
+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.
+ * 
+ */
+function setHeading()
+{
+    var markup_text = fillChars("=", document.getElementById("heading").value);
+    document.getElementById("heading").selectedIndex = 0;
+    wikify(markup_text, markup_text);
+}
+
+/**
+ * This is a simple util
+ * function to fill a character 
+ * array and return as a string,
+ * given a character and array count.
+ * 
+ */
+function fillChars(c, n)
+{
+    for (var e = ""; e.length < n; ) {
+        e += c;
+    }
+    return e;
+}
+
+/**
+ * Util method to trim
+ * starting and trailing spaces
+ * in stings.
+ */
+function trimString(string)
+{
+    return string.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+}
\ 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)

