From 98222cf7ebd0bc50b3ceeede626baa62d0fb1032 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Wed, 21 Aug 2024 14:32:44 -0600 Subject: [PATCH 01/20] bump logback --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f601b03a30..21338e826c 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ ch.qos.logback logback-classic - 1.1.3 + 1.5.7 @@ -695,4 +695,4 @@ https://maven.pkg.github.com/WildbookOrg/Wildbook - \ No newline at end of file + From f9087676220ddd75d954c488e42e5107ee8ff8a5 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Wed, 21 Aug 2024 14:52:51 -0600 Subject: [PATCH 02/20] version change for rabbitmq lib --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f601b03a30..166502244a 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ com.rabbitmq amqp-client - 5.1.2 + 5.21.0 @@ -695,4 +695,4 @@ https://maven.pkg.github.com/WildbookOrg/Wildbook - \ No newline at end of file + From fc03c5ac18801c501b68aca8d52561ff14a76321 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Wed, 21 Aug 2024 15:44:40 -0600 Subject: [PATCH 03/20] fast-forward to 11 years into the future of json! --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ebcec5535a..f36c2b1d74 100644 --- a/pom.xml +++ b/pom.xml @@ -269,7 +269,7 @@ org.json json - 20131018 + 20240303 " + locP + " extract to " + dirP); - return YouTube.extractFrames(locP.toFile(), dirP.toFile()); + throw new IOException("deprecated"); } // returns success (frames extracted) -- passed in parent/_original MA ... maybe later we would want to also allow _video child option? TODO @@ -335,7 +312,7 @@ private static MediaAsset _createFrameChild(Shepherd myShepherd, MediaAsset pare } JSONObject sp = astore.createParameters(f); sp.put("key", parent.getUUID() + "/" + f.getName()); - sp.put("extractFPS", YouTube.EXTRACT_FPS); + //sp.put("extractFPS", YouTube.EXTRACT_FPS); sp.put("extractOffset", offset); MediaAsset kid = new MediaAsset(astore, sp); kid.copyIn(f); @@ -352,11 +329,13 @@ public MediaAssetMetadata extractMetadata(MediaAsset ma, boolean minimal) JSONObject data = new JSONObject(); // we (attempt to) let the basic stuff finish synchronously, so we have a populated data chunk to save (hopefully)before the detailed one does +/* deprecated due to issue 622, retirement of YouTube agent try { data.put("basic", YouTube.simpleInfo(idFromParameters(ma.getParameters()))); } catch (Exception ex) { System.out.println(ma + " failed simpleInfo(): " + ex.toString()); } +*/ if (!minimal) { data.put("detailed", new JSONObject("{\"_processing\": true, \"timestamp\": " + diff --git a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java index 7dc94f7820..338cbb55e2 100644 --- a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java +++ b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java @@ -306,71 +306,7 @@ public static void executeEmails(Shepherd myShepherd, HttpServletRequest request } private void youTubePostback(Encounter enc2add, Shepherd myShepherd, String context) { - /* - * START YouTube PostBack check - * - */ - try { - System.out.println("In IndividualAddEncounter trying to fire YouTube.."); - if (enc2add.getOccurrenceID() != null) { - if (myShepherd.isOccurrence(enc2add.getOccurrenceID())) { - System.out.println("...In IndividualAddEncounter found an occurrence.."); - Occurrence occur = myShepherd.getOccurrence(enc2add.getOccurrenceID()); - // TBD-support more than just en language - - // determine language for response - String ytRemarks = enc2add.getOccurrenceRemarks().trim().toLowerCase(); - int commentEnd = ytRemarks.indexOf("from youtube video:"); - if (commentEnd > 0) { - ytRemarks = ytRemarks.substring(commentEnd); - } - String detectedLanguage = "en"; - try { - detectedLanguage = DetectTranslate.detectLanguage(ytRemarks); - if (!detectedLanguage.toLowerCase().startsWith("en")) { - ytRemarks = DetectTranslate.translateToEnglish(ytRemarks); - } - if (detectedLanguage.startsWith("es")) { detectedLanguage = "es"; } else { - detectedLanguage = "en"; - } - } catch (Exception e) { - System.out.println("I hit an exception trying to detect language."); - e.printStackTrace(); - } - // end determine language for response - - Properties ytProps = null; - try { - ytProps = ShepherdProperties.getProperties("quest.properties", - detectedLanguage); - } catch (NullPointerException npe) { - System.out.println( - "Exception: Could not find quest.properties for langCode=" + - detectedLanguage + ". Falling back to en."); - } - if (ytProps == null) { - try { - ytProps = ShepherdProperties.getProperties("quest.properties", "en"); - } catch (NullPointerException npe2) { - System.out.println( - "Exception: Could not find quest.properties for en."); - } - } - if (ytProps != null) { - String message = ytProps.getProperty("individualAddEncounter").replaceAll( - "%INDIVIDUAL%", enc2add.getIndividualID()); - System.out.println( - "Will post back to YouTube OP this message if appropriate: " + message); - YouTube.postOccurrenceMessageToYouTubeIfAppropriate(message, occur, - myShepherd, context); - } - } - } - } catch (Exception e) { e.printStackTrace(); } - /* - * END YouTube PostBack check - * - */ + System.out.println("youTubePostback(): YouTube agent support has been deprecated"); } private void setDateLastModified(Encounter enc) { From c08e6215cd27f0fe12d02324ebbbfac82b46637f Mon Sep 17 00:00:00 2001 From: Tanya Date: Mon, 26 Aug 2024 14:37:58 -0700 Subject: [PATCH 06/20] outdated files; deleting the cruft --- src/main/resources/bundles/awsec2.properties | 2 -- src/main/resources/bundles/ec2.properties | 14 -------------- 2 files changed, 16 deletions(-) delete mode 100755 src/main/resources/bundles/awsec2.properties delete mode 100755 src/main/resources/bundles/ec2.properties diff --git a/src/main/resources/bundles/awsec2.properties b/src/main/resources/bundles/awsec2.properties deleted file mode 100755 index 201b186078..0000000000 --- a/src/main/resources/bundles/awsec2.properties +++ /dev/null @@ -1,2 +0,0 @@ -accessKey = CHANGEME -secretKey = CHANGEME \ No newline at end of file diff --git a/src/main/resources/bundles/ec2.properties b/src/main/resources/bundles/ec2.properties deleted file mode 100755 index 557ab1400c..0000000000 --- a/src/main/resources/bundles/ec2.properties +++ /dev/null @@ -1,14 +0,0 @@ -#Amazon EC2 properies for whaleshark.org - -endpoint = ec2.us-west-2.amazonaws.com -credentialsFileFullPath = PATH_TO_awsec2.properties -amiID = myAMI_ID -instanceType = c3.2xlarge -keyName = KEY_NAME_NEEDED - -#nodes from the regular on-demand -maxInstances = 1 - -#nodes from the spot market -spotInstanceBidPrice = 0.35 -maxSpotInstances = 1 \ No newline at end of file From 9cba0e6707c8454497363832a84a49f682a8d379 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 15:51:13 -0600 Subject: [PATCH 07/20] long overdue utility method --- src/main/java/org/ecocean/Util.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/ecocean/Util.java b/src/main/java/org/ecocean/Util.java index c74e1696e7..a74b2cb9fb 100644 --- a/src/main/java/org/ecocean/Util.java +++ b/src/main/java/org/ecocean/Util.java @@ -826,6 +826,9 @@ public static boolean stringExists(String str) { return (str != null && !str.trim().equals("") && !str.toLowerCase().equals("none") && !str.toLowerCase().equals("unknown")); } + public static boolean stringIsEmptyOrNull(String str) { + return ((str == null) || str.equals("")); + } public static boolean stringsEqualish(String s1, String s2) { if (!stringExists(s1)) { From 3eaa89fca58b7ccb9ab70e58efcb3518a844eba2 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 15:51:35 -0600 Subject: [PATCH 08/20] drop stanford NLP for simple utility --- src/main/java/org/ecocean/servlet/ProjectCreate.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/ecocean/servlet/ProjectCreate.java b/src/main/java/org/ecocean/servlet/ProjectCreate.java index 6ac6174e0b..18826b9c2f 100644 --- a/src/main/java/org/ecocean/servlet/ProjectCreate.java +++ b/src/main/java/org/ecocean/servlet/ProjectCreate.java @@ -9,8 +9,6 @@ import javax.servlet.ServletException; import org.json.JSONObject; -import edu.stanford.nlp.util.StringUtils; - import org.json.JSONArray; import org.json.JSONException; @@ -116,7 +114,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) if (projectUserIds != null && projectUserIds.length() > 0) { for (int i = 0; i < projectUserIds.length(); i++) { String userIdentifier = projectUserIds.getString(i); - if (!StringUtils.isNullOrEmpty(userIdentifier)) { + if (!Util.stringIsEmptyOrNull(userIdentifier)) { User user = null; if (Util.isUUID(userIdentifier)) { user = myShepherd.getUserByUUID(userIdentifier); From d0d3286e9d5448ca0f893919906d882f20657306 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 16:13:27 -0600 Subject: [PATCH 09/20] remove SUTime cruft (continued?") --- .../org/ecocean/servlet/SUTimeServlet.java | 246 - src/main/webapp/WEB-INF/web.xml | 14 - src/main/webapp/sutime/calendarview.css | 82 - src/main/webapp/sutime/calendarview.js | 839 ---- src/main/webapp/sutime/prototype.js | 4221 ----------------- src/main/webapp/sutime/su-footer.jsp | 7 - src/main/webapp/sutime/su-header.jsp | 142 - src/main/webapp/sutime/sutime.css | 25 - 8 files changed, 5576 deletions(-) delete mode 100644 src/main/java/org/ecocean/servlet/SUTimeServlet.java delete mode 100644 src/main/webapp/sutime/calendarview.css delete mode 100644 src/main/webapp/sutime/calendarview.js delete mode 100644 src/main/webapp/sutime/prototype.js delete mode 100644 src/main/webapp/sutime/su-footer.jsp delete mode 100644 src/main/webapp/sutime/su-header.jsp delete mode 100644 src/main/webapp/sutime/sutime.css diff --git a/src/main/java/org/ecocean/servlet/SUTimeServlet.java b/src/main/java/org/ecocean/servlet/SUTimeServlet.java deleted file mode 100644 index 3d584ec787..0000000000 --- a/src/main/java/org/ecocean/servlet/SUTimeServlet.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.ecocean.servlet; - -import javax.servlet.*; -import javax.servlet.http.*; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import edu.stanford.nlp.ling.CoreAnnotations; -import edu.stanford.nlp.ling.CoreLabel; -import edu.stanford.nlp.pipeline.Annotation; -import edu.stanford.nlp.pipeline.Annotator; -import edu.stanford.nlp.time.Options; -import edu.stanford.nlp.time.TimeAnnotations; -import edu.stanford.nlp.time.Timex; -import edu.stanford.nlp.util.CoreMap; - -import edu.stanford.nlp.util.StringUtils; -import org.apache.commons.lang3.StringEscapeUtils; - -public class SUTimeServlet extends HttpServlet { - private SUTimePipeline pipeline; // = null; - - @Override public void init() - throws ServletException { - String dataDir = getServletContext().getRealPath("/WEB-INF/data"); - String taggerFilename = dataDir + "/english-left3words-distsim.tagger"; - Properties pipelineProps = new Properties(); - - pipelineProps.setProperty("pos.model", taggerFilename); - pipeline = new SUTimePipeline(pipelineProps); - System.setProperty("de.jollyday.config", - getServletContext().getRealPath("/WEB-INF/classes/holidays/jollyday.properties")); - } - - public static boolean parseBoolean(String value) { - if (StringUtils.isNullOrEmpty(value)) { - return false; - } - if (value.equalsIgnoreCase("on")) { - return true; - } - return Boolean.parseBoolean(value); - } - - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - if (request.getCharacterEncoding() == null) { - request.setCharacterEncoding("utf-8"); - } - response.setContentType("text/html; charset=UTF-8"); - - this.getServletContext().getRequestDispatcher("/sutime/su-header.jsp").include(request, - response); - addResults(request, response); - this.getServletContext().getRequestDispatcher("/sutime/su-footer.jsp").include(request, - response); - } - - @Override public void doPost(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - doGet(request, response); - } - - private String getRuleFilepaths(String... files) { - String rulesDir = getServletContext().getRealPath("/WEB-INF/data/sutime/rules"); - StringBuilder sb = new StringBuilder(); - - for (String file : files) { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(rulesDir + "/" + file); - } - return sb.toString(); - } - - private Properties getTimeAnnotatorProperties(HttpServletRequest request) { - // Parses request and set up properties for time annotators - boolean markTimeRanges = parseBoolean(request.getParameter("markTimeRanges")); - boolean includeNested = parseBoolean(request.getParameter("includeNested")); - boolean includeRange = parseBoolean(request.getParameter("includeRange")); - boolean readRules = true; - String heuristicLevel = request.getParameter("relativeHeuristicLevel"); - - Options.RelativeHeuristicLevel relativeHeuristicLevel = Options.RelativeHeuristicLevel.NONE; - if (!StringUtils.isNullOrEmpty(heuristicLevel)) { - relativeHeuristicLevel = Options.RelativeHeuristicLevel.valueOf(heuristicLevel); - } - String ruleFile = null; - if (readRules) { - String rules = request.getParameter("rules"); - if ("English".equalsIgnoreCase(rules)) { - ruleFile = getRuleFilepaths("defs.sutime.txt", "english.sutime.txt", - "english.holidays.sutime.txt"); - } - } - // Create properties - Properties props = new Properties(); - if (markTimeRanges) { - props.setProperty("sutime.markTimeRanges", "true"); - } - if (includeNested) { - props.setProperty("sutime.includeNested", "true"); - } - if (includeRange) { - props.setProperty("sutime.includeRange", "true"); - } - if (ruleFile != null) { - props.setProperty("sutime.rules", ruleFile); - props.setProperty("sutime.binders", "1"); - props.setProperty("sutime.binder.1", "edu.stanford.nlp.time.JollyDayHolidays"); - props.setProperty("sutime.binder.1.xml", - getServletContext().getRealPath("/WEB-INF/data/holidays/Holidays_sutime.xml")); - props.setProperty("sutime.binder.1.pathtype", "file"); - } - props.setProperty("sutime.teRelHeurLevel", relativeHeuristicLevel.toString()); -// props.setProperty("sutime.verbose", "true"); - -// props.setProperty("heideltime.path", getServletContext().getRealPath("/packages/heideltime")); -// props.setProperty("gutime.path", getServletContext().getRealPath("/packages/gutime")); - return props; - } - - private static void displayAnnotation(PrintWriter out, String query, Annotation anno, - boolean includeOffsets) { - List timexAnns = anno.get(TimeAnnotations.TimexAnnotations.class); - List pieces = new ArrayList<>(); - List tagged = new ArrayList<>(); - int previousEnd = 0; - - for (CoreMap timexAnn : timexAnns) { - int begin = timexAnn.get(CoreAnnotations.CharacterOffsetBeginAnnotation.class); - int end = timexAnn.get(CoreAnnotations.CharacterOffsetEndAnnotation.class); - if (begin >= previousEnd) { - pieces.add(query.substring(previousEnd, begin)); - tagged.add(false); - pieces.add(query.substring(begin, end)); - tagged.add(true); - previousEnd = end; - } - } - if (previousEnd < query.length()) { - pieces.add(query.substring(previousEnd)); - tagged.add(false); - } - out.println("
"); - for (int i = 0; i < pieces.size(); ++i) { - if (tagged.get(i)) { - out.print(""); - out.print(StringEscapeUtils.escapeHtml4(pieces.get(i))); - out.print(""); - } else { - out.print(StringEscapeUtils.escapeHtml4(pieces.get(i))); - } - } - out.println("
"); - - out.println("

Temporal Expressions

"); - if (timexAnns.size() > 0) { - out.println(""); - out.println(""); - if (includeOffsets) { - out.println( - ""); - } - out.println(""); - for (CoreMap timexAnn : timexAnns) { - out.println(""); - Timex timex = timexAnn.get(TimeAnnotations.TimexAnnotation.class); - int begin = timexAnn.get(CoreAnnotations.CharacterOffsetBeginAnnotation.class); - int end = timexAnn.get(CoreAnnotations.CharacterOffsetEndAnnotation.class); - out.print(""); - out.print(""); - if (includeOffsets) { - out.print(""); - out.print(""); - out.print(""); - out.print(""); - } - out.print(""); - out.println(""); - } - out.println("
TextValueChar BeginChar EndToken BeginToken EndTimex3 Tag
" + StringEscapeUtils.escapeHtml4(query.substring(begin, - end)) + "" + ((timex.value() != - null) ? StringEscapeUtils.escapeHtml4(timex.value()) : "") + "" + begin + "" + end + "" + timexAnn.get(CoreAnnotations.TokenBeginAnnotation.class) + - "" + timexAnn.get(CoreAnnotations.TokenEndAnnotation.class) + - "" + StringEscapeUtils.escapeHtml4(timex.toString()) + "
"); - } else { - out.println("No temporal expressions."); - } - out.println("

POS Tags

"); - out.println("
"); - for (CoreMap sentence : anno.get(CoreAnnotations.SentencesAnnotation.class)) { - List tokens = sentence.get(CoreAnnotations.TokensAnnotation.class); - for (CoreLabel token : tokens) { - String tokenOutput = StringEscapeUtils.escapeHtml4(token.word() + "/" + - token.tag()); - out.print(tokenOutput + " "); - } - out.println("
"); - } - out.println("
"); - } - - private void addResults(HttpServletRequest request, HttpServletResponse response) - throws IOException { - // if we can't handle UTF-8, need to do something like this... - // String originalQuery = request.getParameter("q"); - // String query = WebappUtil.convertString(originalQuery); - - String query = request.getParameter("q"); - String dateString = request.getParameter("d"); - // TODO: this always returns true... - boolean dateError = !pipeline.isDateOkay(dateString); - boolean includeOffsets = parseBoolean(request.getParameter("includeOffsets")); - PrintWriter out = response.getWriter(); - - if (dateError) { - out.println("

Warning: unparseable date " + - StringEscapeUtils.escapeHtml4(dateString)); - } - if (!StringUtils.isNullOrEmpty(query)) { - Properties props = getTimeAnnotatorProperties(request); - String annotatorType = request.getParameter("annotator"); - if (annotatorType == null) { - annotatorType = "sutime"; - } - Annotator timeAnnotator = pipeline.getTimeAnnotator(annotatorType, props); - if (timeAnnotator != null) { - Annotation anno = pipeline.process(query, dateString, timeAnnotator); - out.println("

Annotated Text

(tagged using " + annotatorType + - ")"); - displayAnnotation(out, query, anno, includeOffsets); - } else { - out.println("

