diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js
index 9b8dccd8a..df774ae39 100644
--- a/dev/Common/Globals.js
+++ b/dev/Common/Globals.js
@@ -13,6 +13,12 @@ export const moveAction = ko.observable(false);
export const leftPanelDisabled = ko.observable(false);
export const leftPanelType = ko.observable('');
+export const createElement = (name, attr) => {
+ let el = doc.createElement(name);
+ attr && Object.entries(attr).forEach(([k,v]) => el.setAttribute(k,v));
+ return el;
+};
+
leftPanelDisabled.subscribe(value => {
value && moveAction() && moveAction(false);
$htmlCL.toggle('rl-left-panel-disabled', value);
diff --git a/vendors/inputosaurus/inputosaurus.js b/dev/Component/EmailAddresses.js
similarity index 75%
rename from vendors/inputosaurus/inputosaurus.js
rename to dev/Component/EmailAddresses.js
index d50851a01..99bf6d3ee 100644
--- a/vendors/inputosaurus/inputosaurus.js
+++ b/dev/Component/EmailAddresses.js
@@ -1,40 +1,24 @@
-/**
- * Inputosaurus Text
- *
- * Must be instantiated on an element
- * Allows multiple input items. Each item is represented with a removable tag that appears to be inside the input area.
- *
- * @version 0.1.6
- * @author Dan Kielp
- * @created October 3,2012
- *
- * @modified by RainLoop Team
- * @modified by DJMaze
- */
+import { doc, createElement } from 'Common/Globals';
+import { EmailModel } from 'Model/Email';
-(doc => {
+const contentType = 'snappymail/emailaddress';
-const createEl = (name, attr) => {
- let el = doc.createElement(name);
- attr && Object.entries(attr).forEach(([k,v]) => el.setAttribute(k,v));
- return el;
- },
- datalist = createEl('datalist',{id:"inputosaurus-datalist"}),
+let dragAddress, datalist;
- contentType = 'inputosaurus/item';
-
-doc.body.append(datalist);
-
-let dragData;
-
-this.Inputosaurus = class {
+// mailbox-list
+export class EmailAddressesComponent {
constructor(element, options) {
+ if (!datalist) {
+ datalist = createElement('datalist',{id:"emailaddresses-datalist"});
+ doc.body.append(datalist);
+ }
+
var self = this,
// In Chrome we have no access to dataTransfer.getData unless it's the 'drop' event
// In Chrome Mobile dataTransfer.types.includes(contentType) fails, only text/plain is set
- validDropzone = () => dragData && dragData.li.parentNode !== self.ul,
+ validDropzone = () => dragAddress && dragAddress.li.parentNode !== self.ul,
fnDrag = e => validDropzone() && e.preventDefault();
self.element = element;
@@ -46,12 +30,6 @@ this.Inputosaurus = class {
// simply passing an autoComplete source (array, string or function) will instantiate autocomplete functionality
autoCompleteSource : '',
- // manipulate and return the input value after parseInput() parsing
- // the array of tag names is passed and expected to be returned as an array after manipulation
- parseHook : null,
-
- splitHook : null,
-
onChange : null
}, options);
@@ -60,21 +38,21 @@ this.Inputosaurus = class {
self._lastEdit = '';
// Create the elements
- self.ul = createEl('ul',{class:"inputosaurus-container"});
+ self.ul = createElement('ul',{class:"emailaddresses"});
self.ul.addEventListener('click', e => self._focus(e));
self.ul.addEventListener('dblclick', e => self._editTag(e));
self.ul.addEventListener("dragenter", fnDrag);
self.ul.addEventListener("dragover", fnDrag);
self.ul.addEventListener("drop", e => {
- if (validDropzone() && dragData.value) {
+ if (validDropzone() && dragAddress.value) {
e.preventDefault();
- dragData.source._removeDraggedTag(dragData.li);
- self._parseValue(dragData.value);
+ dragAddress.source._removeDraggedTag(dragAddress.li);
+ self._parseValue(dragAddress.value);
}
});
- self.input = createEl('input',{type:"text", list:datalist.id,
+ self.input = createElement('input',{type:"text", list:datalist.id,
autocomplete:"off", autocorrect:"off", autocapitalize:"off", spellcheck:"false"});
self.input.addEventListener('focus', () => self._focusTrigger(true));
@@ -111,7 +89,7 @@ this.Inputosaurus = class {
self.input.placeholder = element.placeholder;
}
- self.inputCont = createEl('li',{class:"inputosaurus-input"});
+ self.inputCont = createElement('li',{class:"emailaddresses-input"});
self.inputCont.append(self.input);
self.ul.append(self.inputCont);
@@ -140,7 +118,7 @@ this.Inputosaurus = class {
}
_focusTrigger(bValue) {
- this.ul.classList.toggle('inputosaurus-focused', bValue);
+ this.ul.classList.toggle('emailaddresses-focused', bValue);
this.options.focusCallback(bValue);
}
@@ -157,18 +135,18 @@ this.Inputosaurus = class {
}
_parseValue(val) {
- var self = this,
- hook,
- values = [];
-
if (val) {
- if ((hook = self.options.splitHook(val))) {
- values = hook;
- } else {
- values.push(val);
- }
+ var self = this,
+ values = [];
- values = self.options.parseHook(values);
+ const v = val.trim(),
+ hook = (v && [',', ';', '\n'].includes(v.substr(-1)))
+ ? EmailModel.splitEmailLine(val)
+ : null;
+
+ values = (hook || [val]).map(value => EmailModel.parseEmailLine(value))
+ .flat(Infinity)
+ .map(item => (item.toLine ? [item.toLine(false), item] : [item, null]));
if (values.length) {
self._setChosen(values);
@@ -187,7 +165,7 @@ this.Inputosaurus = class {
_editTag(ev) {
var li = ev.target.closest('li'),
- tagKey = li && li.inputosaurusKey;
+ tagKey = li && li.emailaddress.key;
if (!tagKey) {
return true;
@@ -289,15 +267,15 @@ this.Inputosaurus = class {
self._chosenValues.forEach(v => {
if (v.obj) {
- let li = createEl('li',{title:v.obj.toLine(false, false, true),draggable:'true'}),
- el = createEl('span');
+ let li = createElement('li',{title:v.obj.toLine(false, false, true),draggable:'true'}),
+ el = createElement('span');
el.append(v.obj.toLine(true, false, true));
li.append(el);
- el = createEl('a',{href:'#', class:'ficon'});
+ el = createElement('a',{href:'#', class:'ficon'});
el.append('✖');
el.addEventListener('click', e => self._removeTag(e, li));
- el.addEventListener('focus', () => li.className = 'inputosaurus-selected');
+ el.addEventListener('focus', () => li.className = 'emailaddresses-selected');
el.addEventListener('blur', () => li.className = null);
el.addEventListener('keydown', e => {
switch (e.key) {
@@ -339,23 +317,22 @@ this.Inputosaurus = class {
});
li.append(el);
- li.inputosaurusKey = v.key;
- li.inputosaurusValue = v.obj.toLine();
+ li.emailaddress = v;
li.addEventListener("dragstart", e => {
- dragData = {
+ dragAddress = {
source: self,
li: li,
- value: li.inputosaurusValue
+ value: li.emailaddress.obj.toLine()
};
-// e.dataTransfer.setData(contentType, li.inputosaurusValue);
+// e.dataTransfer.setData(contentType, li.emailaddress.obj.toLine());
e.dataTransfer.setData('text/plain', contentType);
// e.dataTransfer.setDragImage(li, 0, 0);
e.dataTransfer.effectAllowed = 'move';
li.style.opacity = 0.25;
});
li.addEventListener("dragend", () => {
- dragData = null;
+ dragAddress = null;
li.style.cssText = '';
});
@@ -367,7 +344,7 @@ this.Inputosaurus = class {
_removeTag(ev, li) {
ev.preventDefault();
- var key = li.inputosaurusKey,
+ var key = li.emailaddress.key,
self = this,
indexFound = self._chosenValues.findIndex(v => key === v.key);
@@ -381,7 +358,7 @@ this.Inputosaurus = class {
_removeDraggedTag(li) {
var
- key = li.inputosaurusKey,
+ key = li.emailaddress.key,
self = this,
indexFound = self._chosenValues.findIndex(v => key === v.key)
;
@@ -403,38 +380,21 @@ this.Inputosaurus = class {
_focus(ev) {
var li = ev.target.closest('li');
- if (li && li.inputosaurusKey) {
+ if (li && li.emailaddress.key) {
li.querySelector('a').focus();
} else {
this.focus();
}
}
- refresh() {
- var self = this,
- val = self.element.value,
- values = [];
-
- values.push(val);
-
- if (val) {
- var hook = self.options.splitHook(val);
- if (hook) {
- values = hook;
- }
- }
-
- if (values.length) {
+ set value(value) {
+ var self = this;
+ if (self.element.value !== value) {
+// self.input.value = '';
+// self._resizeInput();
self._chosenValues = [];
-
- values = self.options.parseHook(values);
-
- self._setChosen(values);
self._renderTags();
- self.input.value = '';
- self._resizeInput();
+ self._parseValue(self.element.value = value);
}
}
-};
-
-})(document);
+}
diff --git a/dev/External/User/ko.js b/dev/External/User/ko.js
index 2aa9cba3b..dd59d117e 100644
--- a/dev/External/User/ko.js
+++ b/dev/External/User/ko.js
@@ -2,8 +2,8 @@ import 'External/ko';
import ko from 'ko';
import { HtmlEditor } from 'Common/Html';
import { timeToNode } from 'Common/Momentor';
-import { EmailModel } from 'Model/Email';
import { doc } from 'Common/Globals';
+import { EmailAddressesComponent } from 'Component/EmailAddresses';
const rlContentType = 'snappymail/action',
@@ -64,42 +64,22 @@ ko.bindingHandlers.moment = {
ko.bindingHandlers.emailsTags = {
init: (element, fValueAccessor, fAllBindingsAccessor) => {
const fValue = fValueAccessor(),
- fAllBindings = fAllBindingsAccessor(),
- inputDelimiters = [',', ';', '\n'];
+ fAllBindings = fAllBindingsAccessor();
- element.inputosaurus = new window.Inputosaurus(element, {
+ element.addresses = new EmailAddressesComponent(element, {
focusCallback: value => fValue.focused && fValue.focused(!!value),
autoCompleteSource: fAllBindings.autoCompleteSource || null,
- splitHook: value => {
- const v = value.trim();
- return (v && inputDelimiters.includes(v.substr(-1)))
- ? EmailModel.splitEmailLine(value)
- : null;
- },
- parseHook: input =>
- input.map(inputValue => EmailModel.parseEmailLine(inputValue))
- .flat(Infinity)
- .map(item => (item.toLine ? [item.toLine(false), item] : [item, null])),
- onChange: value => {
- element.EmailsTagsValue = value;
- fValue(value);
- }
+ onChange: value => fValue(value)
});
if (fValue.focused && fValue.focused.subscribe) {
fValue.focused.subscribe(value =>
- element.inputosaurus[value ? 'focus' : 'blur']()
+ element.addresses[value ? 'focus' : 'blur']()
);
}
},
update: (element, fValueAccessor) => {
- const value = ko.unwrap(fValueAccessor());
-
- if (element.EmailsTagsValue !== value) {
- element.value = value;
- element.EmailsTagsValue = value;
- element.inputosaurus.refresh();
- }
+ element.addresses.value = ko.unwrap(fValueAccessor());
}
};
diff --git a/dev/Styles/@Main.less b/dev/Styles/@Main.less
index 322d84028..65918ee75 100644
--- a/dev/Styles/@Main.less
+++ b/dev/Styles/@Main.less
@@ -22,7 +22,6 @@
@import "_FontasticToBoot.less";
@import "_BootstrapFix.less";
-@import "_InputosaurusFix.less";
@import "_CkeFix.less";
@import "Ui.less";
@@ -50,6 +49,7 @@
@import "MessageView.less";
@import "Contacts.less";
@import "Compose.less";
+@import "EmailAddresses.less";
@import "Admin.less";
@import "AdminGeneral.less";
diff --git a/vendors/inputosaurus/inputosaurus.css b/dev/Styles/EmailAddresses.less
similarity index 64%
rename from vendors/inputosaurus/inputosaurus.css
rename to dev/Styles/EmailAddresses.less
index a3119dc15..ab084bc4a 100644
--- a/vendors/inputosaurus/inputosaurus.css
+++ b/dev/Styles/EmailAddresses.less
@@ -1,4 +1,4 @@
-.inputosaurus-container {
+.emailaddresses {
background-color: #fff;
border: 1px solid #ccc;
border-radius: 3px;
@@ -12,10 +12,16 @@
transition: border linear .2s, box-shadow linear .2s;
}
-.inputosaurus-container li {
+.emailaddresses.emailaddresses-focused {
+ background-color: #fff;
+ border: @rlInputBorderSize solid darken(@inputBorder, 20%);
+ box-shadow: none;
+}
+
+.emailaddresses li {
display: inline-block;
}
-.inputosaurus-container li[draggable] {
+.emailaddresses li[draggable] {
background-color: #eee;
border: 1px solid #aaa;
border-radius: 2px;
@@ -32,15 +38,15 @@
white-space: nowrap;
}
-.inputosaurus-container li.pgp {
+.emailaddresses li.pgp {
background-color: #E5F3E2;
}
-.inputosaurus-container li span {
+.emailaddresses li span {
padding-right: 3px;
}
-.inputosaurus-container li a {
+.emailaddresses li a {
font-size: 12px;
color: #999;
outline: 0;
@@ -50,18 +56,18 @@
text-decoration: none;
top: 1px;
}
-.inputosaurus-container li a:hover {
+.emailaddresses li a:hover {
color: #666;
}
-.inputosaurus-container .inputosaurus-input {
+.emailaddresses .emailaddresses-input {
margin: 0 2px;
padding: 0;
}
-.inputosaurus-container input[type="text"],
-.inputosaurus-container input[type="text"]:focus,
-.inputosaurus-container input[type="text"]:hover {
+.emailaddresses input[type="text"],
+.emailaddresses input[type="text"]:focus,
+.emailaddresses input[type="text"]:hover {
border: 0;
box-shadow: none;
height: 24px;
@@ -71,8 +77,8 @@
vertical-align: baseline;
}
-.inputosaurus-container li.inputosaurus-selected,
-.inputosaurus-container li.inputosaurus-selected a {
+.emailaddresses li.emailaddresses-selected,
+.emailaddresses li.emailaddresses-selected a {
background-color: Highlight;
color: HighlightText;
}
diff --git a/dev/Styles/_InputosaurusFix.less b/dev/Styles/_InputosaurusFix.less
deleted file mode 100644
index 6732d958e..000000000
--- a/dev/Styles/_InputosaurusFix.less
+++ /dev/null
@@ -1,10 +0,0 @@
-
-.inputosaurus-container {
-
- &.inputosaurus-focused {
- background-color: #fff;
- border: @rlInputBorderSize solid darken(@inputBorder, 20%);
- box-shadow: none;
- }
-
-}