diff --git a/action.php b/action.php
index e0b5384..6a141eb 100644
--- a/action.php
+++ b/action.php
@@ -190,17 +190,28 @@ switch ($VARS['action']) {
$data['uid'] = $_SESSION['uid'];
$database->insert('mail_lists', $data);
$listid = $database->id();
- if (is_empty($VARS['cloneid']) || !$database->has("mail_lists", ['listid' => $VARS['cloneid']])) {
- // Yeah, I'm copypasting. Deal with it.
- } else {
- $addresses = $database->select("addresses", ["email", "name"], ["listid" => $VARS['cloneid']]);
- foreach ($addresses as $addr) {
- $addr["listid"] = $listid;
- $database->insert("addresses", $addr);
- }
- }
} else {
$database->update('mail_lists', $data, ['listid' => $VARS['listid']]);
+ $listid = $VARS['listid'];
+ }
+
+ $emails = explode(",", $VARS['emails']);
+ $dbemails = $database->select('addresses', 'email', ['listid' => $listid]);
+ $todelete = $dbemails;
+ $toadd = [];
+ foreach ($emails as $m) {
+ if (!in_array($m, $dbemails)) {
+ $toadd[] = $m;
+ }
+
+ $todelete = array_diff($todelete, [$m]);
+ }
+
+ foreach ($todelete as $m) {
+ $database->delete('addresses', ["AND" => ['listid' => $listid, "email" => $m]]);
+ }
+ foreach ($toadd as $m) {
+ $database->insert('addresses', ['listid' => $listid, 'email' => $m, 'name' => '']);
}
returnToSender("list_saved");
case "deletelist":
diff --git a/lang/en_us.php b/lang/en_us.php
index 1c466ea..08845ac 100644
--- a/lang/en_us.php
+++ b/lang/en_us.php
@@ -86,4 +86,5 @@ define("STRINGS", [
"addresses" => "Addresses",
"theme" => "Theme",
"format" => "Format",
+ "addresses comma separated" => "Addresses (comma separated)"
]);
\ No newline at end of file
diff --git a/lib/getlisttable.php b/lib/getlisttable.php
index 4faf024..f0b6cbe 100644
--- a/lib/getlisttable.php
+++ b/lib/getlisttable.php
@@ -88,6 +88,7 @@ for ($i = 0; $i < count($lists); $i++) {
}
$lists[$i]["username"] = $usercache[$lists[$i]['uid']]['name'];
}
+ $lists[$i]['count'] = $database->count('addresses', ['listid' => $lists[$i]["listid"]]);
}
$out['lists'] = $lists;
diff --git a/pages.php b/pages.php
index f0e65d0..1049875 100644
--- a/pages.php
+++ b/pages.php
@@ -59,7 +59,11 @@ define("PAGES", [
"editlist" => [
"title" => "edit list",
"navbar" => false,
+ "styles" => [
+ "static/css/tagsinput.css"
+ ],
"scripts" => [
+ "static/js/jquery.tagsinput.min.js",
"static/js/editlist.js"
],
],
diff --git a/pages/editlist.php b/pages/editlist.php
index 6c9a31b..13c35f3 100644
--- a/pages/editlist.php
+++ b/pages/editlist.php
@@ -12,6 +12,7 @@ $data = [
'name' => '',
'id' => ''
];
+$emails = [];
$editing = false;
$cloning = false;
@@ -30,6 +31,7 @@ if (!is_empty($VARS['id'])) {
], [
'listid' => $VARS['id']
])[0];
+ $emails = $database->select('addresses', 'email', ['listid' => $VARS['id']]);
} else {
// item id is invalid, redirect to a page that won't cause an error when pressing Save
header('Location: app.php?page=editlist');
@@ -63,8 +65,13 @@ if (!is_empty($VARS['id'])) {
" required="required" value="" />
-
@@ -74,9 +81,6 @@ if (!is_empty($VARS['id'])) {
}
?>" />
-
-
-
diff --git a/static/css/tagsinput.css b/static/css/tagsinput.css
new file mode 100644
index 0000000..9a6daf6
--- /dev/null
+++ b/static/css/tagsinput.css
@@ -0,0 +1,61 @@
+/*
+ * From https://github.com/xoxco/jQuery-Tags-Input
+ * MIT License
+ */
+div.tagsinput {
+ padding: 5px;
+ padding-top: 10px;
+ padding-left: 10px;
+ width: 300px;
+ height: 100px;
+ overflow-y: auto;
+ font-size: 16px;
+}
+
+div.tagsinput span.tag {
+ border: 1px solid #a5d24a;
+ display: block;
+ border-radius: 2px;
+ float: left;
+ padding: 5px;
+ text-decoration: none;
+ background-color: #4CAF50;
+ color: #fff;
+ margin-right: 8px;
+ margin-bottom: 8px;
+ box-shadow: 0 1px 4px rgba(0,0,0,0.4);
+ line-height: 1.5;
+ border-radius: 0.25rem;
+}
+
+div.tagsinput span.tag a {
+ font-weight: bold;
+ color: #fff;
+ text-decoration: none;
+ font-size: 12px;
+ text-transform: uppercase;
+ padding-right: 3px;
+}
+
+div.tagsinput input {
+ width: 100%;
+ margin: 0px;
+ border: 1px solid transparent;
+ padding: 5px;
+ background: transparent;
+ color: #000;
+ outline: 0px;
+ margin-right: 5px;
+ margin-bottom: 5px;
+}
+
+div.tagsinput div {
+ display: block;
+ float: left;
+}
+
+.tags_clear {
+ clear: both;
+ width: 100%;
+ height: 0px;
+}
\ No newline at end of file
diff --git a/static/js/editlist.js b/static/js/editlist.js
index 7e3b16d..ef9675d 100644
--- a/static/js/editlist.js
+++ b/static/js/editlist.js
@@ -4,4 +4,20 @@
$('#name').on('input propertychange paste', function () {
$('#name_title').text($('#name').val());
+});
+
+$("#emails").tagsInput({
+ height: "100%",
+ width: "100%",
+ defaultText: "Click to add",
+ onAddTag: function (tag) {
+ if (!
+/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(tag)) {
+ $("#emails").removeTag(tag);
+ alert(tag + " does not appear to be a valid email address.");
+ } else if (tag.length > 255) {
+ $("#emails").removeTag(tag);
+ alert(tag + " is too long. Email addresses must be less than 256 characters in length.");
+ }
+ }
});
\ No newline at end of file
diff --git a/static/js/jquery.tagsinput.min.js b/static/js/jquery.tagsinput.min.js
new file mode 100644
index 0000000..fbb0c7f
--- /dev/null
+++ b/static/js/jquery.tagsinput.min.js
@@ -0,0 +1 @@
+!function(a){var b=new Array,c=new Array;a.fn.doAutosize=function(b){var c=a(this).data("minwidth"),d=a(this).data("maxwidth"),e="",f=a(this),g=a("#"+a(this).data("tester_id"));if(e!==(e=f.val())){var h=e.replace(/&/g,"&").replace(/\s/g," ").replace(//g,">");g.html(h);var i=g.width(),j=i+b.comfortZone>=c?i+b.comfortZone:c,k=f.width(),l=k>j&&j>=c||j>c&&d>j;l&&f.width(j)}},a.fn.resetAutosize=function(b){var c=a(this).data("minwidth")||b.minInputWidth||a(this).width(),d=a(this).data("maxwidth")||b.maxInputWidth||a(this).closest(".tagsinput").width()-b.inputPadding,e=a(this),f=a("").css({position:"absolute",top:-9999,left:-9999,width:"auto",fontSize:e.css("fontSize"),fontFamily:e.css("fontFamily"),fontWeight:e.css("fontWeight"),letterSpacing:e.css("letterSpacing"),whiteSpace:"nowrap"}),g=a(this).attr("id")+"_autosize_tester";!a("#"+g).length>0&&(f.attr("id",g),f.appendTo("body")),e.data("minwidth",c),e.data("maxwidth",d),e.data("tester_id",g),e.css("width",c)},a.fn.addTag=function(d,e){return e=jQuery.extend({focus:!1,callback:!0},e),this.each(function(){var f=a(this).attr("id"),g=a(this).val().split(b[f]);if(""==g[0]&&(g=new Array),d=jQuery.trim(d),e.unique){var h=a(this).tagExist(d);1==h&&a("#"+f+"_tag").addClass("not_valid")}else var h=!1;if(""!=d&&1!=h){if(a("").addClass("tag").append(a("").text(d).append(" "),a("",{href:"#",title:"Removing tag",text:"x"}).click(function(){return a("#"+f).removeTag(escape(d))})).insertBefore("#"+f+"_addTag"),g.push(d),a("#"+f+"_tag").val(""),e.focus?a("#"+f+"_tag").focus():a("#"+f+"_tag").blur(),a.fn.tagsInput.updateTagsField(this,g),e.callback&&c[f]&&c[f].onAddTag){var i=c[f].onAddTag;i.call(this,d)}if(c[f]&&c[f].onChange){var j=g.length,i=c[f].onChange;i.call(this,a(this),g[j-1])}}}),!1},a.fn.removeTag=function(d){return d=unescape(d),this.each(function(){var e=a(this).attr("id"),f=a(this).val().split(b[e]);for(a("#"+e+"_tagsinput .tag").remove(),str="",i=0;i=0},a.fn.importTags=function(b){var c=a(this).attr("id");a("#"+c+"_tagsinput .tag").remove(),a.fn.tagsInput.importTags(this,b)},a.fn.tagsInput=function(e){var f=jQuery.extend({interactive:!0,defaultText:"add a tag",minChars:0,width:"300px",height:"100px",autocomplete:{selectFirst:!1},hide:!0,delimiter:",",unique:!0,removeWithBackspace:!0,placeholderColor:"#666666",autosize:!0,comfortZone:20,inputPadding:12},e),g=0;return this.each(function(){if("undefined"==typeof a(this).attr("data-tagsinput-init")){a(this).attr("data-tagsinput-init",!0),f.hide&&a(this).hide();var e=a(this).attr("id");(!e||b[a(this).attr("id")])&&(e=a(this).attr("id","tags"+(new Date).getTime()+g++).attr("id"));var h=jQuery.extend({pid:e,real_input:"#"+e,holder:"#"+e+"_tagsinput",input_wrapper:"#"+e+"_addTag",fake_input:"#"+e+"_tag"},f);b[e]=h.delimiter,(f.onAddTag||f.onRemoveTag||f.onChange)&&(c[e]=new Array,c[e].onAddTag=f.onAddTag,c[e].onRemoveTag=f.onRemoveTag,c[e].onChange=f.onChange);var i='',a(i).insertAfter(this),a(h.holder).css("width",f.width),a(h.holder).css("min-height",f.height),a(h.holder).css("height",f.height),""!=a(h.real_input).val()&&a.fn.tagsInput.importTags(a(h.real_input),a(h.real_input).val()),f.interactive){if(a(h.fake_input).val(a(h.fake_input).attr("data-default")),a(h.fake_input).css("color",f.placeholderColor),a(h.fake_input).resetAutosize(f),a(h.holder).bind("click",h,function(b){a(b.data.fake_input).focus()}),a(h.fake_input).bind("focus",h,function(b){a(b.data.fake_input).val()==a(b.data.fake_input).attr("data-default")&&a(b.data.fake_input).val(""),a(b.data.fake_input).css("color","#000000")}),void 0!=f.autocomplete_url){autocomplete_options={source:f.autocomplete_url};for(attrname in f.autocomplete)autocomplete_options[attrname]=f.autocomplete[attrname];void 0!==jQuery.Autocompleter?(a(h.fake_input).autocomplete(f.autocomplete_url,f.autocomplete),a(h.fake_input).bind("result",h,function(b,c,d){c&&a("#"+e).addTag(c[0]+"",{focus:!0,unique:f.unique})})):void 0!==jQuery.ui.autocomplete&&(a(h.fake_input).autocomplete(autocomplete_options),a(h.fake_input).bind("autocompleteselect",h,function(b,c){return a(b.data.real_input).addTag(c.item.value,{focus:!0,unique:f.unique}),!1}))}else a(h.fake_input).bind("blur",h,function(b){var c=a(this).attr("data-default");return""!=a(b.data.fake_input).val()&&a(b.data.fake_input).val()!=c?b.data.minChars<=a(b.data.fake_input).val().length&&(!b.data.maxChars||b.data.maxChars>=a(b.data.fake_input).val().length)&&a(b.data.real_input).addTag(a(b.data.fake_input).val(),{focus:!0,unique:f.unique}):(a(b.data.fake_input).val(a(b.data.fake_input).attr("data-default")),a(b.data.fake_input).css("color",f.placeholderColor)),!1});a(h.fake_input).bind("keypress",h,function(b){return d(b)?(b.preventDefault(),b.data.minChars<=a(b.data.fake_input).val().length&&(!b.data.maxChars||b.data.maxChars>=a(b.data.fake_input).val().length)&&a(b.data.real_input).addTag(a(b.data.fake_input).val(),{focus:!0,unique:f.unique}),a(b.data.fake_input).resetAutosize(f),!1):void(b.data.autosize&&a(b.data.fake_input).doAutosize(f))}),h.removeWithBackspace&&a(h.fake_input).bind("keydown",function(b){if(8==b.keyCode&&""==a(this).val()){b.preventDefault();var c=a(this).closest(".tagsinput").find(".tag:last").text(),d=a(this).attr("id").replace(/_tag$/,"");c=c.replace(/[\s]+x$/,""),a("#"+d).removeTag(escape(c)),a(this).trigger("focus")}}),a(h.fake_input).blur(),h.unique&&a(h.fake_input).keydown(function(b){(8==b.keyCode||String.fromCharCode(b.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/))&&a(this).removeClass("not_valid")})}}}),this},a.fn.tagsInput.updateTagsField=function(c,d){var e=a(c).attr("id");a(c).val(d.join(b[e]))},a.fn.tagsInput.importTags=function(d,e){a(d).val("");var f=a(d).attr("id"),g=e.split(b[f]);for(i=0;i