Error creating annotator for " + - StringEscapeUtils.escapeHtml4(annotatorType)); - } - } - } - - private static final long serialVersionUID = 1L; -} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 10f2f56a4e..85c5981d27 100755 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -336,8 +336,6 @@ /OccurrenceSearchExportMetadataExcel = authc, roles[researcher] /OccurrenceSearchExportGtm = authc, roles[researcher] - /SUTimeServlet = authc, roles[admin] - #lockdown Keyword handling /appadmin/kwAdmin.jsp = authc, roles[admin] /KeywordHandler = authc, roles[admin] @@ -1864,18 +1862,6 @@ /TranslationsGet - - - SUTimeServlet - org.ecocean.servlet.SUTimeServlet - - - - SUTimeServlet - /SUTimeServlet - - - OccurrenceSearchExportGtm /OccurrenceSearchExportGtm diff --git a/src/main/webapp/sutime/calendarview.css b/src/main/webapp/sutime/calendarview.css deleted file mode 100644 index 9e2c90455e..0000000000 --- a/src/main/webapp/sutime/calendarview.css +++ /dev/null @@ -1,82 +0,0 @@ - -div.calendar -{ - font-size: smaller; - color: #000; -} - -div.calendar.popup -{ - margin-left: -40px; - margin-top: -100px; -} - -div.calendar table -{ - background-color: #eee; - border: 1px solid #aaa; - border-collapse: collapse; -} - -div.calendar thead { - background-color: white; -} - -div.calendar td, -div.calendar th -{ - padding: 3px; - text-align: center; -} - -div.calendar td.title -{ - font-weight: bold; -} - -div.calendar th -{ - background: #ddd; - border-bottom: 1px solid #ccc; - border-top: 1px solid #ccc; - font-weight: bold; - color: #555; -} - -div.calendar tr.days td { - width: 2em; - color: #555; - text-align: center; - cursor: pointer; -} - -div.calendar tr.days td:hover, -div.calendar td.button:hover -{ - background-color: #34ABFA; - cursor: pointer; -} - -div.calendar tr.days td:active -div.calendar td.button:active -{ - background-color: #cde; -} - -div.calendar tr.days td.selected -{ - font-weight: bold; - background-color: #fff; - color: #000; -} - -div.calendar tr.days td.today -{ - font-weight: bold; - color: #D50000; -} - -div.calendar tr.days td.otherDay -{ - color: #bbb; -} diff --git a/src/main/webapp/sutime/calendarview.js b/src/main/webapp/sutime/calendarview.js deleted file mode 100644 index f4be8f7581..0000000000 --- a/src/main/webapp/sutime/calendarview.js +++ /dev/null @@ -1,839 +0,0 @@ -// -// CalendarView (for Prototype) -// calendarview.org -// -// Maintained by Justin Mecham -// -// Portions Copyright 2002-2005 Mihai Bazon -// -// This calendar is based very loosely on the Dynarch Calendar in that it was -// used as a base, but completely gutted and more or less rewritten in place -// to use the Prototype JavaScript library. -// -// As such, CalendarView is licensed under the terms of the GNU Lesser General -// Public License (LGPL). More information on the Dynarch Calendar can be -// found at: -// -// www.dynarch.com/projects/calendar -// - -var Calendar = Class.create() - -//------------------------------------------------------------------------------ -// Constants -//------------------------------------------------------------------------------ - -Calendar.VERSION = '1.2' - -Calendar.DAY_NAMES = new Array( - 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', - 'Sunday' -) - -Calendar.SHORT_DAY_NAMES = new Array( - 'S', 'M', 'T', 'W', 'T', 'F', 'S', 'S' -) - -Calendar.MONTH_NAMES = new Array( - 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', - 'September', 'October', 'November', 'December' -) - -Calendar.SHORT_MONTH_NAMES = new Array( - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', - 'Dec' -) - -Calendar.NAV_PREVIOUS_YEAR = -2 -Calendar.NAV_PREVIOUS_MONTH = -1 -Calendar.NAV_TODAY = 0 -Calendar.NAV_NEXT_MONTH = 1 -Calendar.NAV_NEXT_YEAR = 2 - -//------------------------------------------------------------------------------ -// Static Methods -//------------------------------------------------------------------------------ - -// This gets called when the user presses a mouse button anywhere in the -// document, if the calendar is shown. If the click was outside the open -// calendar this function closes it. -Calendar._checkCalendar = function(event) { - if (!window._popupCalendar) - return false - if (Element.descendantOf(Event.element(event), window._popupCalendar.container)) - return - window._popupCalendar.callCloseHandler() - return Event.stop(event) -} - -//------------------------------------------------------------------------------ -// Event Handlers -//------------------------------------------------------------------------------ - -Calendar.handleMouseDownEvent = function(event) -{ - Event.observe(document, 'mouseup', Calendar.handleMouseUpEvent) - Event.stop(event) -} - -// XXX I am not happy with how clicks of different actions are handled. Need to -// clean this up! -Calendar.handleMouseUpEvent = function(event) -{ - var el = Event.element(event) - var calendar = el.calendar - var isNewDate = false - - // If the element that was clicked on does not have an associated Calendar - // object, return as we have nothing to do. - if (!calendar) return false - - // Clicked on a day - if (typeof el.navAction == 'undefined') - { - if (calendar.currentDateElement) { - Element.removeClassName(calendar.currentDateElement, 'selected') - Element.addClassName(el, 'selected') - calendar.shouldClose = (calendar.currentDateElement == el) - if (!calendar.shouldClose) calendar.currentDateElement = el - } - calendar.date.setDateOnly(el.date) - isNewDate = true - calendar.shouldClose = !el.hasClassName('otherDay') - var isOtherMonth = !calendar.shouldClose - if (isOtherMonth) calendar.update(calendar.date) - } - - // Clicked on an action button - else - { - var date = new Date(calendar.date) - - if (el.navAction == Calendar.NAV_TODAY) - date.setDateOnly(new Date()) - - var year = date.getFullYear() - var mon = date.getMonth() - function setMonth(m) { - var day = date.getDate() - var max = date.getMonthDays(m) - if (day > max) date.setDate(max) - date.setMonth(m) - } - switch (el.navAction) { - - // Previous Year - case Calendar.NAV_PREVIOUS_YEAR: - if (year > calendar.minYear) - date.setFullYear(year - 1) - break - - // Previous Month - case Calendar.NAV_PREVIOUS_MONTH: - if (mon > 0) { - setMonth(mon - 1) - } - else if (year-- > calendar.minYear) { - date.setFullYear(year) - setMonth(11) - } - break - - // Today - case Calendar.NAV_TODAY: - break - - // Next Month - case Calendar.NAV_NEXT_MONTH: - if (mon < 11) { - setMonth(mon + 1) - } - else if (year < calendar.maxYear) { - date.setFullYear(year + 1) - setMonth(0) - } - break - - // Next Year - case Calendar.NAV_NEXT_YEAR: - if (year < calendar.maxYear) - date.setFullYear(year + 1) - break - - } - - if (!date.equalsTo(calendar.date)) { - calendar.setDate(date) - isNewDate = true - } else if (el.navAction == 0) { - isNewDate = (calendar.shouldClose = true) - } - } - - if (isNewDate) event && calendar.callSelectHandler() - if (calendar.shouldClose) event && calendar.callCloseHandler() - - Event.stopObserving(document, 'mouseup', Calendar.handleMouseUpEvent) - - return Event.stop(event) -} - -Calendar.defaultSelectHandler = function(calendar) -{ - if (!calendar.dateField) return false - - // Update dateField value - if (calendar.dateField.tagName == 'DIV') - Element.update(calendar.dateField, calendar.date.print(calendar.dateFormat)) - else if (calendar.dateField.tagName == 'INPUT') { - calendar.dateField.value = calendar.date.print(calendar.dateFormat) } - - // Trigger the onchange callback on the dateField, if one has been defined - if (typeof calendar.dateField.onchange == 'function') - calendar.dateField.onchange() - - // Call the close handler, if necessary - if (calendar.shouldClose) calendar.callCloseHandler() -} - -Calendar.defaultCloseHandler = function(calendar) -{ - calendar.hide() -} - - -//------------------------------------------------------------------------------ -// Calendar Setup -//------------------------------------------------------------------------------ - -Calendar.setup = function(params) -{ - - function param_default(name, def) { - if (!params[name]) params[name] = def - } - - param_default('dateField', null) - param_default('triggerElement', null) - param_default('parentElement', null) - param_default('selectHandler', null) - param_default('closeHandler', null) - - // In-Page Calendar - if (params.parentElement) - { - var calendar = new Calendar(params.parentElement) - calendar.setSelectHandler(params.selectHandler || Calendar.defaultSelectHandler) - if (params.dateFormat) - calendar.setDateFormat(params.dateFormat) - if (params.dateField) { - calendar.setDateField(params.dateField) - calendar.parseDate(calendar.dateField.innerHTML || calendar.dateField.value) - } - calendar.show() - return calendar - } - - // Popup Calendars - // - // XXX There is significant optimization to be had here by creating the - // calendar and storing it on the page, but then you will have issues with - // multiple calendars on the same page. - else - { - var triggerElement = $(params.triggerElement || params.dateField) - triggerElement.onclick = function() { - var calendar = new Calendar() - calendar.setSelectHandler(params.selectHandler || Calendar.defaultSelectHandler) - calendar.setCloseHandler(params.closeHandler || Calendar.defaultCloseHandler) - if (params.dateFormat) - calendar.setDateFormat(params.dateFormat) - if (params.dateField) { - calendar.setDateField(params.dateField) - calendar.parseDate(calendar.dateField.innerHTML || calendar.dateField.value) - } - if (params.dateField) - Date.parseDate(calendar.dateField.value || calendar.dateField.innerHTML, calendar.dateFormat) - calendar.showAtElement(triggerElement) - return calendar - } - } - -} - - - -//------------------------------------------------------------------------------ -// Calendar Instance -//------------------------------------------------------------------------------ - -Calendar.prototype = { - - // The HTML Container Element - container: null, - - // Callbacks - selectHandler: null, - closeHandler: null, - - // Configuration - minYear: 1900, - maxYear: 2100, - dateFormat: '%Y-%m-%d', - - // Dates - date: new Date(), - currentDateElement: null, - - // Status - shouldClose: false, - isPopup: true, - - dateField: null, - - - //---------------------------------------------------------------------------- - // Initialize - //---------------------------------------------------------------------------- - - initialize: function(parent) - { - if (parent) - this.create($(parent)) - else - this.create() - }, - - - - //---------------------------------------------------------------------------- - // Update / (Re)initialize Calendar - //---------------------------------------------------------------------------- - - update: function(date) - { - var calendar = this - var today = new Date() - var thisYear = today.getFullYear() - var thisMonth = today.getMonth() - var thisDay = today.getDate() - var month = date.getMonth(); - var dayOfMonth = date.getDate(); - - // Ensure date is within the defined range - if (date.getFullYear() < this.minYear) - date.setFullYear(this.minYear) - else if (date.getFullYear() > this.maxYear) - date.setFullYear(this.maxYear) - - this.date = new Date(date) - - // Calculate the first day to display (including the previous month) - date.setDate(1) - date.setDate(-(date.getDay()) + 1) - - // Fill in the days of the month - Element.getElementsBySelector(this.container, 'tbody tr').each( - function(row, i) { - var rowHasDays = false - row.immediateDescendants().each( - function(cell, j) { - var day = date.getDate() - var dayOfWeek = date.getDay() - var isCurrentMonth = (date.getMonth() == month) - - // Reset classes on the cell - cell.className = '' - cell.date = new Date(date) - cell.update(day) - - // Account for days of the month other than the current month - if (!isCurrentMonth) - cell.addClassName('otherDay') - else - rowHasDays = true - - // Ensure the current day is selected - if (isCurrentMonth && day == dayOfMonth) { - cell.addClassName('selected') - calendar.currentDateElement = cell - } - - // Today - if (date.getFullYear() == thisYear && date.getMonth() == thisMonth && day == thisDay) - cell.addClassName('today') - - // Weekend - if ([0, 6].indexOf(dayOfWeek) != -1) - cell.addClassName('weekend') - - // Set the date to tommorrow - date.setDate(day + 1) - } - ) - // Hide the extra row if it contains only days from another month - !rowHasDays ? row.hide() : row.show() - } - ) - - this.container.getElementsBySelector('td.title')[0].update( - Calendar.MONTH_NAMES[month] + ' ' + this.date.getFullYear() - ) - }, - - - - //---------------------------------------------------------------------------- - // Create/Draw the Calendar HTML Elements - //---------------------------------------------------------------------------- - - create: function(parent) - { - - // If no parent was specified, assume that we are creating a popup calendar. - if (!parent) { - parent = document.getElementsByTagName('body')[0] - this.isPopup = true - } else { - this.isPopup = false - } - - // Calendar Table - var table = new Element('table') - - // Calendar Header - var thead = new Element('thead') - table.appendChild(thead) - - // Title Placeholder - var row = new Element('tr') - var cell = new Element('td', { colSpan: 7 } ) - cell.addClassName('title') - row.appendChild(cell) - thead.appendChild(row) - - // Calendar Navigation - row = new Element('tr') - this._drawButtonCell(row, '«', 1, Calendar.NAV_PREVIOUS_YEAR) - this._drawButtonCell(row, '‹', 1, Calendar.NAV_PREVIOUS_MONTH) - this._drawButtonCell(row, 'Today', 3, Calendar.NAV_TODAY) - this._drawButtonCell(row, '›', 1, Calendar.NAV_NEXT_MONTH) - this._drawButtonCell(row, '»', 1, Calendar.NAV_NEXT_YEAR) - thead.appendChild(row) - - // Day Names - row = new Element('tr') - for (var i = 0; i < 7; ++i) { - cell = new Element('th').update(Calendar.SHORT_DAY_NAMES[i]) - if (i == 0 || i == 6) - cell.addClassName('weekend') - row.appendChild(cell) - } - thead.appendChild(row) - - // Calendar Days - var tbody = table.appendChild(new Element('tbody')) - for (i = 6; i > 0; --i) { - row = tbody.appendChild(new Element('tr')) - row.addClassName('days') - for (var j = 7; j > 0; --j) { - cell = row.appendChild(new Element('td')) - cell.calendar = this - } - } - - // Calendar Container (div) - this.container = new Element('div') - this.container.addClassName('calendar') - if (this.isPopup) { - this.container.setStyle({ position: 'absolute', display: 'none' }) - this.container.addClassName('popup') - } - this.container.appendChild(table) - - // Initialize Calendar - this.update(this.date) - - // Observe the container for mousedown events - Event.observe(this.container, 'mousedown', Calendar.handleMouseDownEvent) - - // Append to parent element - parent.appendChild(this.container) - - }, - - _drawButtonCell: function(parent, text, colSpan, navAction) - { - var cell = new Element('td') - if (colSpan > 1) cell.colSpan = colSpan - cell.className = 'button' - cell.calendar = this - cell.navAction = navAction - cell.innerHTML = text - cell.unselectable = 'on' // IE - parent.appendChild(cell) - return cell - }, - - - - //------------------------------------------------------------------------------ - // Callbacks - //------------------------------------------------------------------------------ - - // Calls the Select Handler (if defined) - callSelectHandler: function() - { - if (this.selectHandler) - this.selectHandler(this, this.date.print(this.dateFormat)) - }, - - // Calls the Close Handler (if defined) - callCloseHandler: function() - { - if (this.closeHandler) - this.closeHandler(this) - }, - - - - //------------------------------------------------------------------------------ - // Calendar Display Functions - //------------------------------------------------------------------------------ - - // Shows the Calendar - show: function() - { - this.container.show() - if (this.isPopup) { - window._popupCalendar = this - Event.observe(document, 'mousedown', Calendar._checkCalendar) - } - }, - - // Shows the calendar at the given absolute position - showAt: function (x, y) - { - this.container.setStyle({ left: x + 'px', top: y + 'px' }) - this.show() - }, - - // Shows the Calendar at the coordinates of the provided element - showAtElement: function(element) - { - var pos = Position.cumulativeOffset(element) - this.showAt(pos[0], pos[1]) - }, - - // Hides the Calendar - hide: function() - { - if (this.isPopup) - Event.stopObserving(document, 'mousedown', Calendar._checkCalendar) - this.container.hide() - }, - - - - //------------------------------------------------------------------------------ - // Miscellaneous - //------------------------------------------------------------------------------ - - // Tries to identify the date represented in a string. If successful it also - // calls this.setDate which moves the calendar to the given date. - parseDate: function(str, format) - { - if (!format) - format = this.dateFormat - this.setDate(Date.parseDate(str, format)) - }, - - - - //------------------------------------------------------------------------------ - // Getters/Setters - //------------------------------------------------------------------------------ - - setSelectHandler: function(selectHandler) - { - this.selectHandler = selectHandler - }, - - setCloseHandler: function(closeHandler) - { - this.closeHandler = closeHandler - }, - - setDate: function(date) - { - if (!date.equalsTo(this.date)) - this.update(date) - }, - - setDateFormat: function(format) - { - this.dateFormat = format - }, - - setDateField: function(field) - { - this.dateField = $(field) - }, - - setRange: function(minYear, maxYear) - { - this.minYear = minYear - this.maxYear = maxYear - } - -} - -// global object that remembers the calendar -window._popupCalendar = null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//============================================================================== -// -// Date Object Patches -// -// This is pretty much untouched from the original. I really would like to get -// rid of these patches if at all possible and find a cleaner way of -// accomplishing the same things. It's a shame Prototype doesn't extend Date at -// all. -// -//============================================================================== - -Date.DAYS_IN_MONTH = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) -Date.SECOND = 1000 /* milliseconds */ -Date.MINUTE = 60 * Date.SECOND -Date.HOUR = 60 * Date.MINUTE -Date.DAY = 24 * Date.HOUR -Date.WEEK = 7 * Date.DAY - -// Parses Date -Date.parseDate = function(str, fmt) { - var today = new Date(); - var y = 0; - var m = -1; - var d = 0; - var a = str.split(/\W+/); - var b = fmt.match(/%./g); - var i = 0, j = 0; - var hr = 0; - var min = 0; - - for (i = 0; i < a.length; ++i) { - if (!a[i]) continue; - switch (b[i]) { - case "%d": - case "%e": - d = parseInt(a[i], 10); - break; - case "%m": - m = parseInt(a[i], 10) - 1; - break; - case "%Y": - case "%y": - y = parseInt(a[i], 10); - (y < 100) && (y += (y > 29) ? 1900 : 2000); - break; - case "%b": - case "%B": - for (j = 0; j < 12; ++j) { - if (Calendar.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { - m = j; - break; - } - } - break; - case "%H": - case "%I": - case "%k": - case "%l": - hr = parseInt(a[i], 10); - break; - case "%P": - case "%p": - if (/pm/i.test(a[i]) && hr < 12) - hr += 12; - else if (/am/i.test(a[i]) && hr >= 12) - hr -= 12; - break; - case "%M": - min = parseInt(a[i], 10); - break; - } - } - if (isNaN(y)) y = today.getFullYear(); - if (isNaN(m)) m = today.getMonth(); - if (isNaN(d)) d = today.getDate(); - if (isNaN(hr)) hr = today.getHours(); - if (isNaN(min)) min = today.getMinutes(); - if (y != 0 && m != -1 && d != 0) - return new Date(y, m, d, hr, min, 0); - y = 0; m = -1; d = 0; - for (i = 0; i < a.length; ++i) { - if (a[i].search(/[a-zA-Z]+/) != -1) { - var t = -1; - for (j = 0; j < 12; ++j) { - if (Calendar.MONTH_NAMES[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } - } - if (t != -1) { - if (m != -1) { - d = m+1; - } - m = t; - } - } else if (parseInt(a[i], 10) <= 12 && m == -1) { - m = a[i]-1; - } else if (parseInt(a[i], 10) > 31 && y == 0) { - y = parseInt(a[i], 10); - (y < 100) && (y += (y > 29) ? 1900 : 2000); - } else if (d == 0) { - d = a[i]; - } - } - if (y == 0) - y = today.getFullYear(); - if (m != -1 && d != 0) - return new Date(y, m, d, hr, min, 0); - return today; -}; - -// Returns the number of days in the current month -Date.prototype.getMonthDays = function(month) { - var year = this.getFullYear() - if (typeof month == "undefined") - month = this.getMonth() - if (((0 == (year % 4)) && ( (0 != (year % 100)) || (0 == (year % 400)))) && month == 1) - return 29 - else - return Date.DAYS_IN_MONTH[month] -}; - -// Returns the number of day in the year -Date.prototype.getDayOfYear = function() { - var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); - var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); - var time = now - then; - return Math.floor(time / Date.DAY); -}; - -/** Returns the number of the week in year, as defined in ISO 8601. */ -Date.prototype.getWeekNumber = function() { - var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); - var DoW = d.getDay(); - d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu - var ms = d.valueOf(); // GMT - d.setMonth(0); - d.setDate(4); // Thu in Week 1 - return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; -}; - -/** Checks date and time equality */ -Date.prototype.equalsTo = function(date) { - return ((this.getFullYear() == date.getFullYear()) && - (this.getMonth() == date.getMonth()) && - (this.getDate() == date.getDate()) && - (this.getHours() == date.getHours()) && - (this.getMinutes() == date.getMinutes())); -}; - -/** Set only the year, month, date parts (keep existing time) */ -Date.prototype.setDateOnly = function(date) { - var tmp = new Date(date); - this.setDate(1); - this.setFullYear(tmp.getFullYear()); - this.setMonth(tmp.getMonth()); - this.setDate(tmp.getDate()); -}; - -/** Prints the date in a string according to the given format. */ -Date.prototype.print = function (str) { - var m = this.getMonth(); - var d = this.getDate(); - var y = this.getFullYear(); - var wn = this.getWeekNumber(); - var w = this.getDay(); - var s = {}; - var hr = this.getHours(); - var pm = (hr >= 12); - var ir = (pm) ? (hr - 12) : hr; - var dy = this.getDayOfYear(); - if (ir == 0) - ir = 12; - var min = this.getMinutes(); - var sec = this.getSeconds(); - s["%a"] = Calendar.SHORT_DAY_NAMES[w]; // abbreviated weekday name [FIXME: I18N] - s["%A"] = Calendar.DAY_NAMES[w]; // full weekday name - s["%b"] = Calendar.SHORT_MONTH_NAMES[m]; // abbreviated month name [FIXME: I18N] - s["%B"] = Calendar.MONTH_NAMES[m]; // full month name - // FIXME: %c : preferred date and time representation for the current locale - s["%C"] = 1 + Math.floor(y / 100); // the century number - s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) - s["%e"] = d; // the day of the month (range 1 to 31) - // FIXME: %D : american date style: %m/%d/%y - // FIXME: %E, %F, %G, %g, %h (man strftime) - s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) - s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) - s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) - s["%k"] = hr; // hour, range 0 to 23 (24h format) - s["%l"] = ir; // hour, range 1 to 12 (12h format) - s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12 - s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 - s["%n"] = "\n"; // a newline character - s["%p"] = pm ? "PM" : "AM"; - s["%P"] = pm ? "pm" : "am"; - // FIXME: %r : the time in am/pm notation %I:%M:%S %p - // FIXME: %R : the time in 24-hour notation %H:%M - s["%s"] = Math.floor(this.getTime() / 1000); - s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 - s["%t"] = "\t"; // a tab character - // FIXME: %T : the time in 24-hour notation (%H:%M:%S) - s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; - s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON) - s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN) - // FIXME: %x : preferred date representation for the current locale without the time - // FIXME: %X : preferred time representation for the current locale without the date - s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99) - s["%Y"] = y; // year with the century - s["%%"] = "%"; // a literal '%' character - - return str.gsub(/%./, function(match) { return s[match] || match }); -}; - -Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; -Date.prototype.setFullYear = function(y) { - var d = new Date(this); - d.__msh_oldSetFullYear(y); - if (d.getMonth() != this.getMonth()) - this.setDate(28); - this.__msh_oldSetFullYear(y); -} diff --git a/src/main/webapp/sutime/prototype.js b/src/main/webapp/sutime/prototype.js deleted file mode 100644 index 6385503a1c..0000000000 --- a/src/main/webapp/sutime/prototype.js +++ /dev/null @@ -1,4221 +0,0 @@ -/* Prototype JavaScript framework, version 1.6.0.2 - * (c) 2005-2008 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://www.prototypejs.org/ - * - *--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.6.0.2', - - Browser: { - IE: !!(window.attachEvent && !window.opera), - Opera: !!window.opera, - WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, - Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, - MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) - }, - - BrowserFeatures: { - XPath: !!document.evaluate, - ElementExtensions: !!window.HTMLElement, - SpecificElementExtensions: - document.createElement('div').__proto__ && - document.createElement('div').__proto__ !== - document.createElement('form').__proto__ - }, - - ScriptFragment: ']*>([\\S\\s]*?)<\/script>', - JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, - - emptyFunction: function() { }, - K: function(x) { return x } -}; - -if (Prototype.Browser.MobileSafari) - Prototype.BrowserFeatures.SpecificElementExtensions = false; - - -/* Based on Alex Arnell's inheritance implementation. */ -var Class = { - create: function() { - var parent = null, properties = $A(arguments); - if (Object.isFunction(properties[0])) - parent = properties.shift(); - - function klass() { - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - var subclass = function() { }; - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); - } - - for (var i = 0; i < properties.length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) - klass.prototype.initialize = Prototype.emptyFunction; - - klass.prototype.constructor = klass; - - return klass; - } -}; - -Class.Methods = { - addMethods: function(source) { - var ancestor = this.superclass && this.superclass.prototype; - var properties = Object.keys(source); - - if (!Object.keys({ toString: true }).length) - properties.push("toString", "valueOf"); - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && Object.isFunction(value) && - value.argumentNames().first() == "$super") { - var method = value, value = Object.extend((function(m) { - return function() { return ancestor[m].apply(this, arguments) }; - })(property).wrap(method), { - valueOf: function() { return method }, - toString: function() { return method.toString() } - }); - } - this.prototype[property] = value; - } - - return this; - } -}; - -var Abstract = { }; - -Object.extend = function(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; -}; - -Object.extend(Object, { - inspect: function(object) { - try { - if (Object.isUndefined(object)) return 'undefined'; - if (object === null) return 'null'; - return object.inspect ? object.inspect() : String(object); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - }, - - toJSON: function(object) { - var type = typeof object; - switch (type) { - case 'undefined': - case 'function': - case 'unknown': return; - case 'boolean': return object.toString(); - } - - if (object === null) return 'null'; - if (object.toJSON) return object.toJSON(); - if (Object.isElement(object)) return; - - var results = []; - for (var property in object) { - var value = Object.toJSON(object[property]); - if (!Object.isUndefined(value)) - results.push(property.toJSON() + ': ' + value); - } - - return '{' + results.join(', ') + '}'; - }, - - toQueryString: function(object) { - return $H(object).toQueryString(); - }, - - toHTML: function(object) { - return object && object.toHTML ? object.toHTML() : String.interpret(object); - }, - - keys: function(object) { - var keys = []; - for (var property in object) - keys.push(property); - return keys; - }, - - values: function(object) { - var values = []; - for (var property in object) - values.push(object[property]); - return values; - }, - - clone: function(object) { - return Object.extend({ }, object); - }, - - isElement: function(object) { - return object && object.nodeType == 1; - }, - - isArray: function(object) { - return object != null && typeof object == "object" && - 'splice' in object && 'join' in object; - }, - - isHash: function(object) { - return object instanceof Hash; - }, - - isFunction: function(object) { - return typeof object == "function"; - }, - - isString: function(object) { - return typeof object == "string"; - }, - - isNumber: function(object) { - return typeof object == "number"; - }, - - isUndefined: function(object) { - return typeof object == "undefined"; - } -}); - -Object.extend(Function.prototype, { - argumentNames: function() { - var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip"); - return names.length == 1 && !names[0] ? [] : names; - }, - - bind: function() { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } - }, - - bindAsEventListener: function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function(event) { - return __method.apply(object, [event || window.event].concat(args)); - } - }, - - curry: function() { - if (!arguments.length) return this; - var __method = this, args = $A(arguments); - return function() { - return __method.apply(this, args.concat($A(arguments))); - } - }, - - delay: function() { - var __method = this, args = $A(arguments), timeout = args.shift() * 1000; - return window.setTimeout(function() { - return __method.apply(__method, args); - }, timeout); - }, - - wrap: function(wrapper) { - var __method = this; - return function() { - return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); - } - }, - - methodize: function() { - if (this._methodized) return this._methodized; - var __method = this; - return this._methodized = function() { - return __method.apply(null, [this].concat($A(arguments))); - }; - } -}); - -Function.prototype.defer = Function.prototype.delay.curry(0.01); - -Date.prototype.toJSON = function() { - return '"' + this.getUTCFullYear() + '-' + - (this.getUTCMonth() + 1).toPaddedString(2) + '-' + - this.getUTCDate().toPaddedString(2) + 'T' + - this.getUTCHours().toPaddedString(2) + ':' + - this.getUTCMinutes().toPaddedString(2) + ':' + - this.getUTCSeconds().toPaddedString(2) + 'Z"'; -}; - -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; - -RegExp.prototype.match = RegExp.prototype.test; - -RegExp.escape = function(str) { - return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); -}; - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create({ - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - execute: function() { - this.callback(this); - }, - - stop: function() { - if (!this.timer) return; - clearInterval(this.timer); - this.timer = null; - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.execute(); - } finally { - this.currentlyExecuting = false; - } - } - } -}); -Object.extend(String, { - interpret: function(value) { - return value == null ? '' : String(value); - }, - specialChar: { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '\\': '\\\\' - } -}); - -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { - var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); - count = Object.isUndefined(count) ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - }, - - scan: function(pattern, iterator) { - this.gsub(pattern, iterator); - return String(this); - }, - - truncate: function(length, truncation) { - length = length || 30; - truncation = Object.isUndefined(truncation) ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : String(this); - }, - - strip: function() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, - - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(function(script) { return eval(script) }); - }, - - escapeHTML: function() { - var self = arguments.callee; - self.text.data = this; - return self.div.innerHTML; - }, - - unescapeHTML: function() { - var div = new Element('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? (div.childNodes.length > 1 ? - $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : - div.childNodes[0].nodeValue) : ''; - }, - - toQueryParams: function(separator) { - var match = this.strip().match(/([^?#]*)(#.*)?$/); - if (!match) return { }; - - return match[1].split(separator || '&').inject({ }, function(hash, pair) { - if ((pair = pair.split('='))[0]) { - var key = decodeURIComponent(pair.shift()); - var value = pair.length > 1 ? pair.join('=') : pair[0]; - if (value != undefined) value = decodeURIComponent(value); - - if (key in hash) { - if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; - hash[key].push(value); - } - else hash[key] = value; - } - return hash; - }); - }, - - toArray: function() { - return this.split(''); - }, - - succ: function() { - return this.slice(0, this.length - 1) + - String.fromCharCode(this.charCodeAt(this.length - 1) + 1); - }, - - times: function(count) { - return count < 1 ? '' : new Array(count + 1).join(this); - }, - - camelize: function() { - var parts = this.split('-'), len = parts.length; - if (len == 1) return parts[0]; - - var camelized = this.charAt(0) == '-' - ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) - : parts[0]; - - for (var i = 1; i < len; i++) - camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); - - return camelized; - }, - - capitalize: function() { - return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); - }, - - underscore: function() { - return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); - }, - - dasherize: function() { - return this.gsub(/_/,'-'); - }, - - inspect: function(useDoubleQuotes) { - var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { - var character = String.specialChar[match[0]]; - return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); - }); - if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; - return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - }, - - toJSON: function() { - return this.inspect(true); - }, - - unfilterJSON: function(filter) { - return this.sub(filter || Prototype.JSONFilter, '#{1}'); - }, - - isJSON: function() { - var str = this; - if (str.blank()) return false; - str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); - return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); - }, - - evalJSON: function(sanitize) { - var json = this.unfilterJSON(); - try { - if (!sanitize || json.isJSON()) return eval('(' + json + ')'); - } catch (e) { } - throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); - }, - - include: function(pattern) { - return this.indexOf(pattern) > -1; - }, - - startsWith: function(pattern) { - return this.indexOf(pattern) === 0; - }, - - endsWith: function(pattern) { - var d = this.length - pattern.length; - return d >= 0 && this.lastIndexOf(pattern) === d; - }, - - empty: function() { - return this == ''; - }, - - blank: function() { - return /^\s*$/.test(this); - }, - - interpolate: function(object, pattern) { - return new Template(this, pattern).evaluate(object); - } -}); - -if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { - escapeHTML: function() { - return this.replace(/&/g,'&').replace(//g,'>'); - }, - unescapeHTML: function() { - return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - } -}); - -String.prototype.gsub.prepareReplacement = function(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -}; - -String.prototype.parseQuery = String.prototype.toQueryParams; - -Object.extend(String.prototype.escapeHTML, { - div: document.createElement('div'), - text: document.createTextNode('') -}); - -with (String.prototype.escapeHTML) div.appendChild(text); - -var Template = Class.create({ - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - if (Object.isFunction(object.toTemplateReplacements)) - object = object.toTemplateReplacements(); - - return this.template.gsub(this.pattern, function(match) { - if (object == null) return ''; - - var before = match[1] || ''; - if (before == '\\') return match[2]; - - var ctx = object, expr = match[3]; - var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; - match = pattern.exec(expr); - if (match == null) return before; - - while (match != null) { - var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; - ctx = ctx[comp]; - if (null == ctx || '' == match[3]) break; - expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); - match = pattern.exec(expr); - } - - return before + String.interpret(ctx); - }); - } -}); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; - -var $break = { }; - -var Enumerable = { - each: function(iterator, context) { - var index = 0; - iterator = iterator.bind(context); - try { - this._each(function(value) { - iterator(value, index++); - }); - } catch (e) { - if (e != $break) throw e; - } - return this; - }, - - eachSlice: function(number, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var index = -number, slices = [], array = this.toArray(); - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - }, - - all: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function(iterator, context) { - iterator = iterator.bind(context); - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator, context) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(filter, iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(filter); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator(value, index)); - }); - return results; - }, - - include: function(object) { - if (Object.isFunction(this.indexOf)) - if (this.indexOf(object) != -1) return true; - - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inGroupsOf: function(number, fillWith) { - fillWith = Object.isUndefined(fillWith) ? null : fillWith; - return this.eachSlice(number, function(slice) { - while(slice.length < number) slice.push(fillWith); - return slice; - }); - }, - - inject: function(memo, iterator, context) { - iterator = iterator.bind(context); - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.map(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var result; - this.each(function(value, index) { - value = iterator(value, index); - if (result == null || value < result) - result = value; - }); - return result; - }, - - partition: function(iterator, context) { - iterator = iterator ? iterator.bind(context) : Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator, context) { - iterator = iterator.bind(context); - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator, context) { - iterator = iterator.bind(context); - return this.map(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.map(); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (Object.isFunction(args.last())) - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - }, - - size: function() { - return this.toArray().length; - }, - - inspect: function() { - return '#'; - } -}; - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - filter: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray, - every: Enumerable.all, - some: Enumerable.any -}); -function $A(iterable) { - if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - -if (Prototype.Browser.WebKit) { - $A = function(iterable) { - if (!iterable) return []; - if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && - iterable.toArray) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - }; -} - -Array.from = $A; - -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0, length = this.length; i < length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(Object.isArray(value) ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - reduce: function() { - return this.length > 1 ? this : this[0]; - }, - - uniq: function(sorted) { - return this.inject([], function(array, value, index) { - if (0 == index || (sorted ? array.last() != value : !array.include(value))) - array.push(value); - return array; - }); - }, - - intersect: function(array) { - return this.uniq().findAll(function(item) { - return array.detect(function(value) { return item === value }); - }); - }, - - clone: function() { - return [].concat(this); - }, - - size: function() { - return this.length; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - }, - - toJSON: function() { - var results = []; - this.each(function(object) { - var value = Object.toJSON(object); - if (!Object.isUndefined(value)) results.push(value); - }); - return '[' + results.join(', ') + ']'; - } -}); - -// use native browser JS 1.6 implementation if available -if (Object.isFunction(Array.prototype.forEach)) - Array.prototype._each = Array.prototype.forEach; - -if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { - i || (i = 0); - var length = this.length; - if (i < 0) i = length + i; - for (; i < length; i++) - if (this[i] === item) return i; - return -1; -}; - -if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { - i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; - var n = this.slice(0, i).reverse().indexOf(item); - return (n < 0) ? n : i - n - 1; -}; - -Array.prototype.toArray = Array.prototype.clone; - -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -if (Prototype.Browser.Opera){ - Array.prototype.concat = function() { - var array = []; - for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); - for (var i = 0, length = arguments.length; i < length; i++) { - if (Object.isArray(arguments[i])) { - for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) - array.push(arguments[i][j]); - } else { - array.push(arguments[i]); - } - } - return array; - }; -} -Object.extend(Number.prototype, { - toColorPart: function() { - return this.toPaddedString(2, 16); - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - }, - - toPaddedString: function(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - }, - - toJSON: function() { - return isFinite(this) ? this.toString() : 'null'; - } -}); - -$w('abs round ceil floor').each(function(method){ - Number.prototype[method] = Math[method].methodize(); -}); -function $H(object) { - return new Hash(object); -}; - -var Hash = Class.create(Enumerable, (function() { - - function toQueryPair(key, value) { - if (Object.isUndefined(value)) return key; - return key + '=' + encodeURIComponent(String.interpret(value)); - } - - return { - initialize: function(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - }, - - _each: function(iterator) { - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - set: function(key, value) { - return this._object[key] = value; - }, - - get: function(key) { - return this._object[key]; - }, - - unset: function(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - }, - - toObject: function() { - return Object.clone(this._object); - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - index: function(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - }, - - merge: function(object) { - return this.clone().update(object); - }, - - update: function(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) - return values.map(toQueryPair.curry(key)).join('&'); - } - return toQueryPair(key, values); - }).join('&'); - }, - - inspect: function() { - return '#'; - }, - - toJSON: function() { - return Object.toJSON(this.toObject()); - }, - - clone: function() { - return new Hash(this); - } - } -})()); - -Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; -Hash.from = $H; -var ObjectRange = Class.create(Enumerable, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - while (this.include(value)) { - iterator(value); - value = value.succ(); - } - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -}; - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || false; - }, - - activeRequestCount: 0 -}; - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responder) { - if (!this.include(responder)) - this.responders.push(responder); - }, - - unregister: function(responder) { - this.responders = this.responders.without(responder); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (Object.isFunction(responder[callback])) { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) { } - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { Ajax.activeRequestCount++ }, - onComplete: function() { Ajax.activeRequestCount-- } -}); - -Ajax.Base = Class.create({ - initialize: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - encoding: 'UTF-8', - parameters: '', - evalJSON: true, - evalJS: true - }; - Object.extend(this.options, options || { }); - - this.options.method = this.options.method.toLowerCase(); - - if (Object.isString(this.options.parameters)) - this.options.parameters = this.options.parameters.toQueryParams(); - else if (Object.isHash(this.options.parameters)) - this.options.parameters = this.options.parameters.toObject(); - } -}); - -Ajax.Request = Class.create(Ajax.Base, { - _complete: false, - - initialize: function($super, url, options) { - $super(options); - this.transport = Ajax.getTransport(); - this.request(url); - }, - - request: function(url) { - this.url = url; - this.method = this.options.method; - var params = Object.clone(this.options.parameters); - - if (!['get', 'post'].include(this.method)) { - // simulate other verbs over post - params['_method'] = this.method; - this.method = 'post'; - } - - this.parameters = params; - - if (params = Object.toQueryString(params)) { - // when GET, append parameters to URL - if (this.method == 'get') - this.url += (this.url.include('?') ? '&' : '?') + params; - else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) - params += '&_='; - } - - try { - var response = new Ajax.Response(this); - if (this.options.onCreate) this.options.onCreate(response); - Ajax.Responders.dispatch('onCreate', this, response); - - this.transport.open(this.method.toUpperCase(), this.url, - this.options.asynchronous); - - if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); - - this.transport.onreadystatechange = this.onStateChange.bind(this); - this.setRequestHeaders(); - - this.body = this.method == 'post' ? (this.options.postBody || params) : null; - this.transport.send(this.body); - - /* Force Firefox to handle ready state 4 for synchronous requests */ - if (!this.options.asynchronous && this.transport.overrideMimeType) - this.onStateChange(); - - } - catch (e) { - this.dispatchException(e); - } - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState > 1 && !((readyState == 4) && this._complete)) - this.respondToReadyState(this.transport.readyState); - }, - - setRequestHeaders: function() { - var headers = { - 'X-Requested-With': 'XMLHttpRequest', - 'X-Prototype-Version': Prototype.Version, - 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' - }; - - if (this.method == 'post') { - headers['Content-type'] = this.options.contentType + - (this.options.encoding ? '; charset=' + this.options.encoding : ''); - - /* Force "Connection: close" for older Mozilla browsers to work - * around a bug where XMLHttpRequest sends an incorrect - * Content-length header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType && - (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) - headers['Connection'] = 'close'; - } - - // user-defined headers - if (typeof this.options.requestHeaders == 'object') { - var extras = this.options.requestHeaders; - - if (Object.isFunction(extras.push)) - for (var i = 0, length = extras.length; i < length; i += 2) - headers[extras[i]] = extras[i+1]; - else - $H(extras).each(function(pair) { headers[pair.key] = pair.value }); - } - - for (var name in headers) - this.transport.setRequestHeader(name, headers[name]); - }, - - success: function() { - var status = this.getStatus(); - return !status || (status >= 200 && status < 300); - }, - - getStatus: function() { - try { - return this.transport.status || 0; - } catch (e) { return 0 } - }, - - respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); - - if (state == 'Complete') { - try { - this._complete = true; - (this.options['on' + response.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - var contentType = response.getHeader('Content-type'); - if (this.options.evalJS == 'force' - || (this.options.evalJS && this.isSameOrigin() && contentType - && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) - this.evalResponse(); - } - - try { - (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); - Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - if (state == 'Complete') { - // avoid memory leak in MSIE: clean up - this.transport.onreadystatechange = Prototype.emptyFunction; - } - }, - - isSameOrigin: function() { - var m = this.url.match(/^\s*https?:\/\/[^\/]*/); - return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ - protocol: location.protocol, - domain: document.domain, - port: location.port ? ':' + location.port : '' - })); - }, - - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name) || null; - } catch (e) { return null } - }, - - evalResponse: function() { - try { - return eval((this.transport.responseText || '').unfilterJSON()); - } catch (e) { - this.dispatchException(e); - } - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Response = Class.create({ - initialize: function(request){ - this.request = request; - var transport = this.transport = request.transport, - readyState = this.readyState = transport.readyState; - - if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { - this.status = this.getStatus(); - this.statusText = this.getStatusText(); - this.responseText = String.interpret(transport.responseText); - this.headerJSON = this._getHeaderJSON(); - } - - if(readyState == 4) { - var xml = transport.responseXML; - this.responseXML = Object.isUndefined(xml) ? null : xml; - this.responseJSON = this._getResponseJSON(); - } - }, - - status: 0, - statusText: '', - - getStatus: Ajax.Request.prototype.getStatus, - - getStatusText: function() { - try { - return this.transport.statusText || ''; - } catch (e) { return '' } - }, - - getHeader: Ajax.Request.prototype.getHeader, - - getAllHeaders: function() { - try { - return this.getAllResponseHeaders(); - } catch (e) { return null } - }, - - getResponseHeader: function(name) { - return this.transport.getResponseHeader(name); - }, - - getAllResponseHeaders: function() { - return this.transport.getAllResponseHeaders(); - }, - - _getHeaderJSON: function() { - var json = this.getHeader('X-JSON'); - if (!json) return null; - json = decodeURIComponent(escape(json)); - try { - return json.evalJSON(this.request.options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - }, - - _getResponseJSON: function() { - var options = this.request.options; - if (!options.evalJSON || (options.evalJSON != 'force' && - !(this.getHeader('Content-type') || '').include('application/json')) || - this.responseText.blank()) - return null; - try { - return this.responseText.evalJSON(options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - } -}); - -Ajax.Updater = Class.create(Ajax.Request, { - initialize: function($super, container, url, options) { - this.container = { - success: (container.success || container), - failure: (container.failure || (container.success ? null : container)) - }; - - options = Object.clone(options); - var onComplete = options.onComplete; - options.onComplete = (function(response, json) { - this.updateContent(response.responseText); - if (Object.isFunction(onComplete)) onComplete(response, json); - }).bind(this); - - $super(url, options); - }, - - updateContent: function(responseText) { - var receiver = this.container[this.success() ? 'success' : 'failure'], - options = this.options; - - if (!options.evalScripts) responseText = responseText.stripScripts(); - - if (receiver = $(receiver)) { - if (options.insertion) { - if (Object.isString(options.insertion)) { - var insertion = { }; insertion[options.insertion] = responseText; - receiver.insert(insertion); - } - else options.insertion(receiver, responseText); - } - else receiver.update(responseText); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { - initialize: function($super, container, url, options) { - $super(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = { }; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.options.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(response) { - if (this.options.decay) { - this.decay = (response.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = response.responseText; - } - this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -function $(element) { - if (arguments.length > 1) { - for (var i = 0, elements = [], length = arguments.length; i < length; i++) - elements.push($(arguments[i])); - return elements; - } - if (Object.isString(element)) - element = document.getElementById(element); - return Element.extend(element); -} - -if (Prototype.BrowserFeatures.XPath) { - document._getElementsByXPath = function(expression, parentElement) { - var results = []; - var query = document.evaluate(expression, $(parentElement) || document, - null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); - for (var i = 0, length = query.snapshotLength; i < length; i++) - results.push(Element.extend(query.snapshotItem(i))); - return results; - }; -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Node) var Node = { }; - -if (!Node.ELEMENT_NODE) { - // DOM level 2 ECMAScript Language Binding - Object.extend(Node, { - ELEMENT_NODE: 1, - ATTRIBUTE_NODE: 2, - TEXT_NODE: 3, - CDATA_SECTION_NODE: 4, - ENTITY_REFERENCE_NODE: 5, - ENTITY_NODE: 6, - PROCESSING_INSTRUCTION_NODE: 7, - COMMENT_NODE: 8, - DOCUMENT_NODE: 9, - DOCUMENT_TYPE_NODE: 10, - DOCUMENT_FRAGMENT_NODE: 11, - NOTATION_NODE: 12 - }); -} - -(function() { - var element = this.Element; - this.Element = function(tagName, attributes) { - attributes = attributes || { }; - tagName = tagName.toLowerCase(); - var cache = Element.cache; - if (Prototype.Browser.IE && attributes.name) { - tagName = '<' + tagName + ' name="' + attributes.name + '">'; - delete attributes.name; - return Element.writeAttribute(document.createElement(tagName), attributes); - } - if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); - return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); - }; - Object.extend(this.Element, element || { }); -}).call(window); - -Element.cache = { }; - -Element.Methods = { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function(element) { - element = $(element); - Element[Element.visible(element) ? 'hide' : 'show'](element); - return element; - }, - - hide: function(element) { - $(element).style.display = 'none'; - return element; - }, - - show: function(element) { - $(element).style.display = ''; - return element; - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - return element; - }, - - update: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - content = Object.toHTML(content); - element.innerHTML = content.stripScripts(); - content.evalScripts.bind(content).defer(); - return element; - }, - - replace: function(element, content) { - element = $(element); - if (content && content.toElement) content = content.toElement(); - else if (!Object.isElement(content)) { - content = Object.toHTML(content); - var range = element.ownerDocument.createRange(); - range.selectNode(element); - content.evalScripts.bind(content).defer(); - content = range.createContextualFragment(content.stripScripts()); - } - element.parentNode.replaceChild(content, element); - return element; - }, - - insert: function(element, insertions) { - element = $(element); - - if (Object.isString(insertions) || Object.isNumber(insertions) || - Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) - insertions = {bottom:insertions}; - - var content, insert, tagName, childNodes; - - for (var position in insertions) { - content = insertions[position]; - position = position.toLowerCase(); - insert = Element._insertionTranslations[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - insert(element, content); - continue; - } - - content = Object.toHTML(content); - - tagName = ((position == 'before' || position == 'after') - ? element.parentNode : element).tagName.toUpperCase(); - - childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - - if (position == 'top' || position == 'after') childNodes.reverse(); - childNodes.each(insert.curry(element)); - - content.evalScripts.bind(content).defer(); - } - - return element; - }, - - wrap: function(element, wrapper, attributes) { - element = $(element); - if (Object.isElement(wrapper)) - $(wrapper).writeAttribute(attributes || { }); - else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); - else wrapper = new Element('div', wrapper); - if (element.parentNode) - element.parentNode.replaceChild(wrapper, element); - wrapper.appendChild(element); - return wrapper; - }, - - inspect: function(element) { - element = $(element); - var result = '<' + element.tagName.toLowerCase(); - $H({'id': 'id', 'className': 'class'}).each(function(pair) { - var property = pair.first(), attribute = pair.last(); - var value = (element[property] || '').toString(); - if (value) result += ' ' + attribute + '=' + value.inspect(true); - }); - return result + '>'; - }, - - recursivelyCollect: function(element, property) { - element = $(element); - var elements = []; - while (element = element[property]) - if (element.nodeType == 1) - elements.push(Element.extend(element)); - return elements; - }, - - ancestors: function(element) { - return $(element).recursivelyCollect('parentNode'); - }, - - descendants: function(element) { - return $(element).select("*"); - }, - - firstDescendant: function(element) { - element = $(element).firstChild; - while (element && element.nodeType != 1) element = element.nextSibling; - return $(element); - }, - - immediateDescendants: function(element) { - if (!(element = $(element).firstChild)) return []; - while (element && element.nodeType != 1) element = element.nextSibling; - if (element) return [element].concat($(element).nextSiblings()); - return []; - }, - - previousSiblings: function(element) { - return $(element).recursivelyCollect('previousSibling'); - }, - - nextSiblings: function(element) { - return $(element).recursivelyCollect('nextSibling'); - }, - - siblings: function(element) { - element = $(element); - return element.previousSiblings().reverse().concat(element.nextSiblings()); - }, - - match: function(element, selector) { - if (Object.isString(selector)) - selector = new Selector(selector); - return selector.match($(element)); - }, - - up: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(element.parentNode); - var ancestors = element.ancestors(); - return Object.isNumber(expression) ? ancestors[expression] : - Selector.findElement(ancestors, expression, index); - }, - - down: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return element.firstDescendant(); - return Object.isNumber(expression) ? element.descendants()[expression] : - element.select(expression)[index || 0]; - }, - - previous: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); - var previousSiblings = element.previousSiblings(); - return Object.isNumber(expression) ? previousSiblings[expression] : - Selector.findElement(previousSiblings, expression, index); - }, - - next: function(element, expression, index) { - element = $(element); - if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); - var nextSiblings = element.nextSiblings(); - return Object.isNumber(expression) ? nextSiblings[expression] : - Selector.findElement(nextSiblings, expression, index); - }, - - select: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element, args); - }, - - adjacent: function() { - var args = $A(arguments), element = $(args.shift()); - return Selector.findChildElements(element.parentNode, args).without(element); - }, - - identify: function(element) { - element = $(element); - var id = element.readAttribute('id'), self = arguments.callee; - if (id) return id; - do { id = 'anonymous_element_' + self.counter++ } while ($(id)); - element.writeAttribute('id', id); - return id; - }, - - readAttribute: function(element, name) { - element = $(element); - if (Prototype.Browser.IE) { - var t = Element._attributeTranslations.read; - if (t.values[name]) return t.values[name](element, name); - if (t.names[name]) name = t.names[name]; - if (name.include(':')) { - return (!element.attributes || !element.attributes[name]) ? null : - element.attributes[name].value; - } - } - return element.getAttribute(name); - }, - - writeAttribute: function(element, name, value) { - element = $(element); - var attributes = { }, t = Element._attributeTranslations.write; - - if (typeof name == 'object') attributes = name; - else attributes[name] = Object.isUndefined(value) ? true : value; - - for (var attr in attributes) { - name = t.names[attr] || attr; - value = attributes[attr]; - if (t.values[attr]) name = t.values[attr](element, value); - if (value === false || value === null) - element.removeAttribute(name); - else if (value === true) - element.setAttribute(name, name); - else element.setAttribute(name, value); - } - return element; - }, - - getHeight: function(element) { - return $(element).getDimensions().height; - }, - - getWidth: function(element) { - return $(element).getDimensions().width; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - var elementClassName = element.className; - return (elementClassName.length > 0 && (elementClassName == className || - new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - if (!element.hasClassName(className)) - element.className += (element.className ? ' ' : '') + className; - return element; - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - element.className = element.className.replace( - new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); - return element; - }, - - toggleClassName: function(element, className) { - if (!(element = $(element))) return; - return element[element.hasClassName(className) ? - 'removeClassName' : 'addClassName'](className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - var node = element.firstChild; - while (node) { - var nextNode = node.nextSibling; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - element.removeChild(node); - node = nextNode; - } - return element; - }, - - empty: function(element) { - return $(element).innerHTML.blank(); - }, - - descendantOf: function(element, ancestor) { - element = $(element), ancestor = $(ancestor); - var originalAncestor = ancestor; - - if (element.compareDocumentPosition) - return (element.compareDocumentPosition(ancestor) & 8) === 8; - - if (element.sourceIndex && !Prototype.Browser.Opera) { - var e = element.sourceIndex, a = ancestor.sourceIndex, - nextAncestor = ancestor.nextSibling; - if (!nextAncestor) { - do { ancestor = ancestor.parentNode; } - while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode); - } - if (nextAncestor && nextAncestor.sourceIndex) - return (e > a && e < nextAncestor.sourceIndex); - } - - while (element = element.parentNode) - if (element == originalAncestor) return true; - return false; - }, - - scrollTo: function(element) { - element = $(element); - var pos = element.cumulativeOffset(); - window.scrollTo(pos[0], pos[1]); - return element; - }, - - getStyle: function(element, style) { - element = $(element); - style = style == 'float' ? 'cssFloat' : style.camelize(); - var value = element.style[style]; - if (!value) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css[style] : null; - } - if (style == 'opacity') return value ? parseFloat(value) : 1.0; - return value == 'auto' ? null : value; - }, - - getOpacity: function(element) { - return $(element).getStyle('opacity'); - }, - - setStyle: function(element, styles) { - element = $(element); - var elementStyle = element.style, match; - if (Object.isString(styles)) { - element.style.cssText += ';' + styles; - return styles.include('opacity') ? - element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; - } - for (var property in styles) - if (property == 'opacity') element.setOpacity(styles[property]); - else - elementStyle[(property == 'float' || property == 'cssFloat') ? - (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : - property] = styles[property]; - - return element; - }, - - setOpacity: function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - return element; - }, - - getDimensions: function(element) { - element = $(element); - var display = $(element).getStyle('display'); - if (display != 'none' && display != null) // Safari bug - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - var originalDisplay = els.display; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = 'block'; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = originalDisplay; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - return element; - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - return element; - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return element; - element._overflow = Element.getStyle(element, 'overflow') || 'auto'; - if (element._overflow !== 'hidden') - element.style.overflow = 'hidden'; - return element; - }, - - undoClipping: function(element) { - element = $(element); - if (!element._overflow) return element; - element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; - element._overflow = null; - return element; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (element.tagName == 'BODY') break; - var p = Element.getStyle(element, 'position'); - if (p !== 'static') break; - } - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - absolutize: function(element) { - element = $(element); - if (element.getStyle('position') == 'absolute') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - var offsets = element.positionedOffset(); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.width = width + 'px'; - element.style.height = height + 'px'; - return element; - }, - - relativize: function(element) { - element = $(element); - if (element.getStyle('position') == 'relative') return; - // Position.prepare(); // To be done manually by Scripty when it needs it. - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - return element; - }, - - cumulativeScrollOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return Element._returnOffset(valueL, valueT); - }, - - getOffsetParent: function(element) { - if (element.offsetParent) return $(element.offsetParent); - if (element == document.body) return $(element); - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return $(element); - - return $(document.body); - }, - - viewportOffset: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent == document.body && - Element.getStyle(element, 'position') == 'absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - if (!Prototype.Browser.Opera || element.tagName == 'BODY') { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } - } while (element = element.parentNode); - - return Element._returnOffset(valueL, valueT); - }, - - clonePosition: function(element, source) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || { }); - - // find page position of source - source = $(source); - var p = source.viewportOffset(); - - // find coordinate system to use - element = $(element); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(element, 'position') == 'absolute') { - parent = element.getOffsetParent(); - delta = parent.viewportOffset(); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if (options.setWidth) element.style.width = source.offsetWidth + 'px'; - if (options.setHeight) element.style.height = source.offsetHeight + 'px'; - return element; - } -}; - -Element.Methods.identify.counter = 1; - -Object.extend(Element.Methods, { - getElementsBySelector: Element.Methods.select, - childElements: Element.Methods.immediateDescendants -}); - -Element._attributeTranslations = { - write: { - names: { - className: 'class', - htmlFor: 'for' - }, - values: { } - } -}; - -if (Prototype.Browser.Opera) { - Element.Methods.getStyle = Element.Methods.getStyle.wrap( - function(proceed, element, style) { - switch (style) { - case 'left': case 'top': case 'right': case 'bottom': - if (proceed(element, 'position') === 'static') return null; - case 'height': case 'width': - // returns '0px' for hidden elements; we want it to return null - if (!Element.visible(element)) return null; - - // returns the border-box dimensions rather than the content-box - // dimensions, so we subtract padding and borders from the value - var dim = parseInt(proceed(element, style), 10); - - if (dim !== element['offset' + style.capitalize()]) - return dim + 'px'; - - var properties; - if (style === 'height') { - properties = ['border-top-width', 'padding-top', - 'padding-bottom', 'border-bottom-width']; - } - else { - properties = ['border-left-width', 'padding-left', - 'padding-right', 'border-right-width']; - } - return properties.inject(dim, function(memo, property) { - var val = proceed(element, property); - return val === null ? memo : memo - parseInt(val, 10); - }) + 'px'; - default: return proceed(element, style); - } - } - ); - - Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( - function(proceed, element, attribute) { - if (attribute === 'title') return element.title; - return proceed(element, attribute); - } - ); -} - -else if (Prototype.Browser.IE) { - // IE doesn't report offsets correctly for static elements, so we change them - // to "relative" to get the values, then change them back. - Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( - function(proceed, element) { - element = $(element); - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - - $w('positionedOffset viewportOffset').each(function(method) { - Element.Methods[method] = Element.Methods[method].wrap( - function(proceed, element) { - element = $(element); - var position = element.getStyle('position'); - if (position !== 'static') return proceed(element); - // Trigger hasLayout on the offset parent so that IE6 reports - // accurate offsetTop and offsetLeft values for position: fixed. - var offsetParent = element.getOffsetParent(); - if (offsetParent && offsetParent.getStyle('position') === 'fixed') - offsetParent.setStyle({ zoom: 1 }); - element.setStyle({ position: 'relative' }); - var value = proceed(element); - element.setStyle({ position: position }); - return value; - } - ); - }); - - Element.Methods.getStyle = function(element, style) { - element = $(element); - style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); - var value = element.style[style]; - if (!value && element.currentStyle) value = element.currentStyle[style]; - - if (style == 'opacity') { - if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) - if (value[1]) return parseFloat(value[1]) / 100; - return 1.0; - } - - if (value == 'auto') { - if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) - return element['offset' + style.capitalize()] + 'px'; - return null; - } - return value; - }; - - Element.Methods.setOpacity = function(element, value) { - function stripAlpha(filter){ - return filter.replace(/alpha\([^\)]*\)/gi,''); - } - element = $(element); - var currentStyle = element.currentStyle; - if ((currentStyle && !currentStyle.hasLayout) || - (!currentStyle && element.style.zoom == 'normal')) - element.style.zoom = 1; - - var filter = element.getStyle('filter'), style = element.style; - if (value == 1 || value === '') { - (filter = stripAlpha(filter)) ? - style.filter = filter : style.removeAttribute('filter'); - return element; - } else if (value < 0.00001) value = 0; - style.filter = stripAlpha(filter) + - 'alpha(opacity=' + (value * 100) + ')'; - return element; - }; - - Element._attributeTranslations = { - read: { - names: { - 'class': 'className', - 'for': 'htmlFor' - }, - values: { - _getAttr: function(element, attribute) { - return element.getAttribute(attribute, 2); - }, - _getAttrNode: function(element, attribute) { - var node = element.getAttributeNode(attribute); - return node ? node.value : ""; - }, - _getEv: function(element, attribute) { - attribute = element.getAttribute(attribute); - return attribute ? attribute.toString().slice(23, -2) : null; - }, - _flag: function(element, attribute) { - return $(element).hasAttribute(attribute) ? attribute : null; - }, - style: function(element) { - return element.style.cssText.toLowerCase(); - }, - title: function(element) { - return element.title; - } - } - } - }; - - Element._attributeTranslations.write = { - names: Object.extend({ - cellpadding: 'cellPadding', - cellspacing: 'cellSpacing' - }, Element._attributeTranslations.read.names), - values: { - checked: function(element, value) { - element.checked = !!value; - }, - - style: function(element, value) { - element.style.cssText = value ? value : ''; - } - } - }; - - Element._attributeTranslations.has = {}; - - $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + - 'encType maxLength readOnly longDesc').each(function(attr) { - Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; - Element._attributeTranslations.has[attr.toLowerCase()] = attr; - }); - - (function(v) { - Object.extend(v, { - href: v._getAttr, - src: v._getAttr, - type: v._getAttr, - action: v._getAttrNode, - disabled: v._flag, - checked: v._flag, - readonly: v._flag, - multiple: v._flag, - onload: v._getEv, - onunload: v._getEv, - onclick: v._getEv, - ondblclick: v._getEv, - onmousedown: v._getEv, - onmouseup: v._getEv, - onmouseover: v._getEv, - onmousemove: v._getEv, - onmouseout: v._getEv, - onfocus: v._getEv, - onblur: v._getEv, - onkeypress: v._getEv, - onkeydown: v._getEv, - onkeyup: v._getEv, - onsubmit: v._getEv, - onreset: v._getEv, - onselect: v._getEv, - onchange: v._getEv - }); - })(Element._attributeTranslations.read.values); -} - -else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1) ? 0.999999 : - (value === '') ? '' : (value < 0.00001) ? 0 : value; - return element; - }; -} - -else if (Prototype.Browser.WebKit) { - Element.Methods.setOpacity = function(element, value) { - element = $(element); - element.style.opacity = (value == 1 || value === '') ? '' : - (value < 0.00001) ? 0 : value; - - if (value == 1) - if(element.tagName == 'IMG' && element.width) { - element.width++; element.width--; - } else try { - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch (e) { } - - return element; - }; - - // Safari returns margins on body which is incorrect if the child is absolutely - // positioned. For performance reasons, redefine Element#cumulativeOffset for - // KHTML/WebKit only. - Element.Methods.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return Element._returnOffset(valueL, valueT); - }; -} - -if (Prototype.Browser.IE || Prototype.Browser.Opera) { - // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements - Element.Methods.update = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) return element.update().insert(content); - - content = Object.toHTML(content); - var tagName = element.tagName.toUpperCase(); - - if (tagName in Element._insertionTranslations.tags) { - $A(element.childNodes).each(function(node) { element.removeChild(node) }); - Element._getContentFromAnonymousElement(tagName, content.stripScripts()) - .each(function(node) { element.appendChild(node) }); - } - else element.innerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -if ('outerHTML' in document.createElement('div')) { - Element.Methods.replace = function(element, content) { - element = $(element); - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - element.parentNode.replaceChild(content, element); - return element; - } - - content = Object.toHTML(content); - var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); - - if (Element._insertionTranslations.tags[tagName]) { - var nextSibling = element.next(); - var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); - parent.removeChild(element); - if (nextSibling) - fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); - else - fragments.each(function(node) { parent.appendChild(node) }); - } - else element.outerHTML = content.stripScripts(); - - content.evalScripts.bind(content).defer(); - return element; - }; -} - -Element._returnOffset = function(l, t) { - var result = [l, t]; - result.left = l; - result.top = t; - return result; -}; - -Element._getContentFromAnonymousElement = function(tagName, html) { - var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; - if (t) { - div.innerHTML = t[0] + html + t[1]; - t[2].times(function() { div = div.firstChild }); - } else div.innerHTML = html; - return $A(div.childNodes); -}; - -Element._insertionTranslations = { - before: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - top: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - bottom: function(element, node) { - element.appendChild(node); - }, - after: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - tags: { - TABLE: ['', '
', 1], - TBODY: ['', '
', 2], - TR: ['', '
', 3], - TD: ['
', '
', 4], - SELECT: ['', 1] - } -}; - -(function() { - Object.extend(this.tags, { - THEAD: this.tags.TBODY, - TFOOT: this.tags.TBODY, - TH: this.tags.TD - }); -}).call(Element._insertionTranslations); - -Element.Methods.Simulated = { - hasAttribute: function(element, attribute) { - attribute = Element._attributeTranslations.has[attribute] || attribute; - var node = $(element).getAttributeNode(attribute); - return node && node.specified; - } -}; - -Element.Methods.ByTag = { }; - -Object.extend(Element, Element.Methods); - -if (!Prototype.BrowserFeatures.ElementExtensions && - document.createElement('div').__proto__) { - window.HTMLElement = { }; - window.HTMLElement.prototype = document.createElement('div').__proto__; - Prototype.BrowserFeatures.ElementExtensions = true; -} - -Element.extend = (function() { - if (Prototype.BrowserFeatures.SpecificElementExtensions) - return Prototype.K; - - var Methods = { }, ByTag = Element.Methods.ByTag; - - var extend = Object.extend(function(element) { - if (!element || element._extendedByPrototype || - element.nodeType != 1 || element == window) return element; - - var methods = Object.clone(Methods), - tagName = element.tagName, property, value; - - // extend methods for specific tags - if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); - - for (property in methods) { - value = methods[property]; - if (Object.isFunction(value) && !(property in element)) - element[property] = value.methodize(); - } - - element._extendedByPrototype = Prototype.emptyFunction; - return element; - - }, { - refresh: function() { - // extend methods for all tags (Safari doesn't need this) - if (!Prototype.BrowserFeatures.ElementExtensions) { - Object.extend(Methods, Element.Methods); - Object.extend(Methods, Element.Methods.Simulated); - } - } - }); - - extend.refresh(); - return extend; -})(); - -Element.hasAttribute = function(element, attribute) { - if (element.hasAttribute) return element.hasAttribute(attribute); - return Element.Methods.Simulated.hasAttribute(element, attribute); -}; - -Element.addMethods = function(methods) { - var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; - - if (!methods) { - Object.extend(Form, Form.Methods); - Object.extend(Form.Element, Form.Element.Methods); - Object.extend(Element.Methods.ByTag, { - "FORM": Object.clone(Form.Methods), - "INPUT": Object.clone(Form.Element.Methods), - "SELECT": Object.clone(Form.Element.Methods), - "TEXTAREA": Object.clone(Form.Element.Methods) - }); - } - - if (arguments.length == 2) { - var tagName = methods; - methods = arguments[1]; - } - - if (!tagName) Object.extend(Element.Methods, methods || { }); - else { - if (Object.isArray(tagName)) tagName.each(extend); - else extend(tagName); - } - - function extend(tagName) { - tagName = tagName.toUpperCase(); - if (!Element.Methods.ByTag[tagName]) - Element.Methods.ByTag[tagName] = { }; - Object.extend(Element.Methods.ByTag[tagName], methods); - } - - function copy(methods, destination, onlyIfAbsent) { - onlyIfAbsent = onlyIfAbsent || false; - for (var property in methods) { - var value = methods[property]; - if (!Object.isFunction(value)) continue; - if (!onlyIfAbsent || !(property in destination)) - destination[property] = value.methodize(); - } - } - - function findDOMClass(tagName) { - var klass; - var trans = { - "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", - "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", - "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", - "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", - "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": - "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": - "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": - "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": - "FrameSet", "IFRAME": "IFrame" - }; - if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName + 'Element'; - if (window[klass]) return window[klass]; - klass = 'HTML' + tagName.capitalize() + 'Element'; - if (window[klass]) return window[klass]; - - window[klass] = { }; - window[klass].prototype = document.createElement(tagName).__proto__; - return window[klass]; - } - - if (F.ElementExtensions) { - copy(Element.Methods, HTMLElement.prototype); - copy(Element.Methods.Simulated, HTMLElement.prototype, true); - } - - if (F.SpecificElementExtensions) { - for (var tag in Element.Methods.ByTag) { - var klass = findDOMClass(tag); - if (Object.isUndefined(klass)) continue; - copy(T[tag], klass.prototype); - } - } - - Object.extend(Element, Element.Methods); - delete Element.ByTag; - - if (Element.extend.refresh) Element.extend.refresh(); - Element.cache = { }; -}; - -document.viewport = { - getDimensions: function() { - var dimensions = { }; - var B = Prototype.Browser; - $w('width height').each(function(d) { - var D = d.capitalize(); - dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] : - (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D]; - }); - return dimensions; - }, - - getWidth: function() { - return this.getDimensions().width; - }, - - getHeight: function() { - return this.getDimensions().height; - }, - - getScrollOffsets: function() { - return Element._returnOffset( - window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, - window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); - } -}; -/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, - * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style - * license. Please see http://www.yui-ext.com/ for more information. */ - -var Selector = Class.create({ - initialize: function(expression) { - this.expression = expression.strip(); - this.compileMatcher(); - }, - - shouldUseXPath: function() { - if (!Prototype.BrowserFeatures.XPath) return false; - - var e = this.expression; - - // Safari 3 chokes on :*-of-type and :empty - if (Prototype.Browser.WebKit && - (e.include("-of-type") || e.include(":empty"))) - return false; - - // XPath can't do namespaced attributes, nor can it read - // the "checked" property from DOM nodes - if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) - return false; - - return true; - }, - - compileMatcher: function() { - if (this.shouldUseXPath()) - return this.compileXPathMatcher(); - - var e = this.expression, ps = Selector.patterns, h = Selector.handlers, - c = Selector.criteria, le, p, m; - - if (Selector._cache[e]) { - this.matcher = Selector._cache[e]; - return; - } - - this.matcher = ["this.matcher = function(root) {", - "var r = root, h = Selector.handlers, c = false, n;"]; - - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : - new Template(c[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.matcher.push("return h.unique(n);\n}"); - eval(this.matcher.join('\n')); - Selector._cache[this.expression] = this.matcher; - }, - - compileXPathMatcher: function() { - var e = this.expression, ps = Selector.patterns, - x = Selector.xpath, le, m; - - if (Selector._cache[e]) { - this.xpath = Selector._cache[e]; return; - } - - this.matcher = ['.//*']; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - if (m = e.match(ps[i])) { - this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : - new Template(x[i]).evaluate(m)); - e = e.replace(m[0], ''); - break; - } - } - } - - this.xpath = this.matcher.join(''); - Selector._cache[this.expression] = this.xpath; - }, - - findElements: function(root) { - root = root || document; - if (this.xpath) return document._getElementsByXPath(this.xpath, root); - return this.matcher(root); - }, - - match: function(element) { - this.tokens = []; - - var e = this.expression, ps = Selector.patterns, as = Selector.assertions; - var le, p, m; - - while (e && le !== e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - // use the Selector.assertions methods unless the selector - // is too complex. - if (as[i]) { - this.tokens.push([i, Object.clone(m)]); - e = e.replace(m[0], ''); - } else { - // reluctantly do a document-wide search - // and look for a match in the array - return this.findElements(document).include(element); - } - } - } - } - - var match = true, name, matches; - for (var i = 0, token; token = this.tokens[i]; i++) { - name = token[0], matches = token[1]; - if (!Selector.assertions[name](element, matches)) { - match = false; break; - } - } - - return match; - }, - - toString: function() { - return this.expression; - }, - - inspect: function() { - return "#"; - } -}); - -Object.extend(Selector, { - _cache: { }, - - xpath: { - descendant: "//*", - child: "/*", - adjacent: "/following-sibling::*[1]", - laterSibling: '/following-sibling::*', - tagName: function(m) { - if (m[1] == '*') return ''; - return "[local-name()='" + m[1].toLowerCase() + - "' or local-name()='" + m[1].toUpperCase() + "']"; - }, - className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", - id: "[@id='#{1}']", - attrPresence: function(m) { - m[1] = m[1].toLowerCase(); - return new Template("[@#{1}]").evaluate(m); - }, - attr: function(m) { - m[1] = m[1].toLowerCase(); - m[3] = m[5] || m[6]; - return new Template(Selector.xpath.operators[m[2]]).evaluate(m); - }, - pseudo: function(m) { - var h = Selector.xpath.pseudos[m[1]]; - if (!h) return ''; - if (Object.isFunction(h)) return h(m); - return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); - }, - operators: { - '=': "[@#{1}='#{3}']", - '!=': "[@#{1}!='#{3}']", - '^=': "[starts-with(@#{1}, '#{3}')]", - '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", - '*=': "[contains(@#{1}, '#{3}')]", - '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", - '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" - }, - pseudos: { - 'first-child': '[not(preceding-sibling::*)]', - 'last-child': '[not(following-sibling::*)]', - 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', - 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", - 'checked': "[@checked]", - 'disabled': "[@disabled]", - 'enabled': "[not(@disabled)]", - 'not': function(m) { - var e = m[6], p = Selector.patterns, - x = Selector.xpath, le, v; - - var exclusion = []; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i in p) { - if (m = e.match(p[i])) { - v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); - exclusion.push("(" + v.substring(1, v.length - 1) + ")"); - e = e.replace(m[0], ''); - break; - } - } - } - return "[not(" + exclusion.join(" and ") + ")]"; - }, - 'nth-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); - }, - 'nth-last-child': function(m) { - return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); - }, - 'nth-of-type': function(m) { - return Selector.xpath.pseudos.nth("position() ", m); - }, - 'nth-last-of-type': function(m) { - return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); - }, - 'first-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); - }, - 'last-of-type': function(m) { - m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); - }, - 'only-of-type': function(m) { - var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); - }, - nth: function(fragment, m) { - var mm, formula = m[6], predicate; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - if (mm = formula.match(/^(\d+)$/)) // digit only - return '[' + fragment + "= " + mm[1] + ']'; - if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (mm[1] == "-") mm[1] = -1; - var a = mm[1] ? Number(mm[1]) : 1; - var b = mm[2] ? Number(mm[2]) : 0; - predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + - "((#{fragment} - #{b}) div #{a} >= 0)]"; - return new Template(predicate).evaluate({ - fragment: fragment, a: a, b: b }); - } - } - } - }, - - criteria: { - tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', - className: 'n = h.className(n, r, "#{1}", c); c = false;', - id: 'n = h.id(n, r, "#{1}", c); c = false;', - attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', - attr: function(m) { - m[3] = (m[5] || m[6]); - return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); - }, - pseudo: function(m) { - if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); - return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); - }, - descendant: 'c = "descendant";', - child: 'c = "child";', - adjacent: 'c = "adjacent";', - laterSibling: 'c = "laterSibling";' - }, - - patterns: { - // combinators must be listed first - // (and descendant needs to be last combinator) - laterSibling: /^\s*~\s*/, - child: /^\s*>\s*/, - adjacent: /^\s*\+\s*/, - descendant: /^\s/, - - // selectors follow - tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, - id: /^#([\w\-\*]+)(\b|$)/, - className: /^\.([\w\-\*]+)(\b|$)/, - pseudo: -/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, - attrPresence: /^\[([\w]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }, - - // for Selector.match and Element#match - assertions: { - tagName: function(element, matches) { - return matches[1].toUpperCase() == element.tagName.toUpperCase(); - }, - - className: function(element, matches) { - return Element.hasClassName(element, matches[1]); - }, - - id: function(element, matches) { - return element.id === matches[1]; - }, - - attrPresence: function(element, matches) { - return Element.hasAttribute(element, matches[1]); - }, - - attr: function(element, matches) { - var nodeValue = Element.readAttribute(element, matches[1]); - return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); - } - }, - - handlers: { - // UTILITY FUNCTIONS - // joins two collections - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - a.push(node); - return a; - }, - - // marks an array of nodes for counting - mark: function(nodes) { - var _true = Prototype.emptyFunction; - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = _true; - return nodes; - }, - - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = undefined; - return nodes; - }, - - // mark each child node with its position (for nth calls) - // "ofType" flag indicates whether we're indexing for nth-of-type - // rather than nth-child - index: function(parentNode, reverse, ofType) { - parentNode._countedByPrototype = Prototype.emptyFunction; - if (reverse) { - for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { - var node = nodes[i]; - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - } else { - for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - }, - - // filters out duplicates and extends all nodes - unique: function(nodes) { - if (nodes.length == 0) return nodes; - var results = [], n; - for (var i = 0, l = nodes.length; i < l; i++) - if (!(n = nodes[i])._countedByPrototype) { - n._countedByPrototype = Prototype.emptyFunction; - results.push(Element.extend(n)); - } - return Selector.handlers.unmark(results); - }, - - // COMBINATOR FUNCTIONS - descendant: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName('*')); - return results; - }, - - child: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) { - for (var j = 0, child; child = node.childNodes[j]; j++) - if (child.nodeType == 1 && child.tagName != '!') results.push(child); - } - return results; - }, - - adjacent: function(nodes) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - var next = this.nextElementSibling(node); - if (next) results.push(next); - } - return results; - }, - - laterSibling: function(nodes) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, Element.nextSiblings(node)); - return results; - }, - - nextElementSibling: function(node) { - while (node = node.nextSibling) - if (node.nodeType == 1) return node; - return null; - }, - - previousElementSibling: function(node) { - while (node = node.previousSibling) - if (node.nodeType == 1) return node; - return null; - }, - - // TOKEN FUNCTIONS - tagName: function(nodes, root, tagName, combinator) { - var uTagName = tagName.toUpperCase(); - var results = [], h = Selector.handlers; - if (nodes) { - if (combinator) { - // fastlane for ordinary descendant combinators - if (combinator == "descendant") { - for (var i = 0, node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName(tagName)); - return results; - } else nodes = this[combinator](nodes); - if (tagName == "*") return nodes; - } - for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName.toUpperCase() === uTagName) results.push(node); - return results; - } else return root.getElementsByTagName(tagName); - }, - - id: function(nodes, root, id, combinator) { - var targetNode = $(id), h = Selector.handlers; - if (!targetNode) return []; - if (!nodes && root == document) return [targetNode]; - if (nodes) { - if (combinator) { - if (combinator == 'child') { - for (var i = 0, node; node = nodes[i]; i++) - if (targetNode.parentNode == node) return [targetNode]; - } else if (combinator == 'descendant') { - for (var i = 0, node; node = nodes[i]; i++) - if (Element.descendantOf(targetNode, node)) return [targetNode]; - } else if (combinator == 'adjacent') { - for (var i = 0, node; node = nodes[i]; i++) - if (Selector.handlers.previousElementSibling(targetNode) == node) - return [targetNode]; - } else nodes = h[combinator](nodes); - } - for (var i = 0, node; node = nodes[i]; i++) - if (node == targetNode) return [targetNode]; - return []; - } - return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; - }, - - className: function(nodes, root, className, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - return Selector.handlers.byClassName(nodes, root, className); - }, - - byClassName: function(nodes, root, className) { - if (!nodes) nodes = Selector.handlers.descendant([root]); - var needle = ' ' + className + ' '; - for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { - nodeClassName = node.className; - if (nodeClassName.length == 0) continue; - if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) - results.push(node); - } - return results; - }, - - attrPresence: function(nodes, root, attr, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var results = []; - for (var i = 0, node; node = nodes[i]; i++) - if (Element.hasAttribute(node, attr)) results.push(node); - return results; - }, - - attr: function(nodes, root, attr, value, operator, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var handler = Selector.operators[operator], results = []; - for (var i = 0, node; node = nodes[i]; i++) { - var nodeValue = Element.readAttribute(node, attr); - if (nodeValue === null) continue; - if (handler(nodeValue, value)) results.push(node); - } - return results; - }, - - pseudo: function(nodes, name, value, root, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - if (!nodes) nodes = root.getElementsByTagName("*"); - return Selector.pseudos[name](nodes, value, root); - } - }, - - pseudos: { - 'first-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.previousElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'last-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Selector.handlers.nextElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'only-child': function(nodes, value, root) { - var h = Selector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) - results.push(node); - return results; - }, - 'nth-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root); - }, - 'nth-last-child': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true); - }, - 'nth-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, false, true); - }, - 'nth-last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, formula, root, true, true); - }, - 'first-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, false, true); - }, - 'last-of-type': function(nodes, formula, root) { - return Selector.pseudos.nth(nodes, "1", root, true, true); - }, - 'only-of-type': function(nodes, formula, root) { - var p = Selector.pseudos; - return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); - }, - - // handles the an+b logic - getIndices: function(a, b, total) { - if (a == 0) return b > 0 ? [b] : []; - return $R(1, total).inject([], function(memo, i) { - if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); - return memo; - }); - }, - - // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type - nth: function(nodes, formula, root, reverse, ofType) { - if (nodes.length == 0) return []; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - var h = Selector.handlers, results = [], indexed = [], m; - h.mark(nodes); - for (var i = 0, node; node = nodes[i]; i++) { - if (!node.parentNode._countedByPrototype) { - h.index(node.parentNode, reverse, ofType); - indexed.push(node.parentNode); - } - } - if (formula.match(/^\d+$/)) { // just a number - formula = Number(formula); - for (var i = 0, node; node = nodes[i]; i++) - if (node.nodeIndex == formula) results.push(node); - } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (m[1] == "-") m[1] = -1; - var a = m[1] ? Number(m[1]) : 1; - var b = m[2] ? Number(m[2]) : 0; - var indices = Selector.pseudos.getIndices(a, b, nodes.length); - for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { - for (var j = 0; j < l; j++) - if (node.nodeIndex == indices[j]) results.push(node); - } - } - h.unmark(nodes); - h.unmark(indexed); - return results; - }, - - 'empty': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - // IE treats comments as element nodes - if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; - results.push(node); - } - return results; - }, - - 'not': function(nodes, selector, root) { - var h = Selector.handlers, selectorType, m; - var exclusions = new Selector(selector).findElements(root); - h.mark(exclusions); - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node._countedByPrototype) results.push(node); - h.unmark(exclusions); - return results; - }, - - 'enabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node.disabled) results.push(node); - return results; - }, - - 'disabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.disabled) results.push(node); - return results; - }, - - 'checked': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.checked) results.push(node); - return results; - } - }, - - operators: { - '=': function(nv, v) { return nv == v; }, - '!=': function(nv, v) { return nv != v; }, - '^=': function(nv, v) { return nv.startsWith(v); }, - '$=': function(nv, v) { return nv.endsWith(v); }, - '*=': function(nv, v) { return nv.include(v); }, - '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, - '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } - }, - - split: function(expression) { - var expressions = []; - expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { - expressions.push(m[1].strip()); - }); - return expressions; - }, - - matchElements: function(elements, expression) { - var matches = $$(expression), h = Selector.handlers; - h.mark(matches); - for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._countedByPrototype) results.push(element); - h.unmark(matches); - return results; - }, - - findElement: function(elements, expression, index) { - if (Object.isNumber(expression)) { - index = expression; expression = false; - } - return Selector.matchElements(elements, expression || '*')[index || 0]; - }, - - findChildElements: function(element, expressions) { - expressions = Selector.split(expressions.join(',')); - var results = [], h = Selector.handlers; - for (var i = 0, l = expressions.length, selector; i < l; i++) { - selector = new Selector(expressions[i].strip()); - h.concat(results, selector.findElements(element)); - } - return (l > 1) ? h.unique(results) : results; - } -}); - -if (Prototype.Browser.IE) { - Object.extend(Selector.handlers, { - // IE returns comment nodes on getElementsByTagName("*"). - // Filter them out. - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - if (node.tagName !== "!") a.push(node); - return a; - }, - - // IE improperly serializes _countedByPrototype in (inner|outer)HTML. - unmark: function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node.removeAttribute('_countedByPrototype'); - return nodes; - } - }); -} - -function $$() { - return Selector.findChildElements(document, $A(arguments)); -} -var Form = { - reset: function(form) { - $(form).reset(); - return form; - }, - - serializeElements: function(elements, options) { - if (typeof options != 'object') options = { hash: !!options }; - else if (Object.isUndefined(options.hash)) options.hash = true; - var key, value, submitted = false, submit = options.submit; - - var data = elements.inject({ }, function(result, element) { - if (!element.disabled && element.name) { - key = element.name; value = $(element).getValue(); - if (value != null && (element.type != 'submit' || (!submitted && - submit !== false && (!submit || key == submit) && (submitted = true)))) { - if (key in result) { - // a key is already present; construct an array of values - if (!Object.isArray(result[key])) result[key] = [result[key]]; - result[key].push(value); - } - else result[key] = value; - } - } - return result; - }); - - return options.hash ? data : Object.toQueryString(data); - } -}; - -Form.Methods = { - serialize: function(form, options) { - return Form.serializeElements(Form.getElements(form), options); - }, - - getElements: function(form) { - return $A($(form).getElementsByTagName('*')).inject([], - function(elements, child) { - if (Form.Element.Serializers[child.tagName.toLowerCase()]) - elements.push(Element.extend(child)); - return elements; - } - ); - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) return $A(inputs).map(Element.extend); - - for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || (name && input.name != name)) - continue; - matchingInputs.push(Element.extend(input)); - } - - return matchingInputs; - }, - - disable: function(form) { - form = $(form); - Form.getElements(form).invoke('disable'); - return form; - }, - - enable: function(form) { - form = $(form); - Form.getElements(form).invoke('enable'); - return form; - }, - - findFirstElement: function(form) { - var elements = $(form).getElements().findAll(function(element) { - return 'hidden' != element.type && !element.disabled; - }); - var firstByIndex = elements.findAll(function(element) { - return element.hasAttribute('tabIndex') && element.tabIndex >= 0; - }).sortBy(function(element) { return element.tabIndex }).first(); - - return firstByIndex ? firstByIndex : elements.find(function(element) { - return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - form = $(form); - form.findFirstElement().activate(); - return form; - }, - - request: function(form, options) { - form = $(form), options = Object.clone(options || { }); - - var params = options.parameters, action = form.readAttribute('action') || ''; - if (action.blank()) action = window.location.href; - options.parameters = form.serialize(true); - - if (params) { - if (Object.isString(params)) params = params.toQueryParams(); - Object.extend(options.parameters, params); - } - - if (form.hasAttribute('method') && !options.method) - options.method = form.method; - - return new Ajax.Request(action, options); - } -}; - -/*--------------------------------------------------------------------------*/ - -Form.Element = { - focus: function(element) { - $(element).focus(); - return element; - }, - - select: function(element) { - $(element).select(); - return element; - } -}; - -Form.Element.Methods = { - serialize: function(element) { - element = $(element); - if (!element.disabled && element.name) { - var value = element.getValue(); - if (value != undefined) { - var pair = { }; - pair[element.name] = value; - return Object.toQueryString(pair); - } - } - return ''; - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - return Form.Element.Serializers[method](element); - }, - - setValue: function(element, value) { - element = $(element); - var method = element.tagName.toLowerCase(); - Form.Element.Serializers[method](element, value); - return element; - }, - - clear: function(element) { - $(element).value = ''; - return element; - }, - - present: function(element) { - return $(element).value != ''; - }, - - activate: function(element) { - element = $(element); - try { - element.focus(); - if (element.select && (element.tagName.toLowerCase() != 'input' || - !['button', 'reset', 'submit'].include(element.type))) - element.select(); - } catch (e) { } - return element; - }, - - disable: function(element) { - element = $(element); - element.blur(); - element.disabled = true; - return element; - }, - - enable: function(element) { - element = $(element); - element.disabled = false; - return element; - } -}; - -/*--------------------------------------------------------------------------*/ - -var Field = Form.Element; -var $F = Form.Element.Methods.getValue; - -/*--------------------------------------------------------------------------*/ - -Form.Element.Serializers = { - input: function(element, value) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element, value); - default: - return Form.Element.Serializers.textarea(element, value); - } - }, - - inputSelector: function(element, value) { - if (Object.isUndefined(value)) return element.checked ? element.value : null; - else element.checked = !!value; - }, - - textarea: function(element, value) { - if (Object.isUndefined(value)) return element.value; - else element.value = value; - }, - - select: function(element, index) { - if (Object.isUndefined(index)) - return this[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - else { - var opt, value, single = !Object.isArray(index); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - value = this.optionValue(opt); - if (single) { - if (value == index) { - opt.selected = true; - return; - } - } - else opt.selected = index.include(value); - } - } - }, - - selectOne: function(element) { - var index = element.selectedIndex; - return index >= 0 ? this.optionValue(element.options[index]) : null; - }, - - selectMany: function(element) { - var values, length = element.length; - if (!length) return null; - - for (var i = 0, values = []; i < length; i++) { - var opt = element.options[i]; - if (opt.selected) values.push(this.optionValue(opt)); - } - return values; - }, - - optionValue: function(opt) { - // extend element because hasAttribute may not be native - return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; - } -}; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = Class.create(PeriodicalExecuter, { - initialize: function($super, element, frequency, callback) { - $super(callback, frequency); - this.element = $(element); - this.lastValue = this.getValue(); - }, - - execute: function() { - var value = this.getValue(); - if (Object.isString(this.lastValue) && Object.isString(value) ? - this.lastValue != value : String(this.lastValue) != String(value)) { - this.callback(this.element, value); - this.lastValue = value; - } - } -}); - -Form.Element.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(Abstract.TimedObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = Class.create({ - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback, this); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - default: - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -}); - -Form.Element.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) var Event = { }; - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - KEY_HOME: 36, - KEY_END: 35, - KEY_PAGEUP: 33, - KEY_PAGEDOWN: 34, - KEY_INSERT: 45, - - cache: { }, - - relatedTarget: function(event) { - var element; - switch(event.type) { - case 'mouseover': element = event.fromElement; break; - case 'mouseout': element = event.toElement; break; - default: return null; - } - return Element.extend(element); - } -}); - -Event.Methods = (function() { - var isButton; - - if (Prototype.Browser.IE) { - var buttonMap = { 0: 1, 1: 4, 2: 2 }; - isButton = function(event, code) { - return event.button == buttonMap[code]; - }; - - } else if (Prototype.Browser.WebKit) { - isButton = function(event, code) { - switch (code) { - case 0: return event.which == 1 && !event.metaKey; - case 1: return event.which == 1 && event.metaKey; - default: return false; - } - }; - - } else { - isButton = function(event, code) { - return event.which ? (event.which === code + 1) : (event.button === code); - }; - } - - return { - isLeftClick: function(event) { return isButton(event, 0) }, - isMiddleClick: function(event) { return isButton(event, 1) }, - isRightClick: function(event) { return isButton(event, 2) }, - - element: function(event) { - var node = Event.extend(event).target; - return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); - }, - - findElement: function(event, expression) { - var element = Event.element(event); - if (!expression) return element; - var elements = [element].concat(element.ancestors()); - return Selector.findElement(elements, expression, 0); - }, - - pointer: function(event) { - return { - x: event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)), - y: event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)) - }; - }, - - pointerX: function(event) { return Event.pointer(event).x }, - pointerY: function(event) { return Event.pointer(event).y }, - - stop: function(event) { - Event.extend(event); - event.preventDefault(); - event.stopPropagation(); - event.stopped = true; - } - }; -})(); - -Event.extend = (function() { - var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { - m[name] = Event.Methods[name].methodize(); - return m; - }); - - if (Prototype.Browser.IE) { - Object.extend(methods, { - stopPropagation: function() { this.cancelBubble = true }, - preventDefault: function() { this.returnValue = false }, - inspect: function() { return "[object Event]" } - }); - - return function(event) { - if (!event) return false; - if (event._extendedByPrototype) return event; - - event._extendedByPrototype = Prototype.emptyFunction; - var pointer = Event.pointer(event); - Object.extend(event, { - target: event.srcElement, - relatedTarget: Event.relatedTarget(event), - pageX: pointer.x, - pageY: pointer.y - }); - return Object.extend(event, methods); - }; - - } else { - Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; - Object.extend(Event.prototype, methods); - return Prototype.K; - } -})(); - -Object.extend(Event, (function() { - var cache = Event.cache; - - function getEventID(element) { - if (element._prototypeEventID) return element._prototypeEventID[0]; - arguments.callee.id = arguments.callee.id || 1; - return element._prototypeEventID = [++arguments.callee.id]; - } - - function getDOMEventName(eventName) { - if (eventName && eventName.include(':')) return "dataavailable"; - return eventName; - } - - function getCacheForID(id) { - return cache[id] = cache[id] || { }; - } - - function getWrappersForEventName(id, eventName) { - var c = getCacheForID(id); - return c[eventName] = c[eventName] || []; - } - - function createWrapper(element, eventName, handler) { - var id = getEventID(element); - var c = getWrappersForEventName(id, eventName); - if (c.pluck("handler").include(handler)) return false; - - var wrapper = function(event) { - if (!Event || !Event.extend || - (event.eventName && event.eventName != eventName)) - return false; - - Event.extend(event); - handler.call(element, event); - }; - - wrapper.handler = handler; - c.push(wrapper); - return wrapper; - } - - function findWrapper(id, eventName, handler) { - var c = getWrappersForEventName(id, eventName); - return c.find(function(wrapper) { return wrapper.handler == handler }); - } - - function destroyWrapper(id, eventName, handler) { - var c = getCacheForID(id); - if (!c[eventName]) return false; - c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); - } - - function destroyCache() { - for (var id in cache) - for (var eventName in cache[id]) - cache[id][eventName] = null; - } - - if (window.attachEvent) { - window.attachEvent("onunload", destroyCache); - } - - return { - observe: function(element, eventName, handler) { - element = $(element); - var name = getDOMEventName(eventName); - - var wrapper = createWrapper(element, eventName, handler); - if (!wrapper) return element; - - if (element.addEventListener) { - element.addEventListener(name, wrapper, false); - } else { - element.attachEvent("on" + name, wrapper); - } - - return element; - }, - - stopObserving: function(element, eventName, handler) { - element = $(element); - var id = getEventID(element), name = getDOMEventName(eventName); - - if (!handler && eventName) { - getWrappersForEventName(id, eventName).each(function(wrapper) { - element.stopObserving(eventName, wrapper.handler); - }); - return element; - - } else if (!eventName) { - Object.keys(getCacheForID(id)).each(function(eventName) { - element.stopObserving(eventName); - }); - return element; - } - - var wrapper = findWrapper(id, eventName, handler); - if (!wrapper) return element; - - if (element.removeEventListener) { - element.removeEventListener(name, wrapper, false); - } else { - element.detachEvent("on" + name, wrapper); - } - - destroyWrapper(id, eventName, handler); - - return element; - }, - - fire: function(element, eventName, memo) { - element = $(element); - if (element == document && document.createEvent && !element.dispatchEvent) - element = document.documentElement; - - var event; - if (document.createEvent) { - event = document.createEvent("HTMLEvents"); - event.initEvent("dataavailable", true, true); - } else { - event = document.createEventObject(); - event.eventType = "ondataavailable"; - } - - event.eventName = eventName; - event.memo = memo || { }; - - if (document.createEvent) { - element.dispatchEvent(event); - } else { - element.fireEvent(event.eventType, event); - } - - return Event.extend(event); - } - }; -})()); - -Object.extend(Event, Event.Methods); - -Element.addMethods({ - fire: Event.fire, - observe: Event.observe, - stopObserving: Event.stopObserving -}); - -Object.extend(document, { - fire: Element.Methods.fire.methodize(), - observe: Element.Methods.observe.methodize(), - stopObserving: Element.Methods.stopObserving.methodize(), - loaded: false -}); - -(function() { - /* Support for the DOMContentLoaded event is based on work by Dan Webb, - Matthias Miller, Dean Edwards and John Resig. */ - - var timer; - - function fireContentLoadedEvent() { - if (document.loaded) return; - if (timer) window.clearInterval(timer); - document.fire("dom:loaded"); - document.loaded = true; - } - - if (document.addEventListener) { - if (Prototype.Browser.WebKit) { - timer = window.setInterval(function() { - if (/loaded|complete/.test(document.readyState)) - fireContentLoadedEvent(); - }, 0); - - Event.observe(window, "load", fireContentLoadedEvent); - - } else { - document.addEventListener("DOMContentLoaded", - fireContentLoadedEvent, false); - } - - } else { - document.write(" - - - - -

