[seam-commits] Seam SVN: r8469 - in trunk/examples/wiki: src/main/org/jboss/seam/wiki/core/wikitext/editor and 7 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Wed Jul 16 08:27:08 EDT 2008


Author: christian.bauer at jboss.com
Date: 2008-07-16 08:27:07 -0400 (Wed, 16 Jul 2008)
New Revision: 8469

Added:
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditorError.java
Modified:
   trunk/examples/wiki/src/etc/i18n/messages_en.properties
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiFormattedTextValidator.java
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditor.java
   trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/engine/WikiTextParser.java
   trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/i18n/messages_forum_en.properties
   trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListControls.xhtml
   trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListTable.xhtml
   trunk/examples/wiki/view/includes/wikitext/editor/editor.xhtml
   trunk/examples/wiki/view/themes/default/js/lacewiki.js
   trunk/examples/wiki/view/themes/inrelationto/js/lacewiki.js
   trunk/examples/wiki/view/themes/sfwkorg/js/lacewiki.js
Log:
Improved wiki text editor error messages

Modified: trunk/examples/wiki/src/etc/i18n/messages_en.properties
===================================================================
--- trunk/examples/wiki/src/etc/i18n/messages_en.properties	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/src/etc/i18n/messages_en.properties	2008-07-16 12:27:07 UTC (rev 8469)
@@ -212,6 +212,7 @@
 lacewiki.label.VerificationError=The entered characters do not match the shown (case sensitive) characters, please try again.
 
 # Wiki Text Editor
+
 lacewiki.label.wikiTextEditor.CharactersLeft=chars left
 lacewiki.label.wikiTextEditor.DisableContentMarkup=Let me type some plain text, not markup
 lacewiki.label.wikiTextEditor.EnableLivePreview=Enable live preview
@@ -238,7 +239,20 @@
 lacewiki.msg.wikiTextValidator.InvalidWikiText=Invalid wiki text, please click HELP for formatting instructions.
 lacewiki.msg.wikiTextValidator.EmptyWikiText=Please enter wiki text, field can not be empty.
 lacewiki.msg.wikiTextValidator.MaxLengthExceeded=Too much content, please shorten the text.
+lacewiki.msg.wikiTextValidator.FormattingErrorPrefix=Formatting error,
+lacewiki.msg.wikiTextValidator.ReachedEndAndMissing=missing
+lacewiki.msg.wikiTextValidator.InsteadFound=instead found
+lacewiki.msg.wikiTextValidator.UnclosedInvalidHTML=unclosed or invalid HTML tag
+lacewiki.msg.wikiTextValidator.WrongPositionFor=wrong position for
+lacewiki.msg.wikiTextValidator.InvalidURI=invalid URI
+lacewiki.msg.wikiTextValidator.InvalidElement=element is not supported
+lacewiki.msg.wikiTextValidator.InvalidAttribute=invalid attribute
+lacewiki.msg.wikiTextValidator.InvalidAttributeValue=invalid value of attribute
+lacewiki.label.wikiTextValidator.HighlightError=Highlight error
+lacewiki.label.wikiTextValidator.ScrollToError=Scroll to error
 
+
+
 # Document Display
 
 lacewiki.label.docDisplay.Tags=Tags

Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiFormattedTextValidator.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiFormattedTextValidator.java	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiFormattedTextValidator.java	2008-07-16 12:27:07 UTC (rev 8469)
@@ -9,11 +9,12 @@
 import org.jboss.seam.ui.validator.FormattedTextValidator;
 import org.jboss.seam.text.SeamTextParser;
 import antlr.SemanticException;
