summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--inc/JSON.php615
-rw-r--r--inc/html.php55
-rw-r--r--inc/lang/en/lang.php3
-rw-r--r--inc/template.php44
-rw-r--r--inc/toolbar.php202
-rw-r--r--lib/images/toolbar/bold.pngbin738 -> 479 bytes
-rw-r--r--lib/images/toolbar/chars.pngbin0 -> 636 bytes
-rw-r--r--lib/images/toolbar/code.pngbin710 -> 0 bytes
-rw-r--r--lib/images/toolbar/empty.pngbin516 -> 0 bytes
-rw-r--r--lib/images/toolbar/extlink.pngbin885 -> 0 bytes
-rw-r--r--lib/images/toolbar/fonth1.pngbin592 -> 0 bytes
-rw-r--r--lib/images/toolbar/fonth2.pngbin708 -> 0 bytes
-rw-r--r--lib/images/toolbar/fonth3.pngbin681 -> 0 bytes
-rw-r--r--lib/images/toolbar/fonth4.pngbin687 -> 0 bytes
-rw-r--r--lib/images/toolbar/fonth5.pngbin674 -> 0 bytes
-rw-r--r--lib/images/toolbar/h1.pngbin0 -> 429 bytes
-rw-r--r--lib/images/toolbar/h2.pngbin0 -> 500 bytes
-rw-r--r--lib/images/toolbar/h3.pngbin0 -> 501 bytes
-rw-r--r--lib/images/toolbar/h4.pngbin0 -> 461 bytes
-rw-r--r--lib/images/toolbar/h5.pngbin0 -> 478 bytes
-rw-r--r--lib/images/toolbar/hr.pngbin0 -> 372 bytes
-rw-r--r--lib/images/toolbar/image.pngbin1010 -> 680 bytes
-rw-r--r--lib/images/toolbar/italic.pngbin676 -> 363 bytes
-rw-r--r--lib/images/toolbar/link.pngbin842 -> 574 bytes
-rw-r--r--lib/images/toolbar/linkextern.pngbin0 -> 1138 bytes
-rw-r--r--lib/images/toolbar/list.pngbin582 -> 0 bytes
-rw-r--r--lib/images/toolbar/list_ul.pngbin560 -> 0 bytes
-rw-r--r--lib/images/toolbar/mono.pngbin0 -> 426 bytes
-rw-r--r--lib/images/toolbar/ol.pngbin0 -> 435 bytes
-rw-r--r--lib/images/toolbar/rule.pngbin565 -> 0 bytes
-rw-r--r--lib/images/toolbar/sig.pngbin699 -> 606 bytes
-rw-r--r--lib/images/toolbar/smiley.pngbin0 -> 860 bytes
-rw-r--r--lib/images/toolbar/spellcheck.pngbin1076 -> 738 bytes
-rw-r--r--lib/images/toolbar/strike.pngbin739 -> 450 bytes
-rw-r--r--lib/images/toolbar/ul.pngbin0 -> 409 bytes
-rw-r--r--lib/images/toolbar/underline.pngbin743 -> 405 bytes
-rw-r--r--lib/scripts/edit.js308
-rw-r--r--lib/scripts/script.js281
-rw-r--r--lib/scripts/spellcheck.js125
-rw-r--r--lib/tpl/default/design.css24
40 files changed, 1369 insertions, 288 deletions
diff --git a/inc/JSON.php b/inc/JSON.php
new file mode 100644
index 000000000..6345743fc
--- /dev/null
+++ b/inc/JSON.php
@@ -0,0 +1,615 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Converts to and from JSON format.
+ *
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
+ * format. It is easy for humans to read and write. It is easy for machines
+ * to parse and generate. It is based on a subset of the JavaScript
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
+ * This feature can also be found in Python. JSON is a text format that is
+ * completely language independent but uses conventions that are familiar
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
+ * ideal data-interchange language.
+ *
+ * This package provides a simple encoder and decoder for JSON notation. It
+ * is intended for use with client-side Javascript applications that make
+ * use of HTTPRequest to perform server communication functions - data can
+ * be encoded into JSON notation for use in a client-side javascript, or
+ * decoded from incoming Javascript requests. JSON format is native to
+ * Javascript, and can be directly eval()'ed with no further parsing
+ * overhead
+ *
+ * All strings should be in ASCII or UTF-8 format!
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met: Redistributions of source code must retain the
+ * above copyright notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * @category
+ * @package
+ * @author Michal Migurski <mike-json@teczno.com>
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright 2005 Michal Migurski
+ * @license http://www.freebsd.org/copyright/freebsd-license.html
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
+ */
+
+/**
+ * Marker constant for JSON::decode(), used to flag stack state
+ */
+define('JSON_SLICE', 1);
+
+/**
+ * Marker constant for JSON::decode(), used to flag stack state
+ */
+define('JSON_IN_STR', 2);
+
+/**
+ * Marker constant for JSON::decode(), used to flag stack state
+ */
+define('JSON_IN_ARR', 4);
+
+/**
+ * Marker constant for JSON::decode(), used to flag stack state
+ */
+define('JSON_IN_OBJ', 8);
+
+/**
+ * Marker constant for JSON::decode(), used to flag stack state
+ */
+define('JSON_IN_CMT', 16);
+
+/**
+ * Behavior switch for JSON::decode()
+ */
+define('JSON_LOOSE_TYPE', 10);
+
+/**
+ * Behavior switch for JSON::decode()
+ */
+define('JSON_STRICT_TYPE', 11);
+
+/**
+ * Converts to and from JSON format.
+ *
+ * @category
+ * @package
+ * @author Michal Migurski <mike-json@teczno.com>
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
+ * @copyright 2005 Michal Migurski
+ * @license http://www.php.net/license/3_0.txt PHP License 3.0
+ * @version
+ * @link
+ * @see
+ * @since
+ * @deprecated
+ */
+class JSON
+{
+ /**
+ * constructs a new JSON instance
+ *
+ * @param int $use object behavior: when encoding or decoding,
+ * be loose or strict about object/array usage
+ *
+ * possible values:
+ * JSON_STRICT_TYPE - strict typing, default
+ * "{...}" syntax creates objects in decode.
+ * JSON_LOOSE_TYPE - loose typing
+ * "{...}" syntax creates associative arrays in decode.
+ */
+ function JSON($use=JSON_STRICT_TYPE)
+ {
+ $this->use = $use;
+ }
+
+ /**
+ * encodes an arbitrary variable into JSON format
+ *
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
+ * see argument 1 to JSON() above for array-parsing behavior.
+ * if var is a strng, note that encode() always expects it
+ * to be in ASCII or UTF-8 format!
+ *
+ * @return string JSON string representation of input var
+ * @access public
+ */
+ function encode($var)
+ {
+ switch (gettype($var)) {
+ case 'boolean':
+ return $var ? 'true' : 'false';
+
+ case 'NULL':
+ return 'null';
+
+ case 'integer':
+ return sprintf('%d', $var);
+
+ case 'double':
+ case 'float':
+ return sprintf('%f', $var);
+
+ case 'string':
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
+ $ascii = '';
+ $strlen_var = strlen($var);
+
+ /*
+ * Iterate over every character in the string,
+ * escaping with a slash or encoding to UTF-8 where necessary
+ */
+ for ($c = 0; $c < $strlen_var; ++$c) {
+
+ $ord_var_c = ord($var{$c});
+
+ switch ($ord_var_c) {
+ case 0x08: $ascii .= '\b'; break;
+ case 0x09: $ascii .= '\t'; break;
+ case 0x0A: $ascii .= '\n'; break;
+ case 0x0C: $ascii .= '\f'; break;
+ case 0x0D: $ascii .= '\r'; break;
+
+ case 0x22:
+ case 0x2F:
+ case 0x5C:
+ // double quote, slash, slosh
+ $ascii .= '\\'.$var{$c};
+ break;
+
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
+ // characters U-00000000 - U-0000007F (same as ASCII)
+ $ascii .= $var{$c};
+ break;
+
+ case (($ord_var_c & 0xE0) == 0xC0):
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c, ord($var{$c+1}));
+ $c+=1;
+ $utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xF0) == 0xE0):
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c+1}),
+ ord($var{$c+2}));
+ $c+=2;
+ $utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xF8) == 0xF0):
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c+1}),
+ ord($var{$c+2}),
+ ord($var{$c+3}));
+ $c+=3;
+ $utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xFC) == 0xF8):
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c+1}),
+ ord($var{$c+2}),
+ ord($var{$c+3}),
+ ord($var{$c+4}));
+ $c+=4;
+ $utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+
+ case (($ord_var_c & 0xFE) == 0xFC):
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $char = pack('C*', $ord_var_c,
+ ord($var{$c+1}),
+ ord($var{$c+2}),
+ ord($var{$c+3}),
+ ord($var{$c+4}),
+ ord($var{$c+5}));
+ $c+=5;
+ $utf16 = mb_convert_encoding($char, 'UTF-16', 'UTF-8');
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
+ break;
+ }
+ }
+
+ return '"'.$ascii.'"';
+
+ case 'array':
+ /*
+ * As per JSON spec if any array key is not an integer
+ * we must treat the the whole array as an object. We
+ * also try to catch a sparsely populated associative
+ * array with numeric keys here because some JS engines
+ * will create an array with empty indexes up to
+ * max_index which can cause memory issues and because
+ * the keys, which may be relevant, will be remapped
+ * otherwise.
+ *
+ * As per the ECMA and JSON specification an object may
+ * have any string as a property. Unfortunately due to
+ * a hole in the ECMA specification if the key is a
+ * ECMA reserved word or starts with a digit the
+ * parameter is only accessible using ECMAScript's
+ * bracket notation.
+ */
+
+ // treat as a JSON object
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
+ return sprintf('{%s}', join(',', array_map(array($this, 'name_value'),
+ array_keys($var),
+ array_values($var))));
+ }
+
+ // treat it like a regular array
+ return sprintf('[%s]', join(',', array_map(array($this, 'encode'), $var)));
+
+ case 'object':
+ $vars = get_object_vars($var);
+ return sprintf('{%s}', join(',', array_map(array($this, 'name_value'),
+ array_keys($vars),
+ array_values($vars))));
+
+ default:
+ return '';
+ }
+ }
+
+ /**
+ * encodes an arbitrary variable into JSON format, alias for encode()
+ */
+ function enc($var)
+ {
+ return $this->encode($var);
+ }
+
+ /** function name_value
+ * array-walking function for use in generating JSON-formatted name-value pairs
+ *
+ * @param string $name name of key to use
+ * @param mixed $value reference to an array element to be encoded
+ *
+ * @return string JSON-formatted name-value pair, like '"name":value'
+ * @access private
+ */
+ function name_value($name, $value)
+ {
+ return (sprintf("%s:%s", $this->encode(strval($name)), $this->encode($value)));
+ }
+
+ /**
+ * reduce a string by removing leading and trailing comments and whitespace
+ *
+ * @param $str string string value to strip of comments and whitespace
+ *
+ * @return string string value stripped of comments and whitespace
+ * @access private
+ */
+ function reduce_string($str)
+ {
+ $str = preg_replace(array(
+
+ // eliminate single line comments in '// ...' form
+ '#^\s*//(.+)$#m',
+
+ // eliminate multi-line comments in '/* ... */' form, at start of string
+ '#^\s*/\*(.+)\*/#Us',
+
+ // eliminate multi-line comments in '/* ... */' form, at end of string
+ '#/\*(.+)\*/\s*$#Us'
+
+ ), '', $str);
+
+ // eliminate extraneous space
+ return trim($str);
+ }
+
+ /**
+ * decodes a JSON string into appropriate variable
+ *
+ * @param string $str JSON-formatted string
+ *
+ * @return mixed number, boolean, string, array, or object
+ * corresponding to given JSON input string.
+ * See argument 1 to JSON() above for object-output behavior.
+ * Note that decode() always returns strings
+ * in ASCII or UTF-8 format!
+ * @access public
+ */
+ function decode($str)
+ {
+ $str = $this->reduce_string($str);
+
+ switch (strtolower($str)) {
+ case 'true':
+ return true;
+
+ case 'false':
+ return false;
+
+ case 'null':
+ return null;
+
+ default:
+ if (is_numeric($str)) {
+ // Lookie-loo, it's a number
+
+ // This would work on its own, but I'm trying to be
+ // good about returning integers where appropriate:
+ // return (float)$str;
+
+ // Return float or int, as appropriate
+ return ((float)$str == (integer)$str)
+ ? (integer)$str
+ : (float)$str;
+
+ } elseif (preg_match('/^("|\').+("|\')$/s', $str, $m) && $m[1] == $m[2]) {
+ // STRINGS RETURNED IN UTF-8 FORMAT
+ $delim = substr($str, 0, 1);
+ $chrs = substr($str, 1, -1);
+ $utf8 = '';
+ $strlen_chrs = strlen($chrs);
+
+ for ($c = 0; $c < $strlen_chrs; ++$c) {
+
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
+ $ord_chrs_c = ord($chrs{$c});
+
+ switch ($substr_chrs_c_2) {
+ case '\b': $utf8 .= chr(0x08); $c+=1; break;
+ case '\t': $utf8 .= chr(0x09); $c+=1; break;
+ case '\n': $utf8 .= chr(0x0A); $c+=1; break;
+ case '\f': $utf8 .= chr(0x0C); $c+=1; break;
+ case '\r': $utf8 .= chr(0x0D); $c+=1; break;
+
+ case '\\"':
+ case '\\\'':
+ case '\\\\':
+ case '\\/':
+ if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
+ ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
+ $utf8 .= $chrs{++$c};
+ }
+ break;
+
+ default:
+ if (preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6))) {
+ // single, escaped unicode character
+ $utf16 = chr(hexdec(substr($chrs, ($c+2), 2)))
+ . chr(hexdec(substr($chrs, ($c+4), 2)));
+ $utf8 .= mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
+ $c+=5;
+
+ } elseif(($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F)) {
+ $utf8 .= $chrs{$c};
+
+ } elseif(($ord_chrs_c & 0xE0) == 0xC0) {
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
+ //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 2); $c += 1;
+
+ } elseif(($ord_chrs_c & 0xF0) == 0xE0) {
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 3); $c += 2;
+
+ } elseif(($ord_chrs_c & 0xF8) == 0xF0) {
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 4); $c += 3;
+
+ } elseif(($ord_chrs_c & 0xFC) == 0xF8) {
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 5); $c += 4;
+
+ } elseif(($ord_chrs_c & 0xFE) == 0xFC) {
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ $utf8 .= substr($chrs, $c, 6); $c += 5;
+
+ }
+ break;
+
+ }
+
+ }
+
+ return $utf8;
+
+ } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
+ // array, or object notation
+
+ if ($str{0} == '[') {
+ $stk = array(JSON_IN_ARR);
+ $arr = array();
+ } else {
+ if ($this->use == JSON_LOOSE_TYPE) {
+ $stk = array(JSON_IN_OBJ);
+ $obj = array();
+ } else {
+ $stk = array(JSON_IN_OBJ);
+ $obj = new stdClass();
+ }
+ }
+
+ array_push($stk, array('what' => JSON_SLICE,
+ 'where' => 0,
+ 'delim' => false));
+
+ $chrs = substr($str, 1, -1);
+ $chrs = $this->reduce_string($chrs);
+
+ if ($chrs == '') {
+ if (reset($stk) == JSON_IN_ARR) {
+ return $arr;
+
+ } else {
+ return $obj;
+
+ }
+ }
+
+ //print("\nparsing {$chrs}\n");
+
+ $strlen_chrs = strlen($chrs);
+
+ for ($c = 0; $c <= $strlen_chrs; ++$c) {
+
+ $top = end($stk);
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
+
+ if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == JSON_SLICE))) {
+ // found a comma that is not inside a string, array, etc.,
+ // OR we've reached the end of the character list
+ $slice = substr($chrs, $top['where'], ($c - $top['where']));
+ array_push($stk, array('what' => JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
+ //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ if (reset($stk) == JSON_IN_ARR) {
+ // we are in an array, so just push an element onto the stack
+ array_push($arr, $this->decode($slice));
+
+ } elseif (reset($stk) == JSON_IN_OBJ) {
+ // we are in an object, so figure
+ // out the property name and set an
+ // element in an associative array,
+ // for now
+ if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+ // "name":value pair
+ $key = $this->decode($parts[1]);
+ $val = $this->decode($parts[2]);
+
+ if ($this->use == JSON_LOOSE_TYPE) {
+ $obj[$key] = $val;
+ } else {
+ $obj->$key = $val;
+ }
+ } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
+ // name:value pair, where name is unquoted
+ $key = $parts[1];
+ $val = $this->decode($parts[2]);
+
+ if ($this->use == JSON_LOOSE_TYPE) {
+ $obj[$key] = $val;
+ } else {
+ $obj->$key = $val;
+ }
+ }
+
+ }
+
+ } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) &&
+ in_array($top['what'], array(JSON_SLICE, JSON_IN_ARR, JSON_IN_OBJ))) {
+ // found a quote, and we are not inside a string
+ array_push($stk, array('what' => JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
+ //print("Found start of string at {$c}\n");
+
+ } elseif (($chrs{$c} == $top['delim']) &&
+ ($top['what'] == JSON_IN_STR) &&
+ (($chrs{$c - 1} != "\\") ||
+ ($chrs{$c - 1} == "\\" && $chrs{$c - 2} == "\\"))) {
+ // found a quote, we're in a string, and it's not escaped
+ array_pop($stk);
+ //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
+
+ } elseif (($chrs{$c} == '[') &&
+ in_array($top['what'], array(JSON_SLICE, JSON_IN_ARR, JSON_IN_OBJ))) {
+ // found a left-bracket, and we are in an array, object, or slice
+ array_push($stk, array('what' => JSON_IN_ARR, 'where' => $c, 'delim' => false));
+ //print("Found start of array at {$c}\n");
+
+ } elseif (($chrs{$c} == ']') && ($top['what'] == JSON_IN_ARR)) {
+ // found a right-bracket, and we're in an array
+ array_pop($stk);
+ //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ } elseif (($chrs{$c} == '{') &&
+ in_array($top['what'], array(JSON_SLICE, JSON_IN_ARR, JSON_IN_OBJ))) {
+ // found a left-brace, and we are in an array, object, or slice
+ array_push($stk, array('what' => JSON_IN_OBJ, 'where' => $c, 'delim' => false));
+ //print("Found start of object at {$c}\n");
+
+ } elseif (($chrs{$c} == '}') && ($top['what'] == JSON_IN_OBJ)) {
+ // found a right-brace, and we're in an object
+ array_pop($stk);
+ //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ } elseif (($substr_chrs_c_2 == '/*') &&
+ in_array($top['what'], array(JSON_SLICE, JSON_IN_ARR, JSON_IN_OBJ))) {
+ // found a comment start, and we are in an array, object, or slice
+ array_push($stk, array('what' => JSON_IN_CMT, 'where' => $c, 'delim' => false));
+ $c++;
+ //print("Found start of comment at {$c}\n");
+
+ } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == JSON_IN_CMT)) {
+ // found a comment end, and we're in one now
+ array_pop($stk);
+ $c++;
+
+ for ($i = $top['where']; $i <= $c; ++$i)
+ $chrs = substr_replace($chrs, ' ', $i, 1);
+
+ //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
+
+ }
+
+ }
+
+ if (reset($stk) == JSON_IN_ARR) {
+ return $arr;
+
+ } elseif (reset($stk) == JSON_IN_OBJ) {
+ return $obj;
+
+ }
+
+ }
+ }
+ }
+
+ /**
+ * decodes a JSON string into appropriate variable; alias for decode()
+ */
+ function dec($var)
+ {
+ return $this->decode($var);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/inc/html.php b/inc/html.php
index d4fafdaf3..d03815f00 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -894,37 +894,12 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
<table style="width:99%">
<tr>
<td class="toolbar" colspan="2">
+ <div id="toolbar"></div>
+
<?php if($wr){?>
<script language="javascript" type="text/javascript" charset="utf-8">
<?php /* sets changed to true when previewed */?>
textChanged = <?php ($pr) ? print 'true' : print 'false' ?>;
-
- formatButton('bold.png','<?php echo $lang['qb_bold']?>','**','**','<?php echo $lang['qb_bold']?>','b');
- formatButton('italic.png','<?php echo $lang['qb_italic']?>',"\/\/","\/\/",'<?php echo $lang['qb_italic']?>','i');
- formatButton('underline.png','<?php echo $lang['qb_underl']?>','__','__','<?php echo $lang['qb_underl']?>','u');
- formatButton('code.png','<?php echo $lang['qb_code']?>','\'\'','\'\'','<?php echo $lang['qb_code']?>','c');
- formatButton('strike.png','<?php echo $lang['qb_strike']?>','&lt;del&gt;','&lt;\/del&gt;','<?php echo $lang['qb_strike']?>','d');
-
- formatButton('fonth1.png','<?php echo $lang['qb_h1']?>','====== ',' ======\n','<?php echo $lang['qb_h1']?>','1');
- formatButton('fonth2.png','<?php echo $lang['qb_h2']?>','===== ',' =====\n','<?php echo $lang['qb_h2']?>','2');
- formatButton('fonth3.png','<?php echo $lang['qb_h3']?>','==== ',' ====\n','<?php echo $lang['qb_h3']?>','3');
- formatButton('fonth4.png','<?php echo $lang['qb_h4']?>','=== ',' ===\n','<?php echo $lang['qb_h4']?>','4');
- formatButton('fonth5.png','<?php echo $lang['qb_h5']?>','== ',' ==\n','<?php echo $lang['qb_h5']?>','5');
-
- formatButton('link.png','<?php echo $lang['qb_link']?>','[[',']]','<?php echo $lang['qb_link']?>','l');
- formatButton('extlink.png','<?php echo $lang['qb_extlink']?>','[[',']]','http://www.example.com|<?php echo $lang['qb_extlink']?>');
-
- formatButton('list.png','<?php echo $lang['qb_ol']?>',' - ','\n','<?php echo $lang['qb_ol']?>');
- formatButton('list_ul.png','<?php echo $lang['qb_ul']?>',' * ','\n','<?php echo $lang['qb_ul']?>');
-
- insertButton('rule.png','<?php echo $lang['qb_hr']?>','----\n');
- mediaButton('image.png','<?php echo $lang['qb_media']?>','m','<?php echo $INFO['namespace']?>');
-
- <?php
- if($conf['useacl'] && $_SERVER['REMOTE_USER']){
- echo "insertButton('sig.png','".$lang['qb_sig']."','".html_signature()."','y');";
- }
- ?>
</script>
<span id="spell_action"></span>
<?php } ?>
@@ -955,14 +930,18 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
<?php }?>
</td>
<td align="right">
+ <div id="sizectl"></div>
+
<script language="javascript" type="text/javascript" charset="utf-8">
- showSizeCtl();
+ //showSizeCtl();
<?php if($wr){ ?>
init_locktimer(<?php echo $conf['locktime']-60?>,'<?php echo $lang['willexpire']?>');
+ //initToolbar('toolbar','wikitext',toolbar);
+
//initialize spellchecker
<?php if($conf['spellchecker']){ ?>
- ajax_spell.init('<?php echo $lang['spell_start']?>','<?php echo $lang['spell_stop']?>','<?php echo $lang['spell_wait']?>','<?php echo $lang['spell_noerr']?>','<?php echo $lang['spell_nosug']?>','<?php echo $lang['spell_change']?>');
+// ajax_spell.init('<?php echo $lang['spell_start']?>','<?php echo $lang['spell_stop']?>','<?php echo $lang['spell_wait']?>','<?php echo $lang['spell_noerr']?>','<?php echo $lang['spell_nosug']?>','<?php echo $lang['spell_change']?>');
<?php } ?>
document.editform.wikitext.focus();
@@ -1004,24 +983,6 @@ function html_minoredit(){
}
/**
- * prepares the signature string as configured in the config
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- */
-function html_signature(){
- global $conf;
- global $INFO;
-
- $sig = $conf['signature'];
- $sig = strftime($sig);
- $sig = str_replace('@USER@',$_SERVER['REMOTE_USER'],$sig);
- $sig = str_replace('@NAME@',$INFO['userinfo']['name'],$sig);
- $sig = str_replace('@MAIL@',$INFO['userinfo']['mail'],$sig);
- $sig = str_replace('@DATE@',date($conf['dformat']),$sig);
- return addslashes($sig);
-}
-
-/**
* prints some debug info
*
* @author Andreas Gohr <andi@splitbrain.org>
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index 9cfae794e..c3de831cd 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -123,6 +123,9 @@ $lang['qb_ol'] = 'Ordered List Item';
$lang['qb_ul'] = 'Unordered List Item';
$lang['qb_media'] = 'Add Images and other files';
$lang['qb_sig'] = 'Insert Signature';
+$lang['qb_smileys'] = 'Smileys';
+$lang['qb_chars'] = 'Special Chars';
+
$lang['del_confirm']= 'Delete this entry?';
diff --git a/inc/template.php b/inc/template.php
index e04998444..8c84515c2 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -207,6 +207,7 @@ function tpl_metaheaders(){
ptln(" var alertText = '".str_replace('\\\\n','\\n',addslashes($lang['qb_alert']))."'",$it);
ptln(" var notSavedYet = '".str_replace('\\\\n','\\n',addslashes($lang['notsavedyet']))."'",$it);
ptln(" var DOKU_BASE = '".DOKU_BASE."'",$it);
+
ptln('</script>',$it);
// load the default JavaScript files
@@ -217,11 +218,6 @@ function tpl_metaheaders(){
ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
DOKU_BASE.'lib/scripts/ajax.js"></script>',$it);
- // load spellchecker script if wanted
- if($conf['spellchecker'] && ($ACT=='edit' || $ACT=='preview')){
- ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
- DOKU_BASE.'lib/scripts/spellcheck.js"></script>',$it);
- }
// dom tool tip library, for insitu footnotes
ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
@@ -229,6 +225,44 @@ function tpl_metaheaders(){
ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
DOKU_BASE.'lib/scripts/domTT.js"></script>',$it);
+ // add size control
+ ptln('<script language="javascript" type="text/javascript" charset="utf-8">',$it);
+ ptln("addEvent(window,'onload',function(){initSizeCtl('sizectl','wikitext')});",$it+2);
+ ptln('</script>',$it);
+
+
+ // editing functions
+ if(($ACT=='edit' || $ACT=='preview') && $INFO['writable']){
+ // load toolbar functions
+ ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
+ DOKU_BASE.'lib/scripts/edit.js"></script>',$it);
+
+ // load spellchecker functions if wanted
+ if($conf['spellchecker']){
+ ptln('<script language="javascript" type="text/javascript" charset="utf-8" src="'.
+ DOKU_BASE.'lib/scripts/spellcheck.js"></script>',$it+2);
+ }
+
+ ptln('<script language="javascript" type="text/javascript" charset="utf-8">',$it);
+
+ // add toolbar
+ require_once(DOKU_INC.'inc/toolbar.php');
+ toolbar_JSdefines('toolbar');
+ ptln("addEvent(window,'onload',function(){initToolbar('toolbar','wikitext',toolbar);});",$it+2);
+
+ // add spellchecker
+ if($conf['spellchecker']){
+ //init here
+ ptln("addEvent(window,'onload',function(){ ajax_spell.init('".$lang['spell_start']."','".
+ $lang['spell_stop']."','".
+ $lang['spell_wait']."','".
+ $lang['spell_noerr']."','".
+ $lang['spell_nosug']."','".
+ $lang['spell_change']."'); });");
+ }
+ ptln('</script>',$it);
+ }
+
// plugin stylesheets and Scripts
plugin_printCSSJS();
}
diff --git a/inc/toolbar.php b/inc/toolbar.php
new file mode 100644
index 000000000..5c4ff030f
--- /dev/null
+++ b/inc/toolbar.php
@@ -0,0 +1,202 @@
+<?php
+/**
+ * Editing toolbar functions
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+ if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
+
+require_once(DOKU_INC.'inc/JSON.php');
+
+
+/**
+ * Prepares and prints an JavaScript array with all toolbar buttons
+ *
+ * @todo add toolbar plugins
+ * @param string $varname Name of the JS variable to fill
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function toolbar_JSdefines($varname){
+ global $ID;
+ global $conf;
+ global $lang;
+
+ // build button array
+ $menu = array(
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_bold'],
+ 'icon' => 'bold.png',
+ 'key' => 'b',
+ 'open' => '**',
+ 'close' => '**',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_italic'],
+ 'icon' => 'italic.png',
+ 'key' => 'i',
+ 'open' => '//',
+ 'close' => '//',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_underl'],
+ 'icon' => 'underline.png',
+ 'key' => 'u',
+ 'open' => '__',
+ 'close' => '__',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_code'],
+ 'icon' => 'mono.png',
+ 'key' => 'c',
+ 'open' => "''",
+ 'close' => "''",
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_strike'],
+ 'icon' => 'strike.png',
+ 'key' => 'd',
+ 'open' => '<del>',
+ 'close' => '<del>',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_h1'],
+ 'icon' => 'h1.png',
+ 'key' => '1',
+ 'open' => '====== ',
+ 'close' => '======\n',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_h2'],
+ 'icon' => 'h2.png',
+ 'key' => '2',
+ 'open' => '===== ',
+ 'close' => '=====\n',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_h3'],
+ 'icon' => 'h3.png',
+ 'key' => '3',
+ 'open' => '==== ',
+ 'close' => '====\n',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_h4'],
+ 'icon' => 'h4.png',
+ 'key' => '4',
+ 'open' => '=== ',
+ 'close' => '===\n',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_h5'],
+ 'icon' => 'h5.png',
+ 'key' => '5',
+ 'open' => '== ',
+ 'close' => '==\n',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_link'],
+ 'icon' => 'link.png',
+ 'key' => 'l',
+ 'open' => '[[',
+ 'close' => ']]',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_extlink'],
+ 'icon' => 'linkextern.png',
+ 'open' => '[[',
+ 'close' => ']]',
+ 'sample' => 'http://example.com|'.$lang['qb_extlink'],
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_ol'],
+ 'icon' => 'ol.png',
+ 'open' => ' - ',
+ 'close' => '\n',
+ ),
+ array(
+ 'type' => 'format',
+ 'title' => $lang['qb_ul'],
+ 'icon' => 'ul.png',
+ 'open' => ' * ',
+ 'close' => '\n',
+ ),
+ array(
+ 'type' => 'insert',
+ 'title' => $lang['qb_hr'],
+ 'icon' => 'hr.png',
+ 'insert' => '----\n',
+ ),
+ array(
+ 'type' => 'popup',
+ 'title' => $lang['qb_media'],
+ 'icon' => 'image.png',
+ 'url' => DOKU_BASE.'lib/exe/media.php?ns='.getNS($ID),
+ 'name' => 'mediaselect',
+ 'options'=> 'width=600,height=320,left=70,top=50,scrollbars=yes,resizable=yes',
+ ),
+ array(
+ 'type' => 'picker',
+ 'title' => $lang['qb_smileys'],
+ 'icon' => 'smiley.png',
+ 'list' => getSmileys(),
+ 'icobase'=> 'smileys',
+ ),
+ array(
+ 'type' => 'picker',
+ 'title' => $lang['qb_chars'],
+ 'icon' => 'chars.png',
+ 'list' => explode(' ','À à Á á Â â Ã ã Ä ä Ǎ ǎ Ă ă Å å Ā ā Ą ą Æ æ Ć ć Ç ç Č č Ĉ ĉ Ċ ċ Ð đ ð Ď ď È è É é Ê ê Ë ë Ě ě Ē ē Ė ė Ę ę Ģ ģ Ĝ ĝ Ğ ğ Ġ ġ Ĥ ĥ Ì ì Í í Î î Ï ï Ǐ ǐ Ī ī İ ı Į į Ĵ ĵ Ķ ķ Ĺ ĺ Ļ ļ Ľ ľ Ł ł Ŀ ŀ Ń ń Ñ ñ Ņ ņ Ň ň Ò ò Ó ó Ô ô Õ õ Ö ö Ǒ ǒ Ō ō Ő ő Ø ø Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ş ş Š š Ŝ ŝ Ţ ţ Ť ť Ù ù Ú ú Û û Ü ü Ǔ ǔ Ŭ ŭ Ū ū Ů ů ǖ ǘ ǚ ǜ Ų ų Ű ű Ŵ ŵ Ý ý Ÿ ÿ Ŷ ŷ Ź ź Ž ž Ż ż Þ þ ß Ħ ħ ¿ ¡ ¢ £ ¤ ¥ € ¦ § ª ¬ ¯ ° ± ÷ ‰ ¼ ½ ¾ ¹ ² ³ µ ¶ † ‡ · • º ∀ ∂ ∃ Ə ə ∅ ∇ ∈ ∉ ∋ ∏ ∑ ‾ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ ⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ◊ ℘ ℑ ℜ ℵ ♠ ♣ ♥ ♦'),
+ ),
+ );
+
+ // if logged in add sig button
+ if($conf['useacl'] && $_SERVER['REMOTE_USER']){
+ $menu[] = array(
+ 'type' => 'insert',
+ 'title' => $lang['qb_sig'],
+ 'icon' => 'sig.png',
+ 'key' => 'y',
+ 'insert' => toolbar_signature(),
+ );
+ }
+
+ // use JSON to build the JavaScript array
+ $json = new JSON();
+ print "var $varname = ".$json->encode($menu).";\n";
+}
+
+/**
+ * prepares the signature string as configured in the config
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function toolbar_signature(){
+ global $conf;
+ global $INFO;
+
+ $sig = $conf['signature'];
+ $sig = strftime($sig);
+ $sig = str_replace('@USER@',$_SERVER['REMOTE_USER'],$sig);
+ $sig = str_replace('@NAME@',$INFO['userinfo']['name'],$sig);
+ $sig = str_replace('@MAIL@',$INFO['userinfo']['mail'],$sig);
+ $sig = str_replace('@DATE@',date($conf['dformat']),$sig);
+ return $sig;
+}
+
+
+//Setup VIM: ex: et ts=4 enc=utf-8 :
diff --git a/lib/images/toolbar/bold.png b/lib/images/toolbar/bold.png
index d12c5710e..6ec336262 100644
--- a/lib/images/toolbar/bold.png
+++ b/lib/images/toolbar/bold.png
Binary files differ
diff --git a/lib/images/toolbar/chars.png b/lib/images/toolbar/chars.png
new file mode 100644
index 000000000..83cdadd75
--- /dev/null
+++ b/lib/images/toolbar/chars.png
Binary files differ
diff --git a/lib/images/toolbar/code.png b/lib/images/toolbar/code.png
deleted file mode 100644
index fb5c0c3d8..000000000
--- a/lib/images/toolbar/code.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/empty.png b/lib/images/toolbar/empty.png
deleted file mode 100644
index e606cfd07..000000000
--- a/lib/images/toolbar/empty.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/extlink.png b/lib/images/toolbar/extlink.png
deleted file mode 100644
index 705527e8c..000000000
--- a/lib/images/toolbar/extlink.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/fonth1.png b/lib/images/toolbar/fonth1.png
deleted file mode 100644
index ded5113cc..000000000
--- a/lib/images/toolbar/fonth1.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/fonth2.png b/lib/images/toolbar/fonth2.png
deleted file mode 100644
index fcf23f5ab..000000000
--- a/lib/images/toolbar/fonth2.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/fonth3.png b/lib/images/toolbar/fonth3.png
deleted file mode 100644
index 04246acf2..000000000
--- a/lib/images/toolbar/fonth3.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/fonth4.png b/lib/images/toolbar/fonth4.png
deleted file mode 100644
index 1e7ac84c6..000000000
--- a/lib/images/toolbar/fonth4.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/fonth5.png b/lib/images/toolbar/fonth5.png
deleted file mode 100644
index 5a1edb14c..000000000
--- a/lib/images/toolbar/fonth5.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/h1.png b/lib/images/toolbar/h1.png
new file mode 100644
index 000000000..ffee5c159
--- /dev/null
+++ b/lib/images/toolbar/h1.png
Binary files differ
diff --git a/lib/images/toolbar/h2.png b/lib/images/toolbar/h2.png
new file mode 100644
index 000000000..a2cc7f253
--- /dev/null
+++ b/lib/images/toolbar/h2.png
Binary files differ
diff --git a/lib/images/toolbar/h3.png b/lib/images/toolbar/h3.png
new file mode 100644
index 000000000..accdaf652
--- /dev/null
+++ b/lib/images/toolbar/h3.png
Binary files differ
diff --git a/lib/images/toolbar/h4.png b/lib/images/toolbar/h4.png
new file mode 100644
index 000000000..8e5767688
--- /dev/null
+++ b/lib/images/toolbar/h4.png
Binary files differ
diff --git a/lib/images/toolbar/h5.png b/lib/images/toolbar/h5.png
new file mode 100644
index 000000000..8fe10e99f
--- /dev/null
+++ b/lib/images/toolbar/h5.png
Binary files differ
diff --git a/lib/images/toolbar/hr.png b/lib/images/toolbar/hr.png
new file mode 100644
index 000000000..6d68d66aa
--- /dev/null
+++ b/lib/images/toolbar/hr.png
Binary files differ
diff --git a/lib/images/toolbar/image.png b/lib/images/toolbar/image.png
index ed35e5a62..d1416fae9 100644
--- a/lib/images/toolbar/image.png
+++ b/lib/images/toolbar/image.png
Binary files differ
diff --git a/lib/images/toolbar/italic.png b/lib/images/toolbar/italic.png
index f4ecd0ddf..ab8943b45 100644
--- a/lib/images/toolbar/italic.png
+++ b/lib/images/toolbar/italic.png
Binary files differ
diff --git a/lib/images/toolbar/link.png b/lib/images/toolbar/link.png
index 99cb40051..453f0d3f1 100644
--- a/lib/images/toolbar/link.png
+++ b/lib/images/toolbar/link.png
Binary files differ
diff --git a/lib/images/toolbar/linkextern.png b/lib/images/toolbar/linkextern.png
new file mode 100644
index 000000000..780c33533
--- /dev/null
+++ b/lib/images/toolbar/linkextern.png
Binary files differ
diff --git a/lib/images/toolbar/list.png b/lib/images/toolbar/list.png
deleted file mode 100644
index ffae5cfbf..000000000
--- a/lib/images/toolbar/list.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/list_ul.png b/lib/images/toolbar/list_ul.png
deleted file mode 100644
index b86bcef7d..000000000
--- a/lib/images/toolbar/list_ul.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/mono.png b/lib/images/toolbar/mono.png
new file mode 100644
index 000000000..dd398411e
--- /dev/null
+++ b/lib/images/toolbar/mono.png
Binary files differ
diff --git a/lib/images/toolbar/ol.png b/lib/images/toolbar/ol.png
new file mode 100644
index 000000000..91ce32b9d
--- /dev/null
+++ b/lib/images/toolbar/ol.png
Binary files differ
diff --git a/lib/images/toolbar/rule.png b/lib/images/toolbar/rule.png
deleted file mode 100644
index 3a32bef34..000000000
--- a/lib/images/toolbar/rule.png
+++ /dev/null
Binary files differ
diff --git a/lib/images/toolbar/sig.png b/lib/images/toolbar/sig.png
index 3e8079f49..e4aa2943c 100644
--- a/lib/images/toolbar/sig.png
+++ b/lib/images/toolbar/sig.png
Binary files differ
diff --git a/lib/images/toolbar/smiley.png b/lib/images/toolbar/smiley.png
new file mode 100644
index 000000000..dee8a962a
--- /dev/null
+++ b/lib/images/toolbar/smiley.png
Binary files differ
diff --git a/lib/images/toolbar/spellcheck.png b/lib/images/toolbar/spellcheck.png
index 797a0433d..9aecbad4b 100644
--- a/lib/images/toolbar/spellcheck.png
+++ b/lib/images/toolbar/spellcheck.png
Binary files differ
diff --git a/lib/images/toolbar/strike.png b/lib/images/toolbar/strike.png
index 197aafa9d..f6dd97647 100644
--- a/lib/images/toolbar/strike.png
+++ b/lib/images/toolbar/strike.png
Binary files differ
diff --git a/lib/images/toolbar/ul.png b/lib/images/toolbar/ul.png
new file mode 100644
index 000000000..4331bc6c2
--- /dev/null
+++ b/lib/images/toolbar/ul.png
Binary files differ
diff --git a/lib/images/toolbar/underline.png b/lib/images/toolbar/underline.png
index db07038fd..ee5e0d9fd 100644
--- a/lib/images/toolbar/underline.png
+++ b/lib/images/toolbar/underline.png
Binary files differ
diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js
new file mode 100644
index 000000000..641124c8f
--- /dev/null
+++ b/lib/scripts/edit.js
@@ -0,0 +1,308 @@
+/**
+ * Functions for text editing (toolbar stuff)
+ *
+ * @todo I'm no JS guru please help if you know how to improve
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+/**
+ * Creates a toolbar button through the DOM
+ *
+ * Style the buttons through the toolbutton class
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function createToolButton(icon,label,key,id){
+ var btn = document.createElement('button');
+ var ico = document.createElement('img');
+
+ // preapare the basic button stuff
+ btn.className = 'toolbutton';
+ btn.title = label;
+ if(key){
+ btn.title += ' [ALT+'+key.toUpperCase()+']';
+ btn.accesskey = key;
+ }
+
+ // set IDs if given
+ if(id){
+ btn.id = id;
+ ico.id = id+'_ico';
+ }
+
+ // create the icon and add it to the button
+ ico.src = DOKU_BASE+'lib/images/toolbar/'+icon;
+ btn.appendChild(ico);
+
+ return btn;
+}
+
+/**
+ * Creates a picker window for inserting text
+ *
+ * The given list can be an associative array with text,icon pairs
+ * or a simple list of text. Style the picker window through the picker
+ * class or the picker buttons with the pickerbutton class. Picker
+ * windows are appended to the body and created invisible.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function createPicker(id,list,icobase,edid){
+ var cnt = list.length;
+
+ var picker = document.createElement('div');
+ picker.className = 'picker';
+ picker.id = id;
+ picker.style.position = 'absolute';
+ picker.style.display = 'none';
+
+ for(var key in list){
+ var btn = document.createElement('button');
+
+ btn.className = 'pickerbutton'
+
+ // associative array?
+ if(isNaN(key)){
+ var ico = document.createElement('img');
+ ico.src = DOKU_BASE+'lib/images/'+icobase+'/'+list[key];
+ btn.title = key;
+ btn.appendChild(ico);
+ eval("btn.onclick = function(){pickerInsert('"+id+"','"+
+ jsEscape(key)+"','"+
+ jsEscape(edid)
+ +"');return false;}");
+ }else{
+ var txt = document.createTextNode(list[key]);
+ btn.title = list[key];
+ btn.appendChild(txt);
+ eval("btn.onclick = function(){pickerInsert('"+id+"','"+
+ jsEscape(list[key])+"','"+
+ jsEscape(edid)
+ +"');return false;}");
+ }
+
+ picker.appendChild(btn);
+ }
+ var body = document.getElementsByTagName('body')[0];
+ body.appendChild(picker);
+}
+
+/**
+ * Called by picker buttons to insert Text and close the picker again
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function pickerInsert(pickerid,text,edid){
+ // insert
+ insertAtCarret(edid,text);
+ // close picker
+ pobj = document.getElementById(pickerid);
+ pobj.style.display = 'none';
+}
+
+/**
+ * Show a previosly created picker window
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function showPicker(pickerid,btn){
+ var picker = document.getElementById(pickerid);
+ var x = findPosX(btn);
+ var y = findPosY(btn);
+ if(picker.style.display == 'none'){
+ picker.style.display = 'block';
+ picker.style.left = (x+3)+'px';
+ picker.style.top = (y+btn.offsetHeight+3)+'px';
+ }else{
+ picker.style.display = 'none';
+ }
+}
+
+/**
+ * Create a toolbar
+ *
+ * @param string tbid ID of the element where to insert the toolbar
+ * @param string edid ID of the editor textarea
+ * @param array tb Associative array defining the buttons
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function initToolbar(tbid,edid,tb){
+ var toolbar = document.getElementById(tbid);
+ var cnt = tb.length;
+ for(i=0; i<cnt; i++){
+ // create new button and add to the toolbar
+ btn = createToolButton(tb[i]['icon'],
+ tb[i]['title'],
+ tb[i]['key']);
+ toolbar.appendChild(btn);
+
+ // add button action dependend on type
+ switch(tb[i]['type']){
+ case 'format':
+ var sample = tb[i]['title'];
+ if(tb[i]['sample']) sample = tb[i]['sample'];
+
+ eval("btn.onclick = function(){insertTags('"+
+ jsEscape(edid)+"','"+
+ jsEscape(tb[i]['open'])+"','"+
+ jsEscape(tb[i]['close'])+"','"+
+ jsEscape(sample)+
+ "');return false;}");
+ break;
+ case 'insert':
+ eval("btn.onclick = function(){insertAtCarret('"+
+ jsEscape(edid)+"','"+
+ jsEscape(tb[i]['insert'])+
+ "');return false;}");
+ break;
+ case 'picker':
+ createPicker('picker'+i,
+ tb[i]['list'],
+ tb[i]['icobase'],
+ edid);
+ eval("btn.onclick = function(){showPicker('picker"+i+
+ "',this);return false;}");
+ break;
+ case 'popup':
+ eval("btn.onclick = function(){window.open('"+
+ jsEscape(tb[i]['url'])+"','"+
+ jsEscape(tb[i]['name'])+"','"+
+ jsEscape(tb[i]['options'])+
+ "');return false;}");
+ break;
+ } // end switch
+ } // end for
+}
+
+/**
+ * Format selection
+ *
+ * Apply tagOpen/tagClose to selection in textarea, use sampleText instead
+ * of selection if there is none. Copied and adapted from phpBB
+ *
+ * @author phpBB development team
+ * @author MediaWiki development team
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Jim Raynor <jim_raynor@web.de>
+ */
+function insertTags(edid,tagOpen, tagClose, sampleText) {
+ var txtarea = document.getElementById(edid);
+ // IE
+ if(document.selection && !is_gecko) {
+ var theSelection = document.selection.createRange().text;
+ var replaced = true;
+ if(!theSelection){
+ replaced = false;
+ theSelection=sampleText;
+ }
+ txtarea.focus();
+
+ // This has change
+ text = theSelection;
+ if(theSelection.charAt(theSelection.length - 1) == " "){// exclude ending space char, if any
+ theSelection = theSelection.substring(0, theSelection.length - 1);
+ r = document.selection.createRange();
+ r.text = tagOpen + theSelection + tagClose + " ";
+ } else {
+ r = document.selection.createRange();
+ r.text = tagOpen + theSelection + tagClose;
+ }
+ if(!replaced){
+ r.moveStart('character',-text.length-tagClose.length);
+ r.moveEnd('character',-tagClose.length);
+ }
+ r.select();
+ // Mozilla
+ } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
+ var replaced = false;
+ var startPos = txtarea.selectionStart;
+ var endPos = txtarea.selectionEnd;
+ if(endPos - startPos) replaced = true;
+ var scrollTop=txtarea.scrollTop;
+ var myText = (txtarea.value).substring(startPos, endPos);
+ if(!myText) { myText=sampleText;}
+ if(myText.charAt(myText.length - 1) == " "){ // exclude ending space char, if any
+ subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
+ } else {
+ subst = tagOpen + myText + tagClose;
+ }
+ txtarea.value = txtarea.value.substring(0, startPos) + subst +
+ txtarea.value.substring(endPos, txtarea.value.length);
+ txtarea.focus();
+
+ //set new selection
+ if(replaced){
+ var cPos=startPos+(tagOpen.length+myText.length+tagClose.length);
+ txtarea.selectionStart=cPos;
+ txtarea.selectionEnd=cPos;
+ }else{
+ txtarea.selectionStart=startPos+tagOpen.length;
+ txtarea.selectionEnd=startPos+tagOpen.length+myText.length;
+ }
+ txtarea.scrollTop=scrollTop;
+ // All others
+ } else {
+ var copy_alertText=alertText;
+ var re1=new RegExp("\\$1","g");
+ var re2=new RegExp("\\$2","g");
+ copy_alertText=copy_alertText.replace(re1,sampleText);
+ copy_alertText=copy_alertText.replace(re2,tagOpen+sampleText+tagClose);
+ var text;
+ if (sampleText) {
+ text=prompt(copy_alertText);
+ } else {
+ text="";
+ }
+ if(!text) { text=sampleText;}
+ text=tagOpen+text+tagClose;
+ //append to the end
+ txtarea.value += "\n"+text;
+
+ // in Safari this causes scrolling
+ if(!is_safari) {
+ txtarea.focus();
+ }
+
+ }
+ // reposition cursor if possible
+ if (txtarea.createTextRange) txtarea.caretPos = document.selection.createRange().duplicate();
+}
+
+/*
+ * Insert the given value at the current cursor position
+ *
+ * @see http://www.alexking.org/index.php?content=software/javascript/content.php
+ */
+function insertAtCarret(edid,value){
+ var field = document.getElementById(edid);
+
+ //IE support
+ if (document.selection) {
+ field.focus();
+ if(opener == null){
+ sel = document.selection.createRange();
+ }else{
+ sel = opener.document.selection.createRange();
+ }
+ sel.text = value;
+ //MOZILLA/NETSCAPE support
+ }else if (field.selectionStart || field.selectionStart == '0') {
+ var startPos = field.selectionStart;
+ var endPos = field.selectionEnd;
+ var scrollTop = field.scrollTop;
+ field.value = field.value.substring(0, startPos)
+ + value
+ + field.value.substring(endPos, field.value.length);
+
+ field.focus();
+ var cPos=startPos+(value.length);
+ field.selectionStart=cPos;
+ field.selectionEnd=cPos;
+ field.scrollTop=scrollTop;
+ } else {
+ field.value += "\n"+value;
+ }
+ // reposition cursor if possible
+ if (field.createTextRange) field.caretPos = document.selection.createRange().duplicate();
+}
+
diff --git a/lib/scripts/script.js b/lib/scripts/script.js
index 8ee3c3805..490394dfb 100644
--- a/lib/scripts/script.js
+++ b/lib/scripts/script.js
@@ -16,9 +16,87 @@ if (clientPC.indexOf('opera')!=-1) {
var is_opera_seven = (window.opera && document.childNodes);
}
+//http://simon.incutio.com/archive/2004/05/26/addLoadEvent#comment2
+function addEvent(oTarget, sType, fpDest) {
+ var oOldEvent = oTarget[sType];
+ if (typeof oOldEvent != "function") {
+ oTarget[sType] = fpDest;
+ } else {
+ oTarget[sType] = function(e) {
+ oOldEvent(e);
+ fpDest(e);
+ }
+ }
+}
+
+/**
+ * Get the X offset of the top left corner of the given object
+ *
+ * @link http://www.quirksmode.org/index.html?/js/findpos.html
+ */
+function findPosX(object){
+ var curleft = 0;
+ if(typeof(object) == 'object'){
+ var obj = object;
+ }else{
+ var obj = document.getElementById(object);
+ }
+ if (obj.offsetParent){
+ while (obj.offsetParent){
+ curleft += obj.offsetLeft;
+ obj = obj.offsetParent;
+ }
+ }
+ else if (obj.x){
+ curleft += obj.x;
+ }
+ return curleft;
+} //end findPosX function
+
+/**
+ * Get the Y offset of the top left corner of the given object
+ *
+ * @link http://www.quirksmode.org/index.html?/js/findpos.html
+ */
+function findPosY(object){
+ var curtop = 0;
+ if(typeof(object) == 'object'){
+ var obj = object;
+ }else{
+ var obj = document.getElementById(object);
+ }
+ if (obj.offsetParent){
+ while (obj.offsetParent){
+ curtop += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ }
+ else if (obj.y){
+ curtop += obj.y;
+ }
+ return curtop;
+} //end findPosY function
+
+/**
+ * Escape special chars in JavaScript
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function jsEscape(text){
+ var re=new RegExp("\\\\","g");
+ text=text.replace(re,"\\\\");
+ var re=new RegExp("'","g");
+ text=text.replace(re,"\\'");
+ re=new RegExp('"',"g");
+ text=text.replace(re,'&quot;');
+ re=new RegExp("\\\\\\\\n","g");
+ text=text.replace(re,"\\n");
+ return text;
+}
/**
* This function escapes some special chars
+ * @deprecated by above function
*/
function escapeQuotes(text) {
var re=new RegExp("'","g");
@@ -72,6 +150,7 @@ function summaryCheck(){
/**
* This function generates the actual toolbar buttons with localized text
* we use it to avoid creating the toolbar where javascript is not enabled
+ * @deprecated
*/
function formatButton(imageFile, speedTip, tagOpen, tagClose, sampleText, accessKey) {
speedTip=escapeQuotes(speedTip);
@@ -97,6 +176,7 @@ function formatButton(imageFile, speedTip, tagOpen, tagClose, sampleText, access
/**
* This function generates the actual toolbar buttons with localized text
* we use it to avoid creating the toolbar where javascript is not enabled
+ * @deprecated
*/
function insertButton(imageFile, speedTip, value, accessKey) {
speedTip=escapeQuotes(speedTip);
@@ -119,6 +199,7 @@ function insertButton(imageFile, speedTip, value, accessKey) {
/**
* This adds a button for the MediaSelection Popup
+ * @deprecated
*/
function mediaButton(imageFile, speedTip, accessKey, namespace) {
speedTip=escapeQuotes(speedTip);
@@ -135,99 +216,6 @@ function mediaButton(imageFile, speedTip, accessKey, namespace) {
return;
}
-/**
- * apply tagOpen/tagClose to selection in textarea, use sampleText instead
- * of selection if there is none copied and adapted from phpBB
- *
- * @author phpBB development team
- * @author MediaWiki development team
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Jim Raynor <jim_raynor@web.de>
- */
-function insertTags(tagOpen, tagClose, sampleText) {
- var txtarea = document.editform.wikitext;
- // IE
- if(document.selection && !is_gecko) {
- var theSelection = document.selection.createRange().text;
- var replaced = true;
- if(!theSelection){
- replaced = false;
- theSelection=sampleText;
- }
- txtarea.focus();
-
- // This has change
- text = theSelection;
- if(theSelection.charAt(theSelection.length - 1) == " "){// exclude ending space char, if any
- theSelection = theSelection.substring(0, theSelection.length - 1);
- r = document.selection.createRange();
- r.text = tagOpen + theSelection + tagClose + " ";
- } else {
- r = document.selection.createRange();
- r.text = tagOpen + theSelection + tagClose;
- }
- if(!replaced){
- r.moveStart('character',-text.length-tagClose.length);
- r.moveEnd('character',-tagClose.length);
- }
- r.select();
- // Mozilla
- } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
- var replaced = false;
- var startPos = txtarea.selectionStart;
- var endPos = txtarea.selectionEnd;
- if(endPos - startPos) replaced = true;
- var scrollTop=txtarea.scrollTop;
- var myText = (txtarea.value).substring(startPos, endPos);
- if(!myText) { myText=sampleText;}
- if(myText.charAt(myText.length - 1) == " "){ // exclude ending space char, if any
- subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
- } else {
- subst = tagOpen + myText + tagClose;
- }
- txtarea.value = txtarea.value.substring(0, startPos) + subst +
- txtarea.value.substring(endPos, txtarea.value.length);
- txtarea.focus();
-
- //set new selection
- if(replaced){
- var cPos=startPos+(tagOpen.length+myText.length+tagClose.length);
- txtarea.selectionStart=cPos;
- txtarea.selectionEnd=cPos;
- }else{
- txtarea.selectionStart=startPos+tagOpen.length;
- txtarea.selectionEnd=startPos+tagOpen.length+myText.length;
- }
- txtarea.scrollTop=scrollTop;
- // All others
- } else {
- var copy_alertText=alertText;
- var re1=new RegExp("\\$1","g");
- var re2=new RegExp("\\$2","g");
- copy_alertText=copy_alertText.replace(re1,sampleText);
- copy_alertText=copy_alertText.replace(re2,tagOpen+sampleText+tagClose);
- var text;
- if (sampleText) {
- text=prompt(copy_alertText);
- } else {
- text="";
- }
- if(!text) { text=sampleText;}
- text=tagOpen+text+tagClose;
- //append to the end
- txtarea.value += "\n"+text;
-
- // in Safari this causes scrolling
- if(!is_safari) {
- txtarea.focus();
- }
-
- }
- // reposition cursor if possible
- if (txtarea.createTextRange) txtarea.caretPos = document.selection.createRange().duplicate();
-}
-
-
/*
* Insert the selected filename and close the window
*
@@ -238,41 +226,6 @@ function mediaSelect(file){
window.close();
}
-/*
- * Insert the given value at the current cursor position
- *
- * @see http://www.alexking.org/index.php?content=software/javascript/content.php
- */
-function insertAtCarret(field,value){
- //IE support
- if (document.selection) {
- field.focus();
- if(opener == null){
- sel = document.selection.createRange();
- }else{
- sel = opener.document.selection.createRange();
- }
- sel.text = value;
- //MOZILLA/NETSCAPE support
- }else if (field.selectionStart || field.selectionStart == '0') {
- var startPos = field.selectionStart;
- var endPos = field.selectionEnd;
- var scrollTop = field.scrollTop;
- field.value = field.value.substring(0, startPos)
- + value
- + field.value.substring(endPos, field.value.length);
-
- field.focus();
- var cPos=startPos+(value.length);
- field.selectionStart=cPos;
- field.selectionEnd=cPos;
- field.scrollTop=scrollTop;
- } else {
- field.value += "\n"+value;
- }
- // reposition cursor if possible
- if (field.createTextRange) field.caretPos = document.selection.createRange().duplicate();
-}
/**
* For the upload Dialog. Prefills the wikiname.
@@ -321,38 +274,6 @@ function toggleToc() {
}
}
-/**
- * Sizecontrol inspired by TikiWiki. This displays the buttons.
- */
-function showSizeCtl(){
- if(document.getElementById) {
- var textarea = document.getElementById('wikitext');
- var hgt = getCookie('DokuWikisizeCtl');
- if(hgt == null){
- textarea.style.height = '300px';
- }else{
- textarea.style.height = hgt;
- }
- document.writeln('<a href="javascript:sizeCtl(100)"><img src="'+DOKU_BASE+'lib/images/larger.gif" width="20" height="20" border="0"></a>');
- document.writeln('<a href="javascript:sizeCtl(-100)"><img src="'+DOKU_BASE+'lib/images/smaller.gif" width="20" height="20" border="0"></a>');
- }
-}
-
-/**
- * This sets the vertical size of the editbox
- */
-function sizeCtl(val){
- var textarea = document.getElementById('wikitext');
- var height = parseInt(textarea.style.height.substr(0,textarea.style.height.length-2));
- height += val;
- textarea.style.height = height+'px';
-
- var now = new Date();
- fixDate(now);
- now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); //expire in a year
- setCookie('DokuWikisizeCtl',textarea.style.height,now);
-}
-
/**
* global var used for not saved yet warning
@@ -497,3 +418,43 @@ function fnt(id, e, evt) {
domTT_activate(e, evt, 'content', footnote, 'type', 'velcro', 'id', 'insitu-fn'+id, 'styleClass', 'insitu-footnote', 'maxWidth', document.body.offsetWidth*0.4);
currentFootnote = id;
}
+
+
+/**
+ * Add the edit window size controls
+ */
+function initSizeCtl(ctlid,edid){
+ var ctl = document.getElementById(ctlid);
+ var textarea = document.getElementById(edid);
+
+ var hgt = getCookie('DokuWikisizeCtl');
+ if(hgt == null){
+ textarea.style.height = '300px';
+ }else{
+ textarea.style.height = hgt;
+ }
+
+ var l = document.createElement('img');
+ var s = document.createElement('img');
+ l.src = DOKU_BASE+'lib/images/larger.gif';
+ s.src = DOKU_BASE+'lib/images/smaller.gif';
+ l.onclick = function(){sizeCtl(edid,100);}
+ s.onclick = function(){sizeCtl(edid,-100);}
+ ctl.appendChild(l);
+ ctl.appendChild(s);
+}
+
+/**
+ * This sets the vertical size of the editbox
+ */
+function sizeCtl(edid,val){
+ var textarea = document.getElementById(edid);
+ var height = parseInt(textarea.style.height.substr(0,textarea.style.height.length-2));
+ height += val;
+ textarea.style.height = height+'px';
+
+ var now = new Date();
+ fixDate(now);
+ now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); //expire in a year
+ setCookie('DokuWikisizeCtl',textarea.style.height,now);
+}
diff --git a/lib/scripts/spellcheck.js b/lib/scripts/spellcheck.js
index e86c079df..d47430c31 100644
--- a/lib/scripts/spellcheck.js
+++ b/lib/scripts/spellcheck.js
@@ -40,45 +40,19 @@
* OF SUCH DAMAGE.
*/
-/**
- * Get the X offset of the top left corner of the given object
+/*
+ * Uses some general functions defined elsewhere. Here is a list:
*
- * @author Garrison Locke <http://www.broken-notebook.com>
- */
-function findPosX(object){
- var curleft = 0;
- var obj = document.getElementById(object);
- if (obj.offsetParent){
- while (obj.offsetParent){
- curleft += obj.offsetLeft;
- obj = obj.offsetParent;
- }
- }
- else if (obj.x){
- curleft += obj.x;
- }
- return curleft;
-} //end findPosX function
-
-/**
- * Get the Y offset of the top left corner of the given object
+ * Defined in script.js:
*
- * @author Garrison Locke <http://www.broken-notebook.com>
+ * findPosX()
+ * findPosY()
+ * addEvent()
+ *
+ * Defined in edit.js:
+ *
+ * createToolButton()
*/
-function findPosY(object){
- var curtop = 0;
- var obj = document.getElementById(object);
- if (obj.offsetParent){
- while (obj.offsetParent){
- curtop += obj.offsetTop;
- obj = obj.offsetParent;
- }
- }
- else if (obj.y){
- curtop += obj.y;
- }
- return curtop;
-} //end findPosY function
/**
* quotes single quotes
@@ -90,29 +64,6 @@ function qquote(str){
}
/**
- * This function generates a spellchecker button with localized tooltips
- */
-function spellButton(imageFile, speedTip, funcCall, accessKey) {
- speedTip=escapeQuotes(speedTip);
- funcCall=escapeQuotes(funcCall);
-
- button = "<a ";
- if(accessKey){
- button = button+"accesskey=\""+accessKey+"\" ";
- speedTip = speedTip+' [ALT+'+accessKey.toUpperCase()+']';
- }
- if(funcCall){
- button = button+"href=\"javascript:"+funcCall+";\"";
- }
- button = button+">";
- button = button+"<img width=\"24\" height=\"24\" src=\""+
- DOKU_BASE+'lib/images/toolbar/'+imageFile+"\" border=\"0\" alt=\""+
- speedTip+"\" title=\""+speedTip+"\">";
- button = button+"</a>";
- return button;
-}
-
-/**
* AJAX Spellchecker Class
*
* Note to some function use a hardcoded instance named ajax_spell to make
@@ -127,11 +78,13 @@ function ajax_spell_class(){
this.utf8ok = 1;
this.handler = DOKU_BASE+'lib/exe/spellcheck.php';
// to hold the page objects (initialized with init())
- this.textboxObj = null;
+ this.textboxObj = null;
this.showboxObj = null;
this.suggestObj = null;
- this.actionObj = null;
this.editbarObj = null;
+ this.buttonObj = null;
+ this.imageObj = null;
+
// hold translations
this.txtStart = 'Check Spelling';
this.txtStop = 'Resume Editing';
@@ -162,7 +115,6 @@ function ajax_spell_class(){
this.editbarObj = document.getElementById('wikieditbar');
this.showboxObj = document.getElementById('spell_result');
this.suggestObj = document.getElementById('spell_suggest');
- this.actionObj = document.getElementById('spell_action');
// set Translation Strings
this.txtStart = txtStart;
@@ -172,11 +124,20 @@ function ajax_spell_class(){
this.txtNoSug = txtNoSug;
this.txtChange= txtChange;
+ // create ToolBar Button with ID and add it to the toolbar with null action
+ var toolbarObj = document.getElementById('toolbar');
+ this.buttonObj = createToolButton('spellcheck.png',txtStart,'k','spellcheck');
+ this.buttonObj.onclick = function(){return false;};
+ toolbarObj.appendChild(this.buttonObj);
+ this.imageObj = document.getElementById('spellcheck_ico');
+
// start UTF-8 compliance test - send an UTF-8 char and see what comes back
ajax.AjaxFailedAlert = '';
ajax.encodeURIString = false;
ajax.onCompletion = this.initReady;
ajax.runAJAX('call=utf8test&data='+encodeURIComponent('ü'));
+
+ // second part of initialisation is in initReady() function
}
/**
@@ -208,16 +169,28 @@ function ajax_spell_class(){
this.setState = function(state){
switch (state){
case 'stop':
- ajax_spell.actionObj.innerHTML = spellButton("spellstop.png",ajax_spell.txtStop,"ajax_spell.resume()","");
+ ajax_spell.buttonObj.onclick = function(){ ajax_spell.resume(); return false; };
+ ajax_spell.buttonObj.title = ajax_spell.txtStop;
+ ajax_spell.buttonObj.accesskey = '';
+ ajax_spell.imageObj.src = DOKU_BASE+'lib/images/toolbar/spellstop.png';
break;
case 'noerr':
- ajax_spell.actionObj.innerHTML = spellButton("spellnoerr.png",ajax_spell.txtNoErr,"ajax_spell.setState(\"start\")","");
+ ajax_spell.buttonObj.onclick = function(){ajax_spell.setState('start'); return false; };
+ ajax_spell.buttonObj.title = ajax_spell.txtNoErr;
+ ajax_spell.buttonObj.accesskey = '';
+ ajax_spell.imageObj.src = DOKU_BASE+'lib/images/toolbar/spellnoerr.png';
break;
case 'run':
- ajax_spell.actionObj.innerHTML = spellButton("spellwait.gif",ajax_spell.txtRun,"","");
+ ajax_spell.buttonObj.onclick = function(){return false;};
+ ajax_spell.buttonObj.title = ajax_spell.txtRun;
+ ajax_spell.buttonObj.accesskey = '';
+ ajax_spell.imageObj.src = DOKU_BASE+'lib/images/toolbar/spellwait.gif';
break;
default:
- ajax_spell.actionObj.innerHTML = spellButton("spellcheck.png",ajax_spell.txtStart,"ajax_spell.run()","k");
+ ajax_spell.buttonObj.onclick = function(){ ajax_spell.run(); return false; };
+ ajax_spell.buttonObj.title = ajax_spell.txtStart+' [ALT-K]';
+ ajax_spell.buttonObj.accesskey = 'k';
+ ajax_spell.imageObj.src = DOKU_BASE+'lib/images/toolbar/spellcheck.png';
break;
}
}
@@ -311,10 +284,10 @@ function ajax_spell_class(){
}
// register click event
- document.onclick = ajax_spell.docClick;
+ addEvent(document,'onclick',ajax_spell.docClick);
// register focus event
- ajax_spell.textboxObj.onfocus = ajax_spell.setState;
+ addEvent(ajax_spell.textboxObj,'onfocus',ajax_spell.setState);
// get started
ajax_spell.setState('start');
@@ -395,14 +368,14 @@ function ajax_spell_class(){
* @author Andreas Gohr <andi@splitbrain.org>
*/
this.run = function(){
- this.setState('run');
- this.textboxObj.disabled = true;
- var ajax = new sack(this.handler);
+ ajax_spell.setState('run');
+ ajax_spell.textboxObj.disabled = true;
+ var ajax = new sack(ajax_spell.handler);
ajax.AjaxFailedAlert = '';
ajax.encodeURIString = false;
ajax.onCompletion = this.start;
ajax.runAJAX('call=check&utf8='+ajax_spell.utf8ok+
- '&data='+encodeURIComponent(this.textboxObj.value));
+ '&data='+encodeURIComponent(ajax_spell.textboxObj.value));
}
/**
@@ -411,13 +384,13 @@ function ajax_spell_class(){
* @author Andreas Gohr <andi@splitbrain.org>
*/
this.resume = function(){
- this.setState('run');
- var text = this.showboxObj.innerHTML;
+ ajax_spell.setState('run');
+ var text = ajax_spell.showboxObj.innerHTML;
if(text != ''){
- var ajax = new sack(this.handler);
+ var ajax = new sack(ajax_spell.handler);
ajax.AjaxFailedAlert = '';
ajax.encodeURIString = false;
- ajax.onCompletion = this.stop;
+ ajax.onCompletion = ajax_spell.stop;
ajax.runAJAX('call=resume&utf8='+ajax_spell.utf8ok+
'&data='+encodeURIComponent(text));
}
diff --git a/lib/tpl/default/design.css b/lib/tpl/default/design.css
index 83547b9b4..7bc6085f2 100644
--- a/lib/tpl/default/design.css
+++ b/lib/tpl/default/design.css
@@ -666,6 +666,30 @@ div.ajax_qsearch {
padding: 4px;
}
+/* --------- Toolbar -------------------- */
+button.toolbutton{
+ background-color: #fff;
+ padding: 0px;
+ margin: 0 1px 0 0;
+ border: 1px solid #8cacbb;
+ cursor: pointer;
+}
+
+div.picker {
+ width: 250px;
+ border: 1px solid #8cacbb;
+ background: #eef3f8;
+}
+
+button.pickerbutton {
+ padding: 0px;
+ margin: 0 1px 1px 0;
+ border: 0;
+ background-color: transparent;
+ font-size: 80%;
+ cursor: pointer;
+}
+
/* ---------- Spellchecking ------------- */
a.spell_error {