From 11aa571751015b31332e2c113c238a050928b191 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sat, 21 Jul 2012 14:24:26 +0200 Subject: [PATCH 1/4] Added option to notify method. --- apps/contacts/js/contacts.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 8d88149876..130d6b6431 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -12,10 +12,28 @@ String.prototype.strip_tags = function(){ Contacts={ UI:{ + /** + * Arguments: + * message: The text message to show. The only mandatory parameter. + * timeout: The timeout in seconds before the notification disappears. Default 10. + * timeouthandler: A function to run on timeout. + * clickhandler: A function to run on click. If a timeouthandler is given it will be cancelled. + */ notify:function(params) { - $('#notification').text(params.message); - $('#notification').fadeIn(); - setTimeout(function() {$('#notification').fadeOut();}, 10000); + var notifier = $('#notification'); + notifier.text(params.message); + notifier.fadeIn(); + var timer = setTimeout(function() { + notifier.fadeOut(); + if(params.timeouthandler && $.isFunction(params.timeouthandler)) { params.timeouthandler();} + }, params.timeout && $.isNumeric(params.timeout) ? parseInt(params.timeout)*1000 : 10000); + if(params.clickhandler && $.isFunction(params.clickhandler)) { + notifier.on('click', function() { + clearTimeout(timer); + notifier.off('click'); + params.clickhandler(); + }); + } }, notImplemented:function() { OC.dialogs.alert(t('contacts', 'Sorry, this functionality has not been implemented yet'), t('contacts', 'Not implemented')); From 00de757169f7ac6787d087de0fb47f5a948cded3 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sat, 21 Jul 2012 14:26:26 +0200 Subject: [PATCH 2/4] White space. --- apps/contacts/js/contacts.js | 74 ++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 130d6b6431..994e1f87fd 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -114,7 +114,7 @@ Contacts={ $('.addresscard,.propertylist li,.propertycontainer').hover( function () { $(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 1.0 }, 200, function() {}); - }, + }, function () { $(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 0.1 }, 200, function() {}); } @@ -125,7 +125,7 @@ Contacts={ obj.tipsy('hide'); Contacts.UI.Card.deleteProperty(obj, 'single'); } - + var goToUrl = function(obj) { var url = Contacts.UI.propertyContainerFor(obj).find('#url').val(); if(url != '') { @@ -133,7 +133,7 @@ Contacts={ newWindow.focus(); } } - + $('#identityprops a.delete').click( function() { deleteItem($(this)) }); $('#identityprops a.delete').keydown( function() { deleteItem($(this)) }); $('#categories_value a.edit').click( function() { $(this).tipsy('hide');OCCategories.edit(); } ); @@ -158,7 +158,7 @@ Contacts={ }); $('#edit_name').click(function(){Contacts.UI.Card.editName()}); $('#edit_name').keydown(function(){Contacts.UI.Card.editName()}); - + $('#phototools li a').click(function() { $(this).tipsy('hide'); }); @@ -185,13 +185,13 @@ Contacts={ OC.dialogs.filepicker(t('contacts', 'Select photo'), Contacts.UI.Card.cloudPhotoSelected, false, 'image', true); }); /* Initialize the photo edit dialog */ - $('#edit_photo_dialog').dialog({ + $('#edit_photo_dialog').dialog({ autoOpen: false, modal: true, height: 'auto', width: 'auto' }); $('#edit_photo_dialog' ).dialog( 'option', 'buttons', [ { text: "Ok", - click: function() { + click: function() { Contacts.UI.Card.savePhoto(this); $(this).dialog('close'); } @@ -201,7 +201,7 @@ Contacts={ click: function() { $(this).dialog('close'); } } ] ); - + // Name has changed. Update it and reorder. $('#fn').change(function(){ var name = $('#fn').val().strip_tags(); @@ -217,7 +217,7 @@ Contacts={ }); $('#contacts_deletecard').click( function() { Contacts.UI.Card.doDelete();return false;} ); - $('#contacts_deletecard').keydown( function(event) { + $('#contacts_deletecard').keydown( function(event) { if(event.which == 13 || event.which == 32) { Contacts.UI.Card.doDelete(); } @@ -225,7 +225,7 @@ Contacts={ }); $('#contacts_downloadcard').click( function() { Contacts.UI.Card.doExport();return false;} ); - $('#contacts_downloadcard').keydown( function(event) { + $('#contacts_downloadcard').keydown( function(event) { if(event.which == 13 || event.which == 32) { Contacts.UI.Card.doExport(); } @@ -240,12 +240,12 @@ Contacts={ $('#contacts_details_photo_wrapper').bind('dragover',function(event){ $(event.target).addClass('droppable'); event.stopPropagation(); - event.preventDefault(); + event.preventDefault(); }); $('#contacts_details_photo_wrapper').bind('dragleave',function(event){ $(event.target).removeClass('droppable'); //event.stopPropagation(); - //event.preventDefault(); + //event.preventDefault(); }); $('#contacts_details_photo_wrapper').bind('drop',function(event){ event.stopPropagation(); @@ -331,10 +331,10 @@ Contacts={ if($('.contacts li').length > 0) { $.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':newid},function(jsondata){ if(jsondata.status == 'success'){ - if(bookid == 'unknown') { - bookid = jsondata.data.addressbookid; + if(bookid == 'unknown') { + bookid = jsondata.data.addressbookid; var contact = Contacts.UI.Contacts.insertContact({ - contactlist:$('#contacts ul[data-id="'+bookid+'"]'), + contactlist:$('#contacts ul[data-id="'+bookid+'"]'), data:jsondata.data }); } @@ -348,7 +348,7 @@ Contacts={ }); } } - + // Make sure proper DOM is loaded. if(!$('#card').length && newid) { console.log('Loading card DOM'); @@ -433,7 +433,7 @@ Contacts={ } }); } - + if(!$('#card').length) { console.log('Loading card DOM'); $.getJSON(OC.filePath('contacts', 'ajax', 'loadcard.php'),{'requesttoken': requesttoken},function(jsondata){ @@ -470,7 +470,7 @@ Contacts={ $('#rightcontent').data('id',newid); this.id = this.fn = this.fullname = this.shortname = this.famname = this.givname = this.addname = this.honpre = this.honsuf = ''; this.data = undefined; - + if($('.contacts li').length > 0) { // Load first in list. Contacts.UI.Card.update({cid:newid, aid:bookid}); } else { @@ -542,7 +542,7 @@ Contacts={ $('#contacts_propertymenu_dropdown a[data-type="'+propname+'"]').parent().hide(); var property = this.data[propname][0]; var value = property['value'], checksum = property['checksum']; - + if(propname == 'BDAY') { var val = $.datepicker.parseDate('yy-mm-dd', value.substring(0, 10)); value = $.datepicker.formatDate('dd-mm-yy', val); @@ -607,7 +607,7 @@ Contacts={ $.each(names, function(key, value) { $('#fn_select') .append($('') - .text(value)); + .text(value)); }); $('#fn_select').combobox('value', this.fn); $('#contact_identity').find('*[data-element="N"]').data('checksum', this.data.N[0]['checksum']); @@ -858,7 +858,7 @@ Contacts={ title: t('contacts', 'Edit name'), height: 'auto', width: 'auto', buttons: { - 'Ok':function() { + 'Ok':function() { Contacts.UI.Card.saveName(this); $(this).dialog('close'); }, @@ -909,9 +909,9 @@ Contacts={ $.each(names, function(key, value) { $('#fn_select') .append($('') - .text(value)); + .text(value)); }); - + if(this.id == '') { var aid = $(dlg).find('#aid').val(); Contacts.UI.Card.add(n.join(';'), $('#short').text(), aid); @@ -975,7 +975,7 @@ Contacts={ container = $('#addressdisplay dl').last(); container.removeClass('template').addClass('propertycontainer'); } else { - params['checksum'] = Contacts.UI.checksumFor(obj); + params['checksum'] = Contacts.UI.checksumFor(obj); } /* Initialize the address edit dialog */ if($('#edit_address_dialog').dialog('isOpen') == true){ @@ -1191,7 +1191,7 @@ Contacts={ $('#phototools li a').tipsy('hide'); var wrapper = $('#contacts_details_photo_wrapper'); wrapper.addClass('loading').addClass('wait'); - + var img = new Image(); $(img).load(function () { $('img.contacts_details_photo').remove() @@ -1200,9 +1200,9 @@ Contacts={ $(this).insertAfter($('#phototools')).fadeIn(); }).error(function () { // notify the user that the image could not be loaded - $(t('contacts','something went wrong.')).insertAfter($('#phototools')); + Contacts.UI.notify({message:t('contacts','Error loading profile picture.')}); }).attr('src', OC.linkTo('contacts', 'photo.php')+'?id='+self.id+refreshstr); - + $.getJSON(OC.filePath('contacts', 'ajax', 'loadphoto.php'),{'id':this.id, 'refresh': refresh},function(jsondata){ if(jsondata.status == 'success'){ $('#contacts_details_photo_wrapper').data('checksum', jsondata.data.checksum); @@ -1448,7 +1448,7 @@ Contacts={ var displayname = $("#displayname_"+bookid).val().trim(); var active = $("#edit_active_"+bookid+":checked").length; var description = $("#description_"+bookid).val(); - + if(displayname.length == 0) { OC.dialogs.alert(t('contacts', 'Displayname cannot be empty.'), t('contacts', 'Error')); return false; @@ -1517,7 +1517,7 @@ Contacts={ }, /** * @params params An object with the propeties 'contactlist':a jquery object of the ul to insert into, - * 'contacts':a jquery object of all items in the list and either 'data': an object with the properties + * 'contacts':a jquery object of all items in the list and either 'data': an object with the properties * id, addressbookid and displayname or 'contact': a listitem to be inserted directly. * If 'contacts' is defined the new contact will be inserted alphabetically into the list, otherwise * it will be appended. @@ -1563,7 +1563,7 @@ Contacts={ $.getJSON(OC.filePath('contacts', 'ajax', 'contacts.php'),opts,function(jsondata){ if(jsondata.status == 'success'){ var books = jsondata.data.entries; - $.each(books, function(b, book) { + $.each(books, function(b, book) { if($('#contacts h3[data-id="'+b+'"]').length == 0) { firstrun = true; if($('#contacts h3').length == 0) { @@ -1582,7 +1582,7 @@ Contacts={ if(!added) { $('#contacts').append(item); } - + } } $('#contacts h3[data-id="'+b+'"]').on('click', function(event) { @@ -1662,13 +1662,13 @@ $(document).ready(function(){ $('#notification').click(function(){ $('#notification').fadeOut(); }); - + $('#chooseaddressbook').click(Contacts.UI.Addressbooks.overview); $('#chooseaddressbook').keydown(Contacts.UI.Addressbooks.overview); $('#contacts_newcontact').click(Contacts.UI.Card.editNew); $('#contacts_newcontact').keydown(Contacts.UI.Card.editNew); - + // Load a contact. $('.contacts').keydown(function(event) { if(event.which == 13 || event.which == 32) { @@ -1740,7 +1740,7 @@ $(document).ready(function(){ } } }; - + fileUpload.onprogress = function(e){ if (e.lengthComputable){ var _progress = Math.round((e.loaded * 100) / e.total); @@ -1770,7 +1770,7 @@ $(document).ready(function(){ $(function() { var uploadingFiles = {}, numfiles = 0, uploadedfiles = 0, retries = 0; var aid; - + $('#import_upload_start').fileupload({ dropZone: $('#contacts'), // restrict dropZone to contacts list. acceptFileTypes: /^text\/(directory|vcard|x-vcard)$/i, @@ -1932,7 +1932,7 @@ $(document).ready(function(){ $(this).dialog('close'); } }, - 'Cancel':function() { + 'Cancel':function() { $(this).dialog('close'); numfiles = uploadedfiles = retries = aid = 0; uploadingFiles = {}; @@ -1959,11 +1959,11 @@ $(document).ready(function(){ } if(data.dataType != 'iframe ') { $('#upload input.stop').hide(); - } + } } }) }); - + Contacts.UI.loadHandlers(); Contacts.UI.Contacts.update({cid:id}); }); From 51bafd32d6182612af1b911d178bac5bd3c16909 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sat, 21 Jul 2012 14:26:57 +0200 Subject: [PATCH 3/4] Made contactlist optional in insertContact(). --- apps/contacts/js/contacts.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 994e1f87fd..c190b2d3ea 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -1523,6 +1523,11 @@ Contacts={ * it will be appended. */ insertContact:function(params) { + if(!params.contactlist) { + params['contactlist'] = params.data + ? $('#contacts ul[data-id="'+params.data.addressbookid+'"]') + : contact.data('bookid'); + } var contact = params.data ? $('
  • '+params.data.displayname+'
  • ') : params.contact; From e07cd265717c31b3a9bd1e056aa3e80d98f70144 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sat, 21 Jul 2012 16:02:12 +0200 Subject: [PATCH 4/4] Implemented undelete for contacts. --- apps/contacts/js/contacts.js | 120 +++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index c190b2d3ea..337f51839d 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -18,6 +18,7 @@ Contacts={ * timeout: The timeout in seconds before the notification disappears. Default 10. * timeouthandler: A function to run on timeout. * clickhandler: A function to run on click. If a timeouthandler is given it will be cancelled. + * data: An object that will be passed as argument to the timeouthandler and clickhandler functions. */ notify:function(params) { var notifier = $('#notification'); @@ -25,13 +26,22 @@ Contacts={ notifier.fadeIn(); var timer = setTimeout(function() { notifier.fadeOut(); - if(params.timeouthandler && $.isFunction(params.timeouthandler)) { params.timeouthandler();} + if(params.timeouthandler && $.isFunction(params.timeouthandler)) { + params.timeouthandler(notifier.data(dataid)); + notifier.off('click'); + notifier.data(dataid, null); + } }, params.timeout && $.isNumeric(params.timeout) ? parseInt(params.timeout)*1000 : 10000); + var dataid = timer.toString(); + if(params.data) { + notifier.data(dataid, params.data); + } if(params.clickhandler && $.isFunction(params.clickhandler)) { notifier.on('click', function() { clearTimeout(timer); notifier.off('click'); - params.clickhandler(); + params.clickhandler(notifier.data(dataid)); + notifier.data(dataid, null); }); } }, @@ -216,10 +226,10 @@ Contacts={ Contacts.UI.Contacts.scrollTo(Contacts.UI.Card.id); }); - $('#contacts_deletecard').click( function() { Contacts.UI.Card.doDelete();return false;} ); + $('#contacts_deletecard').click( function() { Contacts.UI.Card.delayedDelete();return false;} ); $('#contacts_deletecard').keydown( function(event) { if(event.which == 13 || event.which == 32) { - Contacts.UI.Card.doDelete(); + Contacts.UI.Card.delayedDelete(); } return false; }); @@ -450,47 +460,56 @@ Contacts={ localAddcontact(n, fn, aid, isnew); } }, - doDelete:function() { + delayedDelete:function() { $('#contacts_deletecard').tipsy('hide'); - OC.dialogs.confirm(t('contacts', 'Are you sure you want to delete this contact?'), t('contacts', 'Warning'), function(answer) { - if(answer == true) { - $.post(OC.filePath('contacts', 'ajax', 'deletecard.php'),{'id':Contacts.UI.Card.id},function(jsondata){ - if(jsondata.status == 'success'){ - var newid = '', bookid; - var curlistitem = $('#contacts li[data-id="'+jsondata.data.id+'"]'); - var newlistitem = curlistitem.prev('li'); - if(!newlistitem) { - newlistitem = curlistitem.next('li'); - } - curlistitem.remove(); - if($(newlistitem).is('li')) { - newid = newlistitem.data('id'); - bookid = newlistitem.data('bookid'); - } - $('#rightcontent').data('id',newid); - this.id = this.fn = this.fullname = this.shortname = this.famname = this.givname = this.addname = this.honpre = this.honsuf = ''; - this.data = undefined; + var newid = '', bookid; + var curlistitem = $('#contacts li[data-id="'+Contacts.UI.Card.id+'"]'); + curlistitem.removeClass('active'); + var newlistitem = curlistitem.prev('li'); + if(!newlistitem) { + newlistitem = curlistitem.next('li'); + } + curlistitem.detach(); + if($(newlistitem).is('li')) { + newid = newlistitem.data('id'); + bookid = newlistitem.data('bookid'); + } + $('#rightcontent').data('id',newid); + this.id = this.fn = this.fullname = this.shortname = this.famname = this.givname = this.addname = this.honpre = this.honsuf = ''; + this.data = undefined; - if($('.contacts li').length > 0) { // Load first in list. - Contacts.UI.Card.update({cid:newid, aid:bookid}); - } else { - // load intro page - $.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){ - if(jsondata.status == 'success'){ - id = ''; - $('#rightcontent').data('id',''); - $('#rightcontent').html(jsondata.data.page); - } - else{ - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - } - }); - } - } - else{ - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - } - }); + if($('.contacts li').length > 0) { // Load first in list. + Contacts.UI.Card.update({cid:newid, aid:bookid}); + } else { + // load intro page + $.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){ + if(jsondata.status == 'success'){ + id = ''; + $('#rightcontent').data('id',''); + $('#rightcontent').html(jsondata.data.page); + } + else{ + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); + } + Contacts.UI.notify({ + data:curlistitem, + message:t('contacts','Click to undo deletion of "') + curlistitem.find('a').text() + '"', + timeouthandler:function(contact) { + Contacts.UI.Card.doDelete(contact.data('id')); + delete contact; + }, + clickhandler:function(contact) { + Contacts.UI.Contacts.insertContact({contact:contact}); + Contacts.UI.notify({message:t('contacts', 'Cancelled deletion of: "') + curlistitem.find('a').text() + '"'}); + } + }); + }, + doDelete:function(id) { + $.post(OC.filePath('contacts', 'ajax', 'deletecard.php'),{'id':id},function(jsondata) { + if(jsondata.status == 'error'){ + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); } }); return false; @@ -1516,17 +1535,20 @@ Contacts={ alert('Dropping address books not implemented yet'); }, /** - * @params params An object with the propeties 'contactlist':a jquery object of the ul to insert into, + * @params params An object with the properties 'contactlist':a jquery object of the ul to insert into, * 'contacts':a jquery object of all items in the list and either 'data': an object with the properties * id, addressbookid and displayname or 'contact': a listitem to be inserted directly. - * If 'contacts' is defined the new contact will be inserted alphabetically into the list, otherwise - * it will be appended. + * If 'contactlist' or 'contacts' aren't defined they will be search for based in the properties in 'data'. */ insertContact:function(params) { if(!params.contactlist) { - params['contactlist'] = params.data - ? $('#contacts ul[data-id="'+params.data.addressbookid+'"]') - : contact.data('bookid'); + // FIXME: Check if contact really exists. + var bookid = params.data ? params.data.addressbookid : params.contact.data('bookid'); + params.contactlist = $('#contacts ul[data-id="'+bookid+'"]'); + } + if(!params.contacts) { + var bookid = params.data ? params.data.addressbookid : params.contact.data('bookid'); + params.contacts = $('#contacts ul[data-id="'+bookid+'"] li'); } var contact = params.data ? $('
  • '+params.data.displayname+'
  • ')