diff options
author | Ola Bini <ola.bini@gmail.com> | 2014-07-31 19:29:33 -0300 |
---|---|---|
committer | Ola Bini <ola.bini@gmail.com> | 2014-07-31 19:29:33 -0300 |
commit | 04cf441c5ae18400c6b4865b0b37a71718dc9d46 (patch) | |
tree | dd0b0d049ec00389e2d4561b226c46eb1682b997 /web-ui/app/js/helpers | |
parent | 639a663a4c37020003586438fdcd7ac529a00f10 (diff) |
Add web-ui based on previous code
Diffstat (limited to 'web-ui/app/js/helpers')
-rw-r--r-- | web-ui/app/js/helpers/contenttype.js | 164 | ||||
-rw-r--r-- | web-ui/app/js/helpers/iterator.js | 43 | ||||
-rw-r--r-- | web-ui/app/js/helpers/triggering.js | 13 | ||||
-rw-r--r-- | web-ui/app/js/helpers/view_helper.js | 145 |
4 files changed, 365 insertions, 0 deletions
diff --git a/web-ui/app/js/helpers/contenttype.js b/web-ui/app/js/helpers/contenttype.js new file mode 100644 index 00000000..81519452 --- /dev/null +++ b/web-ui/app/js/helpers/contenttype.js @@ -0,0 +1,164 @@ +define([], function () { + var exports = {}; + + // Licence: PUBLIC DOMAIN <http://unlicense.org/> + // Author: Austin Wright <http://github.com/Acubed> + + function MediaType(s, p){ + this.type = ''; + this.params = {}; + if(typeof s=='string'){ + var c = splitQuotedString(s); + this.type = c.shift(); + for(var i=0; i<c.length; i++){ + this.parseParameter(c[i]); + } + }else if(s instanceof MediaType){ + this.type = s.type; + this.q = s.q; + for(var n in s.params) this.params[n]=s.params[n]; + } + if(typeof p=='string'){ + var c = splitQuotedString(p); + for(var i=0; i<c.length; i++){ + this.parseParameter(c[i]); + } + }else if(typeof p=='object'){ + for(var n in p) this.params[n]=p[n]; + } + } + MediaType.prototype.parseParameter = function parseParameter(s){ + var param = s.split('=',1); + var name = param[0].trim(); + var value = s.substr(param[0].length+1).trim(); + if(!value || !name) return; + if(name=='q' && this.q===undefined){ + this.q=parseFloat(value); + }else{ + if(value[0]=='"' && value[value.length-1]=='"'){ + value = value.substr(1, value.length-2); + value = value.replace(/\\(.)/g, function(a,b){return b;}); + } + this.params[name]=value; + } + } + MediaType.prototype.toString = function toString(){ + var str = this.type + ';q='+this.q; + for(var n in this.params){ + str += ';'+n+'='; + if(this.params[n].match(/["=;<>\[\]\(\) ,\-]/)){ + str += '"' + this.params[n].replace(/["\\]/g, function(a){return '\\'+a;}) + '"'; + }else{ + str += this.params[n]; + } + } + return str; + } + exports.MediaType = MediaType; + + // Split a string by character, but ignore quoted parts and backslash-escaped characters + function splitQuotedString(str, delim, quote){ + delim = delim || ';'; + quote = quote || '"'; + var res = []; + var start = 0; + var offset = 0; + function findNextChar(v, c, i, a){ + var p = str.indexOf(c, offset+1); + return (p<0)?v:Math.min(p,v); + } + while(offset>=0){ + offset = [delim,quote].reduce(findNextChar, 1/0); + if(offset===1/0) break; + switch(str[offset]){ + case quote: + // Skip to end of quoted string + while(1){ + offset=str.indexOf(quote, offset+1); + if(offset<0) break; + if(str[offset-1]==='\\') continue; + break; + } + continue; + case delim: + res.push(str.substr(start, offset-start).trim()); + start = ++offset; + break; + } + } + res.push(str.substr(start).trim()); + return res; + } + exports.splitQuotedString = splitQuotedString; + + // Split a list of content types found in an Accept header + // Maybe use it like: splitContentTypes(request.headers.accept).map(parseMedia) + function splitContentTypes(str){ + return splitQuotedString(str, ','); + } + exports.splitContentTypes = splitContentTypes; + + function parseMedia(str){ + var o = new MediaType(str); + if(o.q===undefined) o.q=1; + return o; + } + exports.parseMedia = parseMedia; + + // Pick an ideal representation to send given a list of representations to choose from and the client-preferred list + function select(reps, accept){ + var cr = {q:0}; + var ca = {q:0}; + var cq = 0; + for(var i=0; i<reps.length; i++){ + var r = reps[i]; + var rq = r.q || 1; + for(var j=0; j<accept.length; j++){ + var a=accept[j]; + var aq = a.q || 1; + var cmp = mediaCmp(a, r); + if(cmp!==null && cmp>=0){ + if(aq*rq>cq){ + ca = a; + cr = r; + cq = ca.q*cr.q; + if(cq===1 && cr.type) return cr; + } + } + } + } + return cr.type&&cr; + } + exports.select = select; + + // Determine if one media type is a subset of another + // If a is a superset of b (b is smaller than a), return 1 + // If b is a superset of a, return -1 + // If they are the exact same, return 0 + // If they are disjoint, return null + function mediaCmp(a, b){ + if(a.type==='*/*' && b.type!=='*/*') return 1; + else if(a.type!=='*/*' && b.type==='*/*') return -1; + var ac = (a.type||'').split('/'); + var bc = (b.type||'').split('/'); + if(ac[0]=='*' && bc[0]!='*') return 1; + if(ac[0]!='*' && bc[0]=='*') return -1; + if(a.type!==b.type) return null; + var ap = a.params || {}; + var bp = b.params || {}; + var ak = Object.keys(ap); + var bk = Object.keys(bp); + if(ak.length < bk.length) return 1; + if(ak.length > bk.length) return -1; + var k = ak.concat(bk).sort(); + var dir = 0; + for(var n in ap){ + if(ap[n] && !bp[n]){ if(dir<0) return null; else dir=1; } + if(!ap[n] && bp[n]){ if(dir>0) return null; else dir=-1; } + } + return dir; + } + exports.mediaCmp = mediaCmp; + + return exports; +}); diff --git a/web-ui/app/js/helpers/iterator.js b/web-ui/app/js/helpers/iterator.js new file mode 100644 index 00000000..9d8358a7 --- /dev/null +++ b/web-ui/app/js/helpers/iterator.js @@ -0,0 +1,43 @@ +define(function () { + + return Iterator; + + function Iterator(elems, startingIndex) { + + this.index = startingIndex || 0; + this.elems = elems; + + this.hasPrevious = function () { + return this.index != 0; + }; + + this.hasNext = function () { + return this.index < this.elems.length - 1; + }; + + this.previous = function () { + return this.elems[--this.index]; + }; + + this.next = function () { + return this.elems[++this.index]; + }; + + this.current = function () { + return this.elems[this.index]; + }; + + this.hasElements = function () { + return this.elems.length > 0; + }; + + this.removeCurrent = function () { + var removed = this.current(), + toRemove = this.index; + + !this.hasNext() && this.index--; + this.elems.remove(toRemove); + return removed; + }; + } +});
\ No newline at end of file diff --git a/web-ui/app/js/helpers/triggering.js b/web-ui/app/js/helpers/triggering.js new file mode 100644 index 00000000..7c8ae136 --- /dev/null +++ b/web-ui/app/js/helpers/triggering.js @@ -0,0 +1,13 @@ +define([], function() { + 'use strict'; + + return function(that, event, data, on) { + return function() { + if(on) { + that.trigger(on, event, data || {}); + } else { + that.trigger(event, data || {}); + } + }; + }; +}); diff --git a/web-ui/app/js/helpers/view_helper.js b/web-ui/app/js/helpers/view_helper.js new file mode 100644 index 00000000..3fa9edc1 --- /dev/null +++ b/web-ui/app/js/helpers/view_helper.js @@ -0,0 +1,145 @@ +define( + [ + 'helpers/contenttype', + 'lib/html_whitelister', + 'views/i18n', + 'quoted-printable/quoted-printable' + ], + function(contentType, htmlWhitelister, i18n_lib, quotedPrintable) { + 'use strict'; + + function formatStatusClasses(ss) { + return _.map(ss, function(s) { + return 'status-' + s; + }).join(' '); + } + + function addParagraphsToPlainText(plainTextBodyPart) { + return _.map(plainTextBodyPart.split('\n'), function (paragraph) { + return '<p>' + paragraph + '</p>'; + }).join(''); + } + + function isQuotedPrintableBodyPart (bodyPart) { + return bodyPart.headers['Content-Transfer-Encoding'] && bodyPart.headers['Content-Transfer-Encoding'] === 'quoted-printable'; + } + + function getHtmlContentType (mail) { + return _.find(mail.availableBodyPartsContentType(), function (contentType) { + return contentType.indexOf('text/html') >= 0; + }); + } + + function getSanitizedAndDecodedMailBody (bodyPart) { + var body; + + if (isQuotedPrintableBodyPart(bodyPart)) { + body = quotedPrintable.decode(bodyPart.body); + } else { + body = bodyPart.body; + } + + return htmlWhitelister.sanitize(body, htmlWhitelister.tagPolicy); + } + + function formatMailBody (mail) { + if (mail.isMailMultipartAlternative()) { + var htmlContentType; + + htmlContentType = getHtmlContentType(mail); + + if (htmlContentType) { + return $(getSanitizedAndDecodedMailBody(mail.getMailPartByContentType(htmlContentType))); + } + + return $(addParagraphsToPlainText(mail.getMailMultiParts[0])); + } + + return $(addParagraphsToPlainText(mail.body)); + + /* + var body; + // probably parse MIME parts and ugliness here + // content_type: "multipart/alternative; boundary="----=_Part_1115_17865397.1370312509342"" + var mediaType = new contentType.MediaType(mail.header.content_type); + if(mediaType.type === 'multipart/alternative') { + var parsedBodyParts = getMailMultiParts(mail.body, mediaType); + var selectedBodyPart = getHtmlMailPart(parsedBodyParts) || getPlainTextMailPart(parsedBodyParts) || parsedBodyParts[0]; + body = selectedBodyPart.body; + + if (isQuotedPrintableBodyPart(selectedBodyPart)) { + body = quotedPrintable.decode(body); + } + } else { + body = addParagraphsToPlainText(mail.body); + } + return $(htmlWhitelister.sanitize(body, htmlWhitelister.tagPolicy)); + */ + } + + function moveCaretToEnd(el) { + if (typeof el.selectionStart == "number") { + el.selectionStart = el.selectionEnd = el.value.length; + } else if (typeof el.createTextRange != "undefined") { + el.focus(); + var range = el.createTextRange(); + range.collapse(false); + range.select(); + } + } + + function fixedSizeNumber(num, size) { + var res = num.toString(); + while(res.length < size) { + res = "0" + res; + } + return res; + } + + function getFormattedDate(date){ + var today = createTodayDate(); + if (date.getTime() > today.getTime()) { + return fixedSizeNumber(date.getHours(), 2) + ":" + fixedSizeNumber(date.getMinutes(), 2); + } else { + return "" + date.getFullYear() + "-" + fixedSizeNumber(date.getMonth() + 1, 2) + "-" + fixedSizeNumber(date.getDate(), 2); + } + } + + function createTodayDate() { + var today = new Date(); + today.setHours(0); + today.setMinutes(0); + today.setSeconds(0); + return today; + } + + function moveCaretToEndOfText() { + var self = this; + + moveCaretToEnd(self); + window.setTimeout(function() { + moveCaretToEnd(self); + }, 1); + } + + function quoteMail(mail) { + var quotedLines = _.map(mail.body.split('\n'), function (line) { + return '> ' + line; + }); + + return '\n\n' + quotedLines.join('\n'); + } + + function i18n(text) { + return i18n_lib.get(text); + } + + return { + formatStatusClasses: formatStatusClasses, + formatMailBody: formatMailBody, + moveCaretToEndOfText: moveCaretToEndOfText, + getFormattedDate: getFormattedDate, + quoteMail: quoteMail, + i18n: i18n + }; +}); |