+import antlr.Token;
 
 /**
  * Disables the Seam Text validation for link tags, so wiki links are OK.
  * <p>
- * Also provides some conversation to i18n error messages.
+ * Also provides some conversion to i18n error messages.
  * </p>
  *
  * TODO: Finish the i18n and well, maybe we should just duplicate the
@@ -28,9 +29,8 @@
         parser.setSanitizer(
             new SeamTextParser.DefaultSanitizer() {
 
-                // Disable this part of the validation
-                @Override
-                public void validateLinkTagURI(String s) throws SemanticException {}
+                // Disable this method
+                public void validateLinkTagURI(Token token, String s) throws SemanticException {}
 
                 @Override
                 public String getInvalidURIMessage(String s) {

Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditor.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditor.java	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditor.java	2008-07-16 12:27:07 UTC (rev 8469)
@@ -6,18 +6,23 @@
  */
 package org.jboss.seam.wiki.core.wikitext.editor;
 
+import antlr.*;
+import org.jboss.seam.Component;
+import org.jboss.seam.international.Messages;
 import org.jboss.seam.log.Log;
 import org.jboss.seam.log.Logging;
+import org.jboss.seam.text.SeamTextLexer;
+import org.jboss.seam.text.SeamTextParser;
+import org.jboss.seam.text.SeamTextParserTokenTypes;
+import org.jboss.seam.wiki.core.action.Validatable;
+import org.jboss.seam.wiki.core.model.WikiFile;
 import org.jboss.seam.wiki.core.wikitext.engine.WikiLinkResolver;
-import org.jboss.seam.wiki.core.model.WikiFile;
-import org.jboss.seam.wiki.core.action.Validatable;
-import org.jboss.seam.Component;
 
-import javax.faces.validator.ValidatorException;
-import javax.faces.application.FacesMessage;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.StringReader;
 import java.util.HashSet;
 import java.util.Set;