Stanford Temporal Tagger: SUTime

-
- - - - - -
-Please enter a reference date (format must be YYYY-MM-DD): -

-Date: -value="<%=StringEscapeUtils.escapeHtml4(dateString)%>"<% - }%> /> - -
- -
-Please enter your text here (sample sentence): -

- -
- - -
- -
-
- diff --git a/src/main/webapp/sutime/sutime.css b/src/main/webapp/sutime/sutime.css deleted file mode 100644 index 8dc66607a6..0000000000 --- a/src/main/webapp/sutime/sutime.css +++ /dev/null @@ -1,25 +0,0 @@ -#Footer { - position: relative; - bottom: 0px; -} -#Main td -{ - padding:15px; - vertical-align:top; -} -#Main table -{ - margin:15px; -} -td -{ - padding:5px; -} -table -{ - margin:15px; -} -#Annotated td -{ - font-size: 14px; -} From 75f4731f880fcfdf55b9312e9c80e64cb49c3da2 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 16:30:28 -0600 Subject: [PATCH 10/20] big youtube handling --- .../java/org/ecocean/identity/IBEISIA.java | 259 ------------------ 1 file changed, 259 deletions(-) diff --git a/src/main/java/org/ecocean/identity/IBEISIA.java b/src/main/java/org/ecocean/identity/IBEISIA.java index 9b12921b83..cbfff645a0 100644 --- a/src/main/java/org/ecocean/identity/IBEISIA.java +++ b/src/main/java/org/ecocean/identity/IBEISIA.java @@ -4070,265 +4070,6 @@ public static String IAIntake(List anns, Shepherd myShepherd, HttpSe public static void fromDetection(Occurrence occ, Shepherd myShepherd, String context, String rootDir) { System.out.println(">>>>>> detection created " + occ.toString()); - - // prep the YouTube video date for SUTimee analysis - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - String tempRelativeDate = null; - try { - // tempRelativeDate = YouTube.getVideoPublishedAt(occ, context); deprecated, issue 622 - tempRelativeDate = null; - } catch (Exception e) {} - if ((tempRelativeDate != null) && (tempRelativeDate.indexOf("T") != -1)) { - tempRelativeDate = tempRelativeDate.substring(0, tempRelativeDate.indexOf("T")); - } - if ((tempRelativeDate != null) && (!tempRelativeDate.equals(""))) { - DateTimeFormatter parser2 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTime time = parser2.parseDateTime(tempRelativeDate); - relativeDate = time.toString(parser2); - } - // set the locationID/location/date on all encounters by inspecting detected comments on the first encounter - if ((occ.getEncounters() != null) && (occ.getEncounters().get(0) != null)) { - String locCode = null; - String location = ""; - int year = -1; - int month = -1; - int day = -1; - List encounters = occ.getEncounters(); - int numEncounters = encounters.size(); - Encounter enc = encounters.get(0); - String ytRemarks = null; - // GET AND TRANSLATE VIDEO COMMENTS - // deprecated, issue 622 - // ytRemarks = YouTube.getVideoDescription(occ, myShepherd); - String detectedLanguage = "en"; - try { - detectedLanguage = DetectTranslate.detectLanguage(ytRemarks); - System.out.println("Video description suggests language: " + detectedLanguage); - if (!detectedLanguage.toLowerCase().startsWith("en")) { - ytRemarks = DetectTranslate.translateToEnglish(ytRemarks); - } - } catch (Exception e) { - System.out.println("I hit an exception trying to detect language."); - e.printStackTrace(); - } - // GET AND TRANSLATE VIDEO TITLE - String videoTitle = null; - // deprecated, issue 622 - // videoTitle = YouTube.getVideoTitle(occ, myShepherd); - try { - String titleLanguage = "en"; - titleLanguage = DetectTranslate.detectLanguage(videoTitle); - System.out.println("Video title " + videoTitle + " suggests language: " + - titleLanguage); - // use the title language if there were no comments - if (ytRemarks.equals("")) { - detectedLanguage = titleLanguage; - } - if (!titleLanguage.toLowerCase().startsWith("en")) { - videoTitle = DetectTranslate.translateToEnglish(videoTitle); - } - } catch (Exception e) { - System.out.println( - "I hit an exception trying to detect language in the video title."); - e.printStackTrace(); - } - System.out.println("Final detectedLanguage: " + detectedLanguage); - - // GET AND TRANSLATE OCR TEXT EMBEDDED IN VIDEO FRAMES - // grab texts from yt videos through OCR (before we parse for location/ID and Date) and add it to remarks variable. - String ocrRemarks = ""; - try { - if ((occ.getEncounters() != null) && (occ.getEncounters().size() > 0)) { - Encounter myEnc = occ.getEncounters().get(0); - List assets = myEnc.getMedia(); - if ((assets != null) && (assets.size() > 0)) { - MediaAsset myAsset = assets.get(0); - MediaAsset parent = myAsset.getParent(myShepherd); - if (parent != null) { - ArrayList frames = YouTubeAssetStore.findFrames(parent, - myShepherd); - if ((frames != null) && (frames.size() > 0)) { - // Google OCR - // ArrayList bytesFrames= new ArrayList(GoogleOcr.makeBytesFrames(frames)); - // ocrRemarks = GoogleOcr.detectText(bytesFrames); - // if(ocrRemarks==null)ocrRemarks=""; - // System.out.println("I found Google OCR remarks: "+ocrRemarks); - - // Azure OCR - ocrRemarks = AzureOcr.detectText(frames, detectedLanguage); - if (ocrRemarks == null) ocrRemarks = ""; - System.out.println("I found Azure OCR remarks: " + ocrRemarks); - } - } else { - System.out.println( - "I could not find any frames from YouTubeAssetStore.findFrames for asset:" - + myAsset.getId() + " from Encounter " + myEnc.getCatalogNumber()); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - System.out.println("I hit an exception trying to find ocrRemarks."); - } - try { - String ocrDetectedLanguage = "en"; - ocrDetectedLanguage = DetectTranslate.detectLanguage(ocrRemarks); - - System.out.println("OCR suggests language: " + ocrDetectedLanguage); - if (!ocrDetectedLanguage.toLowerCase().startsWith("en")) { - ocrRemarks = DetectTranslate.translateToEnglish(ocrRemarks); - } - } catch (Exception e) { - System.out.println( - "I hit an exception trying to detect language for OCR comments."); - e.printStackTrace(); - } - String remarks = ytRemarks + " " + ocrRemarks + " " + videoTitle; - - System.out.println("Let's parse these remarks for date and location: " + remarks); - - LinkedProperties props = (LinkedProperties)ShepherdProperties.getProperties( - "submitActionClass.properties", "", context); - - // OK, let's check the comments and tags for retrievable metadata - try { - // first parse for location and locationID - String lowercaseRemarks = remarks.toLowerCase(); - try { - Iterator m_enum = props.orderedKeys().iterator(); - while (m_enum.hasNext()) { - String aLocationSnippet = ((String)m_enum.next()).replaceFirst("\\s++$", - ""); - // System.out.println(" Looking for: "+aLocationSnippet); - if (lowercaseRemarks.indexOf(aLocationSnippet) != -1) { - locCode = props.getProperty(aLocationSnippet); - location += " " + aLocationSnippet; - // System.out.println(".....Building an idea of location: "+location); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - boolean setDate = true; - if (enc.getDateInMilliseconds() != null) { setDate = false; } - // next use natural language processing for date - if (setDate) { - // boolean NLPsuccess=false; - try { - System.out.println(">>>>>> looking for date with NLP"); - // call Stanford NLP function to find and select a date from ytRemarks - // String myDate= ServletUtilities.nlpDateParse(remarks); - String myDate = SUTime.parseDateStringForBestDate(rootDir, remarks, - relativeDate).replaceAll("null", ""); - System.out.println("Finished SUTime.parseDateStringForBestDate: " + myDate); - // parse through the selected date to grab year, month and day separately.Remove cero from month and day with intValue. - if (myDate != null) { - System.out.println(">>>>>> NLP found date: " + myDate); - - // current datetime just for quality comparison - LocalDateTime dt = new LocalDateTime(); - DateTimeFormatter parser1 = ISODateTimeFormat.dateOptionalTimeParser(); - LocalDateTime reportedDateTime = new LocalDateTime( - parser1.parseLocalDateTime(myDate)); - // System.out.println(" reportedDateTime is: "+reportedDateTime.toString(parser1)); - StringTokenizer str = new StringTokenizer(myDate, "-"); - int numTokens = str.countTokens(); - System.out.println(" StringTokenizer for date has " + numTokens + - " tokens for String input " + str.toString()); - if (numTokens >= 1) { - year = reportedDateTime.getYear(); - if (year > (dt.getYear() + 1)) { - year = -1; - } - } - if (numTokens >= 2) { - try { - month = reportedDateTime.getMonthOfYear(); - } catch (Exception e) { month = -1; } - } else { month = -1; } - // see if we can get a day, because we do want to support only yyy-MM too - if (numTokens >= 3) { - try { - day = reportedDateTime.getDayOfMonth(); - } catch (Exception e) { - day = 0; - } - } else { day = -1; } - } - } catch (Exception e) { - System.out.println("Exception in NLP in IBEISIA.class"); - e.printStackTrace(); - } - // if we found a date via NLP or brute force, let's use it here - if (year > -1) { - for (int i = 0; i < numEncounters; i++) { - Encounter enctemp = encounters.get(i); - enctemp.setYear(year); - if (month > -1) { - enctemp.setMonth(month); - if (day > -1) { enctemp.setDay(day); } - } - } - } - } // end if set date - } catch (Exception props_e) { - props_e.printStackTrace(); - } - // if we found a locationID, iterate and set it on every Encounter - if (locCode != null) { - for (int i = 0; i < numEncounters; i++) { - Encounter enctemp = encounters.get(i); - enctemp.setLocationID(locCode); - System.out.println("Setting locationID for detected Encounter to: " + locCode); - if (!location.equals("")) { - enctemp.setLocation(location.trim()); - System.out.println("Setting location for detected Encounter to: " + - location); - } - } - } - // set the Wildbook A.I. user if it exists - if (myShepherd.getUser("wildbookai") != null) { - for (int i = 0; i < numEncounters; i++) { - Encounter enctemp = encounters.get(i); - enctemp.setSubmitterID("wildbookai"); - } - } - // if date and/or location not found, ask youtube poster through comment section. - // cred= ShepherdProperties.getProperties("youtubeCredentials.properties", ""); - try { - // YouTube.init(request); - Properties quest = new Properties(); - // Properties questEs = new Properties(); - - // TBD-simplify to one set of files - System.out.println("Getting quest.properties for language code: " + - detectedLanguage); - quest = ShepherdProperties.getProperties("quest.properties", - detectedLanguage.substring(0, 2)); - // questEs= ShepherdProperties.getProperties("questEs.properties"); - - String questionToPost = null; - if ((enc.getDateInMilliseconds() == null) && (locCode == null)) { - questionToPost = quest.getProperty("whenWhere"); - } else if (enc.getDateInMilliseconds() == null) { - questionToPost = quest.getProperty("when"); - } else if (locCode == null) { - questionToPost = quest.getProperty("where"); - } - if (questionToPost != null) { - String videoId = enc.getEventID().replaceAll("youtube:", ""); - try { - throw new Exception("YouTube agent has been deprecated"); - // YouTube.postQuestion(questionToPost, videoId, occ, context); - } catch (Exception e) { e.printStackTrace(); } - } - } catch (Exception yet) { - System.out.println("Caught exception trying to post a YouTube question."); - yet.printStackTrace(); - } - } - // end set date/location/locationID on Encounters } //// TOTAL HACK... buy jon a drink and he will tell you about these..... From 57d10cf5264c94ce999cb8e49e12e68d1374d4d8 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Mon, 26 Aug 2024 17:39:44 -0600 Subject: [PATCH 11/20] cleanup --- .../ai/utilities/ParseDateLocation.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java index ec0aa562e4..b2da0c3a02 100644 --- a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java +++ b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java @@ -183,17 +183,6 @@ public static String parseDate(String rootDir, String context, Status tweet) { return null; } - /* - TODO FIXME this is made by jon as a desired set of arguments to call from IBEISIA.fromDetection() - - note: rootDir is base path for context, i.e. request.getSession().getServletContext().getRealPath("/") suitable for, e.g. baseDir = - ServletUtilities.dataDir(context, rootDir); - */ - /* - public static String parseDate(String textInput, String context, String rootDir){ - return null; - } - */ // NOTE: parseDate method WITHOUT tweet4j status object as a parameter. There is another parseDate method! public static String parseDate(String rootDir, String textInput, String context) { @@ -226,36 +215,6 @@ public static String parseDate(String rootDir, String textInput, String context) return myDate; } - /* - public static ArrayList nlpLocationParse(String text) throws RuntimeException { - ArrayList locations = new ArrayList<>(); - Properties props = new Properties(); - props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner"); //TODO adding truecase before ner doesn't seem to be making a difference - here. If this doesn't change with some tweaking, you may want to remove the stanford-corenlp class:model-english dependency. Update: the - stanford-corenlp class:model-english dependency seems essential even when truecase is excluded. Very weird. StanfordCoreNLP pipeline = new - StanfordCoreNLP(props); - edu.stanford.nlp.pipeline.Annotation document = new edu.stanford.nlp.pipeline.Annotation(text); - pipeline.annotate(document); - List sentences = document.get(SentencesAnnotation.class); - for(CoreMap sentence: sentences) { - for (CoreLabel token: sentence.get(TokensAnnotation.class)) { - String ne = token.get(NamedEntityTagAnnotation.class); - if(ne.equals("LOCATION")){ - String word = token.get(TextAnnotation.class); - System.out.println("Location captured: " + word); - locations.add(word); - } - } - } - - if (locations.size() > 0){ - return locations; - } else{ - throw new RuntimeException("no locations found"); - } - - } - */ /** * Pass in a MediaAsset that derives from a YouTube video, and this method will go check for any additional info, such as response comments, that From ec23a0672cde20bbeb5e08a497e04fa1c0eeaf34 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Tue, 27 Aug 2024 14:35:15 -0600 Subject: [PATCH 12/20] unused import --- src/main/java/org/ecocean/identity/IBEISIA.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/org/ecocean/identity/IBEISIA.java b/src/main/java/org/ecocean/identity/IBEISIA.java index cbfff645a0..a33c10b376 100644 --- a/src/main/java/org/ecocean/identity/IBEISIA.java +++ b/src/main/java/org/ecocean/identity/IBEISIA.java @@ -1,8 +1,5 @@ package org.ecocean.identity; -import org.ecocean.ai.nlp.SUTime; -import org.ecocean.ai.nmt.azure.DetectTranslate; -import org.ecocean.ai.ocr.azure.AzureOcr; import org.ecocean.Annotation; import org.ecocean.AnnotationLite; import org.ecocean.CommonConfiguration; From 14d6da9e9781363c7ad23f3b5cc03b5812db8ea3 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Tue, 27 Aug 2024 15:19:03 -0600 Subject: [PATCH 13/20] clean house re: SUTime --- src/main/java/org/ecocean/TwitterBot.java | 7 +- src/main/java/org/ecocean/ai/nlp/SUTime.java | 549 -------------- .../ai/utilities/ParseDateLocation.java | 673 ------------------ .../org/ecocean/servlet/SUTimePipeline.java | 94 --- 4 files changed, 4 insertions(+), 1319 deletions(-) delete mode 100644 src/main/java/org/ecocean/ai/nlp/SUTime.java delete mode 100644 src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java delete mode 100644 src/main/java/org/ecocean/servlet/SUTimePipeline.java diff --git a/src/main/java/org/ecocean/TwitterBot.java b/src/main/java/org/ecocean/TwitterBot.java index 8a85d3c75c..55afe7b15d 100644 --- a/src/main/java/org/ecocean/TwitterBot.java +++ b/src/main/java/org/ecocean/TwitterBot.java @@ -18,7 +18,6 @@ import java.util.ArrayList; import java.util.List; import org.ecocean.ai.nmt.azure.DetectTranslate; -import org.ecocean.ai.utilities.ParseDateLocation; import org.ecocean.ia.IA; import org.ecocean.ia.Task; import org.ecocean.media.MediaAsset; @@ -562,9 +561,11 @@ private static void updateEncounter(MediaAsset tweetMA, ArrayList an if ((originTweet == null) || (anns == null)) return; String tx = taxonomyStringFromTweet(originTweet, myShepherd.getContext()); + // ParseDateLocation has been deprecated // use NLP to get Date/Location if available in Tweet - String newDetectedDate = ParseDateLocation.parseDate(rootDir, myShepherd.getContext(), - originTweet); + // String newDetectedDate = ParseDateLocation.parseDate(rootDir, myShepherd.getContext(), originTweet); + String newDetectedDate = null; + for (Annotation ann : anns) { Encounter enc = ann.findEncounter(myShepherd); if (enc == null) continue; diff --git a/src/main/java/org/ecocean/ai/nlp/SUTime.java b/src/main/java/org/ecocean/ai/nlp/SUTime.java deleted file mode 100644 index 9099f63a02..0000000000 --- a/src/main/java/org/ecocean/ai/nlp/SUTime.java +++ /dev/null @@ -1,549 +0,0 @@ -package org.ecocean.ai.nlp; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -import org.ecocean.servlet.*; -import org.ecocean.TwitterUtil; - -import java.io.IOException; - -import edu.stanford.nlp.ling.CoreAnnotations; -import edu.stanford.nlp.pipeline.Annotation; -import edu.stanford.nlp.pipeline.Annotator; -import edu.stanford.nlp.time.Options; -import edu.stanford.nlp.time.SUTime.Temporal; -import edu.stanford.nlp.time.TimeAnnotations; -import edu.stanford.nlp.time.TimeExpression; -import edu.stanford.nlp.util.CoreMap; -import edu.stanford.nlp.util.StringUtils; -import twitter4j.Status; - -import org.apache.commons.lang3.StringEscapeUtils; - -public class SUTime { - public static boolean parseBoolean(String value) { - if (StringUtils.isNullOrEmpty(value)) { - return false; - } - if (value.equalsIgnoreCase("on")) { - return true; - } - return Boolean.parseBoolean(value); - } - - private static String getRuleFilepaths(String rootDir, String... files) { - String rulesDir = ""; - - try { - rulesDir = rootDir + "/WEB-INF/data/sutime/rules"; - } catch (Exception npe) { - // OK, we couldn't find a servlet context, so let's try to get the files from a hardcoded override directory - rulesDir = "/data/wildbook_data_dir/WEB-INF/data/sutime/rules"; - } - StringBuilder sb = new StringBuilder(); - for (String file : files) { - if (sb.length() > 0) { - sb.append(","); - } - sb.append(rulesDir + "/" + file); - System.out.println("Loading SUTime rules file: " + rulesDir + "/" + file); - } - return sb.toString(); - } - - private static Properties getTimeAnnotatorProperties(String rootDir) { - // Parses request and set up properties for time annotators - - System.out.println("Entering " + "SUTime.getTimeAnnotatorProperties"); - - boolean markTimeRanges = false; - // parseBoolean(request.getParameter("markTimeRanges")); - boolean includeNested = false; - // parseBoolean(request.getParameter("includeNested")); - boolean includeRange = false; - // parseBoolean(request.getParameter("includeRange")); - String heuristicLevel = null; - // request.getParameter("relativeHeuristicLevel"); - Options.RelativeHeuristicLevel relativeHeuristicLevel = Options.RelativeHeuristicLevel.NONE; - if (!StringUtils.isNullOrEmpty(heuristicLevel)) { - relativeHeuristicLevel = Options.RelativeHeuristicLevel.valueOf(heuristicLevel); - } - String ruleFile = null; - ruleFile = getRuleFilepaths(rootDir, "defs.sutime.txt", "english.sutime.txt", - "english.holidays.sutime.txt"); - - // Create properties - Properties props = new Properties(); - if (markTimeRanges) { - props.setProperty("sutime.markTimeRanges", "true"); - } - if (includeNested) { - props.setProperty("sutime.includeNested", "true"); - } - if (includeRange) { - props.setProperty("sutime.includeRange", "true"); - } - if (ruleFile != null) { - props.setProperty("sutime.rules", ruleFile); - props.setProperty("sutime.binders", "1"); - props.setProperty("sutime.binder.1", "edu.stanford.nlp.time.JollyDayHolidays"); - - try { - props.setProperty("sutime.binder.1.xml", - (rootDir + "/WEB-INF/data/holidays/Holidays_sutime.xml")); - } catch (Exception npe) { - props.setProperty("sutime.binder.1.xml", - "/data/wildbook_data_dir/WEB-INF/data/holidays/Holidays_sutime.xml"); - npe.printStackTrace(); - } - props.setProperty("sutime.binder.1.pathtype", "file"); - } - props.setProperty("sutime.teRelHeurLevel", relativeHeuristicLevel.toString()); - props.setProperty("sutime.verbose", "true"); - -// props.setProperty("heideltime.path", getServletContext().getRealPath("/packages/heideltime")); -// props.setProperty("gutime.path", getServletContext().getRealPath("/packages/gutime")); - return props; - } - - private static List getTimeAnnotations(String query, Annotation anno, - boolean includeOffsets) { - List timexAnns = anno.get(TimeAnnotations.TimexAnnotations.class); - List pieces = new ArrayList(); - List tagged = new ArrayList(); - int previousEnd = 0; - - for (CoreMap timexAnn : timexAnns) { - int begin = timexAnn.get(CoreAnnotations.CharacterOffsetBeginAnnotation.class); - int end = timexAnn.get(CoreAnnotations.CharacterOffsetEndAnnotation.class); - if (begin >= previousEnd) { - pieces.add(query.substring(previousEnd, begin)); - tagged.add(false); - pieces.add(query.substring(begin, end)); - tagged.add(true); - previousEnd = end; - } - } - if (previousEnd < query.length()) { - pieces.add(query.substring(previousEnd)); - tagged.add(false); - } - return timexAnns; - } - - // use the current date as the reference date - private static List getDates(String query, String rootDir, SUTimePipeline pipeline) - throws IOException { - String dateString = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - - return getDates(query, rootDir, pipeline, dateString); - } - - // use a provided date as a reference date - private static List getDates(String query, String rootDir, SUTimePipeline pipeline, - String dateString) - throws IOException { - System.out.println("Entering SUTime.getDates!"); - - boolean includeOffsets = false; - // boolean includeOffsets = parseBoolean(request.getParameter("includeOffsets")); - if (!StringUtils.isNullOrEmpty(query)) { - Properties props = getTimeAnnotatorProperties(rootDir); - System.out.println(("Found props: " + props.toString())); - // String annotatorType = request.getParameter("annotator"); - // if (annotatorType == null) { - String annotatorType = "sutime"; - // } - Annotator timeAnnotator = pipeline.getTimeAnnotator(annotatorType, props); - if (timeAnnotator != null) { - Annotation anno = pipeline.process(query, dateString, timeAnnotator); - // out.println("

