mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Bugfix: Inputosaurus modifications got broken.
Replaced completely with EmailAddressesComponent
This commit is contained in:
parent
b0e3020aab
commit
6a92912a3d
6 changed files with 81 additions and 139 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1,40 +1,24 @@
|
|||
/**
|
||||
* Inputosaurus Text
|
||||
*
|
||||
* Must be instantiated on an <input> 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 <dan@sproutsocial.com>
|
||||
* @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) {
|
||||
if (val) {
|
||||
var self = this,
|
||||
hook,
|
||||
values = [];
|
||||
|
||||
if (val) {
|
||||
if ((hook = self.options.splitHook(val))) {
|
||||
values = hook;
|
||||
} else {
|
||||
values.push(val);
|
||||
}
|
||||
const v = val.trim(),
|
||||
hook = (v && [',', ';', '\n'].includes(v.substr(-1)))
|
||||
? EmailModel.splitEmailLine(val)
|
||||
: null;
|
||||
|
||||
values = self.options.parseHook(values);
|
||||
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);
|
||||
32
dev/External/User/ko.js
vendored
32
dev/External/User/ko.js
vendored
|
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
.inputosaurus-container {
|
||||
|
||||
&.inputosaurus-focused {
|
||||
background-color: #fff;
|
||||
border: @rlInputBorderSize solid darken(@inputBorder, 20%);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue