You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by br...@apache.org on 2015/06/22 22:11:44 UTC
svn commit: r1686927 [5/11] - in /jspwiki/trunk: ./
jspwiki-war/src/main/config/wro/ jspwiki-war/src/main/java/org/apache/wiki/
jspwiki-war/src/main/resources/templates/
jspwiki-war/src/main/scripts/behaviors/
jspwiki-war/src/main/scripts/dialog/ jspwi...
Added: jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Function.Extend.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Function.Extend.js?rev=1686927&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Function.Extend.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Function.Extend.js Mon Jun 22 20:11:42 2015
@@ -0,0 +1,61 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); fyou may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+Function.implement({
+
+/*
+Event: debounce
+ Returns a function, that, as long as it continues to be invoked, will not
+ be triggered. The function will be called after it stops being called for
+ N milliseconds. If `immediate` is passed, trigger the function on the
+ leading edge, instead of the trailing.
+ I.e. collapse a number of events into a single event.
+
+Credits:
+ http://davidwalsh.name/function-debounce
+
+Example:
+ el.addEvent('resize', resizePage.debounce(250, true).bind(this) );
+*/
+ debounce: function(wait, immediate){
+
+ var func = this, timer;
+
+ return function(){
+
+ var args = arguments,
+ context = this,
+ callNow = immediate && !timer;
+
+ function later(){
+ timer = null;
+ if( !immediate ){ func.apply(context, args); }
+ }
+
+ clearTimeout(timer);
+ timer = setTimeout(later, wait || 250);
+
+ if( callNow ){ func.apply(context, args); }
+
+ };
+
+ }
+
+});
Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/HighlightQuery.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/HighlightQuery.js?rev=1686927&r1=1686926&r2=1686927&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/HighlightQuery.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/HighlightQuery.js Mon Jun 22 20:11:42 2015
@@ -31,7 +31,7 @@ Credit:
Arguments
node - (DOM-element)
query - (optional) query string, default is document referrer query string
- template - (string) html template replacement string, default <span class='highlight'>$1</span>
+ template - (string) html template replacement string, default <mark>$&</mark>
*/
function HighlightQuery( node, query, template ){
@@ -56,7 +56,7 @@ function HighlightQuery( node, query, te
if( regexp.test( s ) ){
n = new Element('span',{
- html: s.replace(regexp, template || "<span class='highlight'>$1</span>")
+ html: s.replace(regexp, template || "<mark>$&</mark>")
});
frag = document.createDocumentFragment();
while( n.firstChild ) frag.appendChild( n.firstChild );
Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Request.File.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Request.File.js?rev=1686927&r1=1686926&r2=1686927&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Request.File.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Request.File.js Mon Jun 22 20:11:42 2015
@@ -1,24 +1,4 @@
/*
- JSPWiki - a JSP-based WikiWiki clone.
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); fyou may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-/*
---
name: Request.File
@@ -63,7 +43,7 @@ Request.File = new Class({
send: function(options){
if (!this.check(options)) return this;
-//console.log(this.formData);
+ //console.log(this.formData, this.options.url);
this.options.isSuccess = this.options.isSuccess || this.isSuccess;
this.running = true;
Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/String.Extend.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/String.Extend.js?rev=1686927&r1=1686926&r2=1686927&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/String.Extend.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/String.Extend.js Mon Jun 22 20:11:42 2015
@@ -20,7 +20,7 @@
*/
/*
Mootools Extension: String.Extend.js
- String-extensions: capitalize,() deCamelize(), trunc(), xsubs()
+ String-extensions: capitalize,() deCamelize(), trunc(), xsubs()
*/
String.implement({
@@ -34,7 +34,7 @@ String.implement({
*/
capitalize: function(){
//fix mootools implementation , supporting i18n chars such as éà è, not matched by \b
- //return String(this).replace(/\b[a-z]/g, function(match){
+ //return String(this).replace(/\b[a-z]/g, function(match){
return this.replace(/(\s|^)\S/g, function(match){
return match.toUpperCase();
});
@@ -59,7 +59,7 @@ String.implement({
Arguments:
size - maximum length of the string, excluding the length of the elips
- elips - (optional) replaces the truncated part (defaults to '...')
+ ellipsis - (optional) replaces the truncated part (defaults to '...')
Alternative
Use css propoerty
@@ -71,9 +71,9 @@ String.implement({
> "this is a long string".trunc(7) === "this is..."
> "this is a long string".trunc(7,'__') === "this is__"
*/
- trunc: function (size, elips){
+ trunc: function (size, ellipsis){
- return this.slice(0, size-1) + ((this.length<size) ? '' : (elips||'â¦'));
+ return this.slice(0, size-1) + ((this.length<size) ? '' : (ellipsis||'â¦'));
},
@@ -92,20 +92,19 @@ String.implement({
(start code)
//initialize the translation strings
String.I18N = {
- "javascript.moreInfo":"More",
- "javascript.imageInfo":"Image {0} of {1}", //indexed parms
- "javascript.imageInfo2":Image {imgCount} of {totalCount}" //named parms
- "javascript.curlyBraces":"Show \{Curly Braces}", //escaped curly braces
+ "javascript.moreInfo": "More",
+ "javascript.imageInfo": "Image {0} of {1}", //indexed parms
+ "javascript.imageInfo2": "Image {imgCount} of {totalCount}" //named parms
+ "javascript.curlyBraces": "Show \{Curly Braces}", //escaped curly braces
}
String.I18N.PREFIX="javascript.";
"moreInfo".localize() === "More";
- "imageInfo".localize(2,4) === "Image 2 of 4"
- "imageInfo2".localize({totalCount:4, imgCount:2}) === "Image 2 of 4"
+ "imageInfo".localize(2, 4) === "Image 2 of 4"
+ "imageInfo2".localize({totalCount: 4, imgCount: 2}) === "Image 2 of 4"
"curlyBraces".localize() === "Show {Curly Braces}"
(end)
-
*/
localize: function( params ){
@@ -137,18 +136,18 @@ String.implement({
return this.substitute(object, regexp);
},
- /*
- Function:slick(props)
- Convert css selector into a new DOM Element
-
- Example:
- > "input#someID.someClass1.someClass2[disabled=true]".slick({text:"Hi"});
- */
- slick:function(props){
+ /*
+ Function:slick(props)
+ Fancy DOM Element builder
- return new Element(this+"", props);
+ Example:
+ > "input#someID.someClass1.someClass2[disabled=true]".slick({text:"Hi"});
+ */
+ slick: function(props){
- },
+ return new Element(this + "", props);
+
+ },
/*
Function: sliceArgs
@@ -159,7 +158,7 @@ String.implement({
> <command>.sliceArgs( args (, regexp) );
Arguments:
- args : (string) or dom-element with classname
+ args : (string) or dom-element with classname
regexp : (optional string) pattern match for the arguments, defaults (-\w+)*
Example
@@ -170,35 +169,35 @@ String.implement({
*/
sliceArgs: function(element, regexp){
- var args = element.grab /*isElement*/ ? element.className : element;
+ var args = element.grab /*isElement*/ ? element.className : element;
- if( !regexp) regexp = "(^|\\s)"+this+"(-\\w+)*(?:\\s|$)"; //default '-' separated arguments
+ if( !regexp) regexp = "(?:^|\\s)("+this+"(?:-\\w+)*)(?:\\s|$)"; //default '-' separated arguments
args = args.match( regexp );
- return args && args[0].split('-').slice(1);
+ return args && args[1].split('-').slice(1);
},
- /*
- Function: fetchContext
- Match an elements classname or string against one of the bootstrap contextual patterns.
- Supported contexts: default, primary, success, info, warning, danger
-
- Return a (string) classname to invoke the contextual colors.
-
- Example
- > 'panel'.fetchContext( 'accordion-danger') => 'panel panel-danger'
- > 'panel'.fetchContext( 'commentbox-success') => 'panel panel-success'
-
- */
- fetchContext : function(element){
-
- var name = element.grab /*isElement*/ ? element.className : element;
+ /*
+ Function: fetchContext
+ Match an elements classname or string against one of the bootstrap contextual patterns.
+ Supported contexts: default, primary, success, info, warning, danger
+
+ Return a (string) classname to invoke the contextual colors.
+
+ Example
+ > 'panel'.fetchContext( 'accordion-danger') => 'panel panel-danger'
+ > 'panel'.fetchContext( 'commentbox-success') => 'panel panel-success'
+
+ */
+ fetchContext : function(element){
+
+ var name = element.grab /*isElement*/ ? element.className : element;
name = (name.match( /\b(default|primary|success|info|warning|danger)(\b|$)/ )||[,'default'])[1];
- return this+' '+this+'-'+name ;
-
- }
+ return this + ' ' + this + '-' + name ;
+
+ }
-});
+});
\ No newline at end of file
Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Textarea.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Textarea.js?rev=1686927&r1=1686926&r2=1686927&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Textarea.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Textarea.js Mon Jun 22 20:11:42 2015
@@ -28,44 +28,28 @@ Class: Textarea
Example:
(start code)
<script>
- var txta = new Textarea( "mainTextarea" );
+ var ta = new Textarea( "mainTextarea" );
</script>
(end)
*/
var Textarea = new Class({
- Implements: [Options,Events],
+ Implements: [Options, Events],
//options: { onChange:function(e){} );
- initialize: function(el,options){
+ initialize: function(el, options){
var self = this,
- txta = self.ta = $(el),
-
- lastValue,
- lastLength = -1,
- changeFn = function(e){
- var v = txta.value;
- if( v.length != lastLength || v !== lastValue ){
- self.fireEvent('change', e);
- lastLength = v.length;
- lastValue = v;
- }
- };
+ ta = self.ta = document.id(el);
self.setOptions(options);
- txta.addEvents({ change:changeFn, keyup:changeFn });
-
- //Create shadow div to support pixel measurement of the caret in the textarea
- //self.taShadow = new Element('div',{
- // styles: { position:'absolute', visibility:'hidden', overflow:'auto'/*,top:0, left:0, zIndex:1, white-space:pre-wrap*/ }
- //})
- self.taShadow = new Element('div[style=position:absolute;visibility:hidden;overflow:auto]')
- .inject(txta,'before')
- .setStyles( txta.getStyles(
- 'font-family0font-size0line-height0text-indent0padding-top0padding-right0padding-bottom0padding-left0border-left-width0border-right-width0border-left-style0border-right-style0white-space0word-wrap'
+ //Create a shadow div to support getCoordinates() of any character in the textarea
+ //This only works if the textarea font is monospace (?)
+ self.taShadow = "div[style=position:absolute;visibility:hidden;overflow:auto]".slick()
+ .setStyles( ta.getStyles(
+ "font-family0font-size0line-height0text-indent0padding-top0padding-right0padding-bottom0padding-left0border-left-width0border-right-width0border-left-style0border-right-style0white-space0word-wrap"
.split(0)
));
@@ -79,9 +63,9 @@ var Textarea = new Class({
the element when passed an instance of the class. (mootools 1.2.x)
Example:
- > var txta = new Textarea('textarea-element');
- > $('textarea-element') == txta.toElement();
- > $('textarea-element') == $(txta); //mootools 1.2.x
+ > var ta = new Textarea("textarea-element");
+ > $("textarea-element") == ta.toElement();
+ > $("textarea-element") == $(ta); //mootools 1.2.x
*/
toElement: function(){
return this.ta;
@@ -96,18 +80,22 @@ var Textarea = new Class({
},
/*
Function: slice
- Mimics the string slice function on the value (text content) of the textarea.
- Arguments:
- Ref. javascript slice function
+ Invokes slice(..) on the value of the textarea
*/
- slice: function(start,end){
- return this.ta.value.slice(start,end);
+ slice: function(start, end){
+ return this.ta.value.slice(start, end);
+ },
+ /*
+ Function: indexOf
+ Invokes indexOf(..) on the value of the textarea
+ */
+ indexOf: function(searchValue, fromIndex){
+ return this.ta.value.indexOf(searchValue, fromIndex);
},
-
/*
Function: getFromStart
- Returns the first not selected part of the textarea, till the start of the selection.
+ Returns the start of the textarea, upto the start of the selection.
*/
getFromStart: function(){
return this.slice( 0, this.getSelectionRange().start );
@@ -115,7 +103,7 @@ var Textarea = new Class({
/*
Function: getTillEnd
- Returns the last not selected part of the textarea, starting from the end of the selection.
+ Returns the end of the textarea, starting from the end of the selection.
*/
getTillEnd: function(){
return this.slice( this.getSelectionRange().end );
@@ -127,7 +115,7 @@ var Textarea = new Class({
Note:
IE fixme: this may return any selection, not only selected text in this textarea
- //if(Browser.Engine.trident) return document.selection.createRange().text;
+ //if(Browser.Engine.trident) return document.selection.createRange().text;
*/
getSelection: function(){
@@ -138,41 +126,42 @@ var Textarea = new Class({
/*
Function: setSelectionRange
- Selects the selection range of the textarea from start to end
+ Set a new selection range of the textarea
Arguments:
- start - start position of the selection
- end - (optional) end position of the seletion (default == start)
+ start - start position of the new selection
+ end - (optional) end position of the new seletion (default is start)
Returns:
Textarea object
*/
setSelectionRange: function(start, end){
- var txta = this.ta,
- value,diff,range;
+ var ta = this.ta,
+ value, diff, range;
- if(!end){ end = start; }
+ if( !end ){ end = start; }
- if( txta.setSelectionRange ){
+ if( ta.setSelectionRange ){
- txta.setSelectionRange(start, end);
+ ta.setSelectionRange(start, end);
} else {
- value = txta.value;
- diff = value.slice(start, end - start).replace(/\r/g, '').length;
- start = value.slice(0, start).replace(/\r/g, '').length;
-
- range = txta.createTextRange();
- range.collapse(1 /*true*/);
- range.moveEnd('character', start + diff);
- range.moveStart('character', start);
+ value = ta.value;
+ diff = value.slice(start, end - start).replace(/\r/g, "").length;
+ start = value.slice(0, start).replace(/\r/g, "").length;
+
+ range = ta.createTextRange();
+ range.collapse( true );
+ range.moveEnd("character", start + diff);
+ range.moveStart("character", start);
range.select();
//textarea.scrollTop = scrollPosition;
//textarea.focus();
}
+ ta.fireEvent("change");
return this;
},
@@ -180,60 +169,61 @@ var Textarea = new Class({
Function: getSelectionRange
Returns an object describing the textarea selection range.
- Returns:
- {{ { 'start':number, 'end':number, 'thin':boolean } }}
- start - coordinate of the selection
- end - coordinate of the selection
- thin - boolean indicates whether selection is empty (start==end)
+ Returns: Object:
+ start - (number) start position of the selection
+ end - (number) end position of the selection
+ thin - (boolean) indicates whether selection is empty (start==end)
*/
-/* ffs
+ /* ffs
getIERanges: function(){
this.ta.focus();
- var txta = this.ta,
+ var ta = this.ta,
range = document.selection.createRange(),
re = this.createTextRange(),
dupe = re.duplicate();
re.moveToBookmark(range.getBookmark());
- dupe.setEndPoint('EndToStart', re);
+ dupe.setEndPoint("EndToStart", re);
return { start: dupe.text.length, end: dupe.text.length + range.text.length, length: range.text.length, text: range.text };
},
-*/
+ */
getSelectionRange: function(){
- var txta = this.ta,
- caret = { start: 0, end: 0 /*, thin: true*/ },
+ var ta = this.ta,
+ start = 0,
+ end = 0,
range, dup, value, offset;
- if( txta.selectionStart!=null ){
+ if( ta.selectionStart != null ){
- caret = { start: txta.selectionStart, end: txta.selectionEnd };
+ //caret = { start: ta.selectionStart, end: ta.selectionEnd };
+ start = ta.selectionStart;
+ end = ta.selectionEnd;
} else {
range = document.selection.createRange();
- //if (!range || range.parentElement() != txta){ return caret; }
- if ( range && range.parentElement() == txta ){
+
+ if ( range && range.parentElement() == ta ){
dup = range.duplicate();
- value = txta.value;
+ value = ta.value;
offset = value.length - value.match(/[\n\r]*$/)[0].length;
- dup.moveToElementText(txta);
- dup.setEndPoint('StartToEnd', range);
- caret.end = offset - dup.text.length;
- dup.setEndPoint('StartToStart', range);
- caret.start = offset - dup.text.length;
+ dup.moveToElementText(ta);
+ dup.setEndPoint("StartToEnd", range);
+ end = offset - dup.text.length;
+
+ dup.setEndPoint("StartToStart", range);
+ start = offset - dup.text.length;
}
}
- caret.thin = (caret.start==caret.end);
-
- return caret;
+ return { start: start, end: end, thin: start == end };
},
/*
Function: setSelection
- Replaces the selection with a new value (concatenation of arguments).
+ Replaces the selection with a new string (concatenation of arguments).
On return, the selection is set to the replaced text string.
Arguments:
@@ -244,28 +234,28 @@ var Textarea = new Class({
Textarea object, with a new selection
Example:
- > txta.setSelection("new", " value"); //replace selection by 'new value'
+ > ta.setSelection("new", " value"); //replace selection by "new value"
*/
setSelection: function(){
- var value = Array.from(arguments).join('').replace(/\r/g, ''),
- txta = this.ta,
- scrollTop = txta.scrollTop, //cache top
- start,end,v,range;
-
- if( txta.selectionStart!=null ){
-
- start = txta.selectionStart;
- end = txta.selectionEnd;
- v = txta.value;
- //txta.value = v.substr(0, start) + value + v.substr(end);
- txta.value = v.slice(0, start) + value + v.substr(end);
- txta.selectionStart = start;
- txta.selectionEnd = start + value.length;
+ var value = Array.from(arguments).join("").replace(/\r/g, ""),
+ ta = this.ta,
+ scrollTop = ta.scrollTop, //cache top
+ start, end, v, range;
+
+ if( ta.selectionStart != null ){
+
+ start = ta.selectionStart;
+ end = ta.selectionEnd;
+ v = ta.value;
+ //ta.value = v.substr(0, start) + value + v.substr(end);
+ ta.value = v.slice(0, start) + value + v.substr(end);
+ ta.selectionStart = start;
+ ta.selectionEnd = start + value.length;
} else {
- txta.focus();
+ ta.focus();
range = document.selection.createRange();
range.text = value;
range.collapse(1 /*true*/);
@@ -273,9 +263,9 @@ var Textarea = new Class({
range.select();
}
- txta.focus();
- txta.scrollTop = scrollTop;
- txta.fireEvent('change');
+ ta.focus();
+ ta.scrollTop = scrollTop;
+ ta.fireEvent("change");
return this;
},
@@ -292,7 +282,7 @@ var Textarea = new Class({
*/
insertAfter: function(){
- var value = Array.from(arguments).join('');
+ var value = Array.from(arguments).join("");
return this.setSelection( value )
.setSelectionRange( this.getSelectionRange().start + value.length );
@@ -301,12 +291,26 @@ var Textarea = new Class({
/*
Function: isCaretAtStartOfLine
- Returns boolean indicating whether caret is at the start of a line.
+ Returns boolean indicating whether caret (or start of the selection)
+ is at the start of a line.
+ (previous char is \n)
*/
isCaretAtStartOfLine: function(){
- var i = this.getSelectionRange().start;
- return( (i<1) || ( this.ta.value.charAt( i-1 ).test( /[\n\r]/ ) ) );
+ var start = this.getSelectionRange().start;
+ return ( (start < 1) || ( this.ta.value.charAt(start - 1).test( /[\n\r]/ ) ) );
+
+ },
+ /*
+ Function: isCaretAtEndOfLine
+ Returns boolean indicating whether the caret or the end of the selection
+ is at the end of a line.
+ (last char is \n)
+ */
+ isCaretAtEndOfLine: function(){
+
+ var end = this.getSelectionRange().end;
+ return ( (end == this.ta.value.length) || ( this.slice(end - 1, end + 1).test( /[\n\r]/ ) ) );
},
@@ -327,34 +331,29 @@ var Textarea = new Class({
*/
getCoordinates: function( offset ){
- var txta = this.ta,
- taShadow = this.taShadow,
- delta = 0,
- el,css,style,t,l,w,h;
-
- //prepare taShadow
- css = txta.getStyles(['padding-left','padding-right','border-left-width','border-right-width']);
- for(style in css){ delta +=css[style].toInt() }
+ var ta = this.ta,
+ //make sure the shadow element is always just before of the textarea
+ taShadow = this.taShadow.inject(ta, "before"),
+ value = ta.value,
+ el, t, l, w, h;
- //default offset is the position of the caret
+ //default character offset is the caret (cursor or begin of the selection)
if( !offset ){ offset = this.getSelectionRange().end; }
el = taShadow.set({
styles: {
- width: txta.offsetWidth - delta,
- height: txta.getStyle('height') //ensure proper handling of scrollbars - if any
+ width: ta.offsetWidth,
+ height: ta.getStyle("height") //ensure proper handling of scrollbars - if any
},
- //FIXME: should we put the full selection inside the <i></i> bracket ? (iso a single char)
- html: txta.value.slice(0, offset) + '<i>A</i>' + txta.value.slice(offset+1)
- }).getElement('i');
+ html: value.slice(0, offset) + "<i>A</i>" + value.slice(offset + 1)
+ }).getElement("i");
- t = txta.offsetTop + el.offsetTop - txta.scrollTop;
- l = txta.offsetLeft + el.offsetLeft - txta.scrollLeft;
+ t = ta.offsetTop + el.offsetTop - ta.scrollTop;
+ l = ta.offsetLeft + el.offsetLeft - ta.scrollLeft;
w = el.offsetWidth;
h = el.offsetHeight;
- return {top:t, left:l, width:w, height:h, right:l+w, bottom:t+h}
+ return { top: t, left: l, width: w, height: h, right: l + w, bottom: t + h };
}
});
-
Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Tips.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Tips.js?rev=1686927&r1=1686926&r2=1686927&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Tips.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/moo-extend/Tips.js Mon Jun 22 20:11:42 2015
@@ -27,16 +27,16 @@ Bootstrap
//tip anchors
<element> Caption
<body> ...body... </body>
- </element>
+ </element>
//layout of the tip, with absolute position
div.tooltip(.active)(.top|.left|.right|.bottom)
div.tooltip-inner
- <body> ... </body>
+ <body> ... </body>
div.tooltip-arrow
(end)
*/
-var Tips = function Tips(elements,options){
+var Tips = function Tips(elements){
var tt = 'div.tooltip',
TheTip = [tt,[tt+'-inner'/*,tt+'-arrow'*/]].slick().inject(document.body),
@@ -44,50 +44,49 @@ var Tips = function Tips(elements,option
$$(elements).addEvents({
- mousemove: function(e){
- TheTip.setStyles({ top:e.page.y +10, left:e.page.x + 10 });
- },
-
- mouseenter: function(e){
- inner.adopt( this.getFirst() ) ;
- TheTip.addClass('in'); //.fade('in');
- },
-
- mouseleave: function(e){
- TheTip.removeClass('in'); //.fade('out');
- this.adopt( inner.getFirst() );
- }
+ mousemove: function(e){
+ TheTip.setStyles({ top:e.page.y +10, left:e.page.x + 10 });
+ },
+
+ mouseenter: function(){
+ inner.adopt( this.getFirst() ) ;
+ TheTip.addClass('in'); //.fade('in');
+ },
+
+ mouseleave: function(){
+ TheTip.removeClass('in'); //.fade('out');
+ this.adopt( inner.getFirst() );
+ }
});
-}
-
+};
/*TIP position logic
- position: function(event){
-
- var windowPadding={x:0, y:0};
+ position: function(event){
- var size = window.getSize(),
- scroll = window.getScroll(),
- tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
- props = {x: 'left', y: 'top'},
- bounds = {y: false, x2: false, y2: false, x: false},
- obj = {};
+ var windowPadding={x:0, y:0};
- for (var z in props){
+ var size = window.getSize(),
+ scroll = window.getScroll(),
+ tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
+ props = {x: 'left', y: 'top'},
+ bounds = {y: false, x2: false, y2: false, x: false},
+ obj = {};
- obj[props[z]] = event.page[z] + this.options.offset[z];
+ for (var z in props){
- if (obj[props[z]] < 0) bounds[z] = true;
+ obj[props[z]] = event.page[z] + this.options.offset[z];
- if ((obj[props[z]] + tip[z] - scroll[z]) > size[z] - windowPadding[z]){
+ if (obj[props[z]] < 0) bounds[z] = true;
- obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
- bounds[z+'2'] = true;
- }
- }
+ if ((obj[props[z]] + tip[z] - scroll[z]) > size[z] - windowPadding[z]){
- this.tip.setStyles(obj);
- },
+ obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
+ bounds[z+'2'] = true;
+ }
+ }
-*/
+ this.tip.setStyles(obj);
+ },
+
+*/
\ No newline at end of file
Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js?rev=1686927&r1=1686926&r2=1686927&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Commands.js Mon Jun 22 20:11:42 2015
@@ -1,4 +1,4 @@
-/*!
+/*
JSPWiki - a JSP-based WikiWiki clone.
Licensed to the Apache Software Foundation (ASF) under one
@@ -32,7 +32,7 @@ Class: SnipEditor.Commands
- click events on command buttons (.cmd.pop)
- suggestion trigger (exec ???)
- FYI - all DIALOGs are created as descendants of the Dialog class.
+ DIALOGs are created as descendants of the Dialog class.
- Dialog : floating dialog panel
- FormDialog : predef content with open/close handlers ???
- Dialog.Selection : selectable list of items
@@ -44,16 +44,16 @@ Class: SnipEditor.Commands
Options:
container: DOM element => contains commands([data-cmd])
- dialogs - predefined set of dialog initialisators
+ dialogs - predefined set of dialog definitions
// **event handlers**
- onOpen - invoked after opening a DIALOG
- onClose - invoked after closing a DIALOG
+ onOpen - invoked after opening any DIALOG
+ onClose - invoked after closing any DIALOG
onAction - action call-back action(cmd,arguments)
Properties
- buttons : collection of DOM-elements with click handlers to either
action() or toggle()
- - dialogs : collection of dialog definitions [Dialog-class, {dialog parameters}]
+ - dialogs : collection of dialog definitions [Dialog-class, {options}]
DOM structure:
<div class="cmd tICON"><i>action command</i></div>
@@ -66,105 +66,111 @@ Snipe.Commands = new Class({
Implements: [Events, Options],
options: {
- //onAction:function()...s
- cmds:'cmd' //toolbar button data attribute
+ //onAction:function(command,value){ .. },
+ cmds: "data-cmd" //toolbar button data attribute
+ //relativeTo: document.body //default position of a dialog
//dialogs:{ cmd1:dialog1, cmd2:dialog2, ...}
},
- btns: {}, //all cmd:buttons (dom element)
- dlgs: {}, //all cmd:instantiated dialogs (lazy activation)
- dialogs: {}, //all cmd:dialogs
+ dlgs: {}, //all cmd:instantiated dialogs (lazy activation)
+ btns: {}, //all buttons
+ dialogs: {}, //all cmd:dialogs definitions
initialize: function( container, options ){
- var self = this.setOptions(options),
- attr = 'data-' + self.options.cmds,
- command,
+ var self = this.setOptions(options),
+ dataCmd = self.options.cmds,
+ command,
dialog,
- dialogs = options.dialogs||{};
+ dialogs = options.dialogs || {};
+
- container.getElements('['+attr+']').each( function(el){
+ //add click buttons and dialogs
+ container.addEvent("click:relay([" + dataCmd + "])", function(event){
- command = el.get(attr);
+ var cmd = this.get( dataCmd ),
+ dlg = self.dlgs[ cmd ];
- self.btns[command] = el.addEvent('click', self.click.pass(command,self));
+ dlg ? dlg.toggle() : self.action( cmd );
- if( dialog = container.getElement('.dialog.' + command) ){
-
- if( dialogs[command] ){
+ // input fields (eg checkboxes) keep the default behaviour; other click events are disabled
+ if( !this.match("input") ){ event.stop(); }
+
+ });
- dialogs[command][1].dialog = dialog;
+ //see if there are any dialogs linked to a button. Eg: "div.dialog.<command>"
+ container.getElements("[" + dataCmd + "]").each( function(button){
- } else {
+ command = button.get(dataCmd);
+ self.btns[command] = button;
- dialogs[command] = dialog;
+ if( dialog = container.getElement(".dialog." + command) ){
+
+ if( !dialogs[command] ){ dialogs[command] = [Dialog, {}]; }
+
+ options = dialogs[command][1];
+ //register the DOM dialog element, and move to top of DOM for proper absolute positioning
+ options.dialog = dialog.inject(document.body);
+ options.relativeTo = button; //register the dialog positioning info
- }
}
});
self.addDialogs( dialogs );
+
},
/*
- Funciton: addDialog
- Add a new dialog.
- The dialog is only created when invoking the command.
- This happens through a button click or through the action() method.
+ Function: addDialog
+ Add a new dialogs.
Arguments:
- dialogs: {cmd1:dialog, cmd2:dialog-def...}
- (dialog-def : array[Dialog-Class, {dialog parameters}]
- relativeTo: create a dialog relative to a positioned object (eg. button, textarea-location)
+ newdialogs: {cmd:[Dialog-Class, {options}]..}
*/
- addDialogs: function(newdialogs, relativeTo){
+ addDialogs: function( newdialogs ){
+
+ var dialog,
+ command,
+ dialogs = this.dialogs;
- var self = this,
- dialog,
- command
- dialogs = self.dialogs;
-
for( command in newdialogs ){
- if( dialogs && dialogs[command] ){
- console.log("AddDialogs - warning: double registration of => " + command);
+ if( dialogs[command] ){
+ console.log("Snipe.Commands addDialogs() - warning: double registration of => " + command);
}
- dialog = dialogs[command] = newdialogs[command]; //array of all dialogs
- if( instanceOf( dialog, Dialog ) ){ self.attach(command,dialog); }
+ dialog = dialogs[command] = newdialogs[command];
- //checkme ...
- if( relativeTo ){ self.btns[ command ] = relativeTo; }
+ //note: make sure to initialize this.dialogs[command] prior to calling show()
+ if( instanceOf( dialog, Dialog ) ){ this.attach(dialog, command); }
- };
- //console.log('allDialogs: '+Object.keys(self.dialogs) );
+ }
+ //console.log("allDialogs: " + Object.keys(this.dialogs) );
},
- attach: function(command, dialog){
+ /*
+ Function: attach
+ Attach event-handlers to a dialogs
+ */
+ attach: function(dialog, command){
var self = this,
- actionHdl = function(v){ self.fireEvent('action', [command,v]); };
+ //fire ACTION event back to the invoker of the Snipe.Commands
+ actionHdl = function(value){ self.fireEvent("action", [command, value]); };
- //console.log('attachDialog: '+command);
+ console.log("Snipe.Commands: attachDialog() ", command, dialog);
return self.dlgs[command] = dialog.addEvents({
- onOpen: self.openDialog.bind(self, command),
- onClose: self.closeDialog.bind(self, command),
- onAction: actionHdl,
- onDrag: actionHdl
+ open: self.openDialog.bind(self, command),
+ close: self.closeDialog.bind(self, command),
+ action: actionHdl,
+ drag: actionHdl
});
},
- click: function( command ){
-
- var dialog = this.dlgs[ command ];
- dialog ? dialog.toggle() : this.action( command );
-
- },
-
/*
Function: action
- Action handler for a simple command. Pass the 'action' event
- up to the Snipe Editor.
+ Action handler for a simple command.
+ Send the "action" event back to the Snipe Editor.
Arguments:
command : command name
@@ -172,28 +178,28 @@ Snipe.Commands = new Class({
*/
action: function( command, value ){
- var self = this,
- active = 'active',
- button = self.btns[command],
- dialog = self.dlgs[command];
+ var self = this,
+ active = "active",
+ button = self.btns[command],
+ dialog;
- //console.log("Commands.action "+command+" value:"+value+" btn="+button+ " dlg="+dialog);
- if( button ) button = document.id( button);
+ //console.log("Commands.action ", command, " value:", value, " btn=", button, " dlg=", dialog);
+ //if( button ) button = document.id( button);
- if( button && button.match('.disabled') ){
+ if( button && button.match(".disabled") ){
- //nothing to do here
+ //nothing to be done here
} else if( self.dialogs[command] ){
- if( !dialog ){ dialog = self.createDialog(command) }
- if( value ){ dialog.setValue( value ); }
+ dialog = self.dlgs[command] || self.createDialog(command);
+ if( value != null ){ dialog.setValue( value ); }
dialog.show();
} else {
if( button ){ button.addClass(active); }
- self.fireEvent('action', [command, value] );
+ self.fireEvent("action", [command, value] );
if( button ){ button.removeClass(active); }
}
@@ -202,115 +208,97 @@ Snipe.Commands = new Class({
/*
Function: createDialog
- Create a new dialog.
- The name of the cmd determines the type (or class) of Dialog to be created
- - cmd: Dialog[cmd] (eg cmd='font' : Dialog.Font)
- - the name of the dialog equals the DOM ID of a predefined HTML dialog
-
- - DOM Element: predefined DOM dialog
- - [ Dialog-class, { dialog parameters } ]
- - { dialog parameters } : the cmd determines the type of Dialog to create
- - "string" : create a Dialog.Selection dialog
+ Create a new dialog, based on dialog creation parameters in this.dlgs :
+ - [ Dialog-class, { options } ]
+ - otherwise convert to Dialog.Selection dialog
Arguments
- cmd - (string) command
+ command - (string) command
The open/close handlers will make sure only one dialog is open at the
- same time. The open dialog is stored in {{this.activeCmd}}.
+ same time. The open dialog is stored in {{this.activecommand}}.
- The key events 'action', 'drag', 'open' and 'close' are propagated upwards.
+ The key events "action", "drag", "open" and "close" are propagated upwards.
Returns:
The created dialog, which is also stored in this.dlgs[] repository.
*/
- createDialog: function( cmd ){
+ createDialog: function( command ){
- var self = this,
- dlg,
- btn = self.btns[cmd],
- factory = Function.from( self.dialogs[cmd] )(),
- type = typeOf(factory);
+ var dialog = Function.from( this.dialogs[command] )();
- //console.log('Commands.createDialog() '+cmd+' '+ ' btn='+btn +" "+type);
+ //console.log("Snipe.Commands: createDialog() " + command + " ",dialog );
- //expect factory to be [Dialog class, {dialog options object}]
- if( type != 'array' || factory.length != 2 ){
+ if( typeOf(dialog) != "array" ){ dialog = [ Dialog.Selection, { body: dialog } ]; }
- factory = ( type == 'element' ) ?
- [Dialog, {dialog:factory}] : [Dialog.Selection, {body:factory}];
- }
+ if( !dialog[1].relativeTo ){ dialog[1].relativeTo = this.options.relativeTo || document.body; }
- dlg = new factory[0]( Object.append( factory[1],{
- //cssClass: 'dialog float',
- autoClose: false, //fixme: suggestion dialog should not be autoclosed
- relativeTo: btn //button or textareaa
- //draggable: true
- }) );
+ dialog[1].autoClose = false; //checkme: suggest-dialogs should not be autoclose?
- //Make sure that this.dlgs[cmd] gets initialized prior to calling show()
- return self.attach(cmd, dlg);
+ //note: make sure to initialize this.dialogs[command] prior to calling show()
+ return this.attach( new dialog[0]( dialog[1] ), command);
},
/*
Function: openDialog
Opens a dialog. If already another dialog was open, that one will first be closed.
- When a toolbar button exists, it will get the css class '.active'.
+ When a toolbar button exists, it will get the css class ".active".
Note: make sure that this.dlgs[cmd] is initialized prior to calling show() !
Argument:
command - dialog to be opened
- preOpen - ...
*/
- openDialog: function(command, dialog){
+ openDialog: function(command){
- var self = this,
- current = self.activeCmd,
- tmp;
+ var self = this,
+ activeDlg = self.activeDlg,
+ newDlg = self.dlgs[command],
+ button = self.btns[command];
- //console.log('Commands.openDialog() ' + command + ' ' + self.activeCmd );
+ //console.log("Snipe.Commands: openDialog() " + command + " " + activeDlg);
- if( ( current!=command ) && ( tmp = self.dlgs[current] ) ){ tmp.hide(); }
- //toobar button will be deactivated by closeDialog()
+ if( activeDlg && (activeDlg != newDlg) ){ activeDlg.hide(); }
+ self.activeDlg = self.dlgs[command];
- self.activeCmd = command;
- if( tmp = self.btns[command] ){ $(tmp).addClass('active'); }
+ if( button ){ button.addClass("active"); }
+
+ self.fireEvent("open", command);
- self.fireEvent('open', command, dialog);
},
/*
Function: closeDialog
Arguments:
- cmd - (mandatory) dialog to be closed
+ command - (mandatory) dialog to be closed
*/
- closeDialog: function(cmd, dialog){
+ closeDialog: function(command, dialog){
+
+ var self = this,
+ button = self.btns[command];
- var self = this,
- btn = self.btns[cmd];
+ //console.log("Snipe.Commands: closeDialog() " + command )
- //console.log('Commands.closeDialog() ' + cmd + ' ' + self.activeCmd )
+ if( self.dlgs[command] == self.activeDlg ){ self.activeDlg = null; }
- if( cmd == self.activeCmd ){ self.activeCmd = null; }
- if( btn ){ $(btn).removeClass('active'); }
+ if( button ){ button.removeClass("active"); }
+
+ self.fireEvent("close", command);
- self.fireEvent('close', cmd, dialog);
},
/*
Function: close
- Close the active dialog, if any.
+ Close any active dialog.
*/
close: function(){
- var activeCmd = this.activeCmd;
- if( activeCmd ){ this.dlgs[activeCmd].hide(); }
+ var activeDlg = this.activeDlg;
+ if( activeDlg ){ activeDlg.hide(); }
}
-});
-
-
+});
\ No newline at end of file
Modified: jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js?rev=1686927&r1=1686926&r2=1686927&view=diff
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js (original)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Sections.js Mon Jun 22 20:11:42 2015
@@ -1,6 +1,5 @@
-/*!
+/*
JSPWiki - a JSP-based WikiWiki clone.
-
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
@@ -8,9 +7,7 @@
to you under the Apache License, Version 2.0 (the
"License"); fyou may not use this file except in compliance
with the License. You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
-
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,14 +18,13 @@
/*
Class: SnipEditor.Sections
This dialog displays the list of page sections.
- A page section includes the header
(all) - allows to select all sections (auto generated)
start-of-page - only present when first section starts on an offset > 0
section1..n - section titles, with indentation level depending on their weight
The set of sections is generated by the parseSections() callback handler.
- This parser returns an array of section 'descriptors':
+ This parser returns an array of section "descriptors":
> [ {title:text, start:char-offset, indent:indentation-level}, ... ]
Clicking an entry triggers the updateSections() callback handler.
@@ -37,39 +33,58 @@ Class: SnipEditor.Sections
Depends:
Snipe
+Example:
+(start code)
+ div.cage
+ div.btn.btn-link
+ span.icon-bookmark
+ span.caret
+ ul.dropdown-menu [data-sections="div"][data-hover-parent=".cage"]
+ li a first
+ li a ..
+ li a.dropdown-divider
+ li a ..
+
+
+ new Snipe.Sections( sectionDropDown, {
+ snipe: snipe,
+ parser: function(text){ .. return [[{title, start, depth}],..]; }
+ });
+(end)
*/
Snipe.Sections = new Class({
Implements: [Events],
- Binds: ['show','update','action'],
-
+ Binds: ["show","update","action"],
+
options: {
//snipe:snip-editor
- //parser: function
+ //parser: function(text){ returns [[title,start,depth]..] }
all: "( all )".localize(),
startOfPage: "Start of Page".localize()
},
initialize: function(element, options){
- var self = this;
+ var self = this,
+ snipe = options.snipe;
- self.element = element //dropdown menu
- .onHover( self.container = element.get('data-sections'), self.show )
- .addEvent( 'click:relay(a)', self.action );
- self.container = element.getParent( element.get('data-sections') );
-
+ self.container = element;
self.parser = options.parser;
- self.main = options.snipe.get('mainarea');
- self.work = options.snipe.toElement().addEvents({
- keyup: self.update,
- change: self.update
+
+ self.list = element.getElement("ul").addEvent("click:relay(a)", self.action);
+
+ self.main = snipe.get("mainarea");
+ self.work = $(snipe.get("textarea")).addEvents({
+ keyup: self.update,
+ change: self.update
});
self.parse();
- self.action( location.search ); //url?section=0..n
+ self.action( location.search ); //url?section=0..n
self.show();
+
},
/*
@@ -88,9 +103,10 @@ Snipe.Sections = new Class({
},
/*
- Function: onOpen
- UPDATE/RFEFRESH the textarea section dialog.
- Build the DOM list-items
+ Function: show
+ UPDATE/RFEFRESH the section dropdown-menu.
+ Highlight the current item.
+
(start code)
ul.dropdown-menu
li
@@ -104,96 +120,95 @@ Snipe.Sections = new Class({
a.indent-0.section1 Title-Section-1
...
li
- a.indent-0.section99 Title-Section-2
- (end)
+ a.indent-0.section99 Title-Section-2
+ (end)
*/
- //onOpen: function( dialog ){
show: function( ){
- var options = this.options,
- data = [],
+ //console.log("Sections show",this.current, this.sections.length, this.sections[3]);
+
+ var data = [],
+ options = this.options,
+ current = this.current,
sections = this.sections,
-
+
addItem = function(indent,name,offset){
- data.push('li',['a.indent-'+indent+'.section'+offset,{ html:name }]);
- }
+ data.push("li" + (offset==current ? ".active" : ""),[
+ "a.indent-" + indent + ".section" + offset, { html:name }
+ ]);
+ };
addItem(0, options.all ,-2);
-
+
if( sections[0] ){
-
+
if( sections[0].start > 0 ){ addItem(0, options.startOfPage, -1); }
- data.push('li.divider');
-
- sections.each( function(item, idx){
- addItem( item.depth, item.title.trunc(36), idx );
+ data.push( "li.divider" );
+
+ sections.each( function(item, idx){
+
+ addItem( item.depth, item.title/*.trunc(36)*/, idx );
+
});
}
-
- this.element.empty().adopt( data.slick() );
+
+ this.list.empty().adopt( data.slick() );
},
/*
Function: update
Make sure that changes to the work textarea are propagated to the main textarea.
- This functions handles the correct insertion of the changed section into the main
- textarea.
+ This function handles the propagation of changes into the main textarea.
*/
update: function(){
- //console.log("Sections: update");
var self = this,
main = self.main,
work = self.work.value,
- sections = self.sections,
- s = main.value,
- //insert \n to ensure the next section always starts on a new line.
- linefeed = (work.slice(-1) != '\n') ? '\n' : '';
+ s = main.value;
+
+ //insert \n to ensure the next section always starts on a new line.
+ if( work.slice(-1) != "\n" ){ work +="\n"; }
+
+ //console.log("change txta: from="+self.begin+ " end="+self.end);
+ main.value = s.slice(0, self.begin) + work + s.slice(self.end);
- //console.log('change txta: from='+sections.begin+ ' end='+sections.end);
- main.value = s.slice(0, self.begin) + work + linefeed + s.slice(self.end);
self.end = self.begin + work.length;
self.parse();
+
},
/*
- Function: onAction
+ Function: action
This function copies the selected section from the main to the work textarea.
It is invoked at initialization and through the dialog onAction click handler.
Arguments:
item - index of selected section: all, -1, 0..n
*/
- //onAction:function( item ){
-
- /*
- setValue: function(value){
- },
- action: function(item){
- var value = item.get('title');
- this.setValue(value).parent(value);
- },
- */
action:function( item ){
+ //console.log("Sections: action",item);
var self = this,
main = self.main.value,
+ work = self.work,
sections = self.sections,
begin = 0,
end = main.length;
if( item ){
-
+
//item.target => event.target; this is an onclick invocation
- if( item.target ) item = item.target.className;
-
+ if( item.target ){ item = item.target.className; }
+
//section-2=All, section-1=StartOfPage, section0..section99=rest
item = ( item.match( /section=?(-?\d+)/ )||[,-2])[1].toInt();
-
+
+
if( item == -1 ){
//show the Start Of Page, prior to the first real section
@@ -202,18 +217,29 @@ Snipe.Sections = new Class({
} else if(item >= 0 && sections[item] ){
begin = sections[item].start;
- //if( item+1 < sections.length ){ end = sections[item+1].start; }
if( sections[item+1] ){ end = sections[item+1].start; }
}
+
+ self.current = item;
+
}
- self.work.value = main.slice(begin, end);
+ work.value = ""; //FIXME google chrome 43.0.2357.65 bug -- if omitted, the textarea is displayed EMPTY!! ??
+ work.value = main.slice(begin, end);
self.begin = begin;
self.end = end;
- //now close the hover menu and focus the text-area...
- self.container.removeClass('open');
- self.container.ifClass( item >= -1, 'section-selected');
+ //section-selected class : turn bookmark icon red or blue
+ self.container.ifClass( item >= -1, "section-selected");
+
+ //update the dropdown menu, and highlight the current item
+ self.show();
+
+ work.fireEvent("change"); //needed to rerun page preview
+
+ return false; //stop click event propagation
+
}
-});
+
+});
\ No newline at end of file
Added: jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Snips.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Snips.js?rev=1686927&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Snips.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/wiki-edit/Snipe.Snips.js Mon Jun 22 20:11:42 2015
@@ -0,0 +1,394 @@
+/*
+ JSPWiki - a JSP-based WikiWiki clone.
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); fyou may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+/*
+Snippet:
+ init - initialize snippets; detect shortcut-keys, and suggest dialogs
+ get - retrieve and validate the snippet. Return false when not found.
+ inScope - check whether a snippet is inScope at the current cursor position
+ toggle - ...
+
+
+ suggest - match suggestion dialog => fireEvent(action,cmd)
+ shortcut - match key => fireEvent(action,cmd)
+
+Example
+ var sn = new Snipe.Snips(textarea, { snippets... } });
+ sn.dialogs => snippet dialogs
+ sn.suggest => suggest snippets
+ sn.keys => shortcut keys
+
+*/
+
+Snipe.Snips = new Class({
+
+ Implements: Events,
+
+ initialize: function( workarea, snips ){
+
+ var self = this,
+ cmd, snip, key, suggest,
+ //shortcut = ((navigator.userAgent.indexOf("Mac OS X")!=-1) ? "meta+" : "control+");
+ //control = (Browser.platform == "mac" ? "meta+" : "control+");
+ control = ( navigator.platform.match( /mac/i ) ? "meta+" : "control+");
+
+
+
+ self.workarea = workarea; //Textarea class
+ self.snips = snips;
+
+ self.keys = {};
+ self.dialogs = {};
+ self.suggestions = {};
+
+ for( cmd in snips ){
+
+ snip = Function.from( snips[cmd] )( workarea, cmd );
+
+ // short format of snip
+ if( typeOf(snip)=="string" ){ snip = { snippet:snip }; }
+
+ //Not needed sofar: Function.from( snip.initialize )(cmd, snip);
+
+ if( key = snip.key ){
+
+ // key:"f" => key:"control+f" ; key:"shift+enter" (no change)
+ if( !key.contains("+") ){ key = control + key; }
+ self.keys[ key.toLowerCase() ] = cmd;
+ snip.key = key;
+
+ }
+
+ if( suggest = snip.suggest ){
+
+ if( typeOf(suggest)== "string" ){
+
+ snip.suggest = {
+ pfx: RegExp( suggest + "$" ),
+ match: RegExp( "^" + suggest )
+ }
+ //console.log( snip.suggest );
+ }
+ self.suggestions[cmd] = snip;
+
+ }
+
+ //check for snip dialogs -- they have the same name as the command
+ //EG: find: { find:<this is a snip dialog> }
+ if( snip[cmd] ){ self.dialogs[cmd] = snip[cmd]; }
+
+ snips[cmd] = snip;
+
+ }
+ //console.log(this.keys);
+
+ },
+
+ /*
+ Function: match
+ Lookup a cmd entered just in front of the caret/cursor of the workarea.
+ */
+ match: function(){
+
+ var cmd, fromStart = this.workarea.getFromStart();
+
+ for( cmd in this.snips ){
+ if( fromStart.test( cmd+"$" ) ) return cmd;
+ }
+
+ return false;
+ },
+
+ /*
+ Function: matchSuggest
+ Lookup a cmd enter just in front of the caret/cursor of the workarea..
+
+ snip.suggest => {
+ start: <pos>,
+ match: <match-string-before-caret>,
+ tail: <length-match-after-caret>
+ }
+ */
+ matchSuggest: function(){
+
+ var cmd, snip, pfx, result, suggest,
+ snips = this.suggestions,
+ workarea = this.workarea,
+ caret = workarea.getSelectionRange(),
+ fromStart = workarea.getFromStart();
+
+ for( cmd in snips ){
+
+ snip = snips[cmd];
+ suggest = snip.suggest;
+
+ if( this.inScope(snip, fromStart) ){
+
+ if( suggest.pfx ){
+
+ pfx = fromStart.match( suggest.pfx );
+
+ if( pfx ){
+
+ console.log("SUGGEST Prefix ", cmd, suggest.pfx, pfx.getLast() );
+ pfx = pfx.getLast(); //match last (x)
+ result = workarea.slice( caret.start - pfx.length )
+ .match( suggest.match );
+
+ console.log("SUGGEST Match ", suggest.match, result );
+
+ if( result ){
+ result = { pfx:pfx, match:result.getLast() } ;
+ }
+
+ }
+
+ } else {
+
+ result = Function.from(suggest)(workarea, caret, fromStart);
+
+ }
+
+ if( result ){
+
+ result.cmd = cmd;
+ return result;
+
+ }
+ }
+ }
+ return false;
+
+ },
+
+ /*
+ Function: get
+ Retrieve and validate the snippet.
+ Returns false when the snippet is not found or not in scope.
+
+
+ Arguments:
+ snips - snippet collection object for lookup of the cmd
+ cmd - snippet key. If not present, retrieve the cmd from
+ the textarea just to the left of the caret. (i.e. tab-completion)
+
+ Returns:
+ Return a snippet object or false.
+ - false
+ - snippet object
+
+ Example:
+ (start code)
+ sn.get( "bold" );
+
+ returned_object = false || {
+ key: "snippet-key",
+ snippet: " snippet-string ",
+ text: " converted snippet-string, no-parameter braces, auto-indented ",
+ parms: [parm1, parm2, "last-snippet-string" ]
+ }
+ (end)
+ */
+ get: function( cmd ){
+
+ var self = this,
+ txta = self.workarea,
+ fromStart = txta.getFromStart(),
+ snip = self.snips[cmd],
+ parms = [],
+ s,last;
+
+ if( snip && snip.synonym ){ snip = self.snips[snip.synonym]; }
+
+ if( !snip || !self.inScope(snip, fromStart) ){ return false; }
+
+ s = snip.snippet || "";
+
+ //parse snippet {parameters}
+ s = s.replace( /\\?\{([^{}]+)\}/g, function(match, name){
+
+ if( match.charAt(0) == "{" ){
+ parms.push(name);
+ return name;
+ } else {
+ return match.slice(1)
+ }
+
+ }).replace( /\\\{/g, "{" );
+ //and end by replacing all escaped "\{" by real "{" chars
+
+ //also push the last piece of the snippet onto the parms[] array
+ last = parms.getLast();
+ if( last ){ parms.push( s.slice(s.lastIndexOf(last) + last.length) ); }
+
+ //collapse \n of previous line if the snippet starts with \n
+ if( s.test(/^\n/) && ( fromStart.test( /(^|[\n\r]\s*)$/ ) ) ) {
+ s = s.slice(1);
+ //console.log("remove leading \\n");
+ }
+
+ //collapse \n of subsequent line when the snippet ends with a \n
+ if( s.test(/\n$/) && ( txta.getTillEnd().test( /^\s*[\n\r]/ ) ) ) {
+ s = s.slice(0,-1);
+ //console.log("remove trailing \\n");
+ }
+
+ //finally auto-indent the snippet"s internal newlines \n
+ var prevline = fromStart.split(/\r?\n/).pop(),
+ indent = prevline.match(/^\s+/);
+ if( indent ){ s = s.replace( /\n/g, "\n" + indent[0] ); }
+
+ //complete the snip object
+ snip.text = s;
+ snip.parms = parms;
+
+ //console.log("Snipe.Snips:get() ",snip.text, JSON.encode(snip),"***" );
+ return snip;
+ },
+
+ /*
+ Function: inScope
+ Sometimes it is useful to restrict the scope of a snippet, and only allow
+ the snippet expansion in specific parts of the text. The scope parameter allows
+ you to do that by defining start and end delimiting strings.
+ For example, the following "fn" snippet will only expands when it appears
+ inside the scope of a script tag.
+
+ (start code)
+ "fn": {
+ snippet: "function( {args} )\{ \n {body}\n\}\n",
+ scope: {"<script":"</script"} //should be inside this bracket
+ }
+ (end)
+
+ The opposite is possible too. Use the "nScope" or not-in-scope parameter
+ to make sure the snippet is only inserted when not in scope.
+
+ (start code)
+ "special": {
+ snippet: "{special}",
+ nScope: { "%%(":")" } //should not be inside this bracket
+ },
+ (end)
+
+ Arguments:
+ snip - Snippet Object
+ text - (string) used to check for open scope items
+
+ Returns:
+ True when the snippet is in scope, false otherwise.
+ */
+ inScope: function(snip, text){
+
+ var pattern, pos, scope=snip.scope, nscope=snip.nscope;
+
+ if( scope ){
+
+ if( typeOf(scope)=="function" ){
+
+ return scope( this.textarea );
+
+ } else {
+
+ for( pattern in scope ){
+
+ pos = text.lastIndexOf(pattern);
+ if( (pos > -1) && (text.indexOf( scope[pattern], pos ) == -1) ){
+
+ return true;
+
+ }
+
+ }
+ return false;
+ }
+ }
+
+ if( nscope ){
+
+ for( pattern in nscope ){
+
+ pos = text.lastIndexOf(pattern);
+ if( (pos > -1) && (text.indexOf( nscope[pattern], pos ) == -1) ){
+
+ return false;
+
+ }
+
+ }
+
+ }
+ return 1 /*true*/;
+ },
+
+
+ /*
+ Function: toggle
+ Toggle the prefix and suffix of a snippet.
+ Eg. toggle between {{__text__}} and {{text}}.
+ The selection will be matched against the snippet.
+
+ Precondition:
+ - the selection is not empty (caret.thin = false)
+ - the snippet has exatly one {parameter}
+
+ Arguments:
+ txta - Textarea object
+ snip - Snippet object
+ caret - Caret object {start, end, thin}
+
+ Returns:
+ - (string) replacement string for the selection.
+ By default, returns snip.text
+ - the snip.parms will be set to [] is toggle was executed successfully
+ Eventually the selection will be extended if the
+ prefix and suffix were just outside the selection.
+ */
+ toggle: function(txta, snip, caret){
+
+ var s = snip.text,
+ //get the first and last textual parts of the snippet
+ arr = s.trim().split( snip.parms[0] ),
+ fst = arr[0],
+ lst = arr[1],
+ re = new RegExp( "^\\s*" + fst.trim().escapeRegExp() + "\\s*(.*)\\s*" + lst.trim().escapeRegExp() + "\\s*$" );
+
+ if( (fst + lst)!="" ){
+
+ s = txta.getSelection();
+ snip.parms = [];
+
+ // if pfx & sfx (with optional whitespace) are matched: remove them
+ if( s.test(re) ){
+
+ s = s.replace( re, "$1" );
+
+ // if pfx/sfx are matched just outside the selection: extend selection
+ } else if( txta.getFromStart().test(fst.escapeRegExp()+"$") && txta.getTillEnd().test("^"+lst.escapeRegExp()) ){
+
+ txta.setSelectionRange(caret.start-fst.length, caret.end+lst.length);
+
+ // otherwise, insert snippet and set caret between pfx and sfx
+ } else {
+
+ txta.setSelection( fst+lst ).setSelectionRange( caret.start + fst.length );
+ }
+ }
+
+ return s;
+ }
+});
\ No newline at end of file