// Udviddelser af Javascript objekterne. Generel funktionalitet og formatering
var Globals = function() {
var _jsonDateExp = /\/Date\((\d+)\)\//;
var _bindingExp = /\{([^\}\:]+)(\:[^\}]+)?\}/g;
var _idxBindingExp = /\{(\d)(\:[^\}]+)?\}/g;
var _monthNames = ["januar", "februar", "marts", "april", "maj", "juni", "juli", "august", "september", "oktober", "november", "december"];
var _dayNames = ["søndag", "mandag", "tirsdag", "onsdag", "torsdag", "fredag", "lørdag"];
return {
jsonDateExp: function() { return _jsonDateExp; },
bindingExp: function() { return _bindingExp; },
idxBindingExp: function() { return _idxBindingExp; },
monthNames: function() { return _monthNames; },
dayNames: function() { return _dayNames; }
}
} ();
String.prototype.format = function() {
///<SUMMARY>Bruger strengen som bindingsudtryk, og indsætter argumenterne på de angivne pladser.
///Eks.: "Say: {0}".format("Hello World")</SUMMARY>
/// <PARAM name="args" />Op til 10 objekter der skal indsættes i formateringsstrengen</PARAM>
/// <RETURNS type="String" />
var re = Globals.idxBindingExp();
var params = arguments;
var builder = this.replace(re, function() {
if (arguments[1] >= params.length)
throw new Error("String.format: Bindingsudtryk stemmer ikke over ens med antal af argumenter");
var format = arguments[2] ? arguments[2].slice(1) : "";
return format ? params[arguments[1]].format(format) : params[arguments[1]];
});
return builder;
};
String.prototype.bind = function(item) {
var re = Globals.bindingExp();
var dateRe = Globals.jsonDateExp();
return this.replace(re, function() {
if (typeof (item[arguments[1]]) == "undefined")
throw new Error("String.bind: Ukendt bindingsudtryk: " + arguments[1]);
var format = arguments[2] ? arguments[2].slice(1) : null;
var key = arguments[1];
if (dateRe.test(item[key]))
item[key] = eval(item[key].replace(dateRe, "new Date($1)"));
return format ? item[key].format(format) : item[key];
});
};
String.prototype.repeat = function(n) {
///<SUMMARY>Gentager en given streng n gange</SUMMARY>
return new Array(n + 1).join(this);
};
String.prototype.capitalize = function() {
/// <SUMMARY>Sætter begyndelsesbogstaver i strengen til store bogstaver.</SUMMARY>
var re = /\b(\w)([\wæøå]*)\b/g;
return this.replace(re, function() {
if (arguments.length > 2)
return arguments[1].toUpperCase() + arguments[2];
return null;
});
};
String.prototype.compare = function(str) {
///<SUMMARY>Sammenligner med streng, og returnerer sortering alfabetisk</SUMMARY>
if (this == str)
return 0;
var arr = [this, str];
arr.sort();
return arr[0] == this ? -1 : 1;
};
Number.prototype.fix = function(n) {
/// <SUMMARY>Returnerer tallet med foranstillede nuller</SUMMARY>
/// <PARAM name="n" type="Integer" />Antal karakterer der skla returneres</PARAM>
/// <RETURNS type="String" />
var number = this.toString();
if (number.length > n)
return number;
var builder = "0".repeat(n);
builder = builder.slice(0, builder.length - number.length) + number;
return builder;
};
Date.prototype.format = function(formatString) {
/// <SUMMARY>Formaterer datoer i henhold til det angivne format</SUMMARY>
/// <PARAM type="String" />F.eks.: d. MMM yy hh:mm eller: dd/MM-yyyy</PARAM>
/// <RETURNS type="String" />
var monthNames = Globals.monthNames();
var builder = formatString;
if (m = formatString.match(/^j$/i))
return "\\/Date({0})\\/".format(this.getTime());
if (m = formatString.match(/d{1,2}/)) {
if (m[0].length == 1)
builder = builder.replace(m[0], this.getDate());
else
builder = builder.replace(m[0], this.getDate().fix(2));
}
if (m = formatString.match(/M{1,3}/)) {
var str = m[0].length < 3 ? (this.getMonth() + 1).fix(m[0].length) : monthNames[this.getMonth()];
builder = builder.replace(m[0], str);
}
if (m = formatString.match(/y{2,4}/)) {
var str = m[0].length == 2 ? this.getFullYear().toString().slice(2, 4) : this.getFullYear().fix(m[0].length);
builder = builder.replace(m[0], str);
}
if (m = formatString.match(/h{1,2}/)) {
builder = builder.replace(m[0], this.getHours().fix(m[0].length));
}
if (m = formatString.match(/m{1,2}/)) {
builder = builder.replace(m[0], this.getMinutes().fix(m[0].length));
}
if (m = formatString.match(/s{1,2}/)) {
builder = builder.replace(m[0], this.getSeconds().fix(m[0].length));
}
return builder;
};
Date.prototype.isPast = function() {
return (new Date()) > this;
};
Date.prototype.getDayName = function() {
return Globals.dayNames()[this.getDay()];
};
Date.prototype.isToday = function() {
var today = new Date();
return this.getFullYear() == today.getFullYear() && this.getMonth() == today.getMonth() && this.getDate() == today.getDate();
}
Date.prototype.getWeek = function() {
var date = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
var IsoDayOfWeek = date.getDay() == 0 ? 7 : date.getDay(); // Søndag = 7
date.setDate(date.getDate() + 4 - IsoDayOfWeek); // Ændre til nærmeste torsdag
var DayOfYear = (date.getTime() - Date.UTC(date.getFullYear(), 0, 1)) / 864e5;
var week = Math.floor(DayOfYear / 7) + 1;
return week;
};
Date.prototype.addDays = function(days) {
var result = new Date(this.getTime() + (1000 * 60 * 60 * 24 * days));
var dst = result.getHours() - this.getHours();
if (dst)
result = new Date(this.getTime() + (1000 * 60 * 60 * (24 + dst) * days));
return result;
};
Date.prototype.addMonth = function(months) {
var result = new Date(this);
result.setMonth(this.getMonth() + months);
return result;
};
Array.prototype.each = function(handler) {
/// <SUMMARY>Iterator funktion, der kalder handleren for hvert element i arrayen: handler(item, idx)</SUMMARY>
for (var i = 0; i < this.length; i++)
handler(this[i], i);
};
Array.prototype.where = function(predicate) {
var predicateFunction;
if (typeof predicate == "string") {
predicateFunction = function(itm) {
with (itm) {
return eval(predicate);
}
};
}
else {
predicateFunction = predicate;
}
var result = [];
this.each(function(itm, i) {
if (predicateFunction(itm))
result.push(itm);
});
return result;
};
Array.prototype.limit = function(start, size) {
return this.slice(start, start + size);
}
Array.prototype.select = function(clause) {
var result = [];
if (typeof clause == "string") {
for (var i = 0; i < this.length; i++)
result.push(eval(clause));
}
else {
for (var i = 0; i < this.length; i++)
result.push(clause(this[i]));
}
return result;
};
Array.prototype.orderBy = function(expression, direction) {
///<SUMMARY>Sorterer elementerne i henhold til expression udtrykket
/// Hvis expression er en streng, forudsættes det at den er en property på alle elementer i array'et
/// Hvis expression er en funktion, får den to array-elementer ind, og og forventes at returnerer -1, 0, 1.</SUMMARY>
if (typeof direction != "string" || !/^(desc|asc)$/i.test(direction))
throw new Error("Array.orderBy: direction argument, kan kun have værdien ASC eller DESC");
var sortFunction;
if (typeof expression == "string") {
sortFunction = function(a, b) {
var i = a[expression] - b[expression];
if (isNaN(i)) {
i = a[expression].compare(b[expression]);
}
return i;
}
}
else {
sortFunction = expression;
}
var result = this.clone();
result.sort(sortFunction);
if ((/desc/i).test(direction))
result.reverse();
return result;
};
Array.prototype.clone = function() {
var clone = [];
this.each(function(itm) { clone.push(itm); });
return clone;
};
Array.prototype.render = function(template, renderCallback) {
/// <SUMMARY>Udskriver alle elementer i følge skabelonen</SUMMARY>
/// <PARAM name="template" type="string" />Streng med bindingssyntaks: Klammer med propertynavne. F.eks. Navn: {name}</PARAM>
///<PARAM name="renderCallback" />funktion der modtager resultatet af renderingen. funk(rowString, rowIdx)</PARAM>
var result = [];
var handler = (typeof renderCallback == "undefined") ?
function(item) { result.push(template.bind(item)); } :
function(item, idx) {
var str = template.bind(item);
result.push(str);
renderCallback(str, idx);
};
this.each(handler);
return result;
};