Merge remote-tracking branch 'modules/master' into subtree
this merges the master head of https://github.com/helma-org/apps-modules-mirror into helma
This commit is contained in:
commit
226552bc24
53 changed files with 12023 additions and 0 deletions
83
modules/core/Array.js
Normal file
83
modules/core/Array.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2006 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: Array.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Adds useful methods to the JavaScript Array type.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/Array.js')
|
||||
*
|
||||
* @addon
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Check if this array contains a specific value.
|
||||
* @param {Object} val the value to check
|
||||
* @return {boolean} true if the value is contained
|
||||
*/
|
||||
Array.prototype.contains = function(val) {
|
||||
return this.indexOf(val) > -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the union set of a bunch of arrays
|
||||
* @param {Array} array1,... the arrays to unify
|
||||
* @return {Array} the union set
|
||||
*/
|
||||
Array.union = function() {
|
||||
var result = [];
|
||||
var map = {};
|
||||
for (var i=0; i<arguments.length; i+=1) {
|
||||
for (var n in arguments[i]) {
|
||||
var item = arguments[i][n];
|
||||
if (!map[item]) {
|
||||
result.push(item);
|
||||
map[item] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the intersection set of a bunch of arrays
|
||||
* @param {Array} array1,... the arrays to intersect
|
||||
* @return {Array} the intersection set
|
||||
*/
|
||||
Array.intersection = function() {
|
||||
var all = Array.union.apply(this, arguments);
|
||||
var result = [];
|
||||
for (var n in all) {
|
||||
var chksum = 0;
|
||||
var item = all[n];
|
||||
for (var i=0; i<arguments.length; i+=1) {
|
||||
if (arguments[i].contains(item))
|
||||
chksum += 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (chksum == arguments.length)
|
||||
result.push(item);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// prevent any newly added properties from being enumerated
|
||||
for (var i in Array)
|
||||
Array.dontEnum(i);
|
||||
for (var i in Array.prototype)
|
||||
Array.prototype.dontEnum(i);
|
196
modules/core/Date.js
Normal file
196
modules/core/Date.js
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2005 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: Date.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Adds useful methods to the JavaScript Date type.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/Date.js')
|
||||
*/
|
||||
|
||||
Date.ONESECOND = 1000;
|
||||
Date.ONEMINUTE = 60 * Date.ONESECOND;
|
||||
Date.ONEHOUR = 60 * Date.ONEMINUTE;
|
||||
Date.ONEDAY = 24 * Date.ONEHOUR;
|
||||
Date.ONEWEEK = 7 * Date.ONEDAY;
|
||||
Date.ONEMONTH = 30 * Date.ONEDAY;
|
||||
Date.ONEYEAR = 12 * Date.ONEMONTH;
|
||||
Date.ISOFORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
||||
|
||||
|
||||
/**
|
||||
* Format a Date to a string.
|
||||
* For details on the format pattern, see
|
||||
* http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html
|
||||
*
|
||||
* @param String Format pattern
|
||||
* @param Object Java Locale Object (optional)
|
||||
* @param Object Java TimeZone Object (optional)
|
||||
* @return String formatted Date
|
||||
* @see http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html
|
||||
*/
|
||||
Date.prototype.format = function (format, locale, timezone) {
|
||||
if (!format)
|
||||
return this.toString();
|
||||
var sdf = locale ? new java.text.SimpleDateFormat(format, locale)
|
||||
: new java.text.SimpleDateFormat(format);
|
||||
if (timezone && timezone != sdf.getTimeZone())
|
||||
sdf.setTimeZone(timezone);
|
||||
return sdf.format(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* set the date/time to UTC by subtracting
|
||||
* the timezone offset
|
||||
*/
|
||||
Date.prototype.toUtc = function() {
|
||||
this.setMinutes(this.getMinutes() + this.getTimezoneOffset());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* set the date/time to local time by adding
|
||||
* the timezone offset
|
||||
*/
|
||||
Date.prototype.toLocalTime = function() {
|
||||
this.setMinutes(this.getMinutes() - this.getTimezoneOffset());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* returns the difference between this and another
|
||||
* date object in milliseconds
|
||||
*/
|
||||
Date.prototype.diff = function(dateObj) {
|
||||
return this.getTime() - dateObj.getTime();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* return the timespan to current date/time or a different Date object
|
||||
* @param Object parameter object containing optional properties:
|
||||
* .now = String to use if difference is < 1 minute
|
||||
* .day|days = String to use for single|multiple day(s)
|
||||
* .hour|hours = String to use for single|multiple hour(s)
|
||||
* .minute|minutes = String to use for single|multiple minute(s)
|
||||
* .date = Date object to use for calculating the timespan
|
||||
* @return Object containing properties:
|
||||
* .isFuture = (Boolean)
|
||||
* .span = (String) timespan
|
||||
* @see Date.prototype.getAge
|
||||
* @see Date.prototype.getExpiry
|
||||
*/
|
||||
Date.prototype.getTimespan = function(param) {
|
||||
if (!param)
|
||||
param = {date: new Date()};
|
||||
else if (!param.date)
|
||||
param.date = new Date();
|
||||
|
||||
var result = {isFuture: this > param.date};
|
||||
var diff = Math.abs(param.date.diff(this));
|
||||
var age = {days: Math.floor(diff / Date.ONEDAY),
|
||||
hours: Math.floor((diff % Date.ONEDAY) / Date.ONEHOUR),
|
||||
minutes: Math.floor((diff % Date.ONEHOUR) / Date.ONEMINUTE)};
|
||||
|
||||
res.push();
|
||||
if (diff < Date.ONEMINUTE)
|
||||
res.write(param.now || "now");
|
||||
else {
|
||||
var arr = [{one: "day", many: "days"},
|
||||
{one: "hour", many: "hours"},
|
||||
{one: "minute", many: "minutes"}];
|
||||
for (var i in arr) {
|
||||
var value = age[arr[i].many];
|
||||
if (value != 0) {
|
||||
var prop = (value == 1 ? arr[i].one : arr[i].many);
|
||||
res.write(value);
|
||||
res.write(" ");
|
||||
res.write(param[prop] || prop);
|
||||
if (i < arr.length -1)
|
||||
res.write(param.delimiter || ", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
result.span = res.pop();
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* return the past timespan between this Date object and
|
||||
* the current Date or a different Date object
|
||||
* @see Date.prototype.getTimespan
|
||||
*/
|
||||
Date.prototype.getAge = function(param) {
|
||||
var age = this.getTimespan(param);
|
||||
if (!age.isFuture)
|
||||
return age.span;
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* return the future timespan between this Date object and
|
||||
* the current Date or a different Date object
|
||||
* @see Date.prototype.getTimespan
|
||||
*/
|
||||
Date.prototype.getExpiry = function(param) {
|
||||
var age = this.getTimespan(param);
|
||||
if (age.isFuture)
|
||||
return age.span;
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* checks if a date object equals another date object
|
||||
* @param Object Date object to compare
|
||||
* @param Int indicating how far the comparison should go
|
||||
* @return Boolean
|
||||
*/
|
||||
Date.prototype.equals = function(date, extend) {
|
||||
if (!extend)
|
||||
var extend = Date.ONEDAY;
|
||||
switch (extend) {
|
||||
case Date.ONESECOND:
|
||||
if (this.getSeconds() != date.getSeconds())
|
||||
return false;
|
||||
case Date.ONEMINUTE:
|
||||
if (this.getMinutes() != date.getMinutes())
|
||||
return false;
|
||||
case Date.ONEHOUR:
|
||||
if (this.getHours() != date.getHours())
|
||||
return false;
|
||||
case Date.ONEDAY:
|
||||
if (this.getDate() != date.getDate())
|
||||
return false;
|
||||
case Date.ONEMONTH:
|
||||
if (this.getMonth() != date.getMonth())
|
||||
return false;
|
||||
case Date.ONEYEAR:
|
||||
if (this.getFullYear() != date.getFullYear())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
// prevent any newly added properties from being enumerated
|
||||
for (var i in Date)
|
||||
Date.dontEnum(i);
|
||||
for (var i in Date.prototype)
|
||||
Date.prototype.dontEnum(i);
|
209
modules/core/Filters.js
Normal file
209
modules/core/Filters.js
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2007 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile$
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Implements some useful macro filters.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/Filters.js')
|
||||
*/
|
||||
|
||||
app.addRepository('modules/core/String.js');
|
||||
|
||||
/**
|
||||
* Transforms a string to lowercase.
|
||||
*
|
||||
* @see String.prototype.toLowerCase
|
||||
*/
|
||||
function lowercase_filter(input) {
|
||||
return (input || "").toString().toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transforms a string to uppercase.
|
||||
*
|
||||
* @see String.prototype.toUpperCase
|
||||
*/
|
||||
function uppercase_filter(input) {
|
||||
return (input || "").toString().toUpperCase();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transforms the first Character of a string to uppercase.
|
||||
*
|
||||
* @see String.prototype.capitalize
|
||||
*/
|
||||
function capitalize_filter(input) {
|
||||
return (input || "").toString().capitalize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transforms the first Character of each word in a string
|
||||
* to uppercase.
|
||||
*
|
||||
* @see String.prototype.titleize
|
||||
*/
|
||||
function titleize_filter(input) {
|
||||
return (input || "").toString().titleize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cuts a String at a certain position, and
|
||||
* optionally appends a suffix, if truncation
|
||||
* has occurred.
|
||||
*
|
||||
* @see String.prototype.head
|
||||
* @param limit Maximum length
|
||||
* @param clipping Appended String, default is the empty String
|
||||
*/
|
||||
function truncate_filter(input, param, limit, clipping) {
|
||||
var limit = param.limit != null ? param.limit : limit;
|
||||
var clipping = param.clipping || clipping || "";
|
||||
return (input || "").toString().head(limit, clipping);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes leading and trailing whitespaces.
|
||||
*
|
||||
* @see String.prototype.trim
|
||||
*/
|
||||
function trim_filter(input) {
|
||||
return (input || "").toString().trim();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes all tags from a String.
|
||||
* Currently simply wraps Helma's stripTags-method.
|
||||
*
|
||||
* @see global.stripTags
|
||||
*/
|
||||
function stripTags_filter(input) {
|
||||
return stripTags((input || "").toString());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Escapes the characters in a String using XML entities.
|
||||
* Currently simply wraps Helma's encodeXml-method.
|
||||
*
|
||||
* @see global.encodeXml
|
||||
*/
|
||||
function escapeXml_filter(input) {
|
||||
return encodeXml((input || "").toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Escapes the characters in a String using HTML entities.
|
||||
*
|
||||
* @see http://www.google.com/codesearch?q=escapeHtml
|
||||
*/
|
||||
function escapeHtml_filter(input) {
|
||||
var replace = Packages.org.mortbay.util.StringUtil.replace;
|
||||
var str = (input || "").toString();
|
||||
return replace(replace(replace(replace(str, '&', '&'), '"', '"'), '>', '>'), '<', '<');
|
||||
}
|
||||
|
||||
var h_filter = escapeHtml_filter;
|
||||
|
||||
|
||||
/**
|
||||
* Escapes the characters in a String to be suitable
|
||||
* to use as an HTTP parameter value.
|
||||
*
|
||||
* @see http://www.google.com/codesearch?q=escapeUrl
|
||||
* @param charset Optional String. The name of a supported
|
||||
* character encoding.
|
||||
*/
|
||||
function escapeUrl_filter(input, param, charset) {
|
||||
var charset = param.charset || charset || app.getCharset();
|
||||
return java.net.URLEncoder.encode(input || "", charset);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Escapes a string so it may be used in JavaScript String
|
||||
* definitions.
|
||||
*/
|
||||
function escapeJavaScript_filter(input) {
|
||||
var replace = Packages.org.mortbay.util.StringUtil.replace;
|
||||
var str = (input || "").toString();
|
||||
return replace(replace(replace(replace(replace(str, '"', '\\"'), "'", "\\'"), '\n', '\\n'), '\r', '\\r'), '\t', '\\t');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces linebreaks with HTML linebreaks.
|
||||
*/
|
||||
function linebreakToHtml_filter(input) {
|
||||
var replace = Packages.org.mortbay.util.StringUtil.replace;
|
||||
var str = (input || "").toString();
|
||||
return replace(str, '\n', '<br />');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs a string replacement.
|
||||
*
|
||||
* @param old
|
||||
* @param new
|
||||
*/
|
||||
function replace_filter(input, param, oldString, newString) {
|
||||
var str = (input || "").toString();
|
||||
var oldString = param["old"] != null ? param["old"] : oldString;
|
||||
var newString = param["new"] != null ? param["new"] : newString;
|
||||
var replace = Packages.org.mortbay.util.StringUtil.replace;
|
||||
return replace(str, oldString, newString);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a substring. Simply wraps the javascript
|
||||
* method 'substring'.
|
||||
*
|
||||
* @see String.prototype.substring
|
||||
* @param from
|
||||
* @param to
|
||||
*/
|
||||
function substring_filter(input, param, from, to) {
|
||||
var from = param.from != null ? param.from : from;
|
||||
var to = param.to != null ? param.to : to;
|
||||
var str = (input || "").toString();
|
||||
return str.substring(from, to);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatted string representation of a Date.
|
||||
* Simply wraps javascripts Date.format-method.
|
||||
*
|
||||
* @see Date.prototype.format
|
||||
* @param format
|
||||
*/
|
||||
function dateFormat_filter(input, param, format) {
|
||||
var format = param.format || format;
|
||||
if (!input) {
|
||||
return;
|
||||
} else {
|
||||
return input.format(format);
|
||||
}
|
||||
}
|
79
modules/core/Global.js
Normal file
79
modules/core/Global.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2005 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: Global.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Adds useful global macros.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/Global.js')
|
||||
*/
|
||||
|
||||
app.addRepository("modules/core/String.js");
|
||||
|
||||
|
||||
/**
|
||||
* write out a property contained in app.properties
|
||||
* @param Object containing the name of the property
|
||||
*/
|
||||
function property_macro(param, name) {
|
||||
res.write(getProperty(name || param.name) || String.NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wrapper to output a string from within a skin
|
||||
* just to be able to use different encodings
|
||||
* @param Object containing the string as text property
|
||||
*/
|
||||
function write_macro(param, text) {
|
||||
res.write(param.text || text || String.NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* renders the current datetime
|
||||
* @param Object containing a formatting string as format property
|
||||
*/
|
||||
function now_macro(param) {
|
||||
var d = new Date();
|
||||
if (param.format) {
|
||||
try {
|
||||
res.write(d.format(param.format));
|
||||
} catch (e) {
|
||||
res.write('<span title="' + e + '">[Invalid date format]</span>');
|
||||
}
|
||||
} else if (param.as == "timestamp") {
|
||||
res.write(d.getTime());
|
||||
} else {
|
||||
res.write(d);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* renders a global skin
|
||||
*/
|
||||
var skin_macro = function(param, name) {
|
||||
var skinName = name || param.name;
|
||||
if (skinName) {
|
||||
renderSkin(skinName, param);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
196
modules/core/HopObject.js
Normal file
196
modules/core/HopObject.js
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2005 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: HopObject.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Adds useful methods to Helma's built-in HopObject prototype.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/HopObject.js')
|
||||
*/
|
||||
|
||||
app.addRepository("modules/core/Number.js");
|
||||
app.addRepository("modules/core/String.js");
|
||||
|
||||
|
||||
/**
|
||||
* Iterates over each child node of the HopObject.
|
||||
* @param {Function} callback The callback function to be
|
||||
* called for each child node. On every call the first
|
||||
* argument of this function is set to the current value
|
||||
* of the counter variable <code>i</code>.
|
||||
*/
|
||||
HopObject.prototype.forEach = function(callback) {
|
||||
if (!callback || callback instanceof Function == false) {
|
||||
return;
|
||||
}
|
||||
for (var i=0; i<this.size(); i+=1) {
|
||||
callback.call(this.get(i), i);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* macro returns the id of a HopObject
|
||||
*/
|
||||
HopObject.prototype.id_macro = function() {
|
||||
res.write(this._id);
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* macro returns the url for any hopobject
|
||||
*/
|
||||
HopObject.prototype.href_macro = function(param, action) {
|
||||
res.write(this.href(action || param.action || String.NULLSTR));
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* macro rendering a skin or displaying
|
||||
* its source (param.as == "source")
|
||||
*/
|
||||
HopObject.prototype.skin_macro = function(param, name) {
|
||||
var skinName = name || param.name;
|
||||
if (skinName) {
|
||||
if (param.as == "source") {
|
||||
var str = app.skinfiles[this._prototype][skinName];
|
||||
if (str && param.unwrap == "true") {
|
||||
str = str.unwrap();
|
||||
}
|
||||
} else {
|
||||
var str = this.renderSkinAsString(skinName, param);
|
||||
}
|
||||
res.write(str);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* this macro renders a text depending on
|
||||
* the value of a given property
|
||||
*/
|
||||
HopObject.prototype.switch_macro = function(param) {
|
||||
if (param.name) {
|
||||
res.write(this[param.name] ? param.on : param.off);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* generic macro that loops over the childobjects
|
||||
* and renders a specified skin for each of them
|
||||
* @param Object providing the following properties:
|
||||
* skin: the skin to render for each item (required)
|
||||
* collection: the collection containing the items
|
||||
* limit: max. number of items per page
|
||||
* (req.data.page determines the page number)
|
||||
* sort: property name to use for sorting
|
||||
* order: sort order (either "asc" or "desc")
|
||||
* itemPrefix: text to prepend to each items skin render
|
||||
* itemSuffix: text to append to each items skin render
|
||||
*/
|
||||
HopObject.prototype.loop_macro = function(param, collection) {
|
||||
if (!param.skin) {
|
||||
return;
|
||||
}
|
||||
if (!collection) {
|
||||
collection = param.collection;
|
||||
}
|
||||
var items = collection ? this[collection] : this;
|
||||
if (!items || !items.size || items.size() < 1) {
|
||||
return;
|
||||
}
|
||||
// set default values
|
||||
var min = 0, max = items.size();
|
||||
var pagesize = max;
|
||||
if (param.limit) {
|
||||
var n = parseInt(param.limit, 10);
|
||||
if (!isNaN(n)) {
|
||||
pagesize = n;
|
||||
}
|
||||
var pagenr = parseInt(req.data.page, 10);
|
||||
if (isNaN(pagenr)) {
|
||||
pagenr = 0;
|
||||
}
|
||||
min = Math.min(max, pagenr * pagesize);
|
||||
max = Math.min(max, min + pagesize);
|
||||
}
|
||||
if (param.sort) {
|
||||
var allitems = items.list();
|
||||
var test = allitems[0][param.sort];
|
||||
if (test == null || isNaN(test)) {
|
||||
var Sorter = String.Sorter;
|
||||
} else {
|
||||
var Sorter = Number.Sorter;
|
||||
}
|
||||
allitems.sort(new Sorter(param.sort, Sorter[param.order.toUpperCase()]));
|
||||
var itemlist = allitems.slice(min, max);
|
||||
} else {
|
||||
var itemlist = items.list(min, max);
|
||||
}
|
||||
var skinParam = {};
|
||||
var itemPrefix = param.itemPrefix || "";
|
||||
var itemSuffix = param.itemSuffix || "";
|
||||
for (var i=0; i<itemlist.length; i+=1) {
|
||||
skinParam.index = pagenr * pagesize + i + 1;
|
||||
res.write(itemPrefix);
|
||||
itemlist[i].renderSkin(param.skin, skinParam);
|
||||
res.write(itemSuffix);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Render the number of child nodes of the HopObject.
|
||||
* Three cases are distinguished which can be customized
|
||||
* by setting param.verbose to "true" and defining the
|
||||
* corresponding field of the <code>param</code>
|
||||
* argument:
|
||||
* <ol>
|
||||
* <li>param.none - not a single child node</li>
|
||||
* <li>param.one - exactly one child node</li>
|
||||
* <li>param.many - more than one child node</li>
|
||||
* </ol>
|
||||
* @param {Object} param The default macro parameter
|
||||
* @param {String} name The default name for a child node
|
||||
*/
|
||||
HopObject.prototype.size_macro = function(param, name) {
|
||||
var EMPTYSTR = "";
|
||||
var n = this.size();
|
||||
if (name) {
|
||||
var text;
|
||||
var plural = name.endsWith("s") ? "es" : "s";
|
||||
if (n > 0) {
|
||||
if (n > 1) {
|
||||
text = n + " " + name + plural;
|
||||
} else {
|
||||
text = (param.one !== null) ? param.one : "one " + name;
|
||||
}
|
||||
} else {
|
||||
text = (param.none !== null) ? param.none : "no " + name + plural;
|
||||
}
|
||||
res.write(text);
|
||||
} else {
|
||||
res.write(n);
|
||||
}
|
||||
return;
|
||||
};
|
179
modules/core/JSON.js
Normal file
179
modules/core/JSON.js
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2006 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: JSON.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Adds JSON methods to the Object, Array and String prototypes.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/JSON.js')
|
||||
*/
|
||||
|
||||
/*
|
||||
json.js
|
||||
2006-04-28 [http://www.json.org/json.js]
|
||||
|
||||
This file adds these methods to JavaScript:
|
||||
|
||||
object.toJSON()
|
||||
|
||||
This method produces a JSON text from an object. The
|
||||
object must not contain any cyclical references.
|
||||
|
||||
array.toJSON()
|
||||
|
||||
This method produces a JSON text from an array. The
|
||||
array must not contain any cyclical references.
|
||||
|
||||
string.parseJSON()
|
||||
|
||||
This method parses a JSON text to produce an object or
|
||||
array. It will return false if there is an error.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
var m = {
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
},
|
||||
|
||||
s = {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
array: function (x) {
|
||||
var a = ['['], b, f, i, l = x.length, v;
|
||||
for (i = 0; i < l; i += 1) {
|
||||
v = x[i];
|
||||
f = s[typeof v];
|
||||
if (f) {
|
||||
v = f(v);
|
||||
if (typeof v == 'string') {
|
||||
if (b) {
|
||||
a[a.length] = ',';
|
||||
}
|
||||
a[a.length] = v;
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
a[a.length] = ']';
|
||||
return a.join('');
|
||||
},
|
||||
|
||||
'boolean': function (x) {
|
||||
return String(x);
|
||||
},
|
||||
|
||||
'null': function (x) {
|
||||
return "null";
|
||||
},
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
number: function (x) {
|
||||
return isFinite(x) ? String(x) : 'null';
|
||||
},
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
object: function (x) {
|
||||
if (x) {
|
||||
if (x instanceof Array) {
|
||||
return s.array(x);
|
||||
}
|
||||
var a = ['{'], b, f, i, v;
|
||||
for (i in x) {
|
||||
v = x[i];
|
||||
f = s[typeof v];
|
||||
if (f) {
|
||||
v = f(v);
|
||||
if (typeof v == 'string') {
|
||||
if (b) {
|
||||
a[a.length] = ',';
|
||||
}
|
||||
a.push(s.string(i), ':', v);
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
a[a.length] = '}';
|
||||
return a.join('');
|
||||
}
|
||||
return 'null';
|
||||
},
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
string: function (x) {
|
||||
if (/["\\\x00-\x1f]/.test(x)) {
|
||||
x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
|
||||
var c = m[b];
|
||||
if (c) {
|
||||
return c;
|
||||
}
|
||||
c = b.charCodeAt();
|
||||
return '\\u00' +
|
||||
Math.floor(c / 16).toString(16) +
|
||||
(c % 16).toString(16);
|
||||
});
|
||||
}
|
||||
return '"' + x + '"';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This method produces a JSON text from an object.
|
||||
* The object must not contain any cyclical references.
|
||||
*/
|
||||
Object.prototype.toJSON = function () {
|
||||
return s.object(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method produces a JSON text from an array.
|
||||
* The array must not contain any cyclical references.
|
||||
*/
|
||||
Array.prototype.toJSON = function () {
|
||||
return s.array(this);
|
||||
};
|
||||
|
||||
Object.prototype.dontEnum("toJSON");
|
||||
Array.prototype.dontEnum("toJSON");
|
||||
return;
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* This method parses a JSON text to produce an object or
|
||||
* array. It will return false if there is an error.
|
||||
*/
|
||||
String.prototype.parseJSON = function () {
|
||||
try {
|
||||
return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(this.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + this + ')');
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
String.prototype.dontEnum("parseJSON");
|
80
modules/core/Number.js
Normal file
80
modules/core/Number.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2006 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: Number.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Adds useful methods to the JavaScript Number type.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/Number.js')
|
||||
*/
|
||||
|
||||
/**
|
||||
* format a Number to a String
|
||||
* @param String Format pattern
|
||||
* @param java.util.Locale An optional Locale instance
|
||||
* @return String Number formatted to a String
|
||||
*/
|
||||
Number.prototype.format = function(fmt, locale) {
|
||||
var symbols;
|
||||
if (locale != null) {
|
||||
symbols = new java.text.DecimalFormatSymbols(locale);
|
||||
} else {
|
||||
symbols = new java.text.DecimalFormatSymbols();
|
||||
}
|
||||
var df = new java.text.DecimalFormat(fmt || "###,##0.##", symbols);
|
||||
return df.format(0 + this); // addition with 0 prevents exception
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* return the percentage of a Number
|
||||
* according to a given total Number
|
||||
* @param Int Total
|
||||
* @param String Format Pattern
|
||||
* @param java.util.Locale An optional Locale instance
|
||||
* @return Int Percentage
|
||||
*/
|
||||
Number.prototype.toPercent = function(total, fmt, locale) {
|
||||
if (!total)
|
||||
return (0).format(fmt, locale);
|
||||
var p = this / (total / 100);
|
||||
return p.format(fmt, locale);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* factory to create functions for sorting objects in an array
|
||||
* @param String name of the field each object is compared with
|
||||
* @param Number order (ascending or descending)
|
||||
* @return Function ready for use in Array.prototype.sort
|
||||
*/
|
||||
Number.Sorter = function(field, order) {
|
||||
if (!order)
|
||||
order = 1;
|
||||
return function(a, b) {
|
||||
return (a[field] - b[field]) * order;
|
||||
};
|
||||
};
|
||||
|
||||
Number.Sorter.ASC = 1;
|
||||
Number.Sorter.DESC = -1;
|
||||
|
||||
|
||||
// prevent any newly added properties from being enumerated
|
||||
for (var i in Number)
|
||||
Number.dontEnum(i);
|
||||
for (var i in Number.prototype)
|
||||
Number.prototype.dontEnum(i);
|
111
modules/core/Object.js
Normal file
111
modules/core/Object.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2006 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: Object.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Adds useful methods to the JavaScript Object type.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/Object.js')
|
||||
*/
|
||||
|
||||
/**
|
||||
* copy the properties of an object into
|
||||
* a new object
|
||||
* @param Object the source object
|
||||
* @param Object the (optional) target object
|
||||
* @return Object the resulting object
|
||||
*/
|
||||
Object.prototype.clone = function(clone, recursive) {
|
||||
if (!clone)
|
||||
clone = new this.constructor();
|
||||
var value;
|
||||
for (var propName in this) {
|
||||
value = this[propName];
|
||||
if (recursive && (value.constructor == HopObject || value.constructor == Object)) {
|
||||
clone[propName] = value.clone(new value.constructor(), recursive);
|
||||
} else {
|
||||
clone[propName] = value;
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* reduce an extended object (ie. a HopObject)
|
||||
* to a generic javascript object
|
||||
* @param HopObject the HopObject to be reduced
|
||||
* @return Object the resulting generic object
|
||||
*/
|
||||
Object.prototype.reduce = function(recursive) {
|
||||
var result = {};
|
||||
for (var i in this) {
|
||||
if (this[i] instanceof HopObject == false)
|
||||
result[i] = this[i];
|
||||
else if (recursive)
|
||||
result[i] = this.reduce(true);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* print the contents of an object for debugging
|
||||
* @param Object the object to dump
|
||||
* @param Boolean recursive flag (if true, dump child objects, too)
|
||||
*/
|
||||
Object.prototype.dump = function(recursive) {
|
||||
var beginList = "<ul>";
|
||||
var endList = "</ul>";
|
||||
var beginItem = "<li>";
|
||||
var endItem = "</li>";
|
||||
var beginKey = "<strong>";
|
||||
var endKey = ":</strong> ";
|
||||
res.write(beginList);
|
||||
for (var p in this) {
|
||||
res.write(beginItem);
|
||||
res.write(beginKey);
|
||||
res.write(p);
|
||||
res.write(endKey);
|
||||
if (recursive && typeof this[p] == "object") {
|
||||
var recurse = true;
|
||||
var types = [Function, Date, String, Number];
|
||||
for (var i in types) {
|
||||
if (this[p] instanceof types[i]) {
|
||||
recurse = false
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (recurse == true)
|
||||
this[p].dump(true);
|
||||
else {
|
||||
res.write(this[p].toSource());
|
||||
}
|
||||
} else if (this[p]) {
|
||||
res.write(encode(this[p].toSource()));
|
||||
}
|
||||
res.write(endItem);
|
||||
}
|
||||
res.write(endList);
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
// prevent any newly added properties from being enumerated
|
||||
for (var i in Object)
|
||||
Object.dontEnum(i);
|
||||
for (var i in Object.prototype)
|
||||
Object.prototype.dontEnum(i);
|
673
modules/core/String.js
Normal file
673
modules/core/String.js
Normal file
|
@ -0,0 +1,673 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2006 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: String.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
String.ANUMPATTERN = /[^a-zA-Z0-9]/;
|
||||
String.APATTERN = /[^a-zA-Z]/;
|
||||
String.NUMPATTERN = /[^0-9]/;
|
||||
String.FILEPATTERN = /[^a-zA-Z0-9-_\. ]/;
|
||||
String.HEXPATTERN = /[^a-fA-F0-9]/;
|
||||
// Email and URL RegExps contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
|
||||
// licensed unter MIT license - http://www.opensource.org/licenses/mit-license.php
|
||||
String.EMAILPATTERN = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i;
|
||||
String.URLPATTERN = /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
|
||||
String.LEFT = -1
|
||||
String.BALANCE = 0
|
||||
String.RIGHT = 1
|
||||
String.ISOFORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
|
||||
String.SPACE = " ";
|
||||
String.EMPTY = "";
|
||||
String.NULL = String.EMPTY; // to be deprecated?
|
||||
|
||||
/**
|
||||
* @fileoverview Adds useful methods to the JavaScript String type.
|
||||
* <br /><br />
|
||||
* To use this optional module, its repository needs to be added to the
|
||||
* application, for example by calling app.addRepository('modules/core/String.js')
|
||||
*/
|
||||
|
||||
/**
|
||||
* checks if a date format pattern is correct
|
||||
* @return Boolean true if the pattern is correct
|
||||
*/
|
||||
String.prototype.isDateFormat = function() {
|
||||
try {
|
||||
new java.text.SimpleDateFormat(this);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* parse a timestamp into a date object. This is used when users
|
||||
* want to set createtime explicitly when creating/editing stories.
|
||||
* @param String date format to be applied
|
||||
* @param Object Java TimeZone Object (optional)
|
||||
* @return Object contains the resulting date
|
||||
*/
|
||||
String.prototype.toDate = function(format, timezone) {
|
||||
var sdf = res.data._dateformat;
|
||||
if (!sdf) {
|
||||
sdf = new java.text.SimpleDateFormat(format);
|
||||
res.data._dateformat = sdf;
|
||||
} else if (format != sdf.toPattern())
|
||||
sdf.applyPattern(format);
|
||||
if (timezone && timezone != sdf.getTimeZone())
|
||||
sdf.setTimeZone(timezone);
|
||||
try {
|
||||
return new Date(sdf.parse(this).getTime());
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function checks if the string passed contains any characters that
|
||||
* are forbidden in URLs and tries to create a java.net.URL from it
|
||||
* FIXME: probably deprecated -> helma.Url
|
||||
* @return Boolean
|
||||
* @see helma.Url.PATTERN
|
||||
*/
|
||||
String.prototype.isUrl = function() {
|
||||
return String.URLPATTERN.test(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function checks if the string passed contains any characters
|
||||
* that are forbidden in image- or filenames
|
||||
* @return Boolean
|
||||
*/
|
||||
String.prototype.isFileName = function() {
|
||||
return !String.FILEPATTERN.test(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function cleans the string passed as argument from any characters
|
||||
* that are forbidden or shouldn't be used in filenames
|
||||
* @return Boolean
|
||||
*/
|
||||
String.prototype.toFileName = function() {
|
||||
return this.replace(new RegExp(String.FILEPATTERN.source, "g"), String.NULL);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function checks a string for a valid color value in hexadecimal format.
|
||||
* it may also contain # as first character
|
||||
* @returns Boolean false, if string length (without #) > 6 or < 6 or
|
||||
* contains any character which is not a valid hex value
|
||||
*/
|
||||
String.prototype.isHexColor = function() {
|
||||
var str = this;
|
||||
if (this.indexOf("#") == 0)
|
||||
str = this.substring(1);
|
||||
if (str.length != 6)
|
||||
return false;
|
||||
return !String.HEXPATTERN.test(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* converts a string into a hexadecimal color
|
||||
* representation (e.g. "ffcc33"). also knows how to
|
||||
* convert a color string like "rgb (255, 204, 51)".
|
||||
* @return String the resulting hex color (w/o "#")
|
||||
*/
|
||||
String.prototype.toHexColor = function() {
|
||||
if (this.startsWith("rgb")) {
|
||||
res.push();
|
||||
var col = this.replace(/[^0-9,]/g, String.NULL);
|
||||
var parts = col.split(",");
|
||||
for (var i in parts) {
|
||||
var num = parseInt(parts[i], 10);
|
||||
var hex = num.toString(16);
|
||||
res.write(hex.pad("0", 2, String.LEFT));
|
||||
}
|
||||
return res.pop();
|
||||
}
|
||||
var col = this.replace(new RegExp(String.HEXPATTERN.source), String.NULL);
|
||||
return col.toLowerCase().pad("0", 6, String.LEFT);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function returns true if the string contains
|
||||
* only a-z and 0-9 (case insensitive!)
|
||||
* @return Boolean true in case string is alpha, false otherwise
|
||||
*/
|
||||
String.prototype.isAlphanumeric = function() {
|
||||
if (!this.length)
|
||||
return false;
|
||||
return !String.ANUMPATTERN.test(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function cleans a string by throwing away all
|
||||
* non-alphanumeric characters
|
||||
* @return cleaned string
|
||||
*/
|
||||
String.prototype.toAlphanumeric = function() {
|
||||
return this.replace(new RegExp(String.ANUMPATTERN.source, "g"), String.NULL);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function returns true if the string contains
|
||||
* only characters a-z
|
||||
* @return Boolean true in case string is alpha, false otherwise
|
||||
*/
|
||||
String.prototype.isAlpha = function() {
|
||||
if (!this.length)
|
||||
return false;
|
||||
return !String.APATTERN.test(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function returns true if the string contains
|
||||
* only 0-9
|
||||
* @return Boolean true in case string is numeric, false otherwise
|
||||
*/
|
||||
String.prototype.isNumeric = function() {
|
||||
if (!this.length)
|
||||
return false;
|
||||
return !String.NUMPATTERN.test(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* transforms the first n characters of a string to uppercase
|
||||
* @param Number amount of characters to transform
|
||||
* @return String the resulting string
|
||||
*/
|
||||
String.prototype.capitalize = function(limit) {
|
||||
if (limit == null)
|
||||
limit = 1;
|
||||
var head = this.substring(0, limit);
|
||||
var tail = this.substring(limit, this.length);
|
||||
return head.toUpperCase() + tail.toLowerCase();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* transforms the first n characters of each
|
||||
* word in a string to uppercase
|
||||
* @return String the resulting string
|
||||
*/
|
||||
String.prototype.titleize = function() {
|
||||
var parts = this.split(" ");
|
||||
res.push();
|
||||
for (var i in parts) {
|
||||
res.write(parts[i].capitalize());
|
||||
if (i < parts.length-1)
|
||||
res.write(" ");
|
||||
}
|
||||
return res.pop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* translates all characters of a string into HTML entities
|
||||
* @return String translated result
|
||||
*/
|
||||
String.prototype.entitize = function() {
|
||||
res.push();
|
||||
for (var i=0; i<this.length; i++) {
|
||||
res.write("&#");
|
||||
res.write(this.charCodeAt(i).toString());
|
||||
res.write(";");
|
||||
}
|
||||
return res.pop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* breaks up a string into two parts called
|
||||
* head and tail at the given position
|
||||
* don't apply this to HTML, i.e. use stripTags() in advance
|
||||
* @param Number number of charactrers or of segments separated by the delimiter
|
||||
* @param String pre-/suffix to be pre-/appended to shortened string
|
||||
* @param String delimiter
|
||||
* @return Object containing head and tail properties
|
||||
*/
|
||||
String.prototype.embody = function(limit, clipping, delimiter) {
|
||||
if (typeof limit == "string")
|
||||
limit = parseInt(limit, 10);
|
||||
var result = {head: this, tail: String.NULL};
|
||||
if (!limit || limit < 1)
|
||||
return result;
|
||||
if (!delimiter || delimiter == String.NULL)
|
||||
result.head= this.substring(0, limit);
|
||||
else {
|
||||
var re = new RegExp ("(" + delimiter + "+)");
|
||||
result.head = this.split(re, 2*limit - 1).join(String.NULL);
|
||||
}
|
||||
if (result.head != this) {
|
||||
result.tail = this.substring(result.head.length).trim();
|
||||
if (result.tail) {
|
||||
if (clipping == null)
|
||||
clipping = "...";
|
||||
result.head = result.head.trim() + clipping;
|
||||
result.tail = clipping + result.tail;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get the head of a string
|
||||
* @see String.prototype.embody()
|
||||
*/
|
||||
String.prototype.head = function(limit, clipping, delimiter) {
|
||||
return this.embody(limit, clipping, delimiter).head;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get the tail of a string
|
||||
* @see String.prototype.embody()
|
||||
*/
|
||||
String.prototype.tail = function(limit, clipping, delimiter) {
|
||||
return this.embody(limit, clipping, delimiter).tail;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* set clip method out of compatibility/convenience reason
|
||||
* FIXME: we eventually have to get rid of this one...
|
||||
* @see String.prototype.head()
|
||||
*/
|
||||
String.prototype.clip = String.prototype.head;
|
||||
|
||||
|
||||
/**
|
||||
* function inserts a string every number of characters
|
||||
* @param Int number of characters after which insertion should take place
|
||||
* @param String string to be inserted
|
||||
* @param Boolean definitely insert at each interval position
|
||||
* @return String resulting string
|
||||
*/
|
||||
String.prototype.group = function(interval, str, ignoreWhiteSpace) {
|
||||
if (!interval || interval < 1)
|
||||
interval = 20;
|
||||
if (!str || this.length < interval)
|
||||
return this;
|
||||
res.push();
|
||||
for (var i=0; i<this.length; i=i+interval) {
|
||||
var strPart = this.substring(i, i+interval);
|
||||
res.write(strPart);
|
||||
if (ignoreWhiteSpace == true ||
|
||||
(strPart.length == interval && !/\s/g.test(strPart))) {
|
||||
res.write(str);
|
||||
}
|
||||
}
|
||||
return res.pop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* replace all linebreaks and optionally all w/br tags
|
||||
* @param Boolean flag indicating if html tags should be replaced
|
||||
* @param String replacement for the linebreaks / html tags
|
||||
* @return String the unwrapped string
|
||||
*/
|
||||
String.prototype.unwrap = function(removeTags, replacement) {
|
||||
if (replacement == null)
|
||||
replacement = String.NULL;
|
||||
var str = this.replace(/[\n|\r]/g, replacement);
|
||||
if (removeTags)
|
||||
str = str.replace(/<[w]?br *\/?>/g, replacement);
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function calculates the md5 hash of a string
|
||||
* @return String md5 hash of the string
|
||||
*/
|
||||
String.prototype.md5 = function() {
|
||||
return Packages.helma.util.MD5Encoder.encode(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function repeats a string the specified amount of times
|
||||
* @param Int amount of repetitions
|
||||
* @return String resulting string
|
||||
*/
|
||||
String.prototype.repeat = function(multiplier) {
|
||||
res.push();
|
||||
for (var i=0; i<multiplier; i++)
|
||||
res.write(this);
|
||||
return res.pop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function returns true if the string starts with
|
||||
* the string passed as argument
|
||||
* @param String string pattern to search for
|
||||
* @return Boolean true in case it matches the beginning
|
||||
* of the string, false otherwise
|
||||
*/
|
||||
String.prototype.startsWith = function(str, offset) {
|
||||
var javaObj = new java.lang.String(this);
|
||||
if (offset != null)
|
||||
return javaObj.startsWith(str, offset);
|
||||
return javaObj.startsWith(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function returns true if the string ends with
|
||||
* the string passed as argument
|
||||
* @param String string pattern to search for
|
||||
* @return Boolean true in case it matches the end of
|
||||
* the string, false otherwise
|
||||
*/
|
||||
String.prototype.endsWith = function(str) {
|
||||
var javaObj = new java.lang.String(this);
|
||||
return javaObj.endsWith(str);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* fills a string with another string up to a desired length
|
||||
* @param String the filling string
|
||||
* @param Number the desired length of the resulting string
|
||||
* @param Number the direction which the string will be padded in:
|
||||
* -1: left 0: both (balance) 1: right
|
||||
* (you can use the constants String.LEFT,
|
||||
* String.BALANCE and String.RIGHT here as well.)
|
||||
* @return String the resulting string
|
||||
*/
|
||||
String.prototype.pad = function(str, len, mode) {
|
||||
if (str == null || len == null)
|
||||
return this;
|
||||
var diff = len - this.length;
|
||||
if (diff == 0)
|
||||
return this;
|
||||
var left, right = 0;
|
||||
if (mode == null || mode == String.RIGHT)
|
||||
right = diff;
|
||||
else if (mode == String.LEFT)
|
||||
left = diff;
|
||||
else if (mode == String.BALANCE) {
|
||||
right = Math.round(diff / 2);
|
||||
left = diff - right;
|
||||
}
|
||||
res.push();
|
||||
for (var i=0; i<left; i++)
|
||||
res.write(str);
|
||||
res.write(this);
|
||||
for (var i=0; i<right; i++)
|
||||
res.write(str);
|
||||
return res.pop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function returns true if a string contains the string
|
||||
* passed as argument
|
||||
* @param String string to search for
|
||||
* @param Int Position to start search
|
||||
* @param Boolean
|
||||
*/
|
||||
String.prototype.contains = function(str, fromIndex) {
|
||||
if (this.indexOf(str, fromIndex ? fromIndex : 0) > -1)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* function compares a string with the one passed as argument
|
||||
* using diff
|
||||
* @param String String to compare against String object value
|
||||
* @param String Optional regular expression string to use for
|
||||
* splitting. If not defined, newlines will be used.
|
||||
* @return Object Array containing one JS object for each line
|
||||
* with the following properties:
|
||||
* .num Line number
|
||||
* .value String line if unchanged
|
||||
* .deleted Obj Array containing deleted lines
|
||||
* .inserted Obj Array containing added lines
|
||||
*/
|
||||
String.prototype.diff = function(mod, separator) {
|
||||
// if no separator use line separator
|
||||
var regexp = (typeof(separator) == "undefined") ?
|
||||
new RegExp("\r\n|\r|\n") :
|
||||
new RegExp(separator);
|
||||
// split both strings into arrays
|
||||
var orig = this.split(regexp);
|
||||
var mod = mod.split(regexp);
|
||||
// create the Diff object
|
||||
var diff = new Packages.helma.util.Diff(orig, mod);
|
||||
// get the diff.
|
||||
var d = diff.diff();
|
||||
if (!d)
|
||||
return null;
|
||||
|
||||
var max = Math.max(orig.length, mod.length);
|
||||
var result = new Array();
|
||||
for (var i=0;i<max;i++) {
|
||||
var line = result[i];
|
||||
if (!line) {
|
||||
line = new Object();
|
||||
line.num = (i+1);
|
||||
result[i] = line;
|
||||
}
|
||||
if (d && i == d.line1) {
|
||||
if (d.deleted) {
|
||||
var del = new Array();
|
||||
for (var j=d.line0; j<d.line0+d.deleted; j++)
|
||||
del[del.length] = orig[j];
|
||||
line.deleted = del;
|
||||
}
|
||||
if (d.inserted) {
|
||||
var ins = new Array();
|
||||
for (var j=d.line1; j<d.line1+d.inserted; j++)
|
||||
ins[ins.length] = mod[j];
|
||||
line.inserted = ins;
|
||||
}
|
||||
i = d.line1 + d.inserted -1;
|
||||
d = d.link;
|
||||
} else {
|
||||
line.value = mod[i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* remove leading and trailing whitespace
|
||||
*/
|
||||
String.prototype.trim = function () {
|
||||
var s = new java.lang.String(this);
|
||||
return String(s.trim());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* returns true if the string looks like an e-mail
|
||||
*/
|
||||
String.prototype.isEmail = function() {
|
||||
return String.EMAILPATTERN.test(this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* returns the amount of occurences of one string in another
|
||||
*/
|
||||
String.prototype.count = function(str) {
|
||||
var count = 0;
|
||||
var offset = 0;
|
||||
while ((offset = this.indexOf(str, offset)) > -1) {
|
||||
count += 1;
|
||||
offset += 1;
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* returns the string encoded using the base64 algorithm
|
||||
*/
|
||||
String.prototype.enbase64 = function() {
|
||||
var bytes = new java.lang.String(this) . getBytes();
|
||||
return new Packages.sun.misc.BASE64Encoder().encode(bytes);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* returns the decoded string using the base64 algorithm
|
||||
*/
|
||||
String.prototype.debase64 = function() {
|
||||
var bytes = new Packages.sun.misc.BASE64Decoder().decodeBuffer(this);
|
||||
return String(new java.lang.String(bytes));
|
||||
};
|
||||
|
||||
|
||||
// wrapper methods for string-related
|
||||
// global helma functions
|
||||
|
||||
String.prototype.encode = function() {
|
||||
return encode(this);
|
||||
};
|
||||
|
||||
String.prototype.encodeXml = function() {
|
||||
return encodeXml(this);
|
||||
};
|
||||
|
||||
String.prototype.encodeForm = function() {
|
||||
return encodeForm(this);
|
||||
};
|
||||
|
||||
String.prototype.format = function() {
|
||||
return format(this);
|
||||
};
|
||||
|
||||
String.prototype.stripTags = function() {
|
||||
return stripTags(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* factory to create functions for sorting objects in an array
|
||||
* @param String name of the field each object is compared with
|
||||
* @param Number order (ascending or descending)
|
||||
* @return Function ready for use in Array.prototype.sort
|
||||
*/
|
||||
String.Sorter = function(field, order) {
|
||||
if (!order)
|
||||
order = 1;
|
||||
var key = field + ":" + order;
|
||||
if (!String.Sorter.cache[key]) {
|
||||
String.Sorter.cache[key] = function(a, b) {
|
||||
var str1 = String(a[field] || String.NULL).toLowerCase();
|
||||
var str2 = String(b[field] || String.NULL).toLowerCase();
|
||||
if (str1 > str2)
|
||||
return order * 1;
|
||||
if (str1 < str2)
|
||||
return order * -1;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
return String.Sorter.cache[key];
|
||||
};
|
||||
|
||||
String.Sorter.ASC = 1;
|
||||
String.Sorter.DESC = -1;
|
||||
String.Sorter.cache = {};
|
||||
|
||||
|
||||
/**
|
||||
* create a string from a bunch of substrings
|
||||
* @param String one or more strings as arguments
|
||||
* @return String the resulting string
|
||||
*/
|
||||
String.compose = function() {
|
||||
res.push();
|
||||
for (var i=0; i<arguments.length; i++)
|
||||
res.write(arguments[i]);
|
||||
return res.pop();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* creates a random string (numbers and chars)
|
||||
* @param len length of key
|
||||
* @param mode determines which letters to use. null or 0 = all letters;
|
||||
* 1 = skip 0, 1, l and o which can easily be mixed with numbers;
|
||||
* 2 = use numbers only
|
||||
* @returns random string
|
||||
*/
|
||||
String.random = function(len, mode) {
|
||||
if (mode == 2) {
|
||||
var x = Math.random() * Math.pow(10,len);
|
||||
return Math.floor(x);
|
||||
}
|
||||
var keystr = String.NULL;
|
||||
for (var i=0; i<len; i++) {
|
||||
var x = Math.floor((Math.random() * 36));
|
||||
if (mode == 1) {
|
||||
// skip 0,1
|
||||
x = (x<2) ? x + 2 : x;
|
||||
// don't use the letters l (charCode 21+87) and o (24+87)
|
||||
x = (x==21) ? 22 : x;
|
||||
x = (x==24) ? 25 : x;
|
||||
}
|
||||
if (x<10) {
|
||||
keystr += String(x);
|
||||
} else {
|
||||
keystr += String.fromCharCode(x+87);
|
||||
}
|
||||
}
|
||||
return keystr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* append one string onto another and add some "glue"
|
||||
* if none of the strings is empty or null.
|
||||
* @param String the first string
|
||||
* @param String the string to be appended onto the first one
|
||||
* @param String the "glue" to be inserted between both strings
|
||||
* @return String the resulting string
|
||||
*/
|
||||
String.join = function(str1, str2, glue) {
|
||||
if (glue == null)
|
||||
glue = String.NULL;
|
||||
if (str1 && str2)
|
||||
return str1 + glue + str2;
|
||||
else if (str2)
|
||||
return str2;
|
||||
return str1;
|
||||
};
|
||||
|
||||
|
||||
// prevent any newly added properties from being enumerated
|
||||
for (var i in String)
|
||||
String.dontEnum(i);
|
||||
for (var i in String.prototype)
|
||||
String.prototype.dontEnum(i);
|
28
modules/core/all.js
Normal file
28
modules/core/all.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2006 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: all.js,v $
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
// convenience SingleFileRepository to load all the
|
||||
// Javascript library files in ./modules/core
|
||||
|
||||
app.addRepository('modules/core/Array.js');
|
||||
app.addRepository('modules/core/Date.js');
|
||||
app.addRepository('modules/core/Number.js');
|
||||
app.addRepository('modules/core/Object.js');
|
||||
app.addRepository('modules/core/String.js');
|
||||
app.addRepository('modules/core/HopObject.js');
|
||||
app.addRepository('modules/core/Global.js');
|
||||
app.addRepository('modules/core/JSON.js');
|
||||
app.addRepository('modules/core/Filters.js');
|
Loading…
Add table
Add a link
Reference in a new issue