From e8e32f7a1194baabd6e158805f40396c667e6c56 Mon Sep 17 00:00:00 2001 From: Unrud Date: Fri, 10 Mar 2017 23:02:35 +0100 Subject: Add InfCloud --- radicale_web/web/infcloud/addressbook.js | 1714 ++++++++++++++++++++++++++++++ 1 file changed, 1714 insertions(+) create mode 100644 radicale_web/web/infcloud/addressbook.js (limited to 'radicale_web/web/infcloud/addressbook.js') diff --git a/radicale_web/web/infcloud/addressbook.js b/radicale_web/web/infcloud/addressbook.js new file mode 100644 index 0000000..fcde7ef --- /dev/null +++ b/radicale_web/web/infcloud/addressbook.js @@ -0,0 +1,1714 @@ +/* +InfCloud - the open source CalDAV/CardDAV Web Client +Copyright (C) 2011-2015 + Jan Mate + Andrej Lezo + Matej Mihalik + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ + +// AddressbookList Class +function AddressbookList() +{ + this.contacts=new Array(); + this.contacts_hash=new Object(); + this.contacts_hash_uidattr=new Object(); + this.companies=new Array(); + this.companies_hash=new Object(); + this.companies_hash_uidattr=new Object(); + this.vcard_groups=new Object(); + this.contact_categories=new Object(); + this.contact_companies=new Object(); + this.contactLoaded=null; + this.contactToReload=null; + this.vcardGroupLoaded=null; + + this.reset=function() + { + this.contacts.splice(0,this.contacts.length); + this.contacts_hash=new Object(); + this.contacts_hash_uidattr=new Object(); + this.companies.splice(0,this.companies.length); + this.companies_hash=new Object(); + this.companies_hash_uidattr=new Object(); + this.vcard_groups=new Object(); // these are not removed from the interface (it's OK) + this.contact_categories=new Object(); + this.contact_companies=new Object(); + this.contactLoaded=null; + this.contactToReload=null; + this.vcardGroupLoaded=null; + }; + + this.getNewUID=function() + { + // we count with uniqueness of generated hash string + var newUID=null; + newUID=generateUID(); + return newUID; + }; + + this.getLoadedContactUID=function() + { + if(this.contactLoaded!=null) + return this.contactLoaded.uid; + else + return ''; + }; + + this.getSortKey=function(inputContact, inputSettings, inputMode) // inputMode (0=sort, 1=display) + { + var vcard_element=('\r\n'+inputContact.vcard).match(vCard.pre['contentline_N']); + if(vcard_element===null || vcard_element.length!==1) // if the N attribute is not present exactly once, vCard is considered invalid + return false; + + var sortKeyCompanyPart=''; + if(typeof (getCRMSortKey)== 'function' && inputMode==0) + { + sortKeyCompanyPart=getCRMSortKey(inputContact); + if(inputContact.isCompany!=undefined && inputContact.isCompany) + return sortKeyCompanyPart; // for company contact we can return here + } + else if(typeof globalGroupContactsByCompanies!='undefined' && globalGroupContactsByCompanies==true) + { + var sortKeyCompanyPart='\u0009'; + var vcard_orgname=('\r\n'+inputContact.vcard).match(vCard.pre['contentline_ORG']); + if(vcard_orgname!=null && vcard_orgname.length>0) // if more than one ORG is present, use the first one + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + var parsed=vcard_orgname[0].match(vCard.pre['contentline_parse']); + var parsed_value=vcardSplitValue(parsed[4], ';'); + + sortKeyCompanyPart=parsed_value[0]+'\u0009'+(parsed_value[1]!=undefined ? parsed_value[1] : '')+'\u0009'; + + if(inputMode==0 && inputContact.isCompany!=undefined && inputContact.isCompany) + return sortKeyCompanyPart; // for company contact we can return here + } + } + + var tmp = []; + var isGroup = this.isContactGroup(inputContact.vcard); + /* backward compatibility for stupid users (remove it in future) */ + if(typeof inputSettings==='string') + tmp = inputSettings.replace(RegExp(',','g'), ', ').split(','); + else if($.isArray(inputSettings)) /* new configuration options (arrays) */ + tmp = inputSettings.slice(); // copy the configuration array + + // display settings for non-group contacts need some flattening + if(inputMode===1 && !isGroup) { + tmp = $.map(tmp, function(el) { + if($.isPlainObject(el.value)) { + return el.value; + } + else { + return [el.value]; + } + + }); + } + + // now flatten the array completely to a company / personal version + tmp = $.map(tmp, function(el) { + if($.isPlainObject(el)) { + if(inputContact.isCompany && el.hasOwnProperty('company')) { + return [el.company]; + } + else if(!inputContact.isCompany && el.hasOwnProperty('personal')) { + return [el.personal]; + } + + return []; + } + + return [el]; + }); + + for(var i=0; i"group.", [2]->"name", [3]->";param;param", [4]->"value" + var parsed=vcard_element2[0].match(vCard.pre['contentline_parse']); + var sort_value=parsed[4]; + } + } + + return (inputMode===0 ? sortKeyCompanyPart+sort_value : sort_value); + }; + + this.isContactGroup=function(inputVcard) + { + var vcard_element=null; + if((vcard_element=('\r\n'+inputVcard).match(vCard.pre['X-ADDRESSBOOKSERVER-KIND']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + var parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + if(parsed[4].toLowerCase()=='group') + return true; + } + return false; + }; + + this.getMyContactGroups=function(inputUid) + { + if(this.contacts_hash[inputUid]!=undefined) + { + var myContactGroups=new Array(); + + if((vcard_element=this.contacts_hash[inputUid].vcard.match(vCard.pre['contentline_UID']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + for(var j=0;j"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + for(var j=0;j"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + var changedContactGroups=new Array(); + + for(var j=0;j0) return false; else globalAddressbookList.applyABFilter(groupChBoxClick(this, \'#ResourceCardDAVList\', \'.resourceCardDAV_header\', \'.resourceCardDAV\', \'.contact_group\', true), false);'}); + + newElement.append(vcardUnescapeValue(inputContact.displayvalue)); + newElement.css('display',''); + if($('#ResourceCardDAVList').find('[data-id="'+jqueryEscapeSelector(inputContact.uid.replace(RegExp('/[^/]*$',''),'/'))+'"]').next('.contact_group').find('[data-id="'+jqueryEscapeSelector(inputContact.uid)+'"]').length==0) + $('#ResourceCardDAVList').find('[data-id="'+jqueryEscapeSelector(inputContact.uid.replace(RegExp('/[^/]*$',''),'/'))+'"]').next('.contact_group').children().eq(insertIndex).after(newElement); + + // make the area droppable if the collection is not read-only + if(globalResourceCardDAVList.getCollectionPrivByUID(inputContact.uid.replace(RegExp('[^/]*$',''),''))==false && (typeof globalDisableDragAndDrop=='undefined' || globalDisableDragAndDrop!=true)) + $('#ResourceCardDAVList').find('[data-id="'+jqueryEscapeSelector(inputContact.uid.replace(RegExp('[^/]*$',''),''))+'"]').parent().find('.contact_group').children().eq(insertIndex+1).droppable({ + accept: '.ablist_item', + tolerance: 'pointer', + hoverClass: 'group_dropped_to', + drop: function(event, ui){ + // animate the clone of the dropped (draggable) element + var tmp=ui.helper.clone(); + tmp.appendTo('body') + .animate({opacity: 0, color: 'transparent', height: 0, width: 0, fontSize: 0, lineHeight: 0, paddingLeft: 0, paddingRight: 0},750,function(){tmp.remove()}); + + // disallow to drag the original dropped element until the processing is finished + ui.draggable.draggable('option', 'disabled', true); + + // animate the original dropped element + ui.draggable.animate({opacity: 0.3}, 750); + + // disallow to drop any new element until the processing is finished + $(this).droppable('option', 'disabled', true); + + // show the loader icon + $(this).addClass('r_operate'); + + var tmp2=globalAddressbookList.getContactByUID(ui.draggable.attr('data-id')); + tmp2.addToContactGroupUID=''; + tmp2.removeToContactGroupUID=new Array(); + tmp2.addToContactGroupUID=$(this).attr('data-id'); + tmp2.uiObjects={contact: ui.draggable, resource: $(this).attr('data-id')}; + + lockAndPerformToCollection(tmp2, globalRefAddContact.attr('data-filter-url'), 'ADD_TO_GROUP'); + } + }); + + // if no new makeActive but forceReload is true then reload the current contact group + if(makeActive==null && forceReload==true) + makeActive=globalRefAddContact.attr('data-filter-url'); + + // load the contact group if it was selected + if(makeActive!=null) + { + $('#ResourceCardDAVList').find('.resourceCardDAV_item').find('.resourceCardDAV_selected').removeClass('resourceCardDAV_selected'); + $('#ResourceCardDAVList').find('[data-id='+jqueryEscapeSelector(makeActive.replace(RegExp('[^/]*$',''),''))+']').addClass('resourceCardDAV_selected'); + $('#ResourceCardDAVList').find('[data-id='+jqueryEscapeSelector(makeActive)+']').addClass('resourceCardDAV_selected'); + } + if(makeChecked!=null) + { + $('#ResourceCardDAVList').find('[data-id='+jqueryEscapeSelector(makeChecked)+']').find('input[type=checkbox]').prop('checked',true); + this.applyABFilter(dataGetChecked('#ResourceCardDAVList'), false); + } + }; + + this.removeContactGroup=function(inputUid, loadNext) + { + for(var i=this.vcard_groups[inputUid.replace(RegExp('/[^/]*$',''),'/')].length-1;i>=0;i--) + if(this.vcard_groups[inputUid.replace(RegExp('/[^/]*$',''),'/')][i].uid==inputUid) + { + var uidRemoved=this.vcard_groups[inputUid.replace(RegExp('/[^/]*$',''),'/')][i].uid; + var item=$('#ResourceCardDAVList').find('[data-id^="'+jqueryEscapeSelector(this.vcard_groups[inputUid.replace(RegExp('/[^/]*$',''),'/')][i].uid)+'"]'); + + // remove the item + item.remove(); + this.vcard_groups[inputUid.replace(RegExp('/[^/]*$',''),'/')].splice(i,1); + +// vcardGroupLoaded bolo zrusene, pozriet co s tym + if(loadNext && this.vcardGroupLoaded!=null && this.vcardGroupLoaded.uid==inputUid) + { + this.vcardGroupLoaded=null; + + // set the whole collection as active + var tmp=uidRemoved.match(RegExp('(^.*/)'),''); +// XXX it is no longer needed +// globalResourceCardDAVList.loadAddressbookByUID(tmp[1]); + } + break; + } + }; + + // hide/show contacts in the interface according to contactGroupOrResourceUid or search filter in the interface (contactGroupOrResourceUid==false) + this.applyABFilter=function(contactGroupOrResourceUid, inputForceLoadNext) + { + if(globalCardDAVInitLoad) + return false; + +// XXX docasne, potom dame prec + if(!(contactGroupOrResourceUid instanceof Array)) + return false; + + var vcardGroupOrCollection=[]; + for(var i=0;i"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + vcardUIDList[vcardUIDList.length]=parsed[4].replace('urn:uuid:',''); + // remove the processed parameter + vcard=vcard.replace(vcard_element[0],'\r\n'); + } + + // update the contacts' "show" attribute + for(var j=0;j"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(vcardUIDList[j]==parsed[4] && this.contacts[k].search_hide==false) + { + this.contacts[k].show=true; + this.contacts_hash[this.contacts[k].uid].show=true + } + } + } + } + } + + var lastActive=null; + var prevHeader=null; + var lastContactForHeader=this.contacts.length-1; + // performance + var tmpListRefChildren=globalRefABListTable.children(); + // init displayed columns text length cache + var columnLengths = []; + for(var i=0; i=0;i--) + { + if(this.contacts[i].headerOnly==undefined) + { + // find the previous header index + for(var j=i-1;j>=0;j--) + if(this.contacts[j].headerOnly!=undefined && this.contacts[j].headerOnly==true) + { + prevHeader=j; + break; + } + + // performance + var tmpListRefChildren_i=tmpListRefChildren.eq(i); + var tmpListRefChildren_prev=tmpListRefChildren.eq(prevHeader); + + var coll_tmp=this.contacts[i].uid.match(RegExp('^(https?://)([^@/]+(?:@[^@/]+)?)@([^/]+)(.*/)([^/]+/)([^/]*)','i')); + var collection_uid=coll_tmp[1]+coll_tmp[2]+'@'+coll_tmp[3]+coll_tmp[4]+coll_tmp[5]; + var coll_color=globalResourceCardDAVList.getCollectionByUID(collection_uid).color; + this.contacts[i].color = coll_color; + tmpListRefChildren_i.find('.ablist_item_color').css('background-color', coll_color); + switch(this.contacts[i].show) + { + case false: + tmpListRefChildren_i.css('display','none'); + if(tmpListRefChildren_i.hasClass('ablist_item_selected')) + lastActive=i; + + var hideHeader=true; + for(j=prevHeader+1;j<=lastContactForHeader;j++) + if(this.contacts[j].show==true) + { + hideHeader=false; + break; + } + + if(hideHeader) + tmpListRefChildren_prev.css('display','none'); + + break; + case true: + // set the contact header to visible + tmpListRefChildren_prev.css('display',''); + + // set the contact to visible + tmpListRefChildren_i.css('display',''); + + // save column text length into cache + tmpListRefChildren_i.children().slice(globalFixedContactDataColumnsCount).each(function(ind) { + columnLengths[ind].push($(this).text().length); + }); + + break; + default: + break; + } + } + else + lastContactForHeader=i-1; + } + + setDataColumnsWidth(columnLengths); + + // the previously loaded contact is hidden or not exists we need to select a new one + if(inputForceLoadNext==true || $('#vCardEditor').attr('data-editor-state')!='edit' && (lastActive!=null || globalRefABListTable.children('.ablist_item_selected').length==0)) + { + var nextCandidateToLoad=null; + // get the nearest candidate to load + // if we can go forward + if(this.contactToReload!=null) + nextCandidateToLoad=this.contactToReload; + else + { + for(j=(previousActiveIndex==null ? 0 : previousActiveIndex);j=0;j--) + if((this.contacts[j].headerOnly==undefined || this.contacts[j].headerOnly==false) && (this.contacts[j].show==true)) + { + nextCandidateToLoad=this.contacts[j]; + break; + } + } + } + // make the contact active + globalRefABListTable.children('.ablist_item.ablist_item_selected').removeClass('ablist_item_selected'); + if(nextCandidateToLoad!=null) + { + // prevent re-loading the contact if it is already loaded + if((this.contactToReload!=null||$('#vCardEditor').attr('data-url')!=nextCandidateToLoad.uid) && !globalCardDAVInitLoad) + { + this.loadContactByUID(nextCandidateToLoad.uid); + } + else // because the collection click unselects the active contact we need to re-select it + { + // Make the selected contact active + globalRefABListTable.children('.ablist_item.ablist_item_selected').removeClass('ablist_item_selected'); + globalRefABListTable.children('[data-id='+jqueryEscapeSelector(nextCandidateToLoad.uid)+']').addClass('ablist_item_selected'); + } + // move scrollbar to ensure that the contact is visible in the interface + if((selected_contact=globalRefABListTable.children('.ablist_item_selected')).length==1) + globalRefABList.scrollTop(globalRefABList.scrollTop()+selected_contact.offset().top-globalRefABList.offset().top-globalRefABList.height()*globalKBNavigationPaddingRate); + } + else + { + this.contactLoaded=null; + $('#ABContactColor').css('background-color', ''); + $('#ABContact').html(''); + } + } + if(this.contactToReload!=null&& (selected_contact=globalRefABListTable.find('[data-id="'+this.contactToReload.uid+'"]')).length==1) + { + selected_contact.addClass('ablist_item_selected'); + globalRefABList.scrollTop(globalRefABList.scrollTop()+selected_contact.offset().top-globalRefABList.offset().top-globalRefABList.height()*globalKBNavigationPaddingRate); + + } + } + + this.getABCategories=function(returnSorted) + { + var categoriesArr=[]; + + for(var category in this.contact_categories) + categoriesArr.push(category); + + if(returnSorted) + return categoriesArr.sort(function(x,y){return x.customCompare(y,globalSortAlphabet,1,false)}); + else + return categoriesArr; + } + + this.getABCompanies=function(returnSorted) + { + var companiesArr=[]; + + for(var company in this.contact_companies) + companiesArr.push(company); + + if(returnSorted) + return companiesArr.sort(function(x,y){return x.customCompare(y,globalSortAlphabet,1,false)}); + else + return companiesArr; + } + + this.getABCompanyDepartments=function(inputCompany) + { + var departmentsArr=[]; + + if(this.contact_companies[inputCompany]!=undefined) + departmentsArr=this.contact_companies[inputCompany].departments.slice(); + + return departmentsArr.sort(function(x,y){return x.customCompare(y,globalSortAlphabet,1,false)}); + } + + // Contact list is not sorted, instead "insert sort" is performed + this.insertContact=function(inputContact, forceReload, disableDOM) + { + // Apple "group" vCards + if(this.isContactGroup(inputContact.vcard)) + return this.insertContactGroup(inputContact, forceReload, false); + + // check for company contact + inputContact.isCompany=false; + var vcard_element=inputContact.vcard.match(vCard.pre['X-ABShowAs']); + if(vcard_element!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + if(vcardUnescapeValue(parsed[4]).match(RegExp('^company$','i'))) + inputContact.isCompany=true; + } + + // check for company contact + if((typeof globalContactsExtVcardToData)=='function') + { + inputContact.isLegacy=false; + var vcard_element=inputContact.vcard.match(RegExp('\r\nX-IsLegacy:.*\r\n', 'mi')); + if(vcard_element!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + var parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + if(vcardUnescapeValue(parsed[4]).match(RegExp('^(?:yes|1|true)$', 'i'))) + inputContact.isLegacy=true; + } + } + + // contact UID attr + var vcard_element=inputContact.vcard.match(vCard.pre['contentline_UID']); + if(vcard_element!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + inputContact.uidattr=vcardUnescapeValue(parsed[4]); + } + else // UID attr is REQUIRED + return false; // invalud vcard + + var this_destination=this.contacts; + var this_destination_hash=this.contacts_hash; + var this_destination_hash_uidattr=this.contacts_hash_uidattr; + + // search plugin requirement + inputContact.search_hide=false; + + // CATEGORIES suggestion + var categoriesArr=(inputContact.categories=='' ? [] : vcardSplitValue(inputContact.categories,',')); + var allCategoriesArr=this.getABCategories(false); + + // The search funcionality uses this ASCII value (you can add additional data here) + + // ORG attribute + var tmp=inputContact.vcard; + var orgArr=[]; + var depArr=[]; + var tmpCurrentCompany=''; + var tmpCurrentDepartment=''; + while((vcard_element=tmp.match(vCard.pre['contentline_ORG']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + var parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + var parsed_valArr=vcardSplitValue(parsed[4], ';'); + + if(isDataColumnDefined('COMPANY')) { + setContactDataColumn(inputContact, 'COMPANY', vcardUnescapeValue(parsed_valArr[0])); + } + + if(isDataColumnDefined('DEPARTMENT')) { + setContactDataColumn(inputContact, 'DEPARTMENT', vcardUnescapeValue(parsed_valArr[1])); + } + + tmpCurrentCompany=(parsed_valArr[0]==undefined || parsed_valArr[0]=='' ? '' : parsed_valArr[0]); + tmpCurrentDepartment=(parsed_valArr[1]==undefined || parsed_valArr[1]=='' ? '' : parsed_valArr[1]); + + if(tmpCurrentCompany!='') + orgArr[orgArr.length]=vcardUnescapeValue(tmpCurrentCompany); + + if(tmpCurrentDepartment) + depArr[depArr.length]=vcardUnescapeValue(tmpCurrentDepartment); + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + var allOrgArr=this.getABCompanies(false); + + // N attribute + while((vcard_element=tmp.match(vCard.pre['contentline_N']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + var parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + var parsed_valArr=vcardSplitValue(parsed[4],';'); + + if(isDataColumnDefined('LASTNAME')) { + setContactDataColumn(inputContact, 'LASTNAME', vcardUnescapeValue(parsed_valArr[0])); + } + + if(isDataColumnDefined('FIRSTNAME')) { + setContactDataColumn(inputContact, 'FIRSTNAME', vcardUnescapeValue(parsed_valArr[1])); + } + + if(isDataColumnDefined('MIDDLENAME')) { + setContactDataColumn(inputContact, 'MIDDLENAME', vcardUnescapeValue(parsed_valArr[2])); + } + + if(isDataColumnDefined('PREFIX')) { + setContactDataColumn(inputContact, 'PREFIX', vcardUnescapeValue(parsed_valArr[3])); + } + + if(isDataColumnDefined('SUFFIX')) { + setContactDataColumn(inputContact, 'SUFFIX', vcardUnescapeValue(parsed_valArr[4])); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // NICKNAME attribute + while((vcard_element=tmp.match(vCard.pre['contentline_NICKNAME']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('NICKNAME')) { + setContactDataColumn(inputContact, 'NICKNAME', parsed[4]); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // X-PHONETIC-LAST-NAME attribute + while((vcard_element=tmp.match(vCard.pre['contentline_X-PHONETIC-LAST-NAME']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('PHONETICLASTNAME')) { + setContactDataColumn(inputContact, 'PHONETICLASTNAME', parsed[4]); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // X-PHONETIC-FIRST-NAME attribute + while((vcard_element=tmp.match(vCard.pre['contentline_X-PHONETIC-FIRST-NAME']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('PHONETICFIRSTNAME')) { + setContactDataColumn(inputContact, 'PHONETICFIRSTNAME', parsed[4]); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // BDAY attribute + while((vcard_element=tmp.match(vCard.pre['contentline_BDAY']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('BIRTHDAY')) { + var bday = null; + try { + bday = $.datepicker.parseDate('yy-mm-dd', parsed[4]); + } + catch(e) { + + } + + if(bday) { + setContactDataColumn(inputContact, 'BIRTHDAY', $.datepicker.formatDate(globalSettings.datepickerformat.value, bday)); + } + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // TITLE attribute + while((vcard_element=tmp.match(vCard.pre['contentline_TITLE']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('JOBTITLE')) { + setContactDataColumn(inputContact, 'JOBTITLE', vcardUnescapeValue(parsed[4])); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // NOTE attribute + while((vcard_element=tmp.match(vCard.pre['contentline_NOTE']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('NOTETEXT')) { + setContactDataColumn(inputContact, 'NOTETEXT', vcardUnescapeValue(parsed[4])); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // ADR attribute + while((vcard_element=tmp.match(vCard.pre['contentline_ADR']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + var parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + var parsed_valArr=vcardSplitValue(parsed[4],';'); + + if(isDataColumnDefined('ADDRESS')) { + var unescapedArr = $.map(parsed_valArr, function(el) { + if(el) { + return vcardUnescapeValue(el); + } + }); + + setContactDataColumn(inputContact, 'ADDRESS', unescapedArr.join(' '), {'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'address_type_store_as')}); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // TEL attribute + while((vcard_element=tmp.match(vCard.pre['contentline_TEL']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('PHONE')) { + setContactDataColumn(inputContact, 'PHONE', parsed[4], {'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'phone_type_store_as')}); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // EMAIL attribute + while((vcard_element=tmp.match(vCard.pre['contentline_EMAIL']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('EMAIL')) { + setContactDataColumn(inputContact, 'EMAIL', parsed[4], {'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'email_type_store_as')}); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // URL attribute + while((vcard_element=tmp.match(vCard.pre['contentline_URL']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('URL')) { + setContactDataColumn(inputContact, 'URL', parsed[4], {'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'url_type_store_as')}); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // X-ABDATE attribute + while((vcard_element=tmp.match(vCard.pre['contentline_X-ABDATE']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('DATES')) { + var abdate = null; + try { + abdate = $.datepicker.parseDate('yy-mm-dd', parsed[4]); + } + catch(e) { + + } + + if(abdate) { + setContactDataColumn(inputContact, 'DATES', $.datepicker.formatDate(globalSettings.datepickerformat.value, abdate), {'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'date_store_as')}); + } + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // X-ABRELATEDNAMES attribute + while((vcard_element=tmp.match(vCard.pre['contentline_X-ABRELATEDNAMES']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('RELATED')) { + setContactDataColumn(inputContact, 'RELATED', parsed[4], {'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'person_type_store_as')}); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // X-SOCIALPROFILE attribute + while((vcard_element=tmp.match(vCard.pre['contentline_X-SOCIALPROFILE']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + + if(isDataColumnDefined('PROFILE')) { + setContactDataColumn(inputContact, 'PROFILE', getParamsFromContentlineParse(tmp, parsed, 'X-USER', null, null, true)[0], {'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'profile_type_store_as')}); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // IMPP attribute + while((vcard_element=tmp.match(vCard.pre['contentline_IMPP']))!=null) + { + // parsed (contentline_parse) = [1]->"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + if(isDataColumnDefined('IM')) { + setContactDataColumn(inputContact, 'IM', parsed[4].replace(vCard.pre['vcardToData_before_val'], ''), { + 'TYPE': getParamsFromContentlineParse(tmp, parsed, 'TYPE', 'X-ABLabel', 'im_type_store_as'), + 'SERVICE-TYPE': getParamsFromContentlineParse(tmp, parsed, 'X-SERVICE-TYPE', null, 'im_service_type_store_as') + }); + } + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + + // CATEGORIES attribute (preparsed) + if(isDataColumnDefined('CATEGORIES')) { + setContactDataColumn(inputContact, 'CATEGORIES', inputContact.categories.splitCustom(',')); + } + + if((inputContact.sortkey=this.getSortKey(inputContact, globalSettings.collectionsort.value || $.map(globalSettings.collectiondisplay.value, function(el) {if($.isPlainObject(el.value)) {return el.value;} else {return [el.value];}}), 0))===false || (inputContact.displayvalue=this.getSortKey(inputContact, globalSettings.collectiondisplay.value, 1))===false) + return false; //invalid vcard + + // if company headers are used add also the header to the searchvalue + var companyHeader=''; + if(typeof globalGroupContactsByCompanies!='undefined' && globalGroupContactsByCompanies==true) + { + if(tmpCurrentCompany!='' || tmpCurrentDepartment!='') + { + if(typeof (getCRMSortKey)=='function') + companyHeader=getCRMSortKey(inputContact); + else + companyHeader=tmpCurrentCompany+'\u0009'+tmpCurrentDepartment+'\u0009'; + } + } + + inputContact.searchvalue=(companyHeader+inputContact.displayvalue).multiReplace(globalSearchTransformAlphabet); + + // CATEGORIES suggestion + for(var i=0;i90 && unicodeValue<97) || (unicodeValue>122 && unicodeValue<127)) + { + headerValue='#'; + inputContact.sortkey='#'+inputContact.sortkey; + } + else + headerValue=inputContact.sortkey.charAt(0).toUpperCase(); + } + else + { + headerValue='#'; + inputContact.sortkey='#'; + } + + headerSortKey=headerValue; + } + + // create the header + var headerObject={headerOnly: true, sortkey: headerSortKey, displayvalue: headerValue}; + + // find the index where to insert the new contact O(n*log(n)) + insertIndex=0; + low=0; + high=this_destination.length-1; + if(this_destination.length>0) + while(low').text(getContactDataColumn(inputContact, columns[i])).appendTo(newElement); + } + + newElement.click(function() { + if($(this).hasClass('ablist_item_selected') || globalObjectLoading) + return false; + else + globalAddressbookList.loadContactByUID(this.getAttribute('data-id')); + }); + + // set the company icon + if(inputContact.isCompany==true) + newElement.addClass('company'); + + if(typeof globalDisableDragAndDrop=='undefined' || globalDisableDragAndDrop!=true) + newElement.draggable({ + delay: 250, + revert: 'invalid', + scroll: false, + opacity: 0.8, + stack: '#SystemCardDavMATE', + containment: '#SystemCardDavMATE', + appendTo: 'body', + start: function( event, ui ){ + // disallow on read-only collection + if(globalResourceCardDAVList.getCollectionPrivByUID($(this).attr('data-id').replace(RegExp('[^/]*$'),''))==true) + return false; + }, + helper: function(){ + $('#ResourceCardDAVList').find('.resourceCardDAV.ui-droppable').droppable( 'option', 'accept', false); + $('#ResourceCardDAVList').find('.group.ui-droppable').droppable( 'option', 'accept', false); + + $('#ResourceCardDAVList').find('.resourceCardDAV[data-id!='+jqueryEscapeSelector($(this).attr('data-id').replace(RegExp('[^/]+$'),''))+'].ui-droppable').droppable( 'option', 'accept', '.ablist_item'); + var myContactGroups=globalAddressbookList.getMyContactGroups($(this).attr('data-id')); + $('#ResourceCardDAVList').find('.group[data-id^='+jqueryEscapeSelector($(this).attr('data-id').replace(RegExp('[^/]+$'),''))+'].ui-droppable').each(function(index, element){ + if(myContactGroups.indexOf($(element).attr('data-id'))==-1) + $(element).droppable( 'option', 'accept', '.ablist_item'); + }); + + var tmp=$(this).clone(); + tmp.addClass('ablist_item_dragged'); + // we cannot use .css() here, because we need to add !important (problem with Gecko based browsers) + var tmp_style='max-width: '+$(this).outerWidth()+'px;'; + if($(this).css('background-image')!='none') + tmp_style+='background-image: url(images/company_s_w.svg) !important;'; + tmp.attr('style', tmp_style); + + return tmp; + } + }); + + globalRefABListTable.children().eq(insertIndex+headerMiss-1).after(newElement); + + if($('#vCardEditor').attr('data-editor-state')=='edit') + { + if((selected_contact=globalRefABListTable.children('.ablist_item_selected')).length==1) + globalRefABList.scrollTop(globalRefABList.scrollTop()+selected_contact.offset().top-globalRefABList.offset().top-globalRefABList.height()*globalKBNavigationPaddingRate); + } +// toto tu asi nahradit zavolanim trigger('click') co vyrazne sprehladni kod +// => + // load the updated contact (because we first deleted it, we need to set it active) + if(makeActive!=null) + { + // make the contact active + globalRefABListTable.children('.ablist_item.ablist_item_selected').removeClass('ablist_item_selected'); + globalRefABListTable.children().eq(insertIndex+headerMiss).addClass('ablist_item_selected'); + this.loadContactByUID(makeActive); + } + } + } + + this.renderContacs=function() + { + var this_destination=this.contacts; + var this_destination_hash=this.contacts_hash; + + var tmpResultObject=[]; + + for(var i=0;i').text(getContactDataColumn(this_destination[i], columns[j])).appendTo(newElement); + } + for(; j').appendTo(newElement); + } + + newElement.click(function() { + if($(this).hasClass('ablist_item_selected') || globalObjectLoading) + return false; + else + globalAddressbookList.loadContactByUID(this.getAttribute('data-id')); + }); + + // set the company icon + if(this_destination[i].isCompany==true) + newElement.addClass('company'); + + if(typeof globalDisableDragAndDrop=='undefined' || globalDisableDragAndDrop!=true) + newElement.draggable({ + delay: 250, + revert: 'invalid', + scroll: false, + opacity: 0.8, + stack: '#SystemCardDavMATE', + containment: '#SystemCardDavMATE', + appendTo: 'body', + start: function( event, ui ){ + // disallow on read-only collection + if(globalResourceCardDAVList.getCollectionPrivByUID($(this).attr('data-id').replace(RegExp('[^/]*$'),''))==true) + return false; + }, + helper: function(){ + $('#ResourceCardDAVList').find('.resourceCardDAV.ui-droppable').droppable( 'option', 'accept', false); + $('#ResourceCardDAVList').find('.group.ui-droppable').droppable( 'option', 'accept', false); + + $('#ResourceCardDAVList').find('.resourceCardDAV[data-id!='+jqueryEscapeSelector($(this).attr('data-id').replace(RegExp('[^/]+$'),''))+'].ui-droppable').droppable( 'option', 'accept', '.ablist_item'); + var myContactGroups=globalAddressbookList.getMyContactGroups($(this).attr('data-id')); + $('#ResourceCardDAVList').find('.group[data-id^='+jqueryEscapeSelector($(this).attr('data-id').replace(RegExp('[^/]+$'),''))+'].ui-droppable').each(function(index, element){ + if(myContactGroups.indexOf($(element).attr('data-id'))==-1) + $(element).droppable( 'option', 'accept', '.ablist_item'); + }); + + var tmp=$(this).clone(); + tmp.addClass('ablist_item_dragged'); + // we cannot use .css() here, because we need to add !important (problem with Gecko based browsers) + var tmp_style='max-width: '+$(this).outerWidth()+'px;'; + if($(this).css('background-image')!='none') + tmp_style+='background-image: url(images/company_s_w.svg) !important;'; + tmp.attr('style', tmp_style); + + return tmp; + } + }); + } + tmpResultObject.push(newElement); + } + + globalRefABListTable.empty().append(tmpResultObject); + } + + this.removeContact=function(inputUid, loadNext, isFromPUT) + { + if(!(inputUid instanceof Array)) + inputUid=[inputUid]; + var tmpRex=new RegExp('/[^/]*$',''); + + // Apple "group" vCards + for(var i=inputUid.length-1;i>=0;i--) + for(var j=this.vcard_groups[inputUid[i].replace(tmpRex,'/')].length-1;j>=0;j--) + if(inputUid.indexOf(this.vcard_groups[inputUid[i].replace(tmpRex,'/')][j].uid)!=-1) + return this.removeContactGroup(inputUid[i], loadNext); + + for(var i=this.contacts.length-1;i>=0;i--) + if(this.contacts[i]!=undefined&&inputUid.indexOf(this.contacts[i].uid)!=-1) + { + var inUID=this.contacts[i].uid; + // CATEGORIES suggestion + var categoriesArr=vcardSplitValue(this.contacts[i].categories,','); + for(var j=0;j"group.", [2]->"name", [3]->";param;param", [4]->"value" + parsed=vcard_element[0].match(vCard.pre['contentline_parse']); + orgArr[orgArr.length]=vcardUnescapeValue(vcardSplitValue(parsed[4],';')[0]); + + // remove the processed parameter + tmp=tmp.replace(vcard_element[0],'\r\n'); + } + for(var j=0;j=0;j--) + if(this.contacts[j].headerOnly!=true && this.contacts[j].show==true) + { + nextCandidateToLoad=this.contacts[j]; + break; + } + } + + // remove the item + item.remove(); + this.contacts.splice(i,1); + if(this.contacts_hash[inUID]!=undefined) + { + delete this.contacts_hash_uidattr[this.contacts_hash[inUID].uidattr]; + delete this.contacts_hash[inUID]; + } + else if(this.companies_hash[inUID]!=undefined) + { + delete this.companies_hash_uidattr[this.contacts_hash[inUID].uidattr]; + delete this.companies_hash[inUID]; + } + + // remove the header if there is no more contact + var removeHeader=true; + var prevHeader=null; + // find the previous header index + for(var j=i-1;j>=0;j--) + if(this.contacts[j].headerOnly!=undefined && this.contacts[j].headerOnly==true) + { + prevHeader=j; + break; + } + + // check for contact existence for the found header + if((prevHeader+1)=0;i--) + if(this.contacts[i]!=undefined /* because the header can be deleted with the contact */ && this.contacts[i].timestamp!=undefined && this.contacts[i].uid.indexOf(inputUidBase)==0 && this.contacts[i].timestamp no animation */ + globalObjectLoading=false; // re-enable keyboard navigation + }); + else + { + $('#ABContactColor').css('background-color', ''); + $('#ABContact').empty(); + globalDisableAnimationMessageHiding='contactRfcNotCompliant'; + var tmpTime=show_editor_message('out','message_error', localization[globalInterfaceLanguage].contactRfcNotCompliant, globalHideInfoMessageAfter); + setTimeout(function(){globalObjectLoading=false;}, tmpTime); // re-enable keyboard navigation + } + // Make the selected contact active + globalRefABListTable.children('.ablist_item.ablist_item_selected').removeClass('ablist_item_selected'); + globalRefABListTable.children('[data-id='+jqueryEscapeSelector(this.contacts_hash[inputUID].uid)+']').addClass('ablist_item_selected'); + this.contactToReload=null; + if(globalRefABListTable.children('[data-id='+jqueryEscapeSelector(this.contacts_hash[inputUID].uid)+']:visible').length>0&&$('#ABInMessageEditBox').css('display')!='none') + { + animate_message('#ABInMessageEditBox', '#ABInMessageTextEditBox', 0, '-='); + $('#ABInMessageEditBox').css('display',''); + + } + else if(globalRefABListTable.children('[data-id='+jqueryEscapeSelector(this.contacts_hash[inputUID].uid)+']:visible').length==0&&$('#ABInMessageEditBox').css('display')=='none') + { + this.contactToReload=this.contacts_hash[inputUID]; + globalDisableAnimationMessageHiding='errContactHidden'; + $('#ABInMessageEditBox').css('display','block'); + $('#ABInMessageTextEditBox').attr('class','message_success'); + $('#ABInMessageTextEditBox').text(localization[globalInterfaceLanguage][globalDisableAnimationMessageHiding]); + animate_message('#ABInMessageEditBox', '#ABInMessageTextEditBox', globalHideInfoMessageAfter); + } + if($('#ResourceCardDAVListOverlay').is(':visible')) + { + if($('#ABContactOverlay').is(':visible')) + { + var animation = 400; + var duration = globalHideInfoMessageAfter + 2*animation; + setTimeout(function(){ + $('#ResourceCardDAVListOverlay').fadeOut(animation); + $('#ABListOverlay').fadeOut(animation,function(){}); + $('#ABContactOverlay').fadeOut(animation,function(){globalRefAddContact.prop('disabled',false);}); + },duration-animation); + } + else + { + $('#ResourceCardDAVListOverlay').fadeOut(globalEditorFadeAnimation); + $('#ABListOverlay').fadeOut(globalEditorFadeAnimation,function(){}); + } + } + } + else + { + $('#ABContactColor').css('background-color', ''); + $('#ABContact').empty(); +// CardDAVeditor_cleanup(false, false); // editor initialization + } + checkContactFormScrollBar(); + } + + this.loadContactByVcard=function(vcard, color, isCompany, inputEditorMode, inputEditorLockedEntries) + { +// sem callback pre index.html a v pripade ak pridavame usera (nie firmu) pridat do vcard prislusny atribut + if(typeof(globalContactsExtLoadByVcardBefore)=='function') + vcard=globalContactsExtLoadByVcardBefore(vcard, isCompany); + + var loadContact=new Object(); + loadContact.vcard=vcard; + loadContact.isCompany=isCompany; + loadContact.color=color; + + globalObjectLoading=true; // temporary disable keyboard navigation + if(vcardToData(loadContact, false /* XXX check this */, isCompany, inputEditorMode, inputEditorLockedEntries)) + $('#EditorBox').fadeTo(0, 1, function(){ /* 0 => no animation */ + // append the UID of previous contact into "data-id" for "cancel" functionality + $('#vCardEditor').find('[data-type="cancel"]').attr('data-id', globalAddressbookList.getLoadedContactUID()); + this.contactLoaded=null; // do not do this earlier + globalObjectLoading=false; // re-enable keyboard navigation + }); + else + { + // todo: replace with icon or text in the editor div + globalDisableAnimationMessageHiding='contactRfcNotCompliant'; + show_editor_message('out', 'message_error', localization[globalInterfaceLanguage].contactRfcNotCompliant, globalHideInfoMessageAfter); + this.contactLoaded=null; // do not do this earlier + globalObjectLoading=false; // re-enable keyboard navigation + } + checkContactFormScrollBar(); + } + + // DONE + this.getContactByUID=function(inputUID) + { + // find the inputUID contact + if(this.contacts_hash[inputUID]!=undefined) + return this.contacts_hash[inputUID]; + else + return null; + } + + // DONE + this.getContactGroupByUID=function(inputUID) + { + var collectionUID=inputUID.replace(RegExp('[^/]*$'),''); + for(var i=0;i