Annotated Text

(tagged using " + annotatorType + ")"); - List timexAnns = getTimeAnnotations(query, anno, includeOffsets); - - return timexAnns; - } else { - System.out.println("

Error creating annotator for " + - StringEscapeUtils.escapeHtml4(annotatorType)); - } - } - return null; - } - - public static SUTimePipeline createPipeline(String rootDir) { - System.out.println("Creating the SUTimePipeline!"); - SUTimePipeline pipeline; // = null; - String dataDir = ""; - - // check if we're calling this from a servlet context, which we should be - try { - dataDir = rootDir + "/WEB-INF/data"; - System.setProperty("de.jollyday.config", - (rootDir + "/WEB-INF/classes/holidays/jollyday.properties")); - } catch (Exception npe) { - // OK, we couldn't find a servlet context, so let's try to get the files from a hardcoded override directory - dataDir = "/data/wildbook_data_dir/WEB-INF/data"; - System.setProperty("de.jollyday.config", - ("/data/wildbook_data_dir/WEB-INF/classes/holidays/jollyday.properties")); - npe.printStackTrace(); - } - String taggerFilename = dataDir + "/english-left3words-distsim.tagger"; - Properties pipelineProps = new Properties(); - System.out.println("pos.model set to " + taggerFilename); - pipelineProps.setProperty("pos.model", taggerFilename); - pipeline = new SUTimePipeline(pipelineProps); - return pipeline; - } - - public static ArrayList parseStringForDates(String rootDir, String text) { - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - - return parseStringForDates(rootDir, text, relativeDate); - } - - public static ArrayList parseStringForDates(String rootDir, String text, - String relativeDate) { - ArrayList arrayListDates = new ArrayList(); - SUTimePipeline pipeline = createPipeline(rootDir); - - // clean up the text - System.out.println("parseDates with text " + text); - - // text = text.replaceAll("[,.!?;:]", "$0 "); - // System.out.println("text: " + text); - // String[] text1 = text.replaceAll("[^A-Za-z0-9 ]", " ").toLowerCase().split("\\s+"); //TODO I think this does a better version of what the - // above (text = text.replaceAll("[,.!?;:]", "$0 ");) does?? -Mark Fisher - // String text2 = String.join(" ", text1); - - // System.out.println("Cleaned up text to text2: " + text2); - - /* - try { - if (request.getCharacterEncoding() == null) { - request.setCharacterEncoding("utf-8"); - } - } - catch(Exception e) { - e.printStackTrace(); - } - */ - - try { - List timexAnnsAll = getDates(text, rootDir, pipeline, relativeDate); - for (CoreMap cm : timexAnnsAll) { - Temporal myDate = cm.get(TimeExpression.Annotation.class).getTemporal(); - // TimeExpression.Annotation:The CoreMap key for storing a TimeExpression annotation. - String dateStr = myDate.toString(); - System.out.println(".....found date: " + dateStr); - arrayListDates.add(dateStr.replaceAll("-XX", "")); - } - System.out.println("NLP dates found+:" + arrayListDates); - - // if (!arrayListDates.isEmpty()) { - // turn arrayList into an array to be able to use the old For loop and compare dates. - - // return arrayListDates; - // } - } catch (Exception ioe) { - ioe.printStackTrace(); - } - return arrayListDates; - } - - // - public static String parseDateStringForBestDate(String rootDir, String text) { - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - - return parseDateStringForBestDate(rootDir, text, relativeDate); - } - - public static String parseDateStringForBestDate(String rootDir, String text, - String relativeDate) { - ArrayList arrayListDates = parseStringForDates(rootDir, text, relativeDate); - String selectedDate = ""; - - try { - selectedDate = selectBestDateFromCandidates(arrayListDates); - } catch (Exception e) { - e.printStackTrace(); - } - if (selectedDate == null || selectedDate.equals("")) { - return null; - } else { - return selectedDate; - } - } - - public static String selectBestDateFromCandidates(ArrayList candidates) - throws Exception { - String selectedDate = ""; - - if (candidates.size() < 1) { - throw new Exception("list of candidate dates was empty"); - } else if (candidates.size() >= 1) { - // filter by options that are valid dates - ArrayList validDates = new ArrayList(); - try { - validDates = removeInvalidDates(candidates); - } catch (Exception e) { - // e.printStackTrace(); - } - try { - System.out.println(validDates); - } catch (Exception e) { - System.out.println("couldn't print validDates"); - // e.printStackTrace(); - } - // filter by options that are not in the future - ArrayList validDatesWithFutureDatesRemoved = new ArrayList(); - try { - validDatesWithFutureDatesRemoved = removeFutureDates(validDates); - System.out.println("Before future removal:"); - System.out.println(validDates); - System.out.println("After future removal:"); - System.out.println(validDatesWithFutureDatesRemoved); - } catch (Exception e) { - System.out.println("couldn't run removeFutureDates"); - // e.printStackTrace(); - } - // remove excessive past dates - ArrayList validDatesWithExcessiveDatesRemoved = new ArrayList(); - try { - validDatesWithExcessiveDatesRemoved = removeExcessivePastDates( - validDatesWithFutureDatesRemoved); - System.out.println("Before excessive past removal:"); - System.out.println(validDatesWithFutureDatesRemoved); - System.out.println("After excessive past removal:"); - System.out.println(validDatesWithExcessiveDatesRemoved); - } catch (Exception e) { - System.out.println("couldn't run removeExcessivePastDates"); - // e.printStackTrace(); - } - // if non-yesterday dates exist as well as yesterday ones, prefer the non-yesterdays. Otherwise, just get the yesterday. - ArrayList validDatesFilteredByYesterday = new ArrayList(); - try { - validDatesFilteredByYesterday = removeYesterdayDatesIfTheyAreNotTheOnlyDates( - validDatesWithExcessiveDatesRemoved); - System.out.println(validDatesFilteredByYesterday); - } catch (Exception e) { - System.out.println("couldn't print validDatesFilteredByYesterday"); - // e.printStackTrace(); - } - // Now select the longest one? - if (validDatesFilteredByYesterday == null || validDatesFilteredByYesterday.size() < 1) { - throw new Exception( - "validDatesFilteredByYesterday is null or empty before selecting the longest string"); - } - if (validDatesFilteredByYesterday.size() > 1) { - for (int j = 0; j < validDatesFilteredByYesterday.size(); j++) { - for (int k = j + 1; k < validDatesFilteredByYesterday.size(); k++) { - if (validDatesFilteredByYesterday.get(j).length() > - validDatesFilteredByYesterday.get(k).length()) { - selectedDate = validDatesFilteredByYesterday.get(j); - } else if (validDatesFilteredByYesterday.get(j).length() < - validDatesFilteredByYesterday.get(k).length()) { - selectedDate = validDatesFilteredByYesterday.get(k); - } else { - selectedDate = validDatesFilteredByYesterday.get(0); - } - } - } - } else if (validDatesFilteredByYesterday.size() == 1) { - selectedDate = validDatesFilteredByYesterday.get(0); - } - } - if (selectedDate == null || selectedDate.equals("")) { - throw new Exception( - "selectedDate either null or empty after selecting for longest one"); - } else { - return selectedDate; - } - } - - public static ArrayList removeInvalidDates(ArrayList candidates) - throws Exception { - ArrayList validDates = new ArrayList(); - DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - DateFormat df2 = new SimpleDateFormat("yyyy-MM"); - DateFormat df3 = new SimpleDateFormat("yyyy"); - String newDateString = null; - - java.util.Date candiDate; - for (int i = 0; i < candidates.size(); i++) { - String candidateString = candidates.get(i); - try { - candiDate = df.parse(candidateString); - newDateString = df.format(candiDate); - validDates.add(newDateString); - } catch (ParseException e) { - try { - candiDate = df2.parse(candidateString); - newDateString = df2.format(candiDate); - validDates.add(newDateString); - } catch (Exception f) { - try { - candiDate = df3.parse(candidateString); - newDateString = df3.format(candiDate); - validDates.add(newDateString); - } catch (Exception g) { - g.printStackTrace(); - continue; - } - } - } - } - if (validDates == null | validDates.size() < 1) { - throw new Exception( - "validDates arrayList is empty or null in removeInvalidDates method"); - } else { - return validDates; - } - } - - public static ArrayList removeFutureDates(ArrayList candidates) - throws Exception { - // TODO add handling for tweets coming from future in datelines - ArrayList returnCandidates = new ArrayList(); - - java.util.Date today = getToday(); - for (int i = 0; i < candidates.size(); i++) { - String currentDateString = candidates.get(i); - try { - java.util.Date currentDateObj = convertStringToDate(currentDateString); - if (currentDateObj == null) { - System.out.println("currentDateObj in removeFutureDates is null"); - } - if (!currentDateObj.after(today)) { - returnCandidates.add(currentDateString); - } - } catch (Exception e) { - e.printStackTrace(); - continue; - } - } - if (returnCandidates == null | returnCandidates.size() < 1) { - throw new Exception("return list is null or empty after removeFutureDates runs"); - } else { - return returnCandidates; - } - } - - public static java.util.Date convertStringToDate(String dateString) - throws Exception { - DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - DateFormat df2 = new SimpleDateFormat("yyyy-MM"); - DateFormat df3 = new SimpleDateFormat("yyyy"); - - java.util.Date returnDate = null; - try { - returnDate = df.parse(dateString); - } catch (Exception e) { - try { - returnDate = df2.parse(dateString); - } catch (Exception f) { - try { - returnDate = df3.parse(dateString); - } catch (Exception g) { - g.printStackTrace(); - } - } - } - if (returnDate == null) { - throw new Exception("date in convertStringToDate is null"); - } else { - return returnDate; - } - } - - public static java.util.Date getToday() { - final Calendar cal = Calendar.getInstance(); - - return cal.getTime(); - } - - public static ArrayList removeYesterdayDatesIfTheyAreNotTheOnlyDates( - ArrayList candidates) - throws Exception { - String yesterday = getYesterdayDateString(); - ArrayList returnCandidates = new ArrayList(); - int yesterdayCounter = 0; - - for (int i = 0; i < candidates.size(); i++) { - if (candidates.get(i).equals(yesterday)) { - yesterdayCounter++; - } else { - returnCandidates.add(candidates.get(i)); - } - } - if (yesterdayCounter == candidates.size() | yesterdayCounter == 0) { - // yesterday is the only date or yesterday doesn't occur at all - returnCandidates = candidates; - } else if (yesterdayCounter != 0 && yesterdayCounter < candidates.size()) { - // keep returnCandidates as it is from the for loop above - } - if (returnCandidates == null | returnCandidates.size() < 1) { - throw new Exception( - "removeYesterdayDatesIfTheyAreNotTheOnlyDates method returned null or empty arrayList"); - } else { - return returnCandidates; - } - } - -// use this function to remove false positive from NLP that are clearly before the project started, such as "1492" - public static ArrayList removeExcessivePastDates(ArrayList candidates) - throws Exception { -// TODO add handling for tweets coming from future in datelines - ArrayList returnCandidates = new ArrayList(); - - for (int i = 0; i < candidates.size(); i++) { - String currentDateString = candidates.get(i); - try { - java.util.Date currentDateObj = convertStringToDate(currentDateString); - if (currentDateObj == null) { - System.out.println("currentDateObj in removeFutureDates is null"); - } - if (!currentDateObj.before(convertStringToDate("1930-01-01"))) { - returnCandidates.add(currentDateString); - } - } catch (Exception e) { - e.printStackTrace(); - continue; - } - } - if (returnCandidates == null | returnCandidates.size() < 1) { - throw new Exception("return list is null or empty after removeExcessivePastDates runs"); - } else { - return returnCandidates; - } - } - - public static String getYesterdayDateString() { - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - - return dateFormat.format(getYesterday()); - } - - public static java.util.Date getYesterday() { - final Calendar cal = Calendar.getInstance(); - - cal.add(Calendar.DATE, -1); - return cal.getTime(); - } - -// overloaded version to deal with tweets - public static String parseDateStringForBestDate(String rootDir, Status tweet) - throws Exception { - String text = TwitterUtil.getText(tweet); - - System.out.println("Entering nlpDateParse twitter version with text " + text); -// create my pipeline with the help of the annotators I added. - - // Date tweetDate=tweet.getCreatedAt(); - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - String selectedDate = parseDateStringForBestDate(rootDir, text, relativeDate); - System.out.println("Best guess for referenced Tweet date from NLP: " + selectedDate); - return selectedDate; - } -} diff --git a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java b/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java deleted file mode 100644 index b2da0c3a02..0000000000 --- a/src/main/java/org/ecocean/ai/utilities/ParseDateLocation.java +++ /dev/null @@ -1,673 +0,0 @@ -package org.ecocean.ai.utilities; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.Collection; -import java.util.Date; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; -import java.util.regex.*; - -import javax.jdo.Query; -import org.ecocean.ai.nlp.SUTime; -import org.ecocean.ai.nmt.azure.DetectTranslate; -import org.ecocean.Encounter; -import org.ecocean.identity.IBEISIA; -import org.ecocean.LinkedProperties; -import org.ecocean.media.MediaAsset; -import org.ecocean.media.MediaAssetMetadata; -import org.ecocean.media.YouTubeAssetStore; -import org.ecocean.Occurrence; -import org.ecocean.Shepherd; -import org.ecocean.ShepherdProperties; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; -import org.json.JSONObject; - -import com.google.api.services.youtube.model.Comment; -import com.google.api.services.youtube.model.CommentSnippet; -import com.google.api.services.youtube.model.CommentThread; -import com.google.api.services.youtube.model.CommentThreadReplies; -import com.google.api.services.youtube.model.CommentThreadSnippet; - -import twitter4j.Status; - -public class ParseDateLocation { - public static ArrayList parseLocation(String text, String context) { - ArrayList locations = new ArrayList<>(); - - // translate to English if not English - try { - text = detectLanguageAndTranslateToEnglish(text, context); - } catch (RuntimeException e) { - e.printStackTrace(); - } - // check for obvious Encounter.locationIDs - try { - locations.add(getLocationCodeKey(text, context)); - } catch (RuntimeException e) { - e.printStackTrace(); - } - /* - //use NLP - TO DO try{ - ArrayList nlpLocations = nlpLocationParse(text); - for (int i = 0; i>>>>> looking for date with NLP"); - // call Stanford NLP function to find and select a date from ytRemarks - myDate = org.ecocean.ai.nlp.SUTime.parseDateStringForBestDate(rootDir, tweet); - // parse through the selected date to grab year, month and day separately.Remove cero from month and day with intValue. - System.out.println(">>>>>> NLP found date: " + myDate); - } catch (Exception e) { - System.out.println("Exception in NLP in IBEISIA.class"); - e.printStackTrace(); - } - return myDate; - } - return null; - } - - - // NOTE: parseDate method WITHOUT tweet4j status object as a parameter. There is another parseDate method! - public static String parseDate(String rootDir, String textInput, String context) { - // int year=-1; - // int month=-1; - // int day=-1; - - try { - String detectedLanguage = DetectTranslate.detectLanguage(textInput); - if (!detectedLanguage.toLowerCase().startsWith("en")) { - textInput = DetectTranslate.translateToEnglish(textInput); - System.out.println("Translated text for parseLocation is " + textInput); - } - } catch (Exception e) { - System.out.println("Exception trying to detect language."); - e.printStackTrace(); - } - String myDate = null; - - // boolean NLPsuccess=false; - try { - System.out.println(">>>>>> looking for date with NLP"); - // call Stanford NLP function to find and select a date from ytRemarks - myDate = org.ecocean.ai.nlp.SUTime.parseDateStringForBestDate(rootDir, textInput); - System.out.println(">>>>>> NLP found date: " + myDate); - } catch (Exception e) { - System.out.println("Exception in NLP in IBEISIA.class"); - e.printStackTrace(); - } - return myDate; - } - - -/** - * Pass in a MediaAsset that derives from a YouTube video, and this method will go check for any additional info, such as response comments, that - * might help refine or populate derived Encounter dates and locations - * - * @param ma - * @param suDirPath - * @param myShepherd a Shepherd object - * @param context The context that WIldbook is running in. A null value will assume context0. - * @param numVideosWithID Allows you to keep a running, thread-safe tabulation of videos that have resulted in individualIDs. Can be null. - * @param numVideos Allows you to keep a running, thread-safe tabulation of a total number of videos as a result of running this method repeatedly. - * Can be null. - * @param numUncuratedVideos Allows you to keep a running, thread-safe tabulation of videos that have NOT been curated (Encounter.state != approved or - * unidentifiable). Can be null. - * @param numCommentedVideos Allows you to keep a running, thread-safe tabulation of videos that the IntelligentAgent has commented upon. Can be null. - * @param numCommentedVideosReplies Allows you to keep a running, thread-safe tabulation of videos that the IntelligentAgent has commented upon AND - * that have replies. Can be null. - * @param goodDataVideos Allows you to keep a running tab of appropriate videos processed outside this method. Can be null. - * @param poorDataVideos Allows you to keep a running tab of inappropriate videos processed outside this method. Can be null. - * @param persistDifferences Whether to save the updated date and location values found by the Intelligent Agent during executing this method. - * @param numDatesFound Allows you to keep a running, thread-safe tabulation of a total number of video-derived date updates made as a result of - * running this method repeatedly. Can be null. - * @param numLocationIDsFound Allows you to keep a running, thread-safe tabulation of a total number of video-derived location updates made as a - * result of running this method repeatedly. Can be null. - * @return String an HTML table row of found text and changes - */ - public static String annotateChildrenOfYouTubeMediaAssetWithDateLocation(MediaAsset ma, - String suDirPath, Shepherd myShepherd, String context, AtomicInteger numVideosWithID, - AtomicInteger numVideos, AtomicInteger numUncuratedVideos, AtomicInteger numCommentedVideos, - AtomicInteger numCommentedVideosReplies, ArrayList goodDataVideos, - ArrayList poorDataVideos, boolean persistDifferences, - AtomicInteger numDatesFound, AtomicInteger numLocationIDsFound) { - // if we're going to persist changes, ensure the Shepherd object is ready - if (persistDifferences && !myShepherd.getPM().currentTransaction().isActive()) { - myShepherd.beginDBTransaction(); - } - // allow context to be NULL but assume context0 if it is set as null - if (context == null) context = "context0"; - // the return string of HTML content - String resultsHTML = ""; - - // whether the video has resulted in an Encounter assigned to a MarkedIndividual - boolean videoHasID = false; - - // whether we found a Wild Me comment on the video - boolean hasWildMeComment = false; - - // whether any found Wild Me comment has a reply - boolean hasWildMeCommentReplies = false; - - // the date of the video, allowing for relative evaluation of the true date via SUTime - // to start with, we assume today's dat but will process this later. - String relativeDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); - // video has metadata for analysis? - if ((ma.getMetadata() != null)) { - if (numVideos != null) numVideos.incrementAndGet(); - MediaAssetMetadata md = ma.getMetadata(); - // video metadata is not null, so proceed - if (md.getData() != null) { - // setup our metadata fields - String videoID = ma.getMetadata().getData().getJSONObject("detailed").optString( - "id"); - String videoTitle = ""; - // just to save money on language detection, reduce number of characters sent - String videoTitleShort = videoTitle; - String videoComments = ""; - String videoCommentsClean = ""; - String locIDWords = ""; - String videoDescription = ""; - String videoTags = ""; - // start capturing metadata about the YouTube video - // video title short form just to save $$$ on language detection by sending fewer characters - if (videoTitle.length() > 500) { videoTitleShort = videoTitle.substring(0, 500); } - if (md.getData().optJSONObject("basic") != null) { - videoTitle = AIUtilities.youtubePredictorPrepareString( - md.getData().getJSONObject("basic").optString("title")); - } - if (md.getData().optJSONObject("detailed") != null) { - videoDescription = AIUtilities.youtubePredictorPrepareString( - md.getData().getJSONObject("detailed").optString("description")); - videoTags = AIUtilities.youtubePredictorPrepareString( - md.getData().getJSONObject("detailed").getJSONArray("tags").toString()); - } - // video description short form just to save $$$ on language detection by sending fewer characters - String videoDescriptionShort = videoDescription; - if (videoDescription.length() > 1000) { - videoDescriptionShort = videoDescription.substring(0, 1000); - } - // video tags short form just to save $$$ on language detection by sending fewer characters - String videoTagsShort = videoTags; - if (videoTags.length() > 500) { videoTagsShort = videoTags.substring(0, 500); } - String ytRemarks = videoTitle + " " + videoDescription + " " + videoTags; - String storedLanguage = "null"; - String detectedLanguage = "en"; - boolean languageIsStored = false; - // first, set metadata lanuage on the mediaasset - if (md.getData().optJSONObject("detected") != null) { - if (md.getData().getJSONObject("detected").optString("langCode") != null) { - String storedData = md.getData().getJSONObject("detected").optString( - "langCode"); - if ((!storedData.trim().equals("")) && - (storedData.toLowerCase().indexOf("unknown") == -1)) { - // if(!detectedLanguage.equals(storedData))changedDetectedLanguage=true; - detectedLanguage = storedData; - languageIsStored = true; - } - } - } - if (!languageIsStored) { - try { - detectedLanguage = DetectTranslate.detectLanguage(videoTitleShort + " " + - videoDescriptionShort + " " + videoTagsShort); - JSONObject json = md.getData(); - JSONObject jsonDetected = new JSONObject(); - jsonDetected.put("langCode", detectedLanguage); - json.put("detected", jsonDetected); - md.setData(json); - ma.setMetadata(new MediaAssetMetadata(json)); - // ma.setMetadata(md); - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } catch (Exception e) { - e.printStackTrace(); - } - } - // Let's get the Encounter objects related to this video - // JDOQL query - String qFilter = - "SELECT FROM org.ecocean.Encounter WHERE (occurrenceRemarks.indexOf('" + - videoID + "') != -1)"; - Query newQ = myShepherd.getPM().newQuery(qFilter); - Collection d = (Collection)newQ.execute(); - ArrayList encresults = new ArrayList(d); - newQ.closeAll(); - int numEncs = encresults.size(); - - // let's iterate our matching Encounters - // first, check if any have been approved (curated) and count them - boolean videoIsCurated = false; - for (int y = 0; y < numEncs; y++) { - Encounter enc = encresults.get(y); - if ((enc.getState() != null) && - ((enc.getState().equals("approved")) || - (enc.getState().equals("unidentifiable")))) { - if ((goodDataVideos != null) && !goodDataVideos.contains(ma)) - goodDataVideos.add(ma); - videoIsCurated = true; - } - if ((enc.getIndividualID() != null) && (!enc.getIndividualID().equals(""))) - videoHasID = true; - } - if (!videoIsCurated && (numUncuratedVideos != null)) - numUncuratedVideos.incrementAndGet(); - Occurrence occur = null; - LinkedProperties props = (LinkedProperties)ShepherdProperties.getProperties( - "submitActionClass.properties", "", context); - String chosenStyleDate = ""; - String chosenStyleLocation = ""; - // if we have matching encounters, then the video is either uncurated, or it has been determined to have useful data (curated) - if (numEncs > 0) { - // check for Occurrence - String occurID = ""; - - // grab the first Encounter for analysis - Encounter enc = encresults.get(0); - - // get the current values for date and location ID - String currentDate = ""; - String currentLocationID = ""; - if (enc.getDate() != null) - currentDate = enc.getDate().replaceAll("Unknown", ""); - if (enc.getLocationID() != null) - currentLocationID = enc.getLocationID().replaceAll("None", ""); - // our encounters should all have an Occurrence, one per video - if (enc.getOccurrenceID() != null) { - occur = myShepherd.getOccurrence(enc.getOccurrenceID()); - - // let's get all our YouTube video metadata and comments - // List comments = YouTube.getVideoCommentsList(occur, context); deprecated, issue 622 - List comments = null; - if ((comments == null) || (comments.size() == 0)) { - videoComments = ""; - videoCommentsClean = ""; - } else { - boolean isWildMeComment = false; - int numComments = comments.size(); - videoComments += "
    \n"; - for (int f = 0; f < numComments; f++) { - CommentThread ct = comments.get(f); - CommentThreadSnippet cts = ct.getSnippet(); - Comment topLevelComment = cts.getTopLevelComment(); - CommentSnippet commentSnippet = topLevelComment.getSnippet(); - String authorName = ""; - if ((commentSnippet != null) && - (commentSnippet.getAuthorDisplayName() != null)) { - authorName = commentSnippet.getAuthorDisplayName(); - // TO DO: set this aside to a Properties file for the agent - if (authorName.equals("Wild Me")) isWildMeComment = true; - } - String style = ""; - if (isWildMeComment) { - style = "color: green;font-weight: bold;"; - hasWildMeComment = true; - } - videoComments += "
  • " + authorName + - ": " + - DetectTranslate.translateIfNotEnglish( - topLevelComment.getSnippet().getTextDisplay()); - - videoCommentsClean += DetectTranslate.translateIfNotEnglish( - topLevelComment.getSnippet().getTextDisplay()).toLowerCase() + - " "; - if (ct.getReplies() != null) { - CommentThreadReplies ctr = ct.getReplies(); - List replies = ctr.getComments(); - int numReplies = 0; - if (replies != null) numReplies = replies.size(); - if (numReplies > 0) { - if (isWildMeComment) hasWildMeCommentReplies = true; - videoComments += "
      \n"; - for (int g = 0; g < numReplies; g++) { - Comment reply = replies.get(g); - - videoComments += "
    • " + - DetectTranslate.translateIfNotEnglish( - reply.getSnippet().getTextDisplay()) + "
    • "; - videoCommentsClean += - DetectTranslate.translateIfNotEnglish( - reply.getSnippet().getTextDisplay()).toLowerCase() + - " "; - } - videoComments += "
    \n"; - } - } - videoComments += "
  • \n"; - style = ""; - } - videoComments += "
\n"; - } - occurID = occur.getOccurrenceID(); - - // prep the YouTube video date for SUTimee analysis - String tempRelativeDate = null; - try { - // tempRelativeDate = YouTube.getVideoPublishedAt(occur, context); deprecated, issue 622 - tempRelativeDate = null; - } catch (Exception e) {} - if ((tempRelativeDate != null) && (tempRelativeDate.indexOf("T") != -1)) { - tempRelativeDate = tempRelativeDate.substring(0, - tempRelativeDate.indexOf("T")); - } - if ((tempRelativeDate != null) && (!tempRelativeDate.equals(""))) { - DateTimeFormatter parser2 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTime time = parser2.parseDateTime(tempRelativeDate); - relativeDate = time.toString(parser2); - } - } - StringBuffer sbOriginalText = new StringBuffer(""); - sbOriginalText.append(videoTitle + " " + videoDescription + " " + videoTags + - " " + videoCommentsClean); - - // let's do some translation to English for standardization - videoTitle = DetectTranslate.translateIfNotEnglish(videoTitleShort); - videoTags = DetectTranslate.translateIfNotEnglish(videoTagsShort); - videoDescription = DetectTranslate.translateIfNotEnglish(videoDescriptionShort); - - StringBuffer sb = new StringBuffer(""); - - sb.append(videoTitle + " " + videoDescription + " " + videoTags + " " + - videoCommentsClean); - - // get video date with SUTime - String newDetectedDate = ""; - try { - newDetectedDate = SUTime.parseDateStringForBestDate(suDirPath, - sb.toString(), relativeDate).replaceAll("null", ""); - } catch (Exception e) { - e.printStackTrace(); - } - if ((numDatesFound != null) && (goodDataVideos != null) && - goodDataVideos.contains(ma) && !newDetectedDate.equals("")) { - numDatesFound.incrementAndGet(); - } - // determine new LocationID, including comments - String newLocationID = ""; - String lowercaseRemarks = sb.toString().toLowerCase(); - try { - Iterator m_enum = props.orderedKeys().iterator(); - while (m_enum.hasNext()) { - String aLocationSnippet = ((String)m_enum.next()).replaceFirst("\\s++$", - ""); - // System.out.println(" Looking for: "+aLocationSnippet); - if (lowercaseRemarks.indexOf(aLocationSnippet) != -1) { - newLocationID = props.getProperty(aLocationSnippet); - locIDWords += " " + aLocationSnippet; - // System.out.println(".....Building an idea of location: "+location); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - if (newLocationID == null) newLocationID = ""; - if ((numLocationIDsFound != null) && (goodDataVideos != null) && - goodDataVideos.contains(ma) && !newLocationID.equals("")) { - numLocationIDsFound.incrementAndGet(); - } - // here is where we would put logic to update encounters if appropriate - if (persistDifferences) { - boolean madeAChange = false; - for (int y = 0; y < numEncs; y++) { - Encounter thisEnc = encresults.get(y); - // SET LOCATION ID - // first, if we even found a location ID in comments, lets' consider it. - // otherwise, there's no point - if ((newLocationID != null) && (!newLocationID.trim().equals(""))) { - // next, if we have a new locationID and one was not set before, then this is an easy win - if ((thisEnc.getLocationID() == null) || - (thisEnc.getLocationID().trim().equals("")) || - (thisEnc.getLocationID().trim().equals("None"))) { - thisEnc.setLocationID(newLocationID); - madeAChange = true; - } else if (!thisEnc.getLocationID().trim().equals( - newLocationID.trim())) { - // ok, the location IDs are different, now what? - // maybe the newLocationID further specifies the older locationID, that would be a win - if (newLocationID.trim().startsWith( - thisEnc.getLocationID().trim())) { - thisEnc.setLocationID(newLocationID.trim()); - madeAChange = true; - } - // if the Encounter is not yet approved, then we can reset it as well since it's uncurated and may have been - // incorrectly detected with older values - else if ((thisEnc.getState() != null) && - (thisEnc.getState().equals("auto_sourced"))) { - thisEnc.setLocationID(newLocationID.trim()); - madeAChange = true; - } - } - } - // now persist - if (madeAChange) { - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } - if (madeAChange) chosenStyleLocation = "font-style: italic;"; - // END SET LOCATION ID - - // SET THE DATE - madeAChange = false; - chosenStyleDate += "year: " + thisEnc.getYear() + ";millis:" + - thisEnc.getDateInMilliseconds() + ";locationID: " + - thisEnc.getLocationID() + ";"; - // let's check and fix date - if ((newDetectedDate != null) && (!newDetectedDate.trim().equals(""))) { - // well we have something to analyze at least - // DateTimeFormatter parser3 = DateTimeFormat.forPattern("yyyy-MM-dd"); - DateTimeFormatter parser3 = ISODateTimeFormat.dateParser(); - DateTime dt = parser3.parseDateTime(newDetectedDate); - // check for the easy case - if ((thisEnc.getDateInMilliseconds() == null) || - (thisEnc.getYear() <= 0)) { - if (newDetectedDate.length() == 10) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - thisEnc.setDay(dt.getDayOfMonth()); - } else if (newDetectedDate.length() == 7) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - } else if (newDetectedDate.length() == 4) { - thisEnc.setYear(dt.getYear()); - } - // thisEnc.setDateInMilliseconds(dt.getMillis()); - - chosenStyleDate += "font-style: italic; color: red;"; - madeAChange = true; - } - // if it's unapproved/uncurated, trust the newer value - else if (thisEnc.getState().equals("auto_sourced")) { - if (newDetectedDate.length() == 10) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - thisEnc.setDay(dt.getDayOfMonth()); - } else if (newDetectedDate.length() == 7) { - thisEnc.setYear(dt.getYear()); - thisEnc.setMonth(dt.getMonthOfYear()); - } else if (newDetectedDate.length() == 4) { - thisEnc.setYear(dt.getYear()); - } - chosenStyleDate += "font-style: italic; color: green;"; - madeAChange = true; - } - } - // now persist - if (madeAChange) { - myShepherd.commitDBTransaction(); - myShepherd.beginDBTransaction(); - } - // END SET DATE - } - } - resultsHTML = - "" + occurID + - "" + videoID + "" + currentDate + - "