-import java.io.Serializable;
 
 /**
  * A wiki (or plain) text editor.
@@ -40,8 +45,8 @@
     private boolean valid = true;
     private boolean valuePlaintext;
     private boolean previewEnabled;
-    private String lastValidationError;
     private Set<WikiFile> linkTargets;
+    private WikiTextEditorError lastValidationError;
 
     public WikiTextEditor(String key) {
         this.key = key;
@@ -151,11 +156,11 @@
         this.previewEnabled = previewEnabled;
     }
 
-    public String getLastValidationError() {
+    public WikiTextEditorError getLastValidationError() {
         return lastValidationError;
     }
 
-    public void setLastValidationError(String lastValidationError) {
+    public void setLastValidationError(WikiTextEditorError lastValidationError) {
         this.lastValidationError = lastValidationError;
     }
 
@@ -198,50 +203,127 @@
         setValid(false);
         if (valueRequired && (value == null || value.length() == 0)) {
             log.debug("validation failed for required but null or empty wiki text with key: " + key);
-            lastValidationError = "lacewiki.msg.wikiTextValidator.EmptyWikiText"; // TODO: make static
+            lastValidationError = new WikiTextEditorError(
+                Messages.instance().get("lacewiki.msg.wikiTextValidator.EmptyWikiText")
+            );
             return;
         }
         if (value != null && value.length() > getValueMaxLength()) {
             log.debug("validation failed for too long wiki text with key: " + key);
-            lastValidationError = "lacewiki.msg.wikiTextValidator.MaxLengthExceeded"; // TODO: make static
+            lastValidationError = new WikiTextEditorError(
+                Messages.instance().get("lacewiki.msg.wikiTextValidator.MaxLengthExceeded")
+            );
             return;
         }
-        try {
-            lastValidationError = null;
-            if (!isValuePlaintext()) {
-                WikiFormattedTextValidator validator = new WikiFormattedTextValidator();
-                validator.validate(null, null, value);
+
+        lastValidationError = null;
+        setValid(true);
+        if (!isValuePlaintext()) {
+            try {
+                SeamTextParser parser = getValidationParser(value);
+                parser.startRule();
+                setValid(true);
             }
-            log.debug("value is valid");
-            setValid(true);
-        } catch (ValidatorException e) {
-            log.debug("exception during validation: " + e.getFacesMessage().getSummary());
-            lastValidationError = convertFacesMessage(e.getFacesMessage());
+            // Error handling for ANTLR lexer/parser errors, see
+            // http://www.doc.ic.ac.uk/lab/secondyear/Antlr/err.html
+            catch (TokenStreamException tse) {
+                setValid(false);
+                // Problem with the token input stream
+                throw new RuntimeException(tse);
+            } catch (RecognitionException re) {
+                setValid(false);
+                lastValidationError = convertException(re);
+            }
         }
         log.debug("completed validation of text editor value for key: " + key);
     }
-    
-    // TODO: These are supposed to be message bundle keys, not the literal ANTLR parser messages, see WikiFormattedTextValidator
-    protected String convertFacesMessage(FacesMessage fm) {
-        // Convert the FacesMessage to a StatusMessage (which of course is then converted back to JSF...)
-        StringBuilder msg = new StringBuilder();
-        msg.append(fm.getSummary());
 
-        // Append the detail only if the summary doesn't end with it already
-        if (!fm.getSummary().endsWith(fm.getDetail())) {
-            msg.append(" (").append(fm.getDetail()).append(")");
-        }
-        return msg.toString();
+    protected SeamTextParser getValidationParser(String text) {
+        Reader r = new StringReader(text);
+        SeamTextLexer lexer = new SeamTextLexer(r);
+        SeamTextParser parser = new SeamTextParser(lexer);
+        parser.setSanitizer(
+            new SeamTextParser.DefaultSanitizer() {
+                @Override
+                public void validateLinkTagURI(Token token, String s) throws SemanticException {
+                    // Disable this part of the validation
+                }
+                @Override
+                public String getInvalidURIMessage(String uri) {
+                    return Messages.instance().get("lacewiki.msg.wikiTextValidator.InvalidURI");
+                }
+                @Override
+                public String getInvalidElementMessage(String elementName) {
+                    return Messages.instance().get("lacewiki.msg.wikiTextValidator.InvalidElement");
+                }
+                @Override
+                public String getInvalidAttributeMessage(String elementName, String attributeName) {
+                    return Messages.instance().get("lacewiki.msg.wikiTextValidator.InvalidAttribute")
+                            + " '" + attributeName + "'";
+                }
+                @Override
+                public String getInvalidAttributeValueMessage(String elementName, String attributeName, String value) {
+                    return Messages.instance().get("lacewiki.msg.wikiTextValidator.InvalidAttributeValue")
+                            + " '" + attributeName + "'";
+                }
+            }
+        );
+        return parser;
     }
 
-    /* TODO: Old stuff
-    public void setShowPluginPrefs(boolean showPluginPrefs) {
-        Contexts.getPageContext().set("showPluginPreferences", showPluginPrefs);
+    // This tries to make sense of the totally useless exceptions thrown by ANTLR parser.
+    protected WikiTextEditorError convertException(RecognitionException ex) {
+        WikiTextEditorError error = new WikiTextEditorError();
+        if (ex instanceof MismatchedTokenException) {
+
+            MismatchedTokenException tokenException = (MismatchedTokenException) ex;
+            String expecting = SeamTextParser._tokenNames[tokenException.expecting];
+
+            String found = "";
+            if (tokenException.token.getType() != SeamTextParserTokenTypes.EOF) {
+                error.setPosition(tokenException.getColumn());
+                found = ", " + Messages.instance().get("lacewiki.msg.wikiTextValidator.InsteadFound")
+                        + " " + SeamTextParser._tokenNames[tokenException.token.getType()];
+            }
+
+            error.setFormattingErrorMessage(
+                Messages.instance().get("lacewiki.msg.wikiTextValidator.ReachedEndAndMissing")
+                + " " + expecting + found
+            );
+
+        } else if (ex instanceof SeamTextParser.HtmlRecognitionException) {
+
+            SeamTextParser.HtmlRecognitionException htmlException = (SeamTextParser.HtmlRecognitionException) ex;
+            Token openingElement = htmlException.getOpeningElement();
+            String elementName = openingElement.getText();
+            String detailMsg;
+            if (!(htmlException.getCause() instanceof MismatchedTokenException)) {
+                detailMsg = ", " + convertException((RecognitionException)htmlException.getCause()).getMessage();
+            } else {
+                detailMsg = "";
+            }
+            error.setFormattingErrorMessage(
+                Messages.instance().get("lacewiki.msg.wikiTextValidator.UnclosedInvalidHTML")
+                + " '<"+elementName+">'" + detailMsg
+            );
+            error.setPosition(openingElement.getColumn());
+
+        } else if (ex instanceof NoViableAltException) {
+
+            NoViableAltException altException = (NoViableAltException) ex;
+            String unexpected = SeamTextParser._tokenNames[altException.token.getType()];
+
+            error.setFormattingErrorMessage(
+                Messages.instance().get("lacewiki.msg.wikiTextValidator.WrongPositionFor")
+                + " " + unexpected
+            );
+            error.setPosition(altException.getColumn());
+
+        } else {
+            error.setFormattingErrorMessage(ex.getMessage());
+            error.setPosition(ex.getColumn());
+        }
+        return error;
     }
 
-    public boolean isShowPluginPrefs() {
-        Boolean showPluginPrefs = (Boolean)Contexts.getPageContext().get("showPluginPreferences");
-        return showPluginPrefs != null && showPluginPrefs;
-    }
-    */
 }

Added: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditorError.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditorError.java	                        (rev 0)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/editor/WikiTextEditorError.java	2008-07-16 12:27:07 UTC (rev 8469)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.seam.wiki.core.wikitext.editor;
+
+import org.jboss.seam.international.Messages;
+
+/**
+ * Encapsulates an error message and, if possible, a location of the error in
+ * the character stream.
+ *
+ * @author Christian Bauer
+*/
+public class WikiTextEditorError {
+
+    private String message;
+    private int position = -1;
+
+    public WikiTextEditorError() {}
+
+    public WikiTextEditorError(String message) {
+        setMessage(message);
+    }
+
+    public WikiTextEditorError(String message, int position) {
+        this(message);
+        this.position = position;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public void setFormattingErrorMessage(String message) {
+        this.message =
+                Messages.instance().get("lacewiki.msg.wikiTextValidator.FormattingErrorPrefix")
+                + " " + message + ".";
+    }
+
+    public int getPosition() {
+        return position;
+    }
+
+    public void setPosition(int position) {
+        this.position = position;
+    }
+}

Modified: trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/engine/WikiTextParser.java
===================================================================
--- trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/engine/WikiTextParser.java	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/src/main/org/jboss/seam/wiki/core/wikitext/engine/WikiTextParser.java	2008-07-16 12:27:07 UTC (rev 8469)
@@ -8,6 +8,7 @@
 
 import antlr.ANTLRException;
 import antlr.SemanticException;
+import antlr.Token;
 import org.jboss.seam.text.SeamTextLexer;
 import org.jboss.seam.text.SeamTextParser;
 import org.jboss.seam.wiki.core.model.*;
@@ -59,7 +60,7 @@
         setSanitizer(
             new DefaultSanitizer() {
                 @Override
-                public void validateLinkTagURI(String s) throws SemanticException {
+                public void validateLinkTagURI(Token token, String s) throws SemanticException {
                     // NOOP, we validate that later in linkTag()
                 }
             }

Modified: trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/i18n/messages_forum_en.properties
===================================================================
--- trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/i18n/messages_forum_en.properties	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/i18n/messages_forum_en.properties	2008-07-16 12:27:07 UTC (rev 8469)
@@ -38,7 +38,7 @@
 forum.label.NewestTopic=Newest Topic
 forum.label.LatestPost=Last Post
 forum.label.Feed=Feed
-forum.label.EnableFeed=Enable syndication feed (disabling invalidates subcriber link)
+forum.label.EnableFeed=Enable syndication feed (renaming forum invalidiates subscriber bookmarks)
 
 forum.label.EditForum=Edit Forum
 forum.label.NewForum=New Forum

Modified: trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListControls.xhtml
===================================================================
--- trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListControls.xhtml	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListControls.xhtml	2008-07-16 12:27:07 UTC (rev 8469)
@@ -49,6 +49,7 @@
         <a:commandLink action="#{forumHome.newForum()}"
                        reRender="forumListPluginContainer, messageBoxContainer"
                        accesskey="#{messages['forum.button.NewForum.accesskey']}"
+                       status="globalStatus"
                        tabindex="1" styleClass="buttonNonpersistent sessionEventTrigger">
             <h:outputText styleClass="buttonLabel" escape="false" value="#{messages['forum.button.NewForum']}"/>
         </a:commandLink>

Modified: trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListTable.xhtml
===================================================================
--- trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListTable.xhtml	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/src/plugin/org/jboss/seam/wiki/plugin/forum/templates/forumListTable.xhtml	2008-07-16 12:27:07 UTC (rev 8469)
@@ -124,6 +124,7 @@
 
         <a:commandLink action="#{forumHome.edit(f.forum.id)}"
                        reRender="forumListControlsContainer, forumListTable, forumFormContainer, messageBoxContainer"
+                       status="globalStatus"
                        tabindex="1" styleClass="buttonNonpersistent sessionEventTrigger">
             <h:outputText styleClass="buttonLabel" value="#{messages['forum.button.Edit']}"/>
         </a:commandLink>

Modified: trunk/examples/wiki/view/includes/wikitext/editor/editor.xhtml
===================================================================
--- trunk/examples/wiki/view/includes/wikitext/editor/editor.xhtml	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/view/includes/wikitext/editor/editor.xhtml	2008-07-16 12:27:07 UTC (rev 8469)
@@ -142,20 +142,56 @@
             styleClass="#{not textEditor.valid ? 'textEditorErrorMessages' : 'textEditorMessages'}">
 
         <s:div styleClass="errorMessage" rendered="#{not textEditor.valid}">
-            <h:panelGrid columns="2" cellpadding="0" cellspacing="0" border="0">
+            <h:panelGrid columns="5" cellpadding="0" cellspacing="0" border="0"
+                         columnClasses="onePercentColumn minorPadding,
+                                        defaultColumn,
+                                        onePercentColumn,
+                                        onePercentColumn">
                 <h:graphicImage value="#{imagePath}/attention.gif"
                                 width="18" height="18"
                                 styleClass="attentionImage"/>
-                <s:span styleClass="attentionMessage"><span
-                        id="#{textEditor.key}MessageText"><h:outputText
-                        value="#{messages[textEditor.lastValidationError]}"/></span></s:span>
+                <s:span styleClass="attentionMessage">
+                        <h:outputText value="#{textEditor.lastValidationError.message}"/>
+                </s:span>
+                <s:fragment>
+                    <s:fragment rendered="#{textEditor.lastValidationError.position > 0}">
+                        <!-- Oh my god... -->
+                        <input id="#{textEditor.key}ThisIsJustADummy" size="2" value="  " disabled="true"
+                               style="display:inline;background:none;padding:0;border:0;margin:0;cursor:default"/>
+                    </s:fragment>
+                </s:fragment>
+                <s:fragment>
+                    <h:outputLink value="javascript://no-op" styleClass="buttonNonpersistent"
+                                  rendered="#{textEditor.lastValidationError.position > 0}"
+                                  onclick="selectText(
+                                            '##{namingContainer}\\\\:#{textEditor.key}TextArea',
+                                            '#{textEditor.lastValidationError.position}',
+                                            3
+                                           );">
+                        <h:outputText styleClass="buttonLabel"
+                                      value="#{messages['lacewiki.label.wikiTextValidator.HighlightError']}"/>
+                    </h:outputLink>
+                </s:fragment>
+                <s:fragment>
+                    <h:outputLink value="javascript://no-op" styleClass="buttonNonpersistent"
+                                  rendered="#{textEditor.lastValidationError.position > 0}"
+                                  onclick="scrollToText(
+                                            '##{namingContainer}\\\\:#{textEditor.key}TextArea',
+                                            '#{textEditor.lastValidationError.position}',
+                                            jQuery('##{textEditor.key}ThisIsJustADummy').width()/2,
+                                            jQuery('##{textEditor.key}ThisIsJustADummy').height()
+                                           );">
+                        <h:outputText styleClass="buttonLabel"
+                                      value="#{messages['lacewiki.label.wikiTextValidator.ScrollToError']}"/>
+                    </h:outputLink>
+                </s:fragment>
             </h:panelGrid>
         </s:div>
 
         <s:fragment rendered="#{not empty tabId}">
             <s:span rendered="#{not textEditor.valid}">
                 <script type="text/javascript">jQuery(function() {
-                    formTabRaiseError("#{tabId}", "#{textEditor.key}TextArea", '#{messages[textEditor.lastValidationError]}');
+                    formTabRaiseError("#{tabId}", "#{textEditor.key}TextArea", '#{textEditor.lastValidationError.message}');
                 });</script>
             </s:span>
             <s:span rendered="#{textEditor.valid}">

Modified: trunk/examples/wiki/view/themes/default/js/lacewiki.js
===================================================================
--- trunk/examples/wiki/view/themes/default/js/lacewiki.js	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/view/themes/default/js/lacewiki.js	2008-07-16 12:27:07 UTC (rev 8469)
@@ -182,3 +182,55 @@
     jQuery(textAreaId).width(editorSizeX);
     jQuery(textAreaId).height(editorSizeY);
 }
