diff --git a/inc/JSON.php b/inc/JSON.php new file mode 100644 index 0000000000..6345743fc4 --- /dev/null +++ b/inc/JSON.php @@ -0,0 +1,615 @@ + + * @author Matt Knapp + * @author Brett Stimmerman + * @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 + * @author Matt Knapp + * @author Brett Stimmerman + * @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 d4fafdaf39..d03815f002 100644 --- a/inc/html.php +++ b/inc/html.php @@ -894,37 +894,12 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
+
+ @@ -955,14 +930,18 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
+
+ ',$it); // load the default JavaScript files @@ -217,11 +218,6 @@ function tpl_metaheaders(){ ptln('',$it); - // load spellchecker script if wanted - if($conf['spellchecker'] && ($ACT=='edit' || $ACT=='preview')){ - ptln('',$it); - } // dom tool tip library, for insitu footnotes ptln('',$it); + // add size control + ptln('',$it); + + + // editing functions + if(($ACT=='edit' || $ACT=='preview') && $INFO['writable']){ + // load toolbar functions + ptln('',$it); + + // load spellchecker functions if wanted + if($conf['spellchecker']){ + ptln('',$it+2); + } + + ptln('',$it); + } + // plugin stylesheets and Scripts plugin_printCSSJS(); } diff --git a/inc/toolbar.php b/inc/toolbar.php new file mode 100644 index 0000000000..5c4ff030f5 --- /dev/null +++ b/inc/toolbar.php @@ -0,0 +1,202 @@ + + */ + + 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 + */ +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' => '', + 'close' => '', + ), + 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 + */ +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 d12c5710e9..6ec336262a 100644 Binary files a/lib/images/toolbar/bold.png and b/lib/images/toolbar/bold.png differ diff --git a/lib/images/toolbar/chars.png b/lib/images/toolbar/chars.png new file mode 100644 index 0000000000..83cdadd755 Binary files /dev/null and b/lib/images/toolbar/chars.png differ diff --git a/lib/images/toolbar/code.png b/lib/images/toolbar/code.png deleted file mode 100644 index fb5c0c3d8b..0000000000 Binary files a/lib/images/toolbar/code.png and /dev/null differ diff --git a/lib/images/toolbar/empty.png b/lib/images/toolbar/empty.png deleted file mode 100644 index e606cfd078..0000000000 Binary files a/lib/images/toolbar/empty.png and /dev/null differ diff --git a/lib/images/toolbar/extlink.png b/lib/images/toolbar/extlink.png deleted file mode 100644 index 705527e8cf..0000000000 Binary files a/lib/images/toolbar/extlink.png and /dev/null differ diff --git a/lib/images/toolbar/fonth1.png b/lib/images/toolbar/fonth1.png deleted file mode 100644 index ded5113ccc..0000000000 Binary files a/lib/images/toolbar/fonth1.png and /dev/null differ diff --git a/lib/images/toolbar/fonth2.png b/lib/images/toolbar/fonth2.png deleted file mode 100644 index fcf23f5ab6..0000000000 Binary files a/lib/images/toolbar/fonth2.png and /dev/null differ diff --git a/lib/images/toolbar/fonth3.png b/lib/images/toolbar/fonth3.png deleted file mode 100644 index 04246acf24..0000000000 Binary files a/lib/images/toolbar/fonth3.png and /dev/null differ diff --git a/lib/images/toolbar/fonth4.png b/lib/images/toolbar/fonth4.png deleted file mode 100644 index 1e7ac84c67..0000000000 Binary files a/lib/images/toolbar/fonth4.png and /dev/null differ diff --git a/lib/images/toolbar/fonth5.png b/lib/images/toolbar/fonth5.png deleted file mode 100644 index 5a1edb14ca..0000000000 Binary files a/lib/images/toolbar/fonth5.png and /dev/null differ diff --git a/lib/images/toolbar/h1.png b/lib/images/toolbar/h1.png new file mode 100644 index 0000000000..ffee5c159f Binary files /dev/null and b/lib/images/toolbar/h1.png differ diff --git a/lib/images/toolbar/h2.png b/lib/images/toolbar/h2.png new file mode 100644 index 0000000000..a2cc7f253a Binary files /dev/null and b/lib/images/toolbar/h2.png differ diff --git a/lib/images/toolbar/h3.png b/lib/images/toolbar/h3.png new file mode 100644 index 0000000000..accdaf652d Binary files /dev/null and b/lib/images/toolbar/h3.png differ diff --git a/lib/images/toolbar/h4.png b/lib/images/toolbar/h4.png new file mode 100644 index 0000000000..8e57676885 Binary files /dev/null and b/lib/images/toolbar/h4.png differ diff --git a/lib/images/toolbar/h5.png b/lib/images/toolbar/h5.png new file mode 100644 index 0000000000..8fe10e99f0 Binary files /dev/null and b/lib/images/toolbar/h5.png differ diff --git a/lib/images/toolbar/hr.png b/lib/images/toolbar/hr.png new file mode 100644 index 0000000000..6d68d66aaf Binary files /dev/null and b/lib/images/toolbar/hr.png differ diff --git a/lib/images/toolbar/image.png b/lib/images/toolbar/image.png index ed35e5a629..d1416fae90 100644 Binary files a/lib/images/toolbar/image.png and b/lib/images/toolbar/image.png differ diff --git a/lib/images/toolbar/italic.png b/lib/images/toolbar/italic.png index f4ecd0ddf2..ab8943b458 100644 Binary files a/lib/images/toolbar/italic.png and b/lib/images/toolbar/italic.png differ diff --git a/lib/images/toolbar/link.png b/lib/images/toolbar/link.png index 99cb400518..453f0d3f12 100644 Binary files a/lib/images/toolbar/link.png and b/lib/images/toolbar/link.png differ diff --git a/lib/images/toolbar/linkextern.png b/lib/images/toolbar/linkextern.png new file mode 100644 index 0000000000..780c335334 Binary files /dev/null and b/lib/images/toolbar/linkextern.png differ diff --git a/lib/images/toolbar/list.png b/lib/images/toolbar/list.png deleted file mode 100644 index ffae5cfbfc..0000000000 Binary files a/lib/images/toolbar/list.png and /dev/null differ diff --git a/lib/images/toolbar/list_ul.png b/lib/images/toolbar/list_ul.png deleted file mode 100644 index b86bcef7d8..0000000000 Binary files a/lib/images/toolbar/list_ul.png and /dev/null differ diff --git a/lib/images/toolbar/mono.png b/lib/images/toolbar/mono.png new file mode 100644 index 0000000000..dd398411ec Binary files /dev/null and b/lib/images/toolbar/mono.png differ diff --git a/lib/images/toolbar/ol.png b/lib/images/toolbar/ol.png new file mode 100644 index 0000000000..91ce32b9d8 Binary files /dev/null and b/lib/images/toolbar/ol.png differ diff --git a/lib/images/toolbar/rule.png b/lib/images/toolbar/rule.png deleted file mode 100644 index 3a32bef348..0000000000 Binary files a/lib/images/toolbar/rule.png and /dev/null differ diff --git a/lib/images/toolbar/sig.png b/lib/images/toolbar/sig.png index 3e8079f493..e4aa2943c0 100644 Binary files a/lib/images/toolbar/sig.png and b/lib/images/toolbar/sig.png differ diff --git a/lib/images/toolbar/smiley.png b/lib/images/toolbar/smiley.png new file mode 100644 index 0000000000..dee8a962ab Binary files /dev/null and b/lib/images/toolbar/smiley.png differ diff --git a/lib/images/toolbar/spellcheck.png b/lib/images/toolbar/spellcheck.png index 797a0433d0..9aecbad4bd 100644 Binary files a/lib/images/toolbar/spellcheck.png and b/lib/images/toolbar/spellcheck.png differ diff --git a/lib/images/toolbar/strike.png b/lib/images/toolbar/strike.png index 197aafa9d2..f6dd97647f 100644 Binary files a/lib/images/toolbar/strike.png and b/lib/images/toolbar/strike.png differ diff --git a/lib/images/toolbar/ul.png b/lib/images/toolbar/ul.png new file mode 100644 index 0000000000..4331bc6c28 Binary files /dev/null and b/lib/images/toolbar/ul.png differ diff --git a/lib/images/toolbar/underline.png b/lib/images/toolbar/underline.png index db07038fde..ee5e0d9fd5 100644 Binary files a/lib/images/toolbar/underline.png and b/lib/images/toolbar/underline.png differ diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js new file mode 100644 index 0000000000..641124c8f9 --- /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 + */ + +/** + * Creates a toolbar button through the DOM + * + * Style the buttons through the toolbutton class + * + * @author Andreas Gohr + */ +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 + */ +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 + */ +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 + */ +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 + */ +function initToolbar(tbid,edid,tb){ + var toolbar = document.getElementById(tbid); + var cnt = tb.length; + for(i=0; i + * @author Jim Raynor + */ +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 8ee3c38052..490394dfbc 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 + */ +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,'"'); + 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 - * @author Jim Raynor - */ -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(''); - document.writeln(''); - } -} - -/** - * 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 e86c079df7..d47430c31f 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 - */ -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 + * 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 @@ -89,29 +63,6 @@ function qquote(str){ return str.split('\'').join('\\\''); } -/** - * This function generates a spellchecker button with localized tooltips - */ -function spellButton(imageFile, speedTip, funcCall, accessKey) { - speedTip=escapeQuotes(speedTip); - funcCall=escapeQuotes(funcCall); - - button = ""; - button = button+"\""+"; - button = button+""; - return button; -} - /** * AJAX Spellchecker Class * @@ -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 */ 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 */ 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 83547b9b44..7bc6085f26 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 {