" + newDetectedDate + - "

" + currentLocationID + "

" + newLocationID + "

" + videoTitle + - "" + videoDescription + "" + videoComments + "" + - videoCommentsClean + "

LocID Words: " + locIDWords + - "

" + relativeDate + "" + storedLanguage + "/" + - detectedLanguage + ""; - } - // this video had no encounters, probably been curated as having no value - else { - if ((poorDataVideos != null) && !poorDataVideos.contains(ma)) { - poorDataVideos.add(ma); - if (numUncuratedVideos != null) numUncuratedVideos.decrementAndGet(); - } - } - } - // video metadata is null, not much we can do here - else { - if ((poorDataVideos != null) && !poorDataVideos.contains(ma)) - poorDataVideos.add(ma); - } - } - // video had no metadata, not much we can do here - // add to poorDataVideos because there's nothing we can with it - else { - if ((poorDataVideos != null) && !poorDataVideos.contains(ma)) poorDataVideos.add(ma); - } - // increment our counters as needed - if (hasWildMeComment && (numCommentedVideos != null)) numCommentedVideos.incrementAndGet(); - if (hasWildMeCommentReplies && (numCommentedVideosReplies != null)) - numCommentedVideosReplies.incrementAndGet(); - if (videoHasID && (numVideosWithID != null)) numVideosWithID.incrementAndGet(); - return resultsHTML; - } - - public static boolean hasRunDetection(MediaAsset ma, Shepherd myShepherd) { - List children = YouTubeAssetStore.findFrames(ma, myShepherd); - - if (children != null) { - int numChildren = children.size(); - for (int i = 0; i < numChildren; i++) { - MediaAsset child = children.get(i); - if ((child.getDetectionStatus() != null) && - (child.getDetectionStatus().equals(IBEISIA.STATUS_COMPLETE))) { - return true; - } - } - } - return false; - } -} diff --git a/src/main/java/org/ecocean/servlet/SUTimePipeline.java b/src/main/java/org/ecocean/servlet/SUTimePipeline.java deleted file mode 100644 index 832bf558ec..0000000000 --- a/src/main/java/org/ecocean/servlet/SUTimePipeline.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.ecocean.servlet; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.IOException; -import java.util.Properties; - -import edu.stanford.nlp.ling.CoreAnnotations; -import edu.stanford.nlp.pipeline.Annotation; -import edu.stanford.nlp.pipeline.Annotator; -import edu.stanford.nlp.pipeline.StanfordCoreNLP; -import edu.stanford.nlp.time.GUTimeAnnotator; -import edu.stanford.nlp.time.HeidelTimeAnnotator; -import edu.stanford.nlp.time.TimeAnnotations; -import edu.stanford.nlp.time.TimeAnnotator; - -public class SUTimePipeline { - /** A logger for this class */ - // private static Redwood.RedwoodChannels log = Redwood.channels(SUTimePipeline.class); - final StanfordCoreNLP pipeline; - - public SUTimePipeline() { - this(new Properties()); - } - - public SUTimePipeline(Properties props) { - // By default, we want to tokenize the text, split it into - // sentences, and then put it through the sutime annotator. - // We also want to pos tag it and put it through the number and - // qen annotators. - // Since there will be different options for the sutime annotator, - // we will actually create a new sutime annotator for each query. - // This should be inexpensive. - if (props.getProperty("annotators") == null) { - props.setProperty("annotators", "tokenize, ssplit, pos"); -// "tokenize, ssplit, pos, number, qen"); - } -/* if (props.getProperty("customAnnotatorClass.number") == null) { - props.setProperty("customAnnotatorClass.number", - "edu.stanford.nlp.pipeline.NumberAnnotator"); - } - if (props.getProperty("customAnnotatorClass.qen") == null) { - props.setProperty("customAnnotatorClass.qen", - "edu.stanford.nlp.pipeline.QuantifiableEntityNormalizingAnnotator"); - } */ - // this replicates the tokenizer behavior in StanfordCoreNLP - props.setProperty("tokenize.options", "invertible,ptb3Escaping=true"); - this.pipeline = new StanfordCoreNLP(props); - } - - public boolean isDateOkay(String dateString) { - return true; // TODO: can we predict which ones it won't like? - } - - public Annotator getTimeAnnotator(String annotatorType, Properties props) { - switch (annotatorType) { - case "sutime": - return new TimeAnnotator("sutime", props); - case "gutime": - return new GUTimeAnnotator("gutime", props); - case "heideltime": - return new HeidelTimeAnnotator("heidelTime", props); - default: - return null; - } - } - - public Annotation process(String sentence, String dateString, Annotator timeAnnotator) { - // log.info("Processing text \"" + sentence + "\" with dateString = " + dateString); - Annotation anno = new Annotation(sentence); - - if (dateString != null && !dateString.isEmpty()) { - anno.set(CoreAnnotations.DocDateAnnotation.class, dateString); - } - pipeline.annotate(anno); - - timeAnnotator.annotate(anno); - return anno; - } - - public static void main(String[] args) - throws IOException { - SUTimePipeline pipeline = new SUTimePipeline(); - Annotator timeAnnotator = pipeline.getTimeAnnotator("sutime", new Properties()); - BufferedReader is = new BufferedReader(new InputStreamReader(System.in)); - - System.out.print("> "); - for (String line; (line = is.readLine()) != null;) { - Annotation ann = pipeline.process(line, null, timeAnnotator); - System.out.println(ann.get(TimeAnnotations.TimexAnnotations.class)); - System.out.print("> "); - } - } -} From a292a7172f9daf69b6dd267083924e5825b8f334 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Tue, 27 Aug 2024 16:10:39 -0600 Subject: [PATCH 14/20] remove pom dependencies, and some misc --- pom.xml | 27 ------------------- .../org/ecocean/media/YouTubeAssetStore.java | 3 +++ src/main/webapp/WEB-INF/web.xml | 1 - 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index f36c2b1d74..3a3339bd31 100644 --- a/pom.xml +++ b/pom.xml @@ -515,33 +515,6 @@ 0.6.1
- - - edu.stanford.nlp - stanford-corenlp - 3.9.1 - - - com.google.protobuf - protobuf-java - - - - - - - sutime-stanford-corenlp-models - sutime-stanford-corenlp-models - 3.6.0 - - - - - edu.stanford.nlp - stanford-parser - 3.9.1 - - nz.ac.waikato.cms.weka diff --git a/src/main/java/org/ecocean/media/YouTubeAssetStore.java b/src/main/java/org/ecocean/media/YouTubeAssetStore.java index 506c0c8262..2085c0a737 100644 --- a/src/main/java/org/ecocean/media/YouTubeAssetStore.java +++ b/src/main/java/org/ecocean/media/YouTubeAssetStore.java @@ -18,6 +18,9 @@ import org.json.JSONException; import org.json.JSONObject; + +// soon to be deprecated: https://github.com/WildMeOrg/Wildbook/issues/694 + /** * YouTubeAssetStore references MediaAssets that reside on YouTube. * currently this is read-only but later could be writable with an API key if needed? diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 85c5981d27..8a643f2a9b 100755 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -404,7 +404,6 @@ /SimpleCMRSpecifySessions.jsp = authc, roles[researcher] /occurrenceExportSearchResults.jsp = authc, roles[researcher] - /sutime/** = authc /EncounterRemoveUser = authc, roles[researcher] /EncounterAddUser = authc, roles[researcher] From 477ff77382797b019559cd8bd95dfd4d0b851cc3 Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Wed, 28 Aug 2024 14:27:23 -0600 Subject: [PATCH 15/20] rm commented deprecated call --- src/main/java/org/ecocean/media/YouTubeAssetStore.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/org/ecocean/media/YouTubeAssetStore.java b/src/main/java/org/ecocean/media/YouTubeAssetStore.java index 2085c0a737..f94138a9fb 100644 --- a/src/main/java/org/ecocean/media/YouTubeAssetStore.java +++ b/src/main/java/org/ecocean/media/YouTubeAssetStore.java @@ -332,13 +332,6 @@ public MediaAssetMetadata extractMetadata(MediaAsset ma, boolean minimal) JSONObject data = new JSONObject(); // we (attempt to) let the basic stuff finish synchronously, so we have a populated data chunk to save (hopefully)before the detailed one does -/* deprecated due to issue 622, retirement of YouTube agent - try { - data.put("basic", YouTube.simpleInfo(idFromParameters(ma.getParameters()))); - } catch (Exception ex) { - System.out.println(ma + " failed simpleInfo(): " + ex.toString()); - } -*/ if (!minimal) { data.put("detailed", new JSONObject("{\"_processing\": true, \"timestamp\": " + From 29345858a69a40046363bd71b614fc745f550d6e Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Thu, 29 Aug 2024 12:14:01 -0600 Subject: [PATCH 16/20] more cruft gone --- .../servlet/IndividualAddEncounter.java | 7 - .../WEB-INF/data/holidays/Holidays_sutime.xml | 44 - .../WEB-INF/data/sutime/rules/defs.sutime.txt | 201 ---- .../sutime/rules/english.holidays.sutime.txt | 29 - .../data/sutime/rules/english.sutime.txt | 964 ------------------ 5 files changed, 1245 deletions(-) delete mode 100644 src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml delete mode 100644 src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt delete mode 100644 src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt delete mode 100644 src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt diff --git a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java index 338cbb55e2..ccd629a6df 100644 --- a/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java +++ b/src/main/java/org/ecocean/servlet/IndividualAddEncounter.java @@ -130,9 +130,6 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) // responseJSON=RESTUtils.getJSONObjectFromPOJO(addToMe, // ((JDOPersistenceManager)myShepherd.getPM()).getExecutionContext()).toString(); responseJSON = addToMe.uiJson(request, false).toString(); - - // youTube postback check - youTubePostback(enc2add, myShepherd, context); } catch (RuntimeException e) { e.printStackTrace(); myShepherd.rollbackDBTransaction(); @@ -305,10 +302,6 @@ public static void executeEmails(Shepherd myShepherd, HttpServletRequest request es.shutdown(); } - private void youTubePostback(Encounter enc2add, Shepherd myShepherd, String context) { - System.out.println("youTubePostback(): YouTube agent support has been deprecated"); - } - private void setDateLastModified(Encounter enc) { String strOutputDateTime = ServletUtilities.getDate(); diff --git a/src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml b/src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml deleted file mode 100644 index 3523b42b13..0000000000 --- a/src/main/webapp/WEB-INF/data/holidays/Holidays_sutime.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt b/src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt deleted file mode 100644 index 28afa933af..0000000000 --- a/src/main/webapp/WEB-INF/data/sutime/rules/defs.sutime.txt +++ /dev/null @@ -1,201 +0,0 @@ - RefTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$RefTime" } - SimpleTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$SimpleTime" } - InexactTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$InexactTime" } - InexactDuration = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$InexactDuration" } - DurationWithFields = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$DurationWithFields" } - //Duration = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$Duration" } - IsoDate = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$IsoDate" } - IsoTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$IsoTime" } - TimeRange = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$Range" } - TimeWithRange = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$TimeWithRange" } - RelativeTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$RelativeTime" } - OrdinalTime = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$OrdinalTime" } - PeriodicTemporalSet = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$PeriodicTemporalSet" } - ExplicitTemporalSet = { type: "CLASS", value: "edu.stanford.nlp.time.SUTime$ExplicitTemporalSet" } - - ANY = -1; - NONE = -1; - NON_TEMPORAL = "NON_TEMPORAL"; - - DURATION_UNKNOWN = DurationWithFields(); - DURATION_NONE = DurationWithFields(); - - TIME_NOW = { - type: REFTIME, - label: "PRESENT_REF", - value: RefTime("NOW") - } - TIME_PRESENT = { - type: REFDATE, - label: "PRESENT_REF", - value: InexactTime( TimeRange(TIME_NOW, TIME_NOW) ) - } - TIME_PAST = { - type: REFDATE, - label: "PAST_REF", - value: InexactTime( TimeRange(TIME_UNKNOWN, TIME_NOW) ) - } - TIME_FUTURE = { - type: REFDATE, - label: "FUTURE_REF", - value: InexactTime( TimeRange(TIME_NOW, TIME_UNKNOWN) ) - } - - // Predefined durations: YEAR, MONTH, DAY, WEEK, HOUR, MINUTE, SECOND - FORTNIGHT = { type: "TIMEUNIT", value: Duration(WEEK, 2) }; - HALFHOUR = Duration(MINUTE, 30); - QUARTERHOUR = Duration(MINUTE, 15); - - // Basic dates/times - MONDAY = DayOfWeek(1); - TUESDAY = DayOfWeek(2); - WEDNESDAY = DayOfWeek(3); - THURSDAY = DayOfWeek(4); - FRIDAY = DayOfWeek(5); - SATURDAY = DayOfWeek(6); - SUNDAY = DayOfWeek(7); - - WEEKEND = { - type: DAYS_OF_WEEK, - label: "WE", - value: TimeWithRange(TimeRange(SATURDAY, SUNDAY, Duration(DAY, 2))) - } - - JANUARY = MonthOfYear(1); - FEBRUARY = MonthOfYear(2); - MARCH = MonthOfYear(3); - APRIL = MonthOfYear(4); - MAY = MonthOfYear(5); - JUNE = MonthOfYear(6); - JULY = MonthOfYear(7); - AUGUST = MonthOfYear(8); - SEPTEMBER = MonthOfYear(9); - OCTOBER = MonthOfYear(10); - NOVEMBER = MonthOfYear(11); - DECEMBER = MonthOfYear(12); - - // Dates are rough with respect to northern hemisphere (actual - // solstice/equinox days depend on the year) - SPRING_EQUINOX = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 3, 20), IsoDate(ANY, 3, 21) ) ) - } - SUMMER_SOLSTICE = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 6, 20), IsoDate(ANY, 6, 21) ) ) - } - FALL_EQUINOX = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 9, 22), IsoDate(ANY, 9, 23) ) ) - } - WINTER_SOLSTICE = { - type: DAY_OF_YEAR, - value: InexactTime( TimeRange( IsoDate(ANY, 12, 21), IsoDate(ANY, 12, 22) ) ) - } - - // Dates for seasons are rough with respect to northern hemisphere - SPRING = { - type: SEASON_OF_YEAR, - label: "SP", - value: InexactTime( SPRING_EQUINOX, QUARTER, TimeRange( MARCH, JUNE, QUARTER ) ) } - SUMMER = { - type: SEASON_OF_YEAR, - label: "SU", - value: InexactTime( SUMMER_SOLSTICE, QUARTER, TimeRange( JUNE, SEPTEMBER, QUARTER ) ) - } - FALL = { - type: SEASON_OF_YEAR, - label: "FA", - value: InexactTime( FALL_EQUINOX, QUARTER, TimeRange( SEPTEMBER, DECEMBER, QUARTER ) ) - } - WINTER = { - type: SEASON_OF_YEAR, - label: "WI", - value: InexactTime( WINTER_SOLSTICE, QUARTER, TimeRange( DECEMBER, MARCH, QUARTER ) ) - } - - // Time of day - NOON = IsoTime( 12, 0, NONE ) - MIDNIGHT = IsoTime( 0, 0, NONE ) - MORNING = { - type: TIME_OF_DAY, - label: "MO", - value: InexactTime( TimeRange ( IsoTime( 6, NONE, NONE), NOON ) ) - } - AM = IsoTime(NIL, NIL, NIL, NIL, HALFDAY_AM) - PM = IsoTime(NIL, NIL, NIL, NIL, HALFDAY_PM) - AFTERNOON = { - type: TIME_OF_DAY, - label: "AF", - value: InexactTime( TimeRange ( NOON, IsoTime( 18, NONE, NONE) ) ) - } - EVENING = { - type: TIME_OF_DAY, - label: "EV", - value: InexactTime( TimeRange ( IsoTime( 18, NONE, NONE), IsoTime ( 20, NONE, NONE) ) ) - } - NIGHT = { - type: TIME_OF_DAY, - label: "NI", - value: InexactTime( MIDNIGHT, TimeRange ( IsoTime( 19, NONE, NONE), Duration(HOUR, 10) ) ) - } - - SUNRISE = { - type: TIME_OF_DAY, - label: "MO", - modifier: "EARLY" - } - - SUNSET = { - type: TIME_OF_DAY, - label: "EV", - modifier: "EARLY" - } - - DAWN = { - type: TIME_OF_DAY, - label: "MO", - modifier: "EARLY" - } - - DUSK = { - type: TIME_OF_DAY, - label: "EV", - modifier: "EARLY" - } - - LUNCHTIME = InexactTime( TimeRange( IsoTime(12, NONE, NONE), IsoTime(14, NONE, NONE) )) - TEATIME = InexactTime( TimeRange( IsoTime(15, NONE, NONE), IsoTime(17, NONE, NONE) )) - DINNERTIME = InexactTime( TimeRange( IsoTime(18, NONE, NONE), IsoTime(20, NONE, NONE) )) - - DAYTIME = { - type: TIME_OF_DAY, - label: "DT", - value: InexactTime( TimeRange(DAWN, SUNSET) ) - } - MORNING_TWILIGHT = { - type: TIME_OF_DAY, - label: "MO", - value: InexactTime( TimeRange(DAWN, SUNRISE) ) - } - EVENING_TWILIGHT = { - type: TIME_OF_DAY, - label: "EV", - value: InexactTime( TimeRange(SUNSET, DUSK) ) - } - // For now, just have TWILIGHT be same as EVENING_TWILIGHT (could possibly be MORNING_TWILIGHT || EVENING_TWILIGHT) - TWILIGHT = EVENING_TWILIGHT - - // Relative days - YESTERDAY = RelativeTime( Duration(DAY, -1) ); - TOMORROW = RelativeTime( Duration(DAY, +1) ); - TODAY = RelativeTime( THIS, DAY ); - TONIGHT = RelativeTime( THIS, NIGHT ); - - HOURLY = PeriodicTemporalSet(NIL, HOUR, "EVERY", "P1X"); - NIGHTLY = PeriodicTemporalSet(NIGHT, DAY, "EVERY", "P1X"); - DAILY = PeriodicTemporalSet(NIL, DAY, "EVERY", "P1X"); - MONTHLY = PeriodicTemporalSet(NIL, MONTH, "EVERY", "P1X"); - QUARTERLY = PeriodicTemporalSet(NIL, QUARTER, "EVERY", "P1X"); - YEARLY = PeriodicTemporalSet(NIL, YEAR, "EVERY", "P1X"); - WEEKLY = PeriodicTemporalSet(NIL, WEEK, "EVERY", "P1X"); \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt b/src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt deleted file mode 100644 index e513dfcdd6..0000000000 --- a/src/main/webapp/WEB-INF/data/sutime/rules/english.holidays.sutime.txt +++ /dev/null @@ -1,29 +0,0 @@ - ENV.defaults["stage"] = 1 - ENV.defaults["ruleType"] = "tokens" - - $POSS = "( /'s/ | /'/ /s/ )" - { (/new/ /year/ $POSS? /eve/ ) => IsoDate(NIL, 12, 31) } - { (/new/ /year/ $POSS? /day/? ) => IsoDate(NIL, 1, 1) } - { (/inauguration/ /day/ ) => IsoDate(NIL, 1, 20) } - { (/groundhog/ /day/ ) => IsoDate(NIL, 2, 2) } - { (/st.?|saint/? /valentine/ $POSS? /day/ ) => IsoDate(NIL, 2, 14) } - { (/st.?|saint/ /patrick/ $POSS? /day/ ) => IsoDate(NIL, 3, 17) } - { (/april/ /fools/ /day/? ) => IsoDate(NIL, 4, 1) } - { (/cinco/ /de/ /mayo/ ) => IsoDate(NIL, 5, 5) } - { (/halloween/ ) => IsoDate(NIL, 10, 31) } - { (/x-?mas|christmas/ /eve/ ) => IsoDate(NIL, 12, 24) } - { (/x-?mas|christmas/ /day/? ) => IsoDate(NIL, 12, 25) } - - - { (/martin/ /luther/ /king/ /day/ | /mlk/ /day/) => JH_MARTIN_LUTHER_KING } - { (/memorial/ /day/) => JH_MEMORIAL } - { (/mother/ $POSS /day/) => JH_MOTHERS_DAY } - { (/father/ $POSS /day/) => JH_FATHERS_DAY } - { (/labou?r/ /day/) => JH_LABOUR_DAY } - { (/columbus/ /day/) => JH_COLUMBUS_DAY } - { (/thanksgiving/) => JH_THANKSGIVING } - - { (/easter/ (/day/|/sunday/)?) => JH_EASTER } - { (/clean/ /monday/) => JH_CLEAN_MONDAY } - { (/good/ /friday/) => JH_GOOD_FRIDAY } - { (/ash/ /wednesday/) => JH_ASH_WEDNESDAY } diff --git a/src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt b/src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt deleted file mode 100644 index 1783cd4a8e..0000000000 --- a/src/main/webapp/WEB-INF/data/sutime/rules/english.sutime.txt +++ /dev/null @@ -1,964 +0,0 @@ - ENV.defaults["stage.limitIters"] = 50 - - tokens = { type: "CLASS", value: "edu.stanford.nlp.ling.CoreAnnotations$TokensAnnotation" } - numtokens = { type: "CLASS", value: "edu.stanford.nlp.ling.CoreAnnotations$NumerizedTokensAnnotation" } - - $TIMEOFDAY = "/morning|afternoon|evening|night|noon|midnight|teatime|lunchtime|dinnertime|suppertime|afternoon|midday|dusk|dawn|sunup|sunrise|sundown|twilight|daybreak/"; - - $NUM = ( [ { numcomptype:NUMBER } ] ); - $INT = ( [ { numcomptype:NUMBER } & !{ word:/.*\.\d+.*/} & !{ word:/.*,.*/ } ] ); - $INTORD = ( [ ({ numcomptype:NUMBER } | { numcomptype:ORDINAL }) & !{ word:/.*\.\d+.*/} & !{ word:/.*,.*/ } ] ); - $INT1000TO3000 = ( [ $INT & !{ word:/\+.*/} & { numcompvalue>1000 } & { numcompvalue<3000 } ] ); - $INT1TO31 = ( [ $INTORD & !{ word:/\+.*/} & { numcompvalue>=1 } & { numcompvalue<=31 } ] ); - $NUM_ORD = ( [ { numcomptype:ORDINAL } ] ); - - $INT_TIMES = ( $INT /times/ | once | twice | thrice ); - $REL_MOD = ( /the/? /next|following|last|previous/ | /this/ /coming|past/? | /the/ /coming|past/ ); - $FREQ_MOD = ( /each/ | /every/ $NUM_ORD | /every/ /other|alternate|alternating/? | /alternate|alternating/ ); - $EARLY_LATE_MOD = ( /late|early|mid-?/ | /the/? /beginning|start|dawn|middle|end/ /of/ ); - $APPROX_MOD = ( /about|around|some|exactly|precisely/ ); - $YEAR = ( /[012]\d\d\d/ | /'\d\d/ | /'/ /\d\d/ | /\w+teen|twenty/ [ { numcompvalue<100 } & { numcompvalue>0 } & $INT ] ); - $POSSIBLE_YEAR = ( $YEAR /a\.?d\.?|b\.?c\.?/? | $INT /a\.?d\.?|b\.?c\.?/ | $INT1000TO3000 ); - $hasTemporal = "( { temporal::EXISTS } & {{ temporal.value != NON_TEMPORAL }} & !{{ tags[\"TIMEZONE\"] }} )" - - # Decades - DECADES_MAP = { - "twenties": "2X", - "thirties": "3X", - "forties": "4X", - "fifties": "5X", - "sixties": "6X", - "seventies": "7X", - "eighties": "8X", - "nineties": "9X" - } - $Decades = CreateRegex(Keys(DECADES_MAP)) - - # Durations - TIMEUNIT_MAP = { - "year": YEAR, - "yr": YEAR, - "month": MONTH, - "mo": MONTH, - "day": DAY, - "hour": HOUR, - "hr": HOUR, - "minute": MINUTE, - "min": MINUTE, - "second": SECOND, - "sec": SECOND, - "millisecond": MILLIS, - "millisec": MILLIS, - "week": WEEK, - "wk": WEEK, - "fortnight": FORTNIGHT, - "quarter": QUARTER, - "century": CENTURY, - "centuries": CENTURY, - "millennia": MILLENNIUM, - "millennium": MILLENNIUM, - "millenia": MILLENNIUM, - "millenium": MILLENNIUM - } - $TEUnits = CreateRegex(Keys(TIMEUNIT_MAP)) - BASIC_NUMBER_MAP = { - "one": 1, - "two": 2, - "three": 3, - "four": 4, - "five": 5, - "six": 6, - "seven": 7, - "eight": 8, - "nine": 9, - "ten": 10, - "eleven": 11, - "twelve": 12, - "thirteen": 13, - "fourteen": 14, - "fifteen": 15, - "sixteen": 16, - "seventeen": 17, - "eighteen": 18, - "nineteen": 19, - "twenty": 20, - "thirty": 30, - "forty": 40, - "fifty": 50, - "sixty": 60, - "seventy": 70, - "eighty": 80, - "ninety": 90, - "hundred": 100 - } - $BasicNumTerm = CreateRegex(Keys(BASIC_NUMBER_MAP)) - BASIC_ORDINAL_MAP = { - "first": 1, - "second": 2, - "third": 3, - "fourth": 4, - "fifth": 5, - "sixth": 6, - "seventh": 7, - "eighth": 8, - "ninth": 9, - "tenth": 10, - "eleventh": 11, - "twelfth": 12, - "thirteenth": 13, - "fourteenth": 14, - "fifteenth": 15, - "sixteenth": 16, - "seventeenth": 17, - "eighteenth": 18, - "nineteenth": 19, - "twentieth": 20, - "thirtieth": 30, - "fortieth": 40, - "fiftieth": 50, - "sixtieth": 60, - "seventieth": 70, - "eightieth": 80, - "ninetieth": 90, - "hundredth": 100 - } - $BasicOrdTerm = CreateRegex(Keys(BASIC_ORDINAL_MAP)) - - ######################################################################################################################## - - ENV.defaults["stage"] = 0 - ENV.defaults["ruleType"] = "tokens" - - { pattern: ( $POSSIBLE_YEAR ), - action: ( - Tag($0, "YEAR", - :case { - $0 =~ ( /\w+teen|twenty/ [ $INT ] ) => Add(Multiply($0[0].numcompvalue, 100), $0[1].numcompvalue), - $0 =~ ( /'/ /\d\d/ ) => Concat("XX", $0[1].word), - $0 =~ ( /'\d\d/ ) => Concat("XX", $0[0].word.substring(1)), - :else => $0[0].numcompvalue - } - ), - Tag($0, "YEAR_ERA", - :case { - $0 =~ ( $INT /a\.?d\.?/ ) => ERA_AD, - $0 =~ ( $INT /b\.?c\.?/ ) => ERA_BC, - :else => ERA_UNKNOWN - } - ) - ) - } - - # Operators - { pattern: ( /this/ ), - action: Tag($0, "TemporalOp", THIS) } - { pattern: ( /next/ ), - action: Tag($0, "TemporalOp", NEXT) } - { pattern: ( /following/ ), - action: Tag($0, "TemporalOp", NEXT) } - { pattern: ( /previous/ ), - action: Tag($0, "TemporalOp", PREV) } - { pattern: ( /last/ ), - action: Tag($0, "TemporalOp", PREV) } - { pattern: ( /this|the/ /coming|following|next/ ), - action: Tag($0, "TemporalOp", NEXT_IMMEDIATE) } - { pattern: ( /this|the/ /past|previous|last/ ), - action: Tag($0, "TemporalOp", PREV_IMMEDIATE) } - - # Modifiers - - # Early late modifiers - { pattern: ( /late/ | /end/ ), - action: Tag($0, "Modifier", "LATE") } - { pattern: ( /early/ | /beginning|start|dawn/ ), - action: Tag($0, "Modifier", "EARLY") } - { pattern: ( /mid-?/ | /middle/ ), - action: Tag($0, "Modifier", "MID") } - - # Frequency modifiers - { pattern: ( /each/ | /every/ ), - action: ( Tag($0, "PTS.quant", $0), Tag($0, "PTS.multiple", 1 ) ) } - { pattern: ( /every/ ($NUM_ORD|$INT) ), - action: ( Tag($0, "PTS.quant", $0), Tag($0, "PTS.multiple", $1[0].numcompvalue ) ) } - { pattern: ( /every/ /other|alternate|alternating/ | /alternate|alternating/ ), - action: ( Tag($0, "PTS.quant", $0), Tag($0, "PTS.multiple", 2 ) ) } - - # Approximate modifiers - { pattern: ( /about|around|some/ ), - action: Tag($0, "Modifier", "APPROX") } - { pattern: ( /exactly|precisely/ ), - action: Tag($0, "Modifier", "EXACT") } - - # Periodic Set - PERIODIC_SET = { - "centennial": TemporalCompose(MULTIPLY, YEARLY, 100), - "yearly": YEARLY, - "annually": YEARLY, - "annual": YEARLY, - "hourly": HOURLY, - "nightly": NIGHTLY, - "daily": DAILY, - "weekly": WEEKLY, - "monthly": MONTHLY, - "quarterly": QUARTERLY - } - $PeriodicSetRegex = CreateRegex(Keys(PERIODIC_SET)) - { pattern: ( /.*($PeriodicSetRegex)/ ), - matchWithResults: TRUE, - action: Tag($0, "PeriodicSet", PERIODIC_SET[Lowercase($$0.matchResults[0].word.group(1))]) } - - ######################################################################################################################## - - ENV.defaults["stage"] = 1 - ENV.defaults["ruleType"] = "text" - - # Durations: 3-months old or three-months old - { text: /(\d+)[-]($TEUnits)(s)?([-\s]old)?/ => Duration( TIMEUNIT_MAP[Lowercase($2)], $1 ) } - { text: /($BasicNumTerm)[-]($TEUnits)(s)?([-\s]old)?/ => - Duration( TIMEUNIT_MAP[Lowercase($2)], BASIC_NUMBER_MAP[Lowercase($1)] ) } - - # Durations - ENV.defaults["ruleType"] = "tokens" - { (/years?|yrs?/) => YEAR } - { (/months?|mos?/) => MONTH } - { (/days?/) => DAY } - { (/hours?|hrs?/) => HOUR } - { (/minutes?|mins?/) => MINUTE } - { (/seconds?|secs?/) => SECOND } - { (/milliseconds?|millisecs?/) => MILLIS } - { (/weeks?|wks?/) => WEEK } - { (/fortnights?/) => FORTNIGHT } - { (/quarters?/) => QUARTER } - { (/decades?/) => DECADE } - { (/centurys?|centuries?/) => CENTURY } - { (/millenn?ias?|millenn?iums?/) => MILLENNIUM } - - # Time of Day - { (/mornings?/) => MORNING } - { (/afternoons?/) => AFTERNOON } - { (/evenings?/) => EVENING } - { (/dusks?/) => DUSK } - { (/twilights?/) => TWILIGHT } - { (/dawns?|daybreaks?/) => DAWN } - { (/sunrises?|sunups?/) => SUNRISE } - { (/sundowns?|sunsets?/) => SUNSET } - { (/middays?|noons?/) => NOON } - { (/midnights?/) => MIDNIGHT } - { (/teatimes?/) => TEATIME } - { (/lunchtimes?/) => LUNCHTIME } - { (/dinnertimes?/) => DINNERTIME } - { (/suppertimes?/) => SUPPERTIME } - { (/daylights?|days?|daytimes?/) => DAYTIME } - { (/nighttimes?|nights?|overnights?/) => NIGHT } - - # Seasons - { (/summers?/) => SUMMER } - { (/winters?/) => WINTER } - { (/falls?|autumns?/) => FALL } - { (/springs?/) => SPRING } - - # Relative times - { (/yesterdays?/) => YESTERDAY } - { (/todays?/) => TODAY } - { (/tomorrows?/) => TOMORROW } - { (/tonights?|tonites?/) => TONIGHT } - - # Day of Week - { (/mondays?/) => MONDAY } - { (/tuesdays?/) => TUESDAY } - { (/wednesdays?/) => WEDNESDAY } - { (/thursdays?/) => THURSDAY } - { (/fridays?/) => FRIDAY } - { (/saturdays?/) => SATURDAY } - { (/sundays?/) => SUNDAY } - { (/mons?/) => MONDAY } - { (/tues?/) => TUESDAY } - { (/weds?/) => WEDNESDAY } - { (/thurs?/) => THURSDAY } - { (/fris?/) => FRIDAY } - { (/sats?/) => SATURDAY } - { (/suns?/) => SUNDAY } - - { (/weekends?/) => WEEKEND } - { (/weekdays?/) => WEEKDAY } - - # Month - { (/januarys?/) => JANUARY } - { (/februarys?/) => FEBRUARY } - { (/marchs?/) => MARCH } - { (/aprils?/) => APRIL } - { (/mays?/) => MAY } - { (/junes?/) => JUNE } - { (/julys?/) => JULY } - { (/augusts?/) => AUGUST } - { (/septembers?/) => SEPTEMBER } - { (/octobers?/) => OCTOBER } - { (/novembers?/) => NOVEMBER } - { (/decembers?/) => DECEMBER } - { (/jan\.?/) => JANUARY } - { (/feb?/) => FEBRUARY } - { (/mar\.?/) => MARCH } - { (/apr\.?/) => APRIL } - { (/jun\.?/) => JUNE } - { (/jul\.?/) => JULY } - { (/aug\.?/) => AUGUST } - { (/sept?\.?/) => SEPTEMBER } - { (/oct\.?/) => OCTOBER } - { (/nov\.?/) => NOVEMBER } - { (/dec\.?/) => DECEMBER } - - { ruleType: "filter", - over: NIL, - pattern: ( [ { temporal::IS_TIMEX_DATE } & {{ tokens[0].tag =~ /NN.*S/ }} ] ), - result: MakePeriodicTemporalSet($0[0].temporal.value) - } - - ######################################################################################################################## - - ENV.defaults["ruleType"] = "tokens" - ENV.defaults["priority"] = 0 - ENV.defaults["locale"] = "en" - - // Military times with time zones from http://www.timeanddate.com/library/abbreviations/timezones/military/ - MILITARY_TIME_ZONE_MAP = { - "A": 1, - "B": 2, - "C": 3, - "D": 4, - "E": 5, - "F": 6, - "G": 7, - "H": 8, - "I": 9, - "K": 10, - "L": 11, - "M": 12, - "N": -1, - "O": -2, - "P": -3, - "Q": -4, - "R": -5, - "S": -6, - "T": -7, - "U": -8, - "V": -9, - "W": -10, - "X": -11, - "Y": -12, - "Z": 0 - } - - { - ruleType: "tokens", - pattern: ( (/(\d\d)(\d\d)([A-Z])/) ), - matchWithResults: TRUE, - result: { type: "Temporal", - value: IsoTime($$1.matchResults[0].word.group(1), $$1.matchResults[0].word.group(2), NIL).setTimeZone( - MILITARY_TIME_ZONE_MAP[$$1.matchResults[0].word.group(3)] ) }, - // Change to TRUE to support military time zones - active: FALSE - } - - # ISO date/times - # TODO: Support other timezone formats - { ruleType: "time", pattern: /yyyy-?MM-?dd-?'T'HH(:?mm(:?ss([.,]S{1,3})?)?)?(Z)?/ } - { ruleType: "time", pattern: /yyyy-MM-dd/ } - { ruleType: "time", pattern: /'T'HH(:?mm(:?ss([.,](S{1,3}))?)?)?(Z)?/ } - # Tokenizer "sometimes adds extra slash - { ruleType: "time", pattern: /yyyy\\?\/MM\\?\/dd/ } - { ruleType: "time", pattern: /MM?\\?\/dd?\\?\/(yyyy|yy)/ } - { ruleType: "time", pattern: /MM?-dd?-(yyyy|yy)/ } - { ruleType: "time", pattern: /HH?:mm(:ss)?(Z)?/ } - { ruleType: "time", pattern: /yyyy-MM/ } - - #WildMe added - { ruleType: "time", pattern: /yyyy\.MM\.dd/ } - - # Euro - Ambiguous pattern - interpret as dd.MM.yy(yy) - { ruleType: "time", pattern: /dd?\.MM?\.(yyyy|yy)/ } - { ruleType: "time", pattern: /HH?''hmm/ } - - # Timezones - { ruleType: "time", pattern: /zzz/, action: Tag(_, "TIMEZONE", TRUE) } - { ruleType: "time", pattern: /ZZZ/, action: Tag(_, "TIMEZONE", TRUE) } - - # Birthdays - { ( [ { tag:NNP } ]+ [ { tag:POS } ] /birthday/ ) => SimpleTime($0) } - - # Generic decade - { ( /the/? ( /\w+teen/ /$Decades/ ) ) - => IsoDate( Concat( Format("%02d", $0[0].numcompvalue), DECADES_MAP[Lowercase($0[1].word)]), NIL, NIL) - } - { ( /the/? ( /$Decades/ ) ) - => IsoDate( Concat("XX", DECADES_MAP[Lowercase($0[0].word)]) , NIL, NIL) - } - { (/the/? /'/ /\d\d/ ) => IsoDate( Format( "XX%02d", $0[-1].numcompvalue), NIL, NIL) } - { (/the/? /'/ /\d0s/ | /the/? /'\d0s/ ) => IsoDate( Replace($0[-1].word, /'?(\d)0s/, "XX$1X"), NIL, NIL) } - { (/the/? /\d\d\d0s/) => IsoDate( Replace($0[-1].word, /(\d\d\d)0s/, "$1X"), NIL, NIL) } - { (/the/? /\d\d00s/) => IsoDate( Replace($0[-1].word, /(\d\d)00s/, "$1XX"), NIL, NIL) } - { (/the/? /mid-\d\d\d0s/) => IsoDate( Replace($0[-1].word, /mid-(\d\d\d)0s/, "$1X"), NIL, NIL) } - { (/the/? /mid-\d\d00s/) => IsoDate( Replace($0[-1].word, /mid-(\d\d)00s/, "$1XX"), NIL, NIL) } - - # some century expressions - { ( (/every/ $NUM_ORD) (/centurys?|ies/) ) => - MakePeriodicTemporalSet(CENTURY, GetTag($1[0], "PTS.quant"), GetTag($1[0], "PTS.multiple") ) } - - { ( /the/? ($NUM_ORD) /-/? /century/ (/b\.?c\.?/) ) - => IsoDate( - Format("-%02dXX", Subtract($1[0].numcompvalue, 1)), - NIL, NIL) - } - { pattern: ( /the/? (/($BasicOrdTerm)-century/) (/b\.?c\.?/) ), - matchWithResults: TRUE, - result: IsoDate( - Format("-%02dXX", Subtract(BASIC_ORDINAL_MAP[Lowercase($$1.matchResults[0].word.group(1))], 1)), - NIL, NIL) - } - { pattern: ( /the/? (/(\d+)(st|nd|rd|th)-century/) (/b\.?c\.?/) ), - matchWithResults: TRUE, - result: IsoDate( - Format("-%02dXX", Subtract( { type: "NUMBER", value: $$1.matchResults[0].word.group(1) }, 1)), - NIL, NIL) - } - - { ( /the/? ($NUM_ORD) /-/? /century/ (/a\.?d\.?/)? ) - => IsoDate( - Format("%02dXX", Subtract($1[0].numcompvalue, 1)), - NIL, NIL) - } - - { pattern: ( /the/? (/($BasicOrdTerm)-century/) (/a\.?d\.?/)? ), - matchWithResults: TRUE, - result: IsoDate( - Format("%02dXX", Subtract(BASIC_ORDINAL_MAP[Lowercase($$1.matchResults[0].word.group(1))], 1)), - NIL, NIL) - } - { pattern: ( /the/? (/(\d+)(st|nd|rd|th)-century/) (/a\.?d\.?/)? ), - matchWithResults: TRUE, - result: IsoDate( - Format("%02dXX", Subtract( { type: "NUMBER", value: $$1.matchResults[0].word.group(1) }, 1)), - NIL, NIL) - } - - # some quarter expressions - need to add year refs - { ( /the/? [{tag:JJ}]? ($NUM_ORD) /-/? [{tag:JJ}]? /quarter/ ) => - TemporalCompose(CREATE, QUARTER_OF_YEAR, $1[0].numcompvalue) } - { text: /(\d+)(st|nd|rd|th)-quarter/ => - TemporalCompose(CREATE, QUARTER_OF_YEAR, $1 ) - } - { text: /($BasicOrdTerm)-quarter/ => - TemporalCompose(CREATE, QUARTER_OF_YEAR, BASIC_ORDINAL_MAP[Lowercase($1)]) - } - - # (unit)ly - { ruleType: "tokens", -# pattern: ( (?m){1,3} /((bi|semi)\s*-?\s*)?((annual|year|month|week|dai|hour|night|quarter)ly|annual)/ ), - pattern: ( (?m){1,3} /((bi|semi)\s*-?\s*)?($PeriodicSetRegex)/ ), - result: :case { - $0[0].word =~ /bi.*/ => TemporalCompose(MULTIPLY, GetTag($0[-1], "PeriodicSet"), 2), - $0[0].word =~ /semi.*/ => TemporalCompose(DIVIDE, GetTag($0[-1], "PeriodicSet"), 2), - :else => GetTag($0[-1], "PeriodicSet") } - } - - # some interval expressions - { text: /\b(\d{4})\s*(?:-)\s*(\d{4})\b/ => - TimeRange( IsoDate($1, NIL, NIL), IsoDate($2, NIL, NIL) ) } - { ( /the/ /weekend/ ) => WEEKEND } - - # Now a few time expressions - { ( (/\d\d\d\d/) /hours?/? (/universal|zulu/ | /[a-z]+/ /standard|daylight/) /time/ ) => IsoTime($1[0].word, NIL, NIL) } - { ( (/\d\d?/) /hours?/ (?: (/\d\d?/) /minutes?/?)? (/universal|zulu/ | /[a-z]+/ /standard|daylight/) /time/ ) - => IsoTime($1[0].word, $1[0].word, NIL) } - { text: /(\d\d):?(\d\d)(:?(\d\d))?\s*h(ou)rs?/ => IsoTime($1,$2,$3) } - { text: /(\d\d?)(:?(\d\d))(:\d\d)?a\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,$3,$4), AM) } - { text: /(\d\d?)(:?(\d\d))(:\d\d)?p\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,$3,$4), PM) } - { text: /(\d\d?)a\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,"0",NIL), AM) } - { text: /(\d\d?)p\.?m\.?/ => TemporalCompose(INTERSECT, IsoTime($1,"0",NIL), PM) } - - { ( /the/ /hour/ /of/ ([ $INT & { numcompvalue<=24 } ]) )=> IsoTime($1[0].numcompvalue, 0, NIL) } - { ( (?: /the/ /hour/ /of/?)? ([ $INT & { numcompvalue<=24 } ]) /o'?clock/ ) => IsoTime($1[0].numcompvalue, 0, NIL) } - - # Year - { ( /the/? /year/ ($POSSIBLE_YEAR) ) - => :case { - $1[0].word =~ /'.*/ => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL ), - :else => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL, GetTag($1[0], "YEAR_ERA"), TRUE) - } - } - - { ( ($POSSIBLE_YEAR) & [ { ner::IS_NIL } | { ner:DATE } | { ner:O } | { ner:NUMBER } ]+ ) - => :case { - $1[0].word =~ /'.*/ => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL ), - :else => IsoDate( GetTag($1[0], "YEAR"), NIL, NIL, GetTag($1[0], "YEAR_ERA"), TRUE) - } - } - - { ( /the/ ($TIMEOFDAY) ) => $1[0].temporal.value } - - { ( /good/ /morning|evening|day|afternoon|night/ ) => NON_TEMPORAL } - - ######################################################################################################################## - # Compositional rules - - ENV.defaults["ruleType"] = "composite" - - { name: "temporal-composite-6b", - priority: 20, - pattern: ( ( $REL_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: RelativeTime( GetTag($1[0], "TemporalOp"), $2[0].temporal.value ) - } - - ######################################################################################################################## - # Composite Duration rules - - ENV.defaults["priority"] = 10 - ENV.defaults["stage"] = 2 - - # Duration (start, end, unit, range_start, range_end) - # Duration rules - # i.e. "the past twenty four years" - { pattern: ( /the/ /past|last|previous/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1,$2,$3,TIME_UNKNOWN,TIME_REF) - } - - { pattern: ( /the/ /next|following/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1,$2,$3,TIME_REF,TIME_UNKNOWN) - } - - # i.e. "another 3 years", "another thirteen months" - { pattern: ( /another/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1, $2, $3, TIME_REF, TIME_UNKNOWN) } - - # i.e. "the 2 months following the crash", "for ten days before leaving" - # TODO: NEED TO FIX THIS, right now it doesn't include "the crash" or "leaving" - # ...need to be able to recognize NPs and VPs using POS tags - { pattern: ( /the/ (?: ($NUM) /to|-/ )? ($NUM) ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration($1, $2, $3) } - - # i.e. "the first 9 months of 1997" - { pattern: ( /the/ /first|initial|last|final|latest/ (?: ($NUM) /to|-/ )? ($NUM)? ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration( $1, $2, $3 ) } - { pattern: ( /the/ /first|initial|last|final|latest/ /half/ /of/ ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration( $1, $2, $3 ) } - - # i.e. "the fifth straight year", "the third straight month in a row", "the ninth day consecutively" - # i.e. "the eighth consecutive day in a row" - # i.e. "the twenty ninth day straight" - { pattern: ( /the/ ($NUM_ORD) /straight|consecutive/ ([ { temporal::IS_TIME_UNIT } ]) (?: /in/ /a/ /row/ | /consecutively/ )? ), - result: Duration (NIL, $1, $2, TIME_UNKNOWN, TIME_REF) } - { pattern: ( /the/ ($NUM_ORD) /straight|consecutive/? ([ { temporal::IS_TIME_UNIT } ]) (?: /in/ /a/ /row/ | /consecutively/ ) ), - result: Duration (NIL, $1, $2, TIME_UNKNOWN, TIME_REF) } - - # hundreds of years - { pattern: ( (/(ten|hundred|thousand|million|billion|trillion)s/) /of/ ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration ( NIL, $1, $2) } - - # i.e. "recent weeks", "several days" - { pattern: ( (/recent|several/) /-/? ([ { temporal::IS_TIME_UNIT } ]) ), - result: InexactDuration( Duration(NIL, NIL, $2) ) } - - # i.e. 3-months old, "four years", "four minutes" - { pattern: ( ($NUM) /to|-/ ($NUM) [ "-" ]? ([ { temporal::IS_TIME_UNIT } ]) (?: [ "-" ]? /old/ )? ), - result: Duration( $1, $2, $3) } - { pattern: ( ($NUM) [ "-" ]? ([ { temporal::IS_TIME_UNIT } ]) (?: [ "-" ]? /old/ )? ), - result: Duration( NIL, $1, $2 ) } - - # i.e. "a decade", "a few decades", NOT "a few hundred decades" - { pattern: ( (?: /the/ /past|next|following|coming|last|first|final/ | /a|an/ )? (/couple/ /of/? ) ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration ( Duration( NIL, NIL, $2 ), 2 ) } - { pattern: ( (?: /the/ /past|next|following|coming|last|first|final/ /half/ /of/ ) ([ { temporal::IS_TIME_UNIT } ]) ), - result: InexactDuration ( Duration( NIL, NIL, $2 ) ) } - { pattern: ( (?: /the/ /past|next|following|coming|last|first|final/ | /a|an/ )? (/few/) ([ { temporal::IS_TIME_UNIT } ]) ), - result: InexactDuration ( Duration( NIL, NIL, $2 ) ) } - - { pattern: ( /the/ [ { tag:JJ } ]? ([ { temporal::IS_TIME_UNIT } & { word:/.*s/ } ]) ), - priority: -1, - result: InexactDuration( $1[0].temporal.value ) } - - { pattern: ( /a|an/ ([ { temporal::IS_TIME_UNIT } ]) ), - result: Duration( $1[0].temporal.value, 1) } - - ###################################################################################################################### - # Compositional date rules - - ENV.defaults["priority"] = 0 - - { ( ($FREQ_MOD|/the/)? ($NUM_ORD) ([ { temporal::IS_TIME_UNIT } | { temporal::DAYOFWEEK } ]) ) => - :case{ - # Only attach ordinal to time if not prefixed by frequency modifier (e.g. every) - ($1 == NIL || $1 =~ ( /the/ ) ) => OrdinalTime($3[0].temporal.value, $2[0].numcompvalue), - # Return NIL otherwise - we have other patterns that handle sets (every 3rd months) later - :else => NIL - } - } - - { name: "composite-date-expression-1a", - priority: 1, - pattern: ( (/every/ $NUM_ORD) (?$month [ { temporal::MONTH }]) ), - result: MakePeriodicTemporalSet( - $month[0].temporal, - GetTag($1[0], "PTS.quant"), GetTag($1[0], "PTS.multiple") ) } - - { name: "composite-date-expression-1", - priority: 1, - pattern: ( ( /the/? (?$day $NUM_ORD & $INT1TO31) /of/? | (?$day /\d\d?/ & $INT1TO31) )? - (?$month [ { temporal::MONTH } ]) - (?$day $NUM_ORD|/\d\d?/ & $INT1TO31)? - (?: /of|,/? (?$year $POSSIBLE_YEAR))? ), - result: TemporalCompose(INTERSECT, - $year[0].temporal, - IsoDate(NIL, $month[0].temporal.value.month, $day[0].numcompvalue)) - } - - { name: "composite-date-expression-1b", - pattern: ( /the/? /ides/ /of|in/? (?$month [ { temporal::MONTH } ]) (?: /of|,/? (?$year $POSSIBLE_YEAR))? ), - result: TemporalCompose(INTERSECT, - $year[0].temporal, - IsoDate(NIL, - $month[0].temporal.value.month, - :case { - $month[0].temporal.value.month == 3 => 15, - $month[0].temporal.value.month == 5 => 15, - $month[0].temporal.value.month == 7 => 15, - $month[0].temporal.value.month == 10 => 15, - :else => 13 - } - )) - } - - { name: "composite-date-expression-1c", - pattern: ( /the/? /nones/ /of|in/? (?$month [ { temporal::MONTH } ]) (?: /of|,/? (?$year $POSSIBLE_YEAR))? ), - result: IsoDate( - GetTag($year[0].numtokens[0], "YEAR"), - $month[0].temporal.value.month, - :case { - $month[0].temporal.value.month == 3 => 7, - $month[0].temporal.value.month == 5 => 7, - $month[0].temporal.value.month == 7 => 7, - $month[0].temporal.value.month == 10 => 7, - :else => 5 - } - ) - } - - { name: "composite-date-expression-2", - pattern: ( /the/? (?$mod /beginning|start|middle|mid-?|end/ ) /of|in/? (?$date [ { temporal::IS_TIMEX_DATE } ]) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, GetTag($mod[0], "Modifier") ) } - - { name: "composite-date-expression-2a1", - pattern: ( /the/? (?$mod /first/ /half/) /of/ (?$date [ { temporal::IS_TIMEX_DATE } ]) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, "EARLY" ) } - - { name: "composite-date-expression-2a2", - pattern: ( /the/? (?$mod /second|last|latter/ /half/) /of/ (?$date [ { temporal::IS_TIMEX_DATE } ]) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, "LATE" ) } - - { name: "composite-date-expression-2b", - pattern: ( /the/? (?$date [ { temporal::IS_TIMEX_DATE } ]) (/'/ /s/ | /'s/ )? (?$mod /beginning|end/) ), - result: TemporalCompose(ADD_MODIFIER, $date[0].temporal, GetTag($mod[0], "Modifier") ) } - - { name: "composite-date-expression-3", - pattern: ( /the/? (?$weeknum ($NUM_ORD|last)) (?$week /week(end)?/ ) /of|in/? [ { temporal::IS_TIMEX_DATE } ] ), - result: TemporalCompose( - IN, - $0[-1].temporal, - TemporalCompose( - CREATE, - $week[0].temporal, - :case { - $weeknum =~ (/last/) => -1, - :else => $weeknum[0].numcompvalue - } )) - } - - { name: "composite-date-expression-3b", - pattern: ( /the/? (?$week /week(end)?/ ) /of|in/? [ { temporal::IS_TIMEX_DATE } ] ), - result: TemporalCompose( - INTERSECT, - $0[-1].temporal, - $week[0].temporal) - } - - { name: "composite-date-expression-3c", - pattern: ( ( [ { temporal::DAYOFWEEK } ] ) /the/? (?$day $NUM_ORD) ), - result: TemporalCompose( - INTERSECT, - $1[0].temporal, - IsoDate(NIL, NIL, $day[0].numcompvalue)) - } - - { name: "composite-date-expression-6", - pattern: ( ([ { temporal::IS_TIMEX_DATE } ]) (morning|afternoon|evening|night) ), - result: TemporalCompose(INTERSECT, $1[0].temporal, $2[0].temporal) - } - - { name: "composite-date-expression-7a", - pattern: ( (?: /the/? /day/ (/before/|/prior/ /to/) ([ { temporal::IS_TIMEX_DATE } ]) ) ), - result: TemporalCompose( - PLUS, - $2[0].temporal, - TemporalCompose( - MULTIPLY, - DAY, - -1)) - } - - { name: "composite-date-expression-7b", - pattern: ( (?: /the/? /day/ (/after/) ([ { temporal::IS_TIMEX_DATE } ]) ) ), - result: TemporalCompose( - PLUS, - $2[0].temporal, - DAY) - } - - { name: "composite-date-expression-8", - pattern: ( /the/ [ { tag:JJ } ]* ([ { temporal::IS_TIME_UNIT } - & !{ word:/.*s/ } ] )), - result: RelativeTime( THIS, $1[0].temporal.value ) - } - - ######################################################################################################################## - # Composite time expressions - - { name: "composite-time-expression-1a", - active: TRUE, - pattern: ( (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue<=24 } ])) - (?$context /in/ /the/ /morning/ | /a\.?m\.?/) - ), - result: :case { - $time => TemporalCompose(INTERSECT, $time[0].temporal.value, AM), - $hour[0].numcompvalue == 12 => IsoTime(0, 0, NIL), - :else => IsoTime($hour[0].numcompvalue, 0, NIL) - } - } - - { name: "composite-time-expression-1b", - active: TRUE, - pattern: ( (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue<=24 } ])) - (?$context /in/ /the/ /afternoon|evening/| /at/ /night/| /p\.?m\.?/) - ), - result: :case { - $time => TemporalCompose(INTERSECT, $time[0].temporal.value, PM), - $hour[0].numcompvalue < 12 => IsoTime(Add($hour[0].numcompvalue, 12), 0, NIL), - ( ($hour[0].numcompvalue == 12) && ($context =~ ( []* /evening|night/)) ) - => TemporalCompose(OFFSET_EXACT, IsoTime(0, 0, NIL), DAY), - :else => IsoTime($hour[0].numcompvalue, 0, NIL) - } - } - - { name: "composite-time-expression-1c", - active: TRUE, - pattern: ( (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue==12 } ])) - (?$context /midnight/) - ), - result: :case { - $time[0].temporal.value.hour == 12 => MIDNIGHT, - $hour[0].numcompvalue == 12 => MIDNIGHT, - :else => NIL - } - } - - { name: "composite-time-expression-2", - pattern: ( (?$minute /a/? /quarter/ | /a/? /half/ | [ $INT & { numcompvalue<=60 } ] /minutes?/? ) - (?$rel /past|after|before|to|until/) - (?: (?$time [ { temporal::IS_TIMEX_TIME } ]) | (?$hour [ $INT & { numcompvalue<=24 } ])) - ), - result: TemporalCompose( - :case { - $rel[0].word =~ /past|after/ => PLUS, - :else => MINUS - }, - :case { - $time => $time[0].temporal, - :else => IsoTime($hour[0].numcompvalue, 0, NIL) - }, - Duration( - MINUTE, - :case { - $minute =~ ( /a/? /quarter/ ) => 15, - $minute =~ ( /a/? /half/ ) => 30, - :else => $0[0].numcompvalue - } - ) - ) } - - { pattern: ( ( /\d\d\d\d/ | $NUM ) [ {tag:/RB/} ] [ {tag:/JJ/} ]+ [ {tag:/NNS/} & !($hasTemporal) ] ), - result: NON_TEMPORAL, - priority: -1 } - { pattern: ( ( /\d\d\d\d/ | $NUM ) [ {tag:/JJ/} ]* [ {tag:/NNS/} & !($hasTemporal) ] ), - result: NON_TEMPORAL, - priority: -1 } - - ######################################################################################################################## - # General compositional rules - ENV.defaults["stage"] = 3 - - { name: "temporal-composite-timezone1", - pattern: ( (?$time [ { temporal::IS_TIMEX_TIME } ]) (?$timezone [ {{ tags["TIMEZONE"] }} ]) ), - result: TemporalCompose(INTERSECT, $time[0].temporal, $timezone[0].temporal) - } - - { name: "temporal-composite-timezone2", - pattern: ( (?$time [ { temporal::IS_TIMEX_TIME } ]) "-LRB-" (?$timezone [ {{ tags["TIMEZONE"] }} ]) "-RRB-" ), - result: TemporalCompose(INTERSECT, $time[0].temporal, $timezone[0].temporal) - } - - { name: "temporal-composite-1", - pattern: ( /the/? - (( [ $hasTemporal ] ) /,|of|in/? ( [ { temporal::IS_TIMEX_DATE } | { temporal::IS_TIMEX_TIME } ] ) | - ( [ { temporal::IS_TIMEX_DATE } ] ) /at/ ( [ { temporal::IS_TIMEX_TIME } ] ) | - ( [ { temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DURATION } ] ) /on/ ( [ { temporal::IS_TIMEX_DATE } ] | [ { temporal::IS_TIMEX_SET } ]) | - ( [ { temporal::IS_TIMEX_DATE } | { temporal::IS_TIMEX_TIME } ] ) (/'s/ | /'/ /s/) ( [ $hasTemporal ] )) ), - result: TemporalCompose(INTERSECT, $1[0].temporal, $1[-1].temporal) - } - - { name: "temporal-composite-2", - pattern: ( ( [ { temporal::IS_TIMEX_DATE } | { temporal::IS_TIMEX_TIME } ] ) (/today|tonight/) ), - result: $0[0].temporal.value - } - - { name: "temporal-composite-3", - pattern: ( ( [ { temporal::IS_TIMEX_DURATION } ] ) (/before|from|since|after/ | /prior/ /to/) - ( [ ({ temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DATE }) ] ) ), - result: TemporalCompose( - OFFSET, $0[-1].temporal, - TemporalCompose( - MULTIPLY, - $0[0].temporal, - :case { - $2 =~ (/before/|/prior/ /to/) => -1, - :else => 1 - } )) - } - - # expand: timex later|earlier|late => one timex - { name: "temporal-composite-4", - pattern: ( ( [ { temporal::IS_TIMEX_DURATION } ] ) (/earlier|later|ago|hence/ | /from/ /now/) ), - result: TemporalCompose(OFFSET, TIME_REF, - TemporalCompose( MULTIPLY, $0[0].temporal, - :case { - $2 =~ (/earlier/|/ago/) => -1, - :else => 1 - })) - } - - # expand: timex later|earlier|late => one timex - { name: "temporal-composite-5", - pattern: ( ( [ $hasTemporal & !{ temporal::IS_TIMEX_DURATION } ] ) - (/before|earlier|later|late|ago|hence/ | /from/ /now/) ), - result: $0[0].temporal.value } - - { name: "temporal-composite-6a", - pattern: ( /the/? ( $EARLY_LATE_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: TemporalCompose( ADD_MODIFIER, $2[0].temporal.value, GetTag($1[0], "Modifier") ) - } - - { name: "temporal-composite-6b", - priority: 4, - pattern: ( ( $REL_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: RelativeTime( GetTag($1[0], "TemporalOp"), $2[0].temporal.value ) - } - - { name: "temporal-composite-6b1", - priority: 4, - pattern: ( ( /no/ /more/ /than/ | /at/ /most/ | /up/ /to/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "EQUAL_OR_LESS" ) - } - { name: "temporal-composite-6b2", - priority: 4, - pattern: ( ( /more/ /than/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "MORE_THAN" ) - } - { name: "temporal-composite-6b3", - priority: 4, - pattern: ( ( /no/ /less/ /than/ | /at/ /least/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "EQUAL_OR_MORE" ) - } - { name: "temporal-composite-6b4", - priority: 4, - pattern: ( ( /less/ /than/ ) - ( [ { temporal::IS_TIMEX_DURATION } & !{{ temporal.value.mod }} ] ) ), - result: TemporalCompose( ADD_MODIFIER, $0[-1].temporal.value, "LESS_THAN" ) - } - - # expand: (the|this|about|nearly|early|later|earlier|late) timex => one timex - # expand: more than| up to| less than timex => one timex - { name: "temporal-composite-6c", - pattern: ( ( /this|about|nearly|early|later|earlier|late/ ) - ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: $0[-1].temporal.value - } - - { name: "temporal-composite-7a", - pattern: ( /every/ ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - result: MakePeriodicTemporalSet($1[0].temporal, "every", 1 ) - } - - { name: "temporal-composite-7b", -# pattern: ( ( $FREQ_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ), - pattern: ( ( $FREQ_MOD ) ( [ $hasTemporal ] ) ), - result: MakePeriodicTemporalSet($2[0].temporal, GetTag($1[0], "PTS.quant"), GetTag($1[0], "PTS.multiple") ) - } - - { name: "temporal-composite-8:ranges", - active: options."markTimeRanges", - pattern: ( /from/? ( [ { temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DATE } ] ) /to|-/ ( [ { temporal::IS_TIMEX_TIME } | { temporal::IS_TIMEX_DATE } ] ) ), - result: TimeRange( $1[0].temporal.value, $2[0].temporal.value ) } - - { name: "temporal-composite-9", - pattern: ( [{ temporal::IS_TIMEX_TIME }] (?: /sharp/|/exactly/|/precisely/|/on/ /the/ /dot/) ), - result: $0[0].temporal.value } - - ######################################################################################################################## - - ENV.defaults["stage"] = 4 - ENV.defaults["ruleType"] = "tokens" - - # Vague times - { ( /the/ /past/ | /recently/ ) => TIME_PAST } - { pattern: ( /at/ /the/ (/time/) ), matchedExpressionGroup: 1, result: TIME_PAST } - { ( /past|once|medieval|previously/ ) => TIME_PAST } - { ( /present|current|currently/ | /right/? /now/ ) => TIME_PRESENT } - { ( /the/? /near/? /future/ ) => TIME_FUTURE } - - # Final rules to determine how to resolve date - ENV.defaults["ruleType"] = "composite" - ENV.defaults["stage.limitIters"] = 1 - { pattern: ( [ { temporal::IS_TIMEX_DURATION } & {{ tokens =~ ( /.*s/ ) }} ] ), - result: InexactDuration( $0[0].temporal.value ) } - - { pattern: ( [ { tag:/VBD/ } | /have/ ] []{0,2} [ $hasTemporal ] ), - action: VTag( $0[-1].temporal.value, "resolveTo", RESOLVE_TO_PAST ) - } - { pattern: ( [ $hasTemporal ] []{0,2} [ { tag:/VBD/ } | /have/ ] ), - action: VTag( $0[0].temporal.value, "resolveTo", RESOLVE_TO_PAST ) - } - { pattern: ( (/would/ | /could/ | /should/ | /will/ | /going/ /to/ | /'/ /ll/ | /'ll/ ) - []{0,2} [ $hasTemporal ] - ), - action: VTag( $0[-1].temporal.value, "resolveTo", RESOLVE_TO_FUTURE ) - } - { pattern: ( [ $hasTemporal ] []{0,2} - (/would/ | /could/ | /should/ | /will/ | /going/ /to/ | /'/ /ll/ | /'ll/ ) ), - action: VTag( $0[0].temporal.value, "resolveTo", RESOLVE_TO_FUTURE ) - } - - ######################################################################################################################## - # Final filtering rules - - ENV.defaults["ruleType"] = "filter" - ENV.defaultTokensAnnotationKey = tokens - - { pattern: ( $NUM /to/ $NUM) } - { pattern: ( /(quarter|sun)s?/ ) } - { pattern: ( [ { word:/(fall|spring|second|march|may|sat|sun|min)s?/ } & !{ tag:/NN.*/ } ] ) } - { pattern: ( /the/ [ { word:/second/ } & !{ tag:/NN.*/ } ] ) } - { pattern: ( [ { word:/((twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety)-)?second/ } ] ) } - { pattern: ( [ {{ temporal.value == NON_TEMPORAL }} ] ), over: NIL } - - # Reject anything that is just a timezone - { pattern: ( [ {{ tags["TIMEZONE"] }} ] ), over: NIL } - From febce5a9bb4a279fecc7d4122ea16a41ab9d312f Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Tue, 3 Sep 2024 16:44:24 -0600 Subject: [PATCH 17/20] math fix TM --- src/main/webapp/encounters/manualAnnotation.jsp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/encounters/manualAnnotation.jsp b/src/main/webapp/encounters/manualAnnotation.jsp index b231ba791f..cf6b44daf0 100644 --- a/src/main/webapp/encounters/manualAnnotation.jsp +++ b/src/main/webapp/encounters/manualAnnotation.jsp @@ -152,6 +152,7 @@ $(document).ready(function() { $('.axis').hide(); }).on('click', function(ev) { let mainImgWidth = $('#main-img').width(); + if (rotated) mainImgWidth = $('#main-img').height(); let widthScale = maWidth/mainImgWidth; if (boxStart) { var w = Math.abs(ev.offsetX - boxStart[0]); @@ -349,8 +350,9 @@ try{

MediaAsset " target="_new" href="../obrowse.jsp?type=MediaAsset&id=<%=ma.getId()%>"><%=ma.getId()%> -