+
+function selectText(textAreaId, position, padding) {
+    var textArea = jQuery(textAreaId)[0];
+
+    // We highlight characters before and after position, if possible
+    var beginPosition = position;
+    var endPosition = position;
+    var i = 0;
+    while (beginPosition > 0 && i < padding) {
+        i++;
+        beginPosition--;
+    }
+    i = 0;
+    while (endPosition < textArea.value.length && i < padding) {
+        i++;
+        endPosition++;
+    }
+
+    if (textArea.createTextRange) {
+        var oRange = textArea.createTextRange();
+        oRange.moveStart("character", beginPosition);
+        oRange.moveEnd("character", endPosition);
+        oRange.select();
+    } else if (textArea.setSelectionRange) {
+        textArea.focus();
+        textArea.setSelectionRange(beginPosition, endPosition);
+    }
+}
+
+function scrollToText(textAreaId, position, charWidth, charHeight) {
+    // This is all guesswork, there is no realiable way to do this
+    var ta = jQuery(textAreaId);
+    var scroll = {
+          taWidthCenter : Math.floor(ta.innerWidth()/2.0),
+          taHeightCenter : Math.floor(ta.innerHeight()/2.0),
+          taNumRows : Math.floor(ta.innerHeight()/(charHeight-3)),
+          taCharsInRow : Math.floor(ta.innerWidth()/(charWidth-4)),
+          taHeight : ta.innerHeight(),
+          taWidth : ta.innerWidth()
+    };
+
+    var btxt = ta.val().substr(0, position);
+    if (btxt && btxt.length > 1) {
+        var regex = new RegExp(".{1,"+scroll.taCharsInRow+"}|\n(?=\n)", "g");
+        var gap = (btxt.match(regex).length) * scroll.taNumRows;
+        if (gap > scroll.taHeight) {
+            ta.scrollTop((gap-scroll.taHeightCenter));
+        } else {
+            ta.scrollTop(0);
+        }
+    }
+}

Modified: trunk/examples/wiki/view/themes/inrelationto/js/lacewiki.js
===================================================================
--- trunk/examples/wiki/view/themes/inrelationto/js/lacewiki.js	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/view/themes/inrelationto/js/lacewiki.js	2008-07-16 12:27:07 UTC (rev 8469)
@@ -182,3 +182,55 @@
     jQuery(textAreaId).width(editorSizeX);
     jQuery(textAreaId).height(editorSizeY);
 }
+
+function selectText(textAreaId, position, padding) {
+    var textArea = jQuery(textAreaId)[0];
+
+    // We highlight characters before and after position, if possible
+    var beginPosition = position;
+    var endPosition = position;
+    var i = 0;
+    while (beginPosition > 0 && i < padding) {
+        i++;
+        beginPosition--;
+    }
+    i = 0;
+    while (endPosition < textArea.value.length && i < padding) {
+        i++;
+        endPosition++;
+    }
+
+    if (textArea.createTextRange) {
+        var oRange = textArea.createTextRange();
+        oRange.moveStart("character", beginPosition);
+        oRange.moveEnd("character", endPosition);
+        oRange.select();
+    } else if (textArea.setSelectionRange) {
+        textArea.focus();
+        textArea.setSelectionRange(beginPosition, endPosition);
+    }
+}
+
+function scrollToText(textAreaId, position, charWidth, charHeight) {
+    // This is all guesswork, there is no realiable way to do this
+    var ta = jQuery(textAreaId);
+    var scroll = {
+          taWidthCenter : Math.floor(ta.innerWidth()/2.0),
+          taHeightCenter : Math.floor(ta.innerHeight()/2.0),
+          taNumRows : Math.floor(ta.innerHeight()/(charHeight-3)),
+          taCharsInRow : Math.floor(ta.innerWidth()/(charWidth-4)),
+          taHeight : ta.innerHeight(),
+          taWidth : ta.innerWidth()
+    };
+
+    var btxt = ta.val().substr(0, position);
+    if (btxt && btxt.length > 1) {
+        var regex = new RegExp(".{1,"+scroll.taCharsInRow+"}|\n(?=\n)", "g");
+        var gap = (btxt.match(regex).length) * scroll.taNumRows;
+        if (gap > scroll.taHeight) {
+            ta.scrollTop((gap-scroll.taHeightCenter));
+        } else {
+            ta.scrollTop(0);
+        }
+    }
+}

Modified: trunk/examples/wiki/view/themes/sfwkorg/js/lacewiki.js
===================================================================
--- trunk/examples/wiki/view/themes/sfwkorg/js/lacewiki.js	2008-07-15 21:28:37 UTC (rev 8468)
+++ trunk/examples/wiki/view/themes/sfwkorg/js/lacewiki.js	2008-07-16 12:27:07 UTC (rev 8469)
@@ -182,3 +182,55 @@
     jQuery(textAreaId).width(editorSizeX);
     jQuery(textAreaId).height(editorSizeY);
 }
+
+function selectText(textAreaId, position, padding) {
+    var textArea = jQuery(textAreaId)[0];
+
+    // We highlight characters before and after position, if possible
+    var beginPosition = position;
+    var endPosition = position;
+    var i = 0;
+    while (beginPosition > 0 && i < padding) {
+        i++;
+        beginPosition--;
+    }
+    i = 0;
+    while (endPosition < textArea.value.length && i < padding) {
+        i++;
+        endPosition++;
+    }
+
+    if (textArea.createTextRange) {
+        var oRange = textArea.createTextRange();
+        oRange.moveStart("character", beginPosition);
+        oRange.moveEnd("character", endPosition);
+        oRange.select();
+    } else if (textArea.setSelectionRange) {
+        textArea.focus();
+        textArea.setSelectionRange(beginPosition, endPosition);
+    }
+}
+
+function scrollToText(textAreaId, position, charWidth, charHeight) {
+    // This is all guesswork, there is no realiable way to do this
+    var ta = jQuery(textAreaId);
+    var scroll = {
+          taWidthCenter : Math.floor(ta.innerWidth()/2.0),
+          taHeightCenter : Math.floor(ta.innerHeight()/2.0),
+          taNumRows : Math.floor(ta.innerHeight()/(charHeight-3)),
+          taCharsInRow : Math.floor(ta.innerWidth()/(charWidth-4)),
+          taHeight : ta.innerHeight(),
+          taWidth : ta.innerWidth()
+    };
+
+    var btxt = ta.val().substr(0, position);
+    if (btxt && btxt.length > 1) {
+        var regex = new RegExp(".{1,"+scroll.taCharsInRow+"}|\n(?=\n)", "g");
+        var gap = (btxt.match(regex).length) * scroll.taNumRows;
+        if (gap > scroll.taHeight) {
+            ta.scrollTop((gap-scroll.taHeightCenter));
+        } else {
+            ta.scrollTop(0);
+        }
+    }
+}




More information about the seam-commits mailing list