interface.js 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298
  1. /*
  2. CardDavMATE - the open source CardDAV Web Client
  3. Copyright (C) 2011-2015
  4. Jan Mate <jan.mate@inf-it.com>
  5. Andrej Lezo <andrej.lezo@inf-it.com>
  6. Matej Mihalik <matej.mihalik@inf-it.com>
  7. This program is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU Affero General Public License as
  9. published by the Free Software Foundation, either version 3 of the
  10. License, or (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Affero General Public License for more details.
  15. You should have received a copy of the GNU Affero General Public License
  16. along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // reorder countries according to localization (returns array becaouse object are unsorted according to ECMA)
  19. function sortCountries(obj)
  20. {
  21. var arr=[];
  22. for(var prop in obj)
  23. if(obj.hasOwnProperty(prop))
  24. arr.push({'key': prop, 'value': obj[prop], 'translated_value': localization[globalInterfaceLanguage]['txtAddressCountry'+prop.toUpperCase()]});
  25. return arr.sort(function(a, b){return a.translated_value.customCompare(b.translated_value, globalSortAlphabet, 1, false)});
  26. }
  27. function loadAdditionalCardDAVCollections()
  28. {
  29. if(globalSettingsSaving!='')
  30. return false;
  31. globalSettingsSaving='addressbook';
  32. var inSettings = $.extend({},globalSettings);
  33. var rex = new RegExp('^(https?://)([^@/]+(?:@[^@/]+)?)@(.*)');
  34. var key='loadedaddressbookcollections';
  35. inSettings.loadedaddressbookcollections = {value : new Array(), locked: globalSettings[key].locked};
  36. $('#ResourceCardDAVList').find('.unloadCheck').each(function(cin,cel)
  37. {
  38. if($(cel).prop('checked'))
  39. {
  40. var uidParts=$(cel).attr('data-id').match(rex);
  41. inSettings.loadedaddressbookcollections.value.splice(inSettings.loadedaddressbookcollections.value.length , 0, uidParts[1]+uidParts[3]);
  42. }
  43. });
  44. if($(inSettings[key]).not(globalSettings[key].value).length > 0 || $(globalSettings[key].value).not(inSettings[key]).length > 0)
  45. {
  46. $('#AddressbookOverlay').removeClass('loader_hidden');
  47. $('#ResourceCardDAVList').find('input[type="checkbox"]').prop('disabled',true);
  48. var setC=0;
  49. for(var i=0;i<globalAccountSettings.length;i++)
  50. if(globalAccountSettings[i].href.indexOf(globalLoginUsername)!=-1 && globalAccountSettings[i].settingsAccount)
  51. {
  52. setC++;
  53. netSaveSettings(globalAccountSettings[i], inSettings, false, true);
  54. break;
  55. }
  56. if(setC==0)
  57. cancelUnloadedCardDAVCollections();
  58. }
  59. else
  60. hideUnloadedCardDAVCollections(true);
  61. }
  62. function showUnloadedCardDAVCollections()
  63. {
  64. if(globalAddressbookCollectionsLoading)
  65. return false;
  66. globalAddressbookCollectionsLoading=true;
  67. if(isAvaible('CalDavZAP'))
  68. {
  69. $('#showUnloadedCalendars').css('display','none');
  70. $('#showUnloadedCalendarsTODO').css('display','none');
  71. }
  72. $('#ResourceCardDAVList').find('input[type="checkbox"]').prop('disabled',true);
  73. $('#AddressbookOverlay').children('.loaderInfo').text(localization[globalInterfaceLanguage].loadingCollectionList).parent().fadeIn(300);
  74. var resList=$('#ResourceCardDAVList');
  75. var resHeader='.resourceCardDAV_header';
  76. var resItem='.resourceCardDAV';
  77. $('#ResourceCardDAVList').find('input[type="checkbox"]').prop('disabled',false);
  78. $('#AddressbookOverlay').children('.loaderInfo').text('').parent().addClass('loader_hidden');
  79. resList.find('.resourceCardDAV_selected').removeClass('resourceCardDAV_selected');
  80. resList.find('input').css('display','none');
  81. // header display
  82. resList.children('.resourceCardDAV_header').each(function(){
  83. if($(this).css('display')=='none')
  84. $(this).addClass('unloaded').css('display','');
  85. var headerClickElm = $('<input type="checkbox" class="unloadCheckHeader" style="position:absolute;top:3px;right:0px;margin-right:6px;"/>');
  86. headerClickElm.change(function(){
  87. loadResourceChBoxClick(this, '#ResourceCardDAVList', resHeader, resItem, '.resourceCardDAV_item');
  88. });
  89. $(this).addClass('load_mode').append(headerClickElm);
  90. });
  91. // carddav_item display
  92. resList.find('.resourceCardDAV').each(function(){
  93. if(typeof $(this).attr('data-id') != 'undefined')
  94. {
  95. var newInputElm = $('<input type="checkbox" class="unloadCheck" data-id="'+$(this).attr('data-id')+'" style="position:absolute;top:8px;right:0px;margin-right:6px;"/>');
  96. newInputElm.change(function(){
  97. loadCollectionChBoxClick(this, '#ResourceCardDAVList', resHeader, resItem, '.resourceCardDAV_item');
  98. });
  99. $(this).siblings('.contact_group').addBack().addClass('load_mode');
  100. $(this).append(newInputElm);
  101. if($(this).parent().css('display')=='none')
  102. $(this).addClass('unloaded');
  103. else
  104. newInputElm.prop('checked',true);
  105. newInputElm.trigger('change');
  106. }
  107. });
  108. $('#showUnloadedAddressbooks').css('display','none');
  109. $('.resourcesCardDAV_h').text(localization[globalInterfaceLanguage].txtEnabledAddressbooks);
  110. var origH = resList.find('.resourceCardDAV_header.unloaded').eq(0).css('height');
  111. var origC = resList.find('.resourceCardDAV.unloaded').parent().eq(0).css('height');
  112. resList.find('.resourceCardDAV_header.unloaded').css({'height':0,'display':''}).animate({height:origH},300);
  113. resList.find('.resourceCardDAV.unloaded').parent().css({'height':0,'display':''}).animate({height:origC},300);
  114. resList.animate({'top':49},300);
  115. }
  116. function cancelUnloadedCardDAVCollections()
  117. {
  118. $('#ResourceCardDAVList').children('.resourceCardDAV_item').children('.resourceCardDAV ').each(function(){
  119. var uidParts=$(this).attr('data-id').match(RegExp('^(https?://)([^@/]+(?:@[^@/]+)?)@(.*)'));
  120. var checkHref=uidParts[1]+uidParts[3];
  121. var isLoaded=false;
  122. if(typeof globalCrossServerSettingsURL!='undefined'&&globalCrossServerSettingsURL!=null&globalCrossServerSettingsURL)
  123. {
  124. var uidParts=$(this).attr('data-id').match(RegExp('/([^/]+/[^/]+/)$'));
  125. var tmpParts = uidParts[1].match('^(.*/)([^/]+)/$');
  126. var checkHref=decodeURIComponent(tmpParts[1])+tmpParts[2]+'/';
  127. var found=false;
  128. for(var l=0;l<globalSettings.loadedaddressbookcollections.value.length;l++)
  129. {
  130. var tmpParts2 = globalSettings.loadedaddressbookcollections.value[l].match('^(.*/)([^/]+)/([^/]+)/$');
  131. var checkHref2=decodeURIComponent(tmpParts2[2])+'/'+tmpParts2[3]+'/';
  132. if(checkHref==checkHref2)
  133. {
  134. found=true;
  135. break;
  136. }
  137. }
  138. isLoaded=found;
  139. }
  140. else
  141. isLoaded=(globalSettings.loadedaddressbookcollections.value.indexOf(checkHref)!=-1)
  142. var unloadCh=$(this).find('.unloadCheck');
  143. var checked=unloadCh.prop('checked');
  144. if((isLoaded && !checked) || (!isLoaded && checked))
  145. unloadCh.prop('checked',!checked).trigger('change');
  146. });
  147. hideUnloadedCardDAVCollections(true);
  148. }
  149. function hideUnloadedCardDAVCollections(withCallback)
  150. {
  151. var resList=$('#ResourceCardDAVList');
  152. resList.find(':input.unloadCheck').remove();
  153. resList.find(':input.unloadCheckHeader').remove();
  154. resList.find('.load_mode').removeClass('load_mode');
  155. resList.find(':input').css('display','');
  156. resList.find('.resourceCardDAV').not('.unloaded').parent().css('height','');
  157. $('.resourcesCardDAV_h').text(localization[globalInterfaceLanguage].txtAddressbooks);
  158. resList.find('.resourceCardDAV_header.unloaded').animate({height:0},300).promise().done(function(){
  159. resList.find('.resourceCardDAV_header.unloaded').css({'display':'none','height':''});
  160. });
  161. resList.find('.resourceCardDAV.unloaded').parent().animate({height:0},300).promise().done(function(){
  162. resList.find('.resourceCardDAV.unloaded').parent().css({'display':'none','height':''});
  163. resList.find('.resourceCardDAV_header').not('.unloaded').each(function(){
  164. var triggerInput=$(this).nextUntil('.resourceCardDAV_header').filter(':visible').first().find('input[type="checkbox"]');
  165. collectionChBoxClick(triggerInput.get(0), '#ResourceCardDAVList', '.resourceCardDAV_header', '.resourceCardDAV', null, false);
  166. });
  167. resList.find('.unloaded').removeClass('unloaded');
  168. globalAddressbookCollectionsLoading=false;
  169. if(withCallback)
  170. hideUnloadedCardDAVCollectionsCallBack();
  171. });
  172. resList.animate({'top':24},300);
  173. if(withCallback)
  174. $('#AddressbookOverlay').fadeOut(300,function(){
  175. $(this).removeClass('loader_hidden');
  176. });
  177. if(isAvaible('CalDavZAP'))
  178. {
  179. $('#showUnloadedCalendars').css('display','block');
  180. $('#showUnloadedCalendarsTODO').css('display','block');
  181. }
  182. }
  183. function hideUnloadedCardDAVCollectionsCallBack()
  184. {
  185. if(globalAddressbookList.contactLoaded!=null)
  186. globalAddressbookList.loadContactByUID(globalAddressbookList.contactLoaded.uid);
  187. $('#showUnloadedAddressbooks').css('display','');
  188. globalFirstHideLoader=true;
  189. globalSettingsSaving='';
  190. selectActiveAddressbook();
  191. $('#AddressbookOverlay').css('display','none');
  192. $('#ResourceCardDAVList').find('input[type="checkbox"]').prop('disabled',false);
  193. }
  194. function selectActiveAddressbook()
  195. {
  196. if(globalAddressbookCollectionsLoading)
  197. return false;
  198. for(var i=0; i<globalResourceCardDAVList.collections.length;i++)
  199. if(globalResourceCardDAVList.collections[i].uid!=undefined)
  200. {
  201. var inputResource=globalResourceCardDAVList.collections[i].uid;
  202. var par=inputResource.split('/');
  203. if(globalSettings.addressbookselected.value!='')
  204. {
  205. if(typeof globalSettings.addressbookselected.value=='string' && inputResource==globalSettings.addressbookselected.value.substring(0,globalSettings.addressbookselected.value.lastIndexOf('/')+1))
  206. {
  207. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  208. $('#ResourceCardDAVList').find('.resourceCardDAV[data-id="'+globalSettings.addressbookselected.value+'"]:visible').addClass('resourceCardDAV_selected');
  209. }
  210. else if(typeof globalSettings.addressbookselected.value=='string' && globalSettings.addressbookselected.value.charAt(globalSettings.addressbookselected.value.length-1)=='/' && (par[par.length-3]+'/'+par[par.length-2]+'/')==globalSettings.addressbookselected.value)
  211. {
  212. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  213. $('#ResourceCardDAVList').find('.resourceCardDAV[data-id="'+inputResource+'"]:visible').addClass('resourceCardDAV_selected');
  214. }
  215. else if(typeof globalSettings.addressbookselected.value=='string' && globalSettings.addressbookselected.value.charAt(globalSettings.addressbookselected.value.length-1)!='/')
  216. {
  217. if((par[par.length-3]+'/'+par[par.length-2]+'/') == globalSettings.addressbookselected.value.substring(0,globalSettings.addressbookselected.value.lastIndexOf('/')+1) && $('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  218. {
  219. if($('#ResourceCardDAVList').find('.resourceCardDAV[data-id="'+inputResource+globalSettings.addressbookselected.value.substring(globalSettings.addressbookselected.value.lastIndexOf('/')+1,globalSettings.addressbookselected.value.length)+'"]:visible').length>0)
  220. $('#ResourceCardDAVList').find('.resourceCardDAV[data-id="'+inputResource+globalSettings.addressbookselected.value.substring(globalSettings.addressbookselected.value.lastIndexOf('/')+1,globalSettings.addressbookselected.value.length)+'"]:visible').addClass('resourceCardDAV_selected');
  221. }
  222. }
  223. else if (typeof globalSettings.addressbookselected.value=='object' && inputResource.match(globalSettings.addressbookselected.value)!=null)
  224. {
  225. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  226. $('#ResourceCardDAVList').find('.resourceCardDAV[data-id="'+inputResource+'"]:visible').addClass('resourceCardDAV_selected');
  227. }
  228. }
  229. }
  230. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length==0)
  231. for(var i=0; i<globalResourceCardDAVList.collections.length;i++)
  232. if(globalResourceCardDAVList.collections[i].uid!=undefined)
  233. {
  234. var inputResource=globalResourceCardDAVList.collections[i].uid;
  235. var par=inputResource.split('/');
  236. if(typeof globalAddressbookSelected!='undefined' && globalAddressbookSelected!=null && globalAddressbookSelected!='')
  237. {
  238. globalSettings.addressbookselected.value = globalAddressbookSelected;
  239. if(typeof globalAddressbookSelected=='string' && inputResource==globalAddressbookSelected.substring(0,globalAddressbookSelected.lastIndexOf('/')+1))
  240. {
  241. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  242. $('#ResourceCardDAVList').find('[data-id="'+globalAddressbookSelected+'"]:visible').addClass('resourceCardDAV_selected');
  243. }
  244. else if(typeof globalAddressbookSelected=='string' && globalAddressbookSelected.charAt(globalAddressbookSelected.length-1)=='/' && (par[par.length-3]+'/'+par[par.length-2]+'/')==globalAddressbookSelected)
  245. {
  246. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  247. $('#ResourceCardDAVList').find('[data-id="'+inputResource+'"]:visible').addClass('resourceCardDAV_selected');
  248. }
  249. else if(typeof globalAddressbookSelected=='string' && globalAddressbookSelected.charAt(globalAddressbookSelected.length-1)!='/')
  250. {
  251. if((par[par.length-3]+'/'+par[par.length-2]+'/') == globalAddressbookSelected.substring(0,globalAddressbookSelected.lastIndexOf('/')+1) && $('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  252. {
  253. if($('#ResourceCardDAVList').find('[data-id="'+inputResource+globalAddressbookSelected.substring(globalAddressbookSelected.lastIndexOf('/')+1,globalAddressbookSelected.length)+'"]:visible').length>0)
  254. $('#ResourceCardDAVList').find('[data-id="'+inputResource+globalAddressbookSelected.substring(globalAddressbookSelected.lastIndexOf('/')+1,globalAddressbookSelected.length)+'"]:visible').addClass('resourceCardDAV_selected');
  255. }
  256. }
  257. else if (typeof globalAddressbookSelected=='object' && inputResource.match(globalAddressbookSelected)!=null)
  258. {
  259. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  260. $('#ResourceCardDAVList').find('[data-id="'+inputResource+'"]:visible').addClass('resourceCardDAV_selected');
  261. }
  262. else if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0)
  263. {
  264. globalSettings.addressbookselected.value=par[par.length-3]+'/'+par[par.length-2]+'/';
  265. $('#ResourceCardDAVList').find('[data-id="'+inputResource+'"]:visible').addClass('resourceCardDAV_selected');
  266. }
  267. }
  268. }
  269. if($('#ResourceCardDAVList').find('.resourceCardDAV_selected:visible').length == 0 && $('#ResourceCardDAVList').find('.resourceCardDAV[data-id]:visible').length > 0)
  270. {
  271. var ui_d = $('#ResourceCardDAVList').find('.resourceCardDAV[data-id]:visible').eq(0).attr('data-id');
  272. var part_u = ui_d.split('/');
  273. globalSettings.addressbookselected.value=part_u[part_u.length-3]+'/'+part_u[part_u.length-2]+'/';
  274. $('#ResourceCardDAVList').find('.resourceCardDAV[data-id]:visible').eq(0).addClass('resourceCardDAV_selected');
  275. }
  276. var selColl=globalResourceCardDAVList.getCollectionByUID($('#ResourceCardDAVList').find('.resourceCardDAV[data-id].resourceCardDAV_selected').attr('data-id'));
  277. if(selColl!=null)
  278. {
  279. selColl.filterUID=selColl.uid;
  280. if(selColl.permissions.read_only==true)
  281. globalRefAddContact.addClass('element_no_display');
  282. else
  283. globalRefAddContact.removeClass('element_no_display');
  284. globalRefAddContact.attr('data-url', selColl.uid.replace(RegExp('[^/]+$'),''));
  285. globalRefAddContact.attr('data-filter-url',selColl.filterUID); // Set the current addressbook filter uid
  286. globalRefAddContact.attr('data-account-uid',selColl.accountUID);
  287. globalRefAddContact.attr('data-color',selColl.color);
  288. // Make the selected collection active
  289. if(!globalCardDAVInitLoad)
  290. {
  291. if(typeof(globalContactsABChange)=='function')
  292. globalContactsABChange(selColl.uid);
  293. $('#ResourceCardDAVList').find('.resourceCardDAV_item').find('.resourceCardDAV_selected').removeClass('resourceCardDAV_selected');
  294. $('#ResourceCardDAVList').find('[data-id='+jqueryEscapeSelector(selColl.uid)+']').addClass('resourceCardDAV_selected');
  295. if(selColl.filterUID[selColl.filterUID.length-1]!='/')
  296. $('#ResourceCardDAVList').find('[data-id='+jqueryEscapeSelector(selColl.filterUID)+']').addClass('resourceCardDAV_selected');
  297. }
  298. }
  299. }
  300. function CardDAVUpdateMainLoader(inputCollection)
  301. {
  302. if(!globalCardDAVInitLoad)
  303. {
  304. if(globalSettingsSaving=='addressbook')
  305. {
  306. globalLoadedCollectionsCount++;
  307. $('#AddressbookOverlay').children('.loaderInfo').text(localization[globalInterfaceLanguage].loadingAddressbooks.replace('%act%', globalLoadedCollectionsCount).replace('%total%', globalLoadedCollectionsNumber));
  308. if(globalSettingsSaving!='' && globalLoadedCollectionsCount==globalLoadedCollectionsNumber)
  309. setTimeout(function(){hideUnloadedCardDAVCollectionsCallBack();if(isAvaible('Settings'))hideSettingsOverlay();},300);
  310. }
  311. selectActiveAddressbook();
  312. for(var adr in globalAddressbookList.vcard_groups)
  313. {
  314. if(globalAddressbookList.vcard_groups[adr].length>0)
  315. {
  316. extendDestSelect();
  317. if(typeof $('#vCardEditor').attr('data-vcard-uid')=='undefined')
  318. $('#vCardEditor').find('[data-attr-name="_DEST_"]').find('optiotn[data-type$="'+$('#ResourceCardDAVList').find('.resourceCardDAV_selected').find(':input[data-id]').attr('data-id')+'"]').prop('selected',true)
  319. }
  320. }
  321. return false;
  322. }
  323. if(inputCollection.makeLoaded)
  324. {
  325. globalAddressbookNumberCount++;
  326. $('#MainLoaderInner').html(localization[globalInterfaceLanguage].loadingAddressbooks.replace('%act%', (globalAddressbookNumberCount)).replace('%total%', globalAddressbookNumber));
  327. }
  328. inputCollection.isLoaded=true;
  329. $('#ResourceCardDAVList [data-id="'+inputCollection.uid+'"]').removeClass('r_operate');
  330. var unloadedCount=0;
  331. for(var i=0; i<globalResourceCardDAVList.collections.length;i++)
  332. if(globalResourceCardDAVList.collections[i].uid!=undefined && !globalResourceCardDAVList.collections[i].isLoaded)
  333. unloadedCount++;
  334. if(unloadedCount==0 && !isCardDAVLoaded)
  335. {
  336. globalCardDAVInitLoad=false;
  337. globalAddressbookList.renderContacs();
  338. var rexo=new RegExp('^(https?://)([^@/]+(?:@[^@/]+)?)@(.*)');
  339. if(!globalDefaultAddressbookCollectionActiveAll)
  340. {
  341. for(var i=0;i<globalSettings.activeaddressbookcollections.value.length;i++)
  342. {
  343. if(typeof globalCrossServerSettingsURL!='undefined'&&globalCrossServerSettingsURL!=null&globalCrossServerSettingsURL)
  344. {
  345. var tmpParts2 = globalSettings.activeaddressbookcollections.value[i].match('^(.*/)([^/]+)/([^/]+)/$');
  346. var checkHref2=tmpParts2[2]+'/'+tmpParts2[3]+'/';
  347. if($('#ResourceCardDAVList input[data-id$="'+checkHref2+'"]:visible').length>0)
  348. $('#ResourceCardDAVList input[data-id$="'+checkHref2+'"]').trigger('click');
  349. }
  350. else
  351. {
  352. var uidPart=globalSettings.activeaddressbookcollections.value[i].match(RegExp('^(https?://)(.*)', 'i'))[1];
  353. var uidPart2=globalSettings.activeaddressbookcollections.value[i].match(RegExp('^(https?://)(.*)', 'i'))[2];
  354. var uidPart3=getAccount(inputCollection.accountUID).userAuth.userName;
  355. var uid = uidPart+uidPart3+'@'+uidPart2;
  356. if($('#ResourceCardDAVList .resourceCardDAV input[data-id="'+uid+'"]:visible').length>0)
  357. $('#ResourceCardDAVList .resourceCardDAV input[data-id="'+uid+'"]').trigger('click');
  358. }
  359. }
  360. if(globalSettings.activeaddressbookcollections.value.length>0 && $('#ResourceCardDAVList .resourceCardDAV input:checked').length==0)
  361. globalDefaultAddressbookCollectionActiveAll=true;
  362. }
  363. if(globalDefaultAddressbookCollectionActiveAll)
  364. for(var i=0;i<globalResourceCardDAVList.collections.length;i++)
  365. if(globalResourceCardDAVList.collections[i].uid!=undefined && $('#ResourceCardDAVList .resourceCardDAV input[data-id="'+globalResourceCardDAVList.collections[i].uid+'"]:visible').length>0)
  366. $('#ResourceCardDAVList input[data-id="'+globalResourceCardDAVList.collections[i].uid+'"]').trigger('click');
  367. selectActiveAddressbook();
  368. globalRefAddContact.prop('disabled', false);
  369. loadNextApplication(true);
  370. }
  371. }
  372. function applyAddrSettings(abContactRef, remValues)
  373. {
  374. var addrVals = new Array();
  375. if(typeof remValues!= 'undefined')
  376. {
  377. abContactRef.find('[data-type="\\%address"]').find('[data-type="country_type"]').each(function(){
  378. addrVals[$(this).parents('[data-type="%address"]').attr('data-id')] = $(this).val();
  379. });
  380. }
  381. var country_option=abContactRef.find('[data-type="\\%address"]').find('[data-type="country_type"]').find('option').last().clone();
  382. abContactRef.find('[data-type="\\%address"]').find('[data-type="country_type"]').html('');
  383. // we need a copy of the object because of the next "delete" operation
  384. var addressTypesTmp=jQuery.extend({}, addressTypes);
  385. // delete custom ordered element before the sort (then we will add them back)
  386. if(globalSettings.addresscountryfavorites.value.length>0)
  387. for(var i=globalSettings.addresscountryfavorites.value.length-1;i>=0;i--)
  388. delete addressTypesTmp[globalSettings.addresscountryfavorites.value[i]];
  389. var addressTypesArr=sortCountries(addressTypesTmp);
  390. // re-add custom ordered elements from the original addressTypes (where all elements are still present)
  391. if(globalSettings.addresscountryfavorites.value.length>0)
  392. for(var i=globalSettings.addresscountryfavorites.value.length-1;i>=0;i--)
  393. addressTypesArr.unshift({'key': globalSettings.addresscountryfavorites.value[i], 'value': addressTypes[globalSettings.addresscountryfavorites.value[i]], 'translated_value': localization[globalInterfaceLanguage]['txtAddressCountry'+globalSettings.addresscountryfavorites.value[i].toUpperCase()]});
  394. for(var i=0;i<addressTypesArr.length;i++)
  395. {
  396. var tmp=country_option;
  397. tmp.attr('data-type',addressTypesArr[i].key);
  398. tmp.attr('data-full-name',addressTypesArr[i].value[0]);
  399. tmp.text(addressTypesArr[i].translated_value); // translation
  400. abContactRef.find('[data-type="\\%address"]').find('[data-type="country_type"]').append(tmp.clone());
  401. }
  402. abContactRef.find('[data-type="\\%address"]').find('[data-type="country_type"]').attr('data-autoselect',globalSettings.defaultaddresscountry.value);
  403. for(var key in addrVals)
  404. abContactRef.find('[data-type="\\%address"][data-id="'+key+'"]').find('[data-type="country_type"]').val(addrVals[key]);
  405. }
  406. function localizeCardDAV()
  407. {
  408. // frequently used
  409. var abContactRef=$('#ABContact');
  410. // restore original templates
  411. $('#ResourceCardDAVList').empty().append(globalOrigCardDAVListTemplate.clone());
  412. abContactRef.empty().append(globalOrigVcardTemplate.clone());
  413. localizeAddressTypes();
  414. // interface translation
  415. $('[data-type="system_logo"]').attr('alt',localization[globalInterfaceLanguage].altLogo);
  416. $('[data-type="system_username"]').attr('placeholder',localization[globalInterfaceLanguage].pholderUsername);
  417. $('[data-type="system_password"]').attr('placeholder',localization[globalInterfaceLanguage].pholderPassword);
  418. $('[data-type="resourcesCardDAV_txt"]').text(localization[globalInterfaceLanguage].txtAddressbooks);
  419. $('[data-type="contact_txt"]').text(localization[globalInterfaceLanguage].txtContact);
  420. $('[data-type="search"]').attr('placeholder',localization[globalInterfaceLanguage].txtSearch);
  421. $('#AddContact').attr('alt',localization[globalInterfaceLanguage].altAddContact);
  422. $('#AddContact').attr('title',localization[globalInterfaceLanguage].altAddContact);
  423. $('#Logout').attr('alt',localization[globalInterfaceLanguage].altLogout);
  424. $('#Logout').attr('title',localization[globalInterfaceLanguage].altLogout);
  425. $('#showUnloadedAddressbooks').attr({title:capitalize(localization[globalInterfaceLanguage].txtEnabledAddressbooks),alt:capitalize(localization[globalInterfaceLanguage].txtEnabledAddressbooks)});
  426. $('#loadUnloadedAddressbooks').val(localization[globalInterfaceLanguage].buttonSave);
  427. $('#loadUnloadedAddressbooksCancel').val(localization[globalInterfaceLanguage].buttonCancel);
  428. abContactRef.find('#photoBox').find('h1').text(localization[globalInterfaceLanguage].txtRemoteImage);
  429. abContactRef.find('#photoURL').attr('placeholder',localization[globalInterfaceLanguage].pholderUrlVal);
  430. abContactRef.find('[data-type="photo"]').text(localization[globalInterfaceLanguage].altPhoto);
  431. abContactRef.find('[data-type="given"]').attr('placeholder',localization[globalInterfaceLanguage].pholderGiven);
  432. abContactRef.find('[data-type="family"]').attr('placeholder',localization[globalInterfaceLanguage].pholderFamily);
  433. abContactRef.find('[data-type="middle"]').attr('placeholder',localization[globalInterfaceLanguage].pholderMiddle);
  434. abContactRef.find('[data-type="nickname"]').attr('placeholder',localization[globalInterfaceLanguage].pholderNickname);
  435. abContactRef.find('[data-type="ph_firstname"]').attr('placeholder',localization[globalInterfaceLanguage].pholderPhGiven);
  436. abContactRef.find('[data-type="ph_lastname"]').attr('placeholder',localization[globalInterfaceLanguage].pholderPhFamily);
  437. abContactRef.find('[data-type="prefix"]').attr('placeholder',localization[globalInterfaceLanguage].pholderPrefix);
  438. abContactRef.find('[data-type="suffix"]').attr('placeholder',localization[globalInterfaceLanguage].pholderSuffix);
  439. abContactRef.find('[data-type="date_bday"]').attr('placeholder',localization[globalInterfaceLanguage].pholderBday);
  440. abContactRef.find('[data-type="title"]').attr('placeholder',localization[globalInterfaceLanguage].pholderTitle);
  441. abContactRef.find('[data-type="org"]').attr('placeholder',localization[globalInterfaceLanguage].pholderOrg);
  442. abContactRef.find('[data-type="department"]').attr('placeholder',localization[globalInterfaceLanguage].pholderDepartment);
  443. abContactRef.find('span[data-type="company_contact"]').text(localization[globalInterfaceLanguage].txtCompanyContact);
  444. abContactRef.find('[data-type="\\%del"]').attr('alt',localization[globalInterfaceLanguage].altDel);
  445. abContactRef.find('[data-type="\\%add"]').attr('alt',localization[globalInterfaceLanguage].altAdd);
  446. abContactRef.find('[data-type="value_handler"]').attr('alt',localization[globalInterfaceLanguage].altValueHandler);
  447. abContactRef.find('[data-type=":custom"]').text(localization[globalInterfaceLanguage].txtCustom);
  448. abContactRef.find('[data-type="custom_value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderCustomVal);
  449. abContactRef.find('[data-type="dates_txt"]').text(localization[globalInterfaceLanguage].txtDates);
  450. abContactRef.find('[data-type="\\%date"]').find('input[data-type="date_value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderDate);
  451. abContactRef.find('[data-type="\\%date"]').find('[data-type=":_$!<anniversary>!$_:"]').text(localization[globalInterfaceLanguage].txtDatesAnniversary);
  452. abContactRef.find('[data-type="\\%date"]').find('[data-type=":_$!<other>!$_:"]').text(localization[globalInterfaceLanguage].txtDatesOther);
  453. abContactRef.find('[data-type="phone_txt"]').text(localization[globalInterfaceLanguage].txtPhone);
  454. abContactRef.find('[data-type="\\%phone"]').find('input[data-type="value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderPhoneVal);
  455. abContactRef.find('[data-type="\\%phone"]').find('[data-type="work"]').text(localization[globalInterfaceLanguage].txtPhoneWork);
  456. abContactRef.find('[data-type="\\%phone"]').find('[data-type="home"]').text(localization[globalInterfaceLanguage].txtPhoneHome);
  457. abContactRef.find('[data-type="\\%phone"]').find('[data-type="cell"]').text(localization[globalInterfaceLanguage].txtPhoneCell);
  458. abContactRef.find('[data-type="\\%phone"]').find('[data-type="cell,work"]').text(localization[globalInterfaceLanguage].txtPhoneCellWork);
  459. abContactRef.find('[data-type="\\%phone"]').find('[data-type="cell,home"]').text(localization[globalInterfaceLanguage].txtPhoneCellHome);
  460. abContactRef.find('[data-type="\\%phone"]').find('[data-type="main"]').text(localization[globalInterfaceLanguage].txtPhoneMain);
  461. abContactRef.find('[data-type="\\%phone"]').find('[data-type="pager"]').text(localization[globalInterfaceLanguage].txtPhonePager);
  462. abContactRef.find('[data-type="\\%phone"]').find('[data-type="fax"]').text(localization[globalInterfaceLanguage].txtPhoneFax);
  463. abContactRef.find('[data-type="\\%phone"]').find('[data-type="fax,work"]').text(localization[globalInterfaceLanguage].txtPhoneFaxWork);
  464. abContactRef.find('[data-type="\\%phone"]').find('[data-type="fax,home"]').text(localization[globalInterfaceLanguage].txtPhoneFaxHome);
  465. abContactRef.find('[data-type="\\%phone"]').find('[data-type="iphone"]').text(localization[globalInterfaceLanguage].txtPhoneIphone);
  466. abContactRef.find('[data-type="\\%phone"]').find('[data-type="other"]').text(localization[globalInterfaceLanguage].txtPhoneOther);
  467. abContactRef.find('[data-type="email_txt"]').text(localization[globalInterfaceLanguage].txtEmail);
  468. abContactRef.find('[data-type="\\%email"]').find('input[data-type="value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderEmailVal);
  469. abContactRef.find('[data-type="\\%email"]').find('[data-type="internet,work"]').text(localization[globalInterfaceLanguage].txtEmailWork);
  470. abContactRef.find('[data-type="\\%email"]').find('[data-type="home,internet"]').text(localization[globalInterfaceLanguage].txtEmailHome);
  471. abContactRef.find('[data-type="\\%email"]').find('[data-type=":mobileme:,internet"]').text(localization[globalInterfaceLanguage].txtEmailMobileme);
  472. abContactRef.find('[data-type="\\%email"]').find('[data-type=":_$!<other>!$_:,internet"]').text(localization[globalInterfaceLanguage].txtEmailOther);
  473. abContactRef.find('[data-type="url_txt"]').text(localization[globalInterfaceLanguage].txtUrl);
  474. abContactRef.find('[data-type="\\%url"]').find('input[data-type="value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderUrlVal);
  475. abContactRef.find('[data-type="\\%url"]').find('[data-type="work"]').text(localization[globalInterfaceLanguage].txtUrlWork);
  476. abContactRef.find('[data-type="\\%url"]').find('[data-type="home"]').text(localization[globalInterfaceLanguage].txtUrlHome);
  477. abContactRef.find('[data-type="\\%url"]').find('[data-type=":_$!<homepage>!$_:"]').text(localization[globalInterfaceLanguage].txtUrlHomepage);
  478. abContactRef.find('[data-type="\\%url"]').find('[data-type=":_$!<other>!$_:"]').text(localization[globalInterfaceLanguage].txtUrlOther);
  479. abContactRef.find('[data-type="related_txt"]').text(localization[globalInterfaceLanguage].txtRelated);
  480. abContactRef.find('[data-type="\\%person"]').find('input[data-type="value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderRelatedVal);
  481. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<manager>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedManager);
  482. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<assistant>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedAssistant);
  483. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<father>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedFather);
  484. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<mother>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedMother);
  485. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<parent>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedParent);
  486. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<brother>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedBrother);
  487. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<sister>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedSister);
  488. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<child>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedChild);
  489. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<friend>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedFriend);
  490. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<spouse>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedSpouse);
  491. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<partner>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedPartner);
  492. abContactRef.find('[data-type="\\%person"]').find('[data-type=":_$!<other>!$_:"]').text(localization[globalInterfaceLanguage].txtRelatedOther);
  493. abContactRef.find('[data-type="im_txt"]').text(localization[globalInterfaceLanguage].txtIm);
  494. abContactRef.find('[data-type="\\%im"]').find('input[data-type="value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderImVal);
  495. abContactRef.find('[data-type="\\%im"]').find('[data-type="work"]').text(localization[globalInterfaceLanguage].txtImWork);
  496. abContactRef.find('[data-type="\\%im"]').find('[data-type="home"]').text(localization[globalInterfaceLanguage].txtImHome);
  497. abContactRef.find('[data-type="\\%im"]').find('[data-type=":mobileme:"]').text(localization[globalInterfaceLanguage].txtImMobileme);
  498. abContactRef.find('[data-type="\\%im"]').find('[data-type=":_$!<other>!$_:"]').text(localization[globalInterfaceLanguage].txtImOther);
  499. abContactRef.find('[data-type="\\%im"]').find('[data-type="aim"]').text(localization[globalInterfaceLanguage].txtImProtAim);
  500. abContactRef.find('[data-type="\\%im"]').find('[data-type="icq"]').text(localization[globalInterfaceLanguage].txtImProtIcq);
  501. abContactRef.find('[data-type="\\%im"]').find('[data-type="irc"]').text(localization[globalInterfaceLanguage].txtImProtIrc);
  502. abContactRef.find('[data-type="\\%im"]').find('[data-type="jabber"]').text(localization[globalInterfaceLanguage].txtImProtJabber);
  503. abContactRef.find('[data-type="\\%im"]').find('[data-type="msn"]').text(localization[globalInterfaceLanguage].txtImProtMsn);
  504. abContactRef.find('[data-type="\\%im"]').find('[data-type="yahoo"]').text(localization[globalInterfaceLanguage].txtImProtYahoo);
  505. abContactRef.find('[data-type="\\%im"]').find('[data-type="facebook"]').text(localization[globalInterfaceLanguage].txtImProtFacebook);
  506. abContactRef.find('[data-type="\\%im"]').find('[data-type="gadugadu"]').text(localization[globalInterfaceLanguage].txtImProtGadugadu);
  507. abContactRef.find('[data-type="\\%im"]').find('[data-type="googletalk"]').text(localization[globalInterfaceLanguage].txtImProtGoogletalk);
  508. abContactRef.find('[data-type="\\%im"]').find('[data-type="qq"]').text(localization[globalInterfaceLanguage].txtImProtQq);
  509. abContactRef.find('[data-type="\\%im"]').find('[data-type="skype"]').text(localization[globalInterfaceLanguage].txtImProtSkype);
  510. abContactRef.find('[data-type="profile_txt"]').text(localization[globalInterfaceLanguage].txtProfile);
  511. abContactRef.find('[data-type="\\%profile"]').find('input[data-type="value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderProfileVal);
  512. abContactRef.find('[data-type="\\%profile"]').find('[data-type="twitter"]').text(localization[globalInterfaceLanguage].txtProfileTwitter);
  513. abContactRef.find('[data-type="\\%profile"]').find('[data-type="facebook"]').text(localization[globalInterfaceLanguage].txtProfileFacebook);
  514. abContactRef.find('[data-type="\\%profile"]').find('[data-type="flickr"]').text(localization[globalInterfaceLanguage].txtProfileFlickr);
  515. abContactRef.find('[data-type="\\%profile"]').find('[data-type="linkedin"]').text(localization[globalInterfaceLanguage].txtProfileLinkedin);
  516. abContactRef.find('[data-type="\\%profile"]').find('[data-type="myspace"]').text(localization[globalInterfaceLanguage].txtProfileMyspace);
  517. abContactRef.find('[data-type="\\%profile"]').find('[data-type="sinaweibo"]').text(localization[globalInterfaceLanguage].txtProfileSinaweibo);
  518. abContactRef.find('[data-type="address_txt"]').text(localization[globalInterfaceLanguage].txtAddress);
  519. abContactRef.find('[data-type="\\%address"]').find('[data-type="work"]').text(localization[globalInterfaceLanguage].txtAddressWork);
  520. abContactRef.find('[data-type="\\%address"]').find('[data-type="home"]').text(localization[globalInterfaceLanguage].txtAddressHome);
  521. abContactRef.find('[data-type="\\%address"]').find('[data-type=":_$!<other>!$_:"]').text(localization[globalInterfaceLanguage].txtAddressOther);
  522. abContactRef.find('[data-type="categories_txt"]').text(localization[globalInterfaceLanguage].txtCategories);
  523. abContactRef.find('[data-type="note_txt"]').text(localization[globalInterfaceLanguage].txtNote);
  524. abContactRef.find('[data-type="\\%note"]').find('textarea[data-type="value"]').attr('placeholder',localization[globalInterfaceLanguage].pholderNoteVal);
  525. abContactRef.find('[data-type="edit"]').val(localization[globalInterfaceLanguage].buttonEdit);
  526. abContactRef.find('[data-type="add_contact"]').val(localization[globalInterfaceLanguage].altAddContact);
  527. abContactRef.find('[data-type="save"]').val(localization[globalInterfaceLanguage].buttonSave);
  528. abContactRef.find('[data-type="cancel"]').val(localization[globalInterfaceLanguage].buttonCancel);
  529. abContactRef.find('[data-type="delete_from_group"]').val(localization[globalInterfaceLanguage].buttonDeleteFromGroup);
  530. abContactRef.find('[data-type="delete"]').val(localization[globalInterfaceLanguage].buttonDelete);
  531. // hook for extension specific localization
  532. if(typeof(globalContactsExtLocalize)=='function')
  533. globalContactsExtLocalize(abContactRef);
  534. globalTranslCardDAVListTemplate=$('#ResourceCardDAVListTemplate').clone();
  535. globalTranslCardDAVListHeader=globalTranslCardDAVListTemplate.find('.resourceCardDAV_header').clone();
  536. globalTranslCardDAVListItem=globalTranslCardDAVListTemplate.find('.resourceCardDAV_item').clone();
  537. globalTranslVcardTemplate=$('#vCardTemplate').contents().clone();
  538. // CUSTOM PLACEHOLDER (initialization for the whole page)
  539. $('input[placeholder],textarea[placeholder]').placeholder();
  540. }
  541. function processEditorElements(inputEditorRef, processingType, inputIsReadonly, inputIsCompany)
  542. {
  543. var cssShowAsTxtClass='element_show_as_text';
  544. var cssGrayedTxt='element_grayed';
  545. var cssElementNoDisplay='element_no_display';
  546. var cssElementHide='element_hide';
  547. var tmp_ref=inputEditorRef;
  548. if(processingType=='hide')
  549. {
  550. tmp_ref.attr('data-editor-state', 'show');
  551. var disabled=true;
  552. var readonly=true;
  553. }
  554. else
  555. {
  556. tmp_ref.attr('data-editor-state', 'edit');
  557. var disabled=false;
  558. var readonly=false;
  559. }
  560. var inputLockedElements=[];
  561. if(typeof(globalContactsExtGetLockedElements)=='function')
  562. inputLockedElements=globalContactsExtGetLockedElements(inputIsCompany);
  563. var inputDisabledElements=[];
  564. if(typeof(globalContactsExtGetDisabledElements)=='function')
  565. inputDisabledElements=globalContactsExtGetDisabledElements(inputIsCompany);
  566. // show "drag" border on photo & delete button
  567. tmp_ref.find('#photo_drag').css('display', (disabled || readonly ? 'none' : 'inline'));
  568. // if the editor state is "edit" show the "delete" button
  569. if(!tmp_ref.find('#photo').hasClass('photo_blank'))
  570. tmp_ref.find('#reset_img').css('display', (disabled || readonly ? 'none': 'inline'));
  571. // checkboxes
  572. var tmp=tmp_ref.find('[type="checkbox"]');
  573. tmp.each(
  574. function(index,element)
  575. {
  576. var tmp=$(element);
  577. var tmp_data_type=tmp.attr('data-type');
  578. tmp.prop('disabled', disabled || inputLockedElements.indexOf('[data-type="'+tmp_data_type+'"]')!=-1);
  579. if(!tmp.prop('checked') && (processingType=='hide' || inputLockedElements.indexOf('[data-type="'+tmp_data_type+'"]')!=-1))
  580. tmp.parent().addClass(cssGrayedTxt);
  581. else
  582. tmp.parent().removeClass(cssGrayedTxt);
  583. }
  584. );
  585. tmp_ref.find('input[data-type^="date_"]').prop('disabled', disabled || readonly);
  586. // family name, given name, and organization name
  587. var typeList=['family', 'given', 'middle', 'nickname', 'prefix', 'suffix', 'ph_firstname', 'ph_lastname', 'date_bday', 'tags', 'title', 'department', 'org'];
  588. for(var i=0; i<typeList.length; i++)
  589. {
  590. var elementRef = tmp_ref.find('[data-type="'+typeList[i]+'"]');
  591. var elementDisabled = inputDisabledElements.indexOf('[data-type="'+typeList[i]+'"]')!=-1 && (processingType=='add' || elementRef.val()=='');
  592. var elementReadOnly = readonly || inputLockedElements.indexOf('[data-type="'+typeList[i]+'"]')!=-1 || elementDisabled;
  593. elementRef.prop({'readonly':elementReadOnly, 'disabled':elementDisabled}).toggleClass('non_editable', elementDisabled);
  594. }
  595. var tmp_tags_prefix=['#tags'];
  596. var typeList=new Array({sel: '[data-type="\\%address"]'}, {sel: '[data-type="\\%phone"]'}, {sel: '[data-type="\\%email"]'}, {sel: '[data-type="\\%url"]'}, {sel: '[data-type="\\%date"]'}, {sel: '[data-type="\\%person"]'}, {sel: '[data-type="\\%im"]'}, {sel: '[data-type="\\%profile"]'}, {sel: '[data-type="\\%categories"]'}, {sel: '[data-type="\\%note"]'});
  597. // hook for extending the list of editor elements
  598. if(typeof(globalContactsExtGetAdditionalElements)=='function')
  599. {
  600. tmp_tags_prefix=tmp_tags_prefix.concat(globalContactsExtGetAdditionalElements('tags'));
  601. typeList=typeList.concat(globalContactsExtGetAdditionalElements('common'));
  602. }
  603. tmp_ref.find('select').prop('disabled', disabled);
  604. /*************************** BAD HACKS SECTION ***************************/
  605. if($.browser.msie || $.browser.mozilla)
  606. {
  607. var newSVG=$((disabled ? SVG_select_dis : SVG_select)).attr('data-type', 'select_icon').css({'pointer-events': 'none', 'z-index': '1', 'display': 'inline', 'margin-left': (disabled ? '-22px' : '-19px'), 'vertical-align': 'top', 'background-color': '#ffffff'}); // background-color = stupid IE9 bug
  608. //XXXX check this - was $('#ABContact')
  609. tmp_ref.find('select').parent().find('svg[data-type="select_icon"]').replaceWith($('<div>').append($(newSVG).clone()).html());
  610. }
  611. /*************************** END OF BAD HACKS SECTION ***************************/
  612. for(var i=0; i<tmp_tags_prefix.length; i++)
  613. {
  614. var tmp=tmp_ref.find(tmp_tags_prefix[i]+'_tag');
  615. tmp.prop('readonly', readonly);
  616. if(readonly)
  617. tmp.closest('div.tagsinput').addClass('readonly');
  618. else
  619. tmp.closest('div.tagsinput').removeClass('readonly');
  620. }
  621. for(var i=0; i<typeList.length; i++)
  622. {
  623. var found_non_empty=0;
  624. var empty = false;
  625. tmp=tmp_ref.find(typeList[i].sel);
  626. tmp.each(
  627. function(index, element)
  628. {
  629. var tmp=$(element).find('[data-type="value"]');
  630. if(tmp.length==0)
  631. tmp=$(element).find('[data-type="date_value"]');
  632. var found=0;
  633. // check if there is any data present (if not, whe hide the element)
  634. if($(element).attr('data-type')=='%address') // address is handled specially
  635. tmp.each(
  636. function(index,element)
  637. {
  638. if($(element).attr('data-addr-field')!='' && $(element).attr('data-addr-field')!='country' && $(element).val()!='')
  639. {
  640. found=1;
  641. return false;
  642. }
  643. }
  644. );
  645. else if(tmp.val()!='') // other elements (not address)
  646. found=1;
  647. if(processingType=='hide')
  648. {
  649. if(found)
  650. {
  651. $(element).find('[data-type="\\%add"]').find('input[type="image"]').addClass(cssElementNoDisplay);
  652. $(element).find('[data-type="\\%del"]').find('input[type="image"]').addClass(cssElementNoDisplay);
  653. $(element).find('select').prop('disabled', disabled);
  654. $(element).find('textarea').prop('disabled', disabled);
  655. /*************************** BAD HACKS SECTION ***************************/
  656. if($.browser.msie || $.browser.mozilla)
  657. {
  658. var newSVG=$((disabled ? SVG_select_dis : SVG_select)).attr('data-type', 'select_icon').css({'pointer-events': 'none', 'z-index': '1', 'display': 'inline', 'margin-left': (disabled ? '-22px' : '-19px'), 'vertical-align': 'top', 'background-color': '#ffffff'}); // background-color = stupid IE9 bug
  659. //XXXX check this - was $('#ABContact')
  660. $(element).find('svg[data-type="select_icon"]').replaceWith($('<div>').append($(newSVG).clone()).html());
  661. }
  662. /*************************** END OF BAD HACKS SECTION ***************************/
  663. tmp.prop('readonly', readonly);
  664. found_non_empty=1;
  665. }
  666. else
  667. $(element).addClass(cssElementNoDisplay);
  668. }
  669. else // 'show'
  670. {
  671. empty = empty || $(element).hasClass(cssElementNoDisplay);
  672. $(element).removeClass(cssElementNoDisplay);
  673. $(element).find('[data-type="\\%add"]').find('input[type="image"]').removeClass(cssElementNoDisplay);
  674. $(element).find('[data-type="\\%del"]').find('input[type="image"]').removeClass(cssElementNoDisplay);
  675. $(element).find('select').prop('disabled', disabled);
  676. $(element).find('textarea').prop('disabled', disabled);
  677. /*************************** BAD HACKS SECTION ***************************/
  678. if($.browser.msie || $.browser.mozilla)
  679. {
  680. var newSVG=$((disabled ? SVG_select_dis : SVG_select)).attr('data-type', 'select_icon').css({'pointer-events': 'none', 'z-index': '1', 'display': 'inline', 'margin-left': (disabled ? '-22px' : '-19px'), 'vertical-align': 'top', 'background-color': '#ffffff'}); // background-color = stupid IE9 bug
  681. //XXXX check this - was $('#ABContact')
  682. $(element).find('svg[data-type="select_icon"]').replaceWith($('<div>').append($(newSVG).clone()).html());
  683. }
  684. /*************************** END OF BAD HACKS SECTION ***************************/
  685. tmp.prop('readonly', readonly);
  686. }
  687. }
  688. );
  689. if(processingType==='show' && !empty) {
  690. if(typeList[i].sel==='[data-type="\\%address"]') {
  691. tmp.each(function() {
  692. var street = $(this).find('[data-addr-field="street"]');
  693. if(street.val()) {
  694. street.trigger('keyup.street');
  695. }
  696. });
  697. }
  698. if(typeof globalContactAutoExpand=='undefined' || globalContactAutoExpand!=false)
  699. tmp.last().find('[data-type="\\%add"]').find('.op').trigger('click');
  700. }
  701. // set the visibility of the buttons
  702. if(processingType=='hide')
  703. {
  704. if(inputIsReadonly!=true)
  705. {
  706. if(typeof globalGroupContactsByCompanies!='undefined' && globalGroupContactsByCompanies==true && inputIsCompany)
  707. tmp_ref.find('[data-type="add_contact"]').removeClass(cssElementNoDisplay);
  708. else
  709. tmp_ref.find('[data-type="add_contact"]').addClass(cssElementNoDisplay);
  710. tmp_ref.find('[data-type="edit"]').removeClass(cssElementNoDisplay);
  711. }
  712. else
  713. {
  714. tmp_ref.find('[data-type="add_contact"]').addClass(cssElementNoDisplay);
  715. tmp_ref.find('[data-type="edit"]').addClass(cssElementNoDisplay);
  716. }
  717. tmp_ref.find('[data-type="save"]').addClass(cssElementNoDisplay);
  718. tmp_ref.find('[data-type="cancel"]').addClass(cssElementNoDisplay);
  719. tmp_ref.find('[data-type="delete_from_group"]').addClass(cssElementNoDisplay);
  720. tmp_ref.find('[data-type="delete"]').addClass(cssElementNoDisplay);
  721. }
  722. else if(processingType=='add')
  723. {
  724. tmp_ref.find('[data-type="add_contact"]').addClass(cssElementNoDisplay);
  725. tmp_ref.find('[data-type="edit"]').addClass(cssElementNoDisplay);
  726. tmp_ref.find('[data-type="save"]').removeClass(cssElementNoDisplay);
  727. tmp_ref.find('[data-type="cancel"]').removeClass(cssElementNoDisplay);
  728. tmp_ref.find('[data-type="delete_from_group"]').addClass(cssElementNoDisplay);
  729. tmp_ref.find('[data-type="delete"]').addClass(cssElementNoDisplay);
  730. }
  731. else
  732. {
  733. tmp_ref.find('[data-type="add_contact"]').addClass(cssElementNoDisplay);
  734. tmp_ref.find('[data-type="edit"]').addClass(cssElementNoDisplay);
  735. tmp_ref.find('[data-type="save"]').removeClass(cssElementNoDisplay);
  736. tmp_ref.find('[data-type="cancel"]').removeClass(cssElementNoDisplay);
  737. // show "Delete from Group" only if there is an active contact group
  738. // XXX we need to use another identificator
  739. // if(globalResourceCardDAVList.getLoadedAddressbook().filterUID[globalResourceCardDAVList.getLoadedAddressbook().filterUID.length-1]!='/')
  740. // tmp.find('[data-type="delete_from_group"]').removeClass(cssElementNoDisplay);
  741. tmp_ref.find('[data-type="delete"]').removeClass(cssElementNoDisplay);
  742. }
  743. if(!found_non_empty)
  744. {
  745. if(processingType=='hide')
  746. tmp.prev().addClass(cssElementNoDisplay);
  747. else
  748. tmp.prev().removeClass(cssElementNoDisplay);
  749. }
  750. }
  751. // set editor "process" hook
  752. if(typeof(globalContactsExtEditorProcess)=='function')
  753. globalContactsExtEditorProcess(tmp_ref, 'post', processingType, inputIsCompany);
  754. }
  755. function loadImage(image)
  756. {
  757. var canvas = $('#photo');
  758. var canvasElement = canvas.get(0);
  759. var imageWidth = image.width;
  760. var imageHeight = image.height;
  761. var canvasWidth = canvas.width()*globalContactPhotoScaleFactor;
  762. var canvasHeight = canvas.height()*globalContactPhotoScaleFactor;
  763. var clipStartX = 0;
  764. var clipStartY = 0;
  765. var clipWidth = imageWidth;
  766. var clipHeight = imageHeight;
  767. canvasElement.width = canvasWidth;
  768. canvasElement.height = canvasHeight;
  769. if(imageWidth-canvasWidth < imageHeight-canvasHeight) {
  770. var clipLength = Math.ceil((imageHeight-imageWidth/canvasWidth*canvasHeight)/2);
  771. clipStartY = clipLength;
  772. clipHeight = imageHeight-clipLength*2;
  773. }
  774. else {
  775. var clipLength = Math.ceil((imageWidth-imageHeight/canvasHeight*canvasWidth)/2);
  776. clipStartX = clipLength;
  777. clipWidth = imageWidth-clipLength*2;
  778. }
  779. canvasElement.getContext('2d').drawImage(image, clipStartX, clipStartY, clipWidth, clipHeight, 0, 0, canvasWidth, canvasHeight);
  780. canvas.removeClass('photo_blank');
  781. }
  782. function CardDAVeditor_cleanup(inputLoadEmpty, inputIsCompany)
  783. {
  784. CardDAVcleanupRegexEnvironment();
  785. // Cleanup the editor and store reference to the editor object
  786. globalRefVcardEditor=globalTranslVcardTemplate.clone();
  787. // cleanup old data form address fields
  788. globalAddressElementOldData={};
  789. if(typeof(globalContactsExtEditorProcess)=='function')
  790. globalContactsExtEditorProcess(globalRefVcardEditor, 'pre', null, inputIsCompany);
  791. /*************************** BAD HACKS SECTION ***************************/
  792. /* IE or FF */
  793. if($.browser.msie || $.browser.mozilla)
  794. {
  795. // ADD empty SVG to interface (we will replace it later)
  796. $('<svg data-type="select_icon"></svg>').css('display', 'none').insertAfter(globalRefVcardEditor.find('select[data-type$="_type"]'));
  797. if($.browser.msie && parseInt($.browser.version, 10)==10) /* IE 10 (because there are no more conditional comments) */
  798. globalRefVcardEditor.find('[data-type="\\%note"]').find('textarea[data-type="value"]').text('').attr('placeholder',$('[data-type="\\%note"]').find('textarea[data-type="value"]').attr('placeholder'));
  799. }
  800. /*************************** END OF BAD HACKS SECTION ***************************/
  801. // bind events (see also add_elements())
  802. // hide the "-" button (we maybe change this in future)
  803. globalRefVcardEditor.find('[data-type="\\%del"]').css('visibility', 'hidden');
  804. var tmp_arr=['[data-type="\\%phone"]', '[data-type="\\%email"]', '[data-type="\\%url"]', '[data-type="\\%date"]', '[data-type="\\%person"]', '[data-type="\\%im"]', '[data-type="\\%profile"]', '[data-type="\\%address"]'];
  805. for(var i=0; i<tmp_arr.length; i++)
  806. {
  807. globalABEditorCounter[tmp_arr[i]]=1; // restart id counters for editor objects
  808. globalRefVcardEditor.find(tmp_arr[i]+' [data-type="\\%add"] input').data('customSelector', tmp_arr[i]).click(function(){add_element($(this).parent(), $(this).data('customSelector'), $(this).data('customSelector'), '[data-type="\\%add"]','[data-type="\\%del"]', globalABEditorCounter[$(this).data('customSelector')]++);checkContactFormScrollBar();});
  809. globalRefVcardEditor.find(tmp_arr[i]+' [data-type="\\%del"] input').data('customSelector', tmp_arr[i]).click(function(){del_element($(this).parent(), $(this).data('customSelector'), '[data-type="\\%add"]','[data-type="\\%del"]');checkContactFormScrollBar();});
  810. if(typeof globalContactAutoExpand=='undefined' || globalContactAutoExpand!=false)
  811. {
  812. globalRefVcardEditor.find(tmp_arr[i]+' input[type="text"]').bind('keyup', function() {
  813. var el = $(this);
  814. var row = el.closest('tr[data-type^="%"]');
  815. var isLast = row.attr('data-type')!==row.next().attr('data-type');
  816. if(isLast && el.val()) {
  817. row.find('[data-type="\\%add"] input').trigger('click');
  818. }
  819. });
  820. }
  821. //globalRefVcardEditor.find(tmp_arr[i]).children().filter('[data-type="\\%add"]').click();
  822. }
  823. // one special thing for address
  824. globalRefVcardEditor.find('[data-type="\\%address"] [data-type="country_type"]').change(function(){set_address_country(this);checkContactFormScrollBar();});
  825. var tmp=globalRefVcardEditor.find('[data-type="\\%address"]');
  826. var tmp_select=tmp.find('[data-type="country_type"]').attr('data-autoselect');
  827. if(tmp_select!='')
  828. {
  829. tmp.find('[data-type="country_type"]').children('[data-type="'+jqueryEscapeSelector(tmp_select)+'"]').prop('selected', true);
  830. tmp.find('[data-autoselect]').change();
  831. }
  832. globalRefVcardEditor.find('[data-type="custom_value"]').bind('keyup change', function(){
  833. $(this).parent().find('[data-type="invalid"]').css('display', (vCard.pre['custom_type'].test($(this).val()) ? 'none' : 'inline'));
  834. });
  835. // init image uploader
  836. globalRefVcardEditor.find('.photo_div').bind('dragover dragenter', function(event){
  837. event.stopPropagation();
  838. event.preventDefault();
  839. // allow image manipulation only if the editor is in "edit" state
  840. if($('#vCardEditor').attr('data-editor-state')!="edit")
  841. return false;
  842. event.originalEvent.dataTransfer.dropEffect='copy'; // explicitly show this is a copy
  843. });
  844. globalRefVcardEditor.find('.photo_div').bind('drop', function(event) {
  845. process_image(event);
  846. });
  847. globalRefVcardEditor.find('#upload_file').bind('change', function(event) {
  848. process_image(event);
  849. });
  850. globalRefVcardEditor.find('#photoBoxButton').bind('click', function(event) {
  851. var photo = $('#photoURL').val();
  852. var newImg = new Image();
  853. newImg.src = photo;
  854. newImg.onload = function() {
  855. // show the image "delete" button
  856. $('#reset_img').css('display', 'inline');
  857. // remove the template related to previous image (start with clean one)
  858. vCard.tplM['contentline_PHOTO'][0]=null;
  859. $('#photoURLHidden').val($('#photoURL').val());
  860. loadImage(this);
  861. hidePhotoBox();
  862. };
  863. newImg.onerror = function() {
  864. $('#photoURL').addClass('invalid');
  865. $('#photoBoxContent').find('[data-type="invalid"]').css('display', 'inline');
  866. };
  867. });
  868. // initialize tagsinput
  869. globalRefVcardEditor.find('#tags').tagsInput({
  870. 'height': null,
  871. 'width': '530px',
  872. 'color': '#2d2d2d',
  873. 'placeholderColor': '#e0e0e0',
  874. 'useNativePlaceholder': true,
  875. 'defaultText': localization[globalInterfaceLanguage].addCategory,
  876. 'delimiter': ',',
  877. 'allowDelimiterInValue': true, // if true delimiter is escaped with '\' ('\' is escaped as '\\')
  878. 'trimInput': false,
  879. 'autocomplete_url': globalAddressbookList.getABCategories(true),
  880. 'autocomplete': {
  881. 'autoFocus': true,
  882. 'minLength': 0
  883. },
  884. 'onChange' : function(tag, tagImported)
  885. {
  886. // copy the array
  887. var xList=globalAddressbookList.getABCategories(true);
  888. var currentTags=$(this).val().splitCustom(',');
  889. for(var i=xList.length-1; i>=0; i--)
  890. {
  891. for(var j=0; j<currentTags.length; j++)
  892. if(xList[i] == currentTags[j])
  893. xList.splice(i, 1);
  894. }
  895. $('#tags_tag').autocomplete('option', 'source', xList);
  896. checkContactFormScrollBar();
  897. }
  898. });
  899. // initialize datepicker
  900. globalRefVcardEditor.find('input[data-type^="date_"]').focus(function(){initDatePicker($(this));});
  901. /*************************** BAD HACKS SECTION ***************************/
  902. if($.browser.msie && parseInt($.browser.version, 10)==10) /* IE 10 (because there are no more conditional comments) */
  903. globalRefVcardEditor.find('#tags_tag').css({'padding-top': '1px', 'padding-left': '1px'});
  904. /*************************** END OF BAD HACKS SECTION ***************************/
  905. globalRefVcardEditor.find('[data-type="org"]').autocomplete({'source': function(request, response){var matcher=RegExp($.ui.autocomplete.escapeRegex(request.term), 'i'); response($.grep(globalAddressbookList.getABCompanies(true), function(value){value=value.label || value.value || value; return matcher.test(value) || matcher.test(value.multiReplace(globalSearchTransformAlphabet));}));}, 'minLength': 0, 'change': function(){$('[data-type="department"]').autocomplete({'source': function(request, response){var matcher=RegExp($.ui.autocomplete.escapeRegex(request.term), 'i'); response($.grep(globalAddressbookList.getABCompanyDepartments($('#vCardEditor').find('[data-type="org"]').val()), function(value){value=value.label || value.value || value; return matcher.test(value) || matcher.test(value.multiReplace(globalSearchTransformAlphabet));}));}, 'minLength': 0})}});
  906. /*
  907. globalABListTop=globalRefABList.offset().top;
  908. globalABListLeft=globalRefABList.offset().left;
  909. // rewrite it and use:
  910. // var start=document.elementFromPoint(globalABListLeft, globalABListTop);
  911. globalLastScrollPos=0; // move to the main.js
  912. globalRefABList.scroll(function(e){
  913. globalRefABListTable.children('.ablist_header:visible').each(function(index, element){
  914. var headerWidth=$(element).outerWidth();
  915. var headerHeight=$(element).outerHeight();
  916. var floating_elem=$('#SystemCardDavMATE > .ablist_header');
  917. if(globalLastScrollPos<=globalRefABList.scrollTop()) // scrolling DOWN
  918. {
  919. var next_h=$(element).nextAll('.ablist_header:visible').first(); // next visible header
  920. if(next_h!=null && next_h.offset().top>globalABListTop) // only if it is below to #ABList do action
  921. {
  922. var cloned=$(element).clone();
  923. // do not create the floating header with the same text twice
  924. if(floating_elem.filter(':contains("'+jqueryEscapeSelector(cloned.text())+'")').length==0)
  925. {
  926. // parameters for the fixed element
  927. cloned.css({'top': globalABListTop, 'left': globalABListLeft, 'width': headerWidth, 'position': 'fixed', 'z-index': 1});
  928. // remove the previous floating header
  929. floating_elem.remove();
  930. // set the opacity back to standard value (item is invisible scrolled above the ABlist top)
  931. globalRefABListTable.children('.ablist_header').each(function(index,element){
  932. if($(element).css('opacity')=='0'){$(element).css('opacity',0.85);}
  933. });
  934. // set the element opacity to 0 and "replace" it with floating element above it
  935. $(element).css('opacity',0);
  936. cloned.appendTo('#SystemCardDavMATE');
  937. }
  938. // move the previous floating header UP
  939. if(next_h.offset().top<globalABListTop+headerHeight) // if next header offset is immediately below to top offset
  940. floating_elem.css('top',globalABListTop-(globalABListTop+headerHeight-next_h.offset().top));
  941. return false;
  942. }
  943. }
  944. else // scrolling UP
  945. {
  946. if($(element).offset().top>=globalABListTop)
  947. {
  948. var prev_h=$(element).prevAll('.ablist_header').first();
  949. if(prev_h!=null) // if there is a previous header in #ABList do action
  950. {
  951. var cloned=$(prev_h).clone();
  952. // do not create the floating header with the same text twice
  953. if(floating_elem.filter(':contains("'+jqueryEscapeSelector(cloned.text())+'")').length==0)
  954. {
  955. // parameters for the fixed element
  956. // cloned.css('top',globalABListTop-headerHeight);
  957. cloned.css({'top': Math.min(globalABListTop,$(element).offset().top-headerHeight), 'left': globalABListLeft, 'width': headerWidth, 'position': 'fixed', 'z-index': 1});
  958. // remove the previous floating header
  959. floating_elem.remove();
  960. // set the opacity back to standard value (item is invisible scrolled above the ABlist top)
  961. globalRefABListTable.children('.ablist_header').each(function(index,element){
  962. if($(element).css('opacity')=='0'){$(element).css('opacity',0.85);}
  963. });
  964. // set the previous element opacity to 0 and "replace" it with floating element above it
  965. $(prev_h).css('opacity',0);
  966. cloned.appendTo('#SystemCardDavMATE');
  967. }
  968. }
  969. // move the next floating header DOWN
  970. if(floating_elem.length!=0 && floating_elem.offset().top<globalABListTop)
  971. floating_elem.css('top',Math.min(globalABListTop,$(element).offset().top-headerHeight));
  972. return false;
  973. }
  974. }
  975. });
  976. globalLastScrollPos=globalRefABList.scrollTop();
  977. });
  978. */
  979. // CUSTOM PLACEHOLDER (initialization for the editor)
  980. globalRefVcardEditor.find('input[placeholder],textarea[placeholder]').placeholder();
  981. // enable autosize for textarea elements
  982. globalRefVcardEditor.find('textarea[data-type="value"]').autosize({defaultStyles: {height: '64', overflow: '', 'overflow-y': '', 'word-wrap': '', resize: 'none'}, callback: function(){checkContactFormScrollBar();}});
  983. if(inputLoadEmpty==true)
  984. $('#EditorBox').fadeTo(0, 1); /* 0 = no animation */
  985. return globalRefVcardEditor;
  986. }
  987. function animate_message(messageSelector, messageTextSelector, duration, operation)
  988. {
  989. if(operation==undefined)
  990. operation='+=';
  991. var height=$(messageTextSelector).height()+14;
  992. var animation=400;
  993. $(messageSelector).animate({'max-height': height+'px', height: (operation==undefined ? '+=' : operation)+height+'px'}, animation, function(){
  994. if(operation=='+=')
  995. {
  996. if(messageSelector=='#ABInMessageEditBox')
  997. {
  998. $(messageTextSelector).text(localization[globalInterfaceLanguage][globalDisableAnimationMessageHiding]);
  999. globalObjectLoading=false
  1000. globalDisableAnimationMessageHiding='';
  1001. }
  1002. else
  1003. setTimeout(function(){
  1004. animate_message(messageSelector, messageTextSelector, 0, '-=');
  1005. }, duration);
  1006. }
  1007. });
  1008. return duration+2*animation;
  1009. }
  1010. function show_editor_message(inputPosition, inputSetClass, inputMessage, inputDuration)
  1011. {
  1012. if(inputPosition==undefined || inputPosition=='in')
  1013. {
  1014. $('#ABContact').scrollTop(0);
  1015. messageSelector='#ABInMessage';
  1016. messageTextSelector='#ABInMessageText';
  1017. }
  1018. else
  1019. {
  1020. messageSelector='#ABMessage';
  1021. messageTextSelector='#ABMessageText';
  1022. }
  1023. $(messageTextSelector).attr('class',inputSetClass);
  1024. $(messageTextSelector).text(inputMessage);
  1025. return animate_message(messageSelector, messageTextSelector, inputDuration);
  1026. }
  1027. function set_address_country(inputSelectedAddressObj)
  1028. {
  1029. var selectedCountry=$(inputSelectedAddressObj).find('option').filter(':selected').attr('data-type');
  1030. var addressElement=$(inputSelectedAddressObj).closest('[data-type="\\%address"]');
  1031. // store the previous data + cleanup the data-addr-fields, placeholders and values
  1032. globalAddressElementOldData = {};
  1033. addressElement.find('[data-addr-fid]').each(
  1034. function(index, element)
  1035. {
  1036. var tmp=$(element).find('input');
  1037. var tmp_field_name=tmp.attr('data-addr-field');
  1038. if(tmp_field_name!=undefined && tmp_field_name!='') {
  1039. if(!globalAddressElementOldData.hasOwnProperty(tmp_field_name)) {
  1040. globalAddressElementOldData[tmp_field_name] = [];
  1041. }
  1042. globalAddressElementOldData[tmp_field_name].push({'value': tmp.val(), 'data-match': tmp.attr('data-match')});
  1043. }
  1044. if(tmp_field_name==='street') {
  1045. tmp.unbind('keyup.street');
  1046. }
  1047. tmp.attr({'data-addr-field': '', 'data-match': '', 'placeholder': ''}).unplaceholder(); // REMOVE CUSTOM PLACEHOLDER
  1048. tmp.val('');
  1049. // set address country "cleanup" hook
  1050. if(typeof(globalContactsExtAddrElemAfterCleanup)=='function')
  1051. globalContactsExtAddrElemAfterCleanup(element);
  1052. }
  1053. );
  1054. addressElement.find('[data-group="street"]').closest('tr[data-type="container"]').not(':first').remove();
  1055. addressElement.find('[data-group]').removeAttr('data-group');
  1056. if(addressTypes[selectedCountry]!=undefined)
  1057. for(var i=1;i<addressTypes[selectedCountry].length;i++)
  1058. {
  1059. if(addressTypes[selectedCountry][i]['type']=='input')
  1060. {
  1061. var tmp=addressElement.find('[data-addr-fid="'+jqueryEscapeSelector(addressTypes[selectedCountry][i]['fid'])+'"]').find('input');
  1062. tmp.attr('data-addr-field',addressTypes[selectedCountry][i]['data-addr-field']);
  1063. tmp.attr('placeholder',addressTypes[selectedCountry][i]['placeholder']);
  1064. if(addressTypes[selectedCountry][i]['data-addr-field']==='street') {
  1065. tmp.closest('tr[data-type="container"]').attr('data-group', 'street');
  1066. tmp.bind('keyup.street', function() {
  1067. var el = $(this);
  1068. var row = el.closest('tr[data-type="container"]');
  1069. var isLast = row.attr('data-group')!==row.next().attr('data-group');
  1070. if(isLast && el.val()) {
  1071. row.clone(true).insertAfter(row).find('input').val('');
  1072. }
  1073. });
  1074. }
  1075. // here we restore the data from globalAddressElementOldData variable
  1076. if(globalAddressElementOldData.hasOwnProperty(addressTypes[selectedCountry][i]['data-addr-field'])) {
  1077. for(var j=0; j<globalAddressElementOldData[addressTypes[selectedCountry][i]['data-addr-field']].length; j++) {
  1078. tmp = addressElement.find('[data-addr-fid="'+jqueryEscapeSelector(addressTypes[selectedCountry][i]['fid'])+'"]').find('input').last();
  1079. tmp.val(globalAddressElementOldData[addressTypes[selectedCountry][i]['data-addr-field']][j]['value']);
  1080. tmp.trigger('keyup.street');
  1081. };
  1082. }
  1083. }
  1084. else if(addressTypes[selectedCountry][i]['type']=='country')
  1085. {
  1086. var tmp=addressElement.find('[data-type="\\%country_container"]');
  1087. tmp.find('select').find('option[data-type]').prop('selected', false);
  1088. tmp.find('select').find('option[data-type="'+jqueryEscapeSelector(selectedCountry)+'"]').prop('selected', true);
  1089. // the country selector is in wrong container -> we need to move it
  1090. if(addressTypes[selectedCountry][i]['fid']!=tmp.closest('[data-addr-fid]').attr('data-addr-fid'))
  1091. $(addressElement).find('[data-addr-fid="'+jqueryEscapeSelector(addressTypes[selectedCountry][i]['fid'])+'"]').append(tmp);
  1092. }
  1093. // set address country "update" hook
  1094. if(typeof(globalContactsExtAddrElemAfterUpdate)=='function')
  1095. globalContactsExtAddrElemAfterUpdate(addressElement, addressTypes[selectedCountry][i]);
  1096. }
  1097. // hide the unused fields by changing the CSS
  1098. addressElement.find('[data-type="container"]').each(
  1099. function(index,element)
  1100. {
  1101. var found=0;
  1102. $(element).find('[data-addr-field]').each(
  1103. function(index,element)
  1104. {
  1105. if($(element).attr('data-addr-field')!='')
  1106. {
  1107. found=1;
  1108. return false;
  1109. }
  1110. }
  1111. );
  1112. if(found)
  1113. $(element).removeClass('element_no_display_af');
  1114. else
  1115. $(element).addClass('element_no_display_af');
  1116. }
  1117. );
  1118. // CUSTOM PLACEHOLDER (reinitialization due to possible placeholder value change)
  1119. addressElement.find('input[data-type="value"][placeholder],textarea[data-type="value"][placeholder]').placeholder();
  1120. }
  1121. function add_element(inputElementID, inputParentSelector, newElementSelector, inputAddClassSelector, inputDelClassSelector, newElementID) // note: newElementSelector is always used with .last()
  1122. {
  1123. // we assume that the new element is inputElementID.parent() to minimize then number of selectors!
  1124. var newElement=inputElementID.parent().clone().wrap('<div>'); // wrap('<div>') is used because we use .find() which not searches the "self"
  1125. // disable the "add" button on the current element (do not move above)
  1126. inputElementID.filter(inputAddClassSelector).css('visibility', 'hidden');
  1127. // CUSTOM PLACEHOLDER
  1128. // remove the "placeholder" data (custom placeholder label for IE)
  1129. newElement.find('label').remove();
  1130. newElement.find('[data-type="date_value"],[data-type="value"]').removeAttr('id', '').removeClass('placeholder-input');
  1131. // unselect each selected element
  1132. newElement.find('option').prop('selected', false);
  1133. // remove the form values
  1134. newElement.find('[data-type$="value"], [data-type$="date_value"]').val('');
  1135. // hide custom types
  1136. newElement.find('[data-type="custom_span"]').css('display', 'none');
  1137. // get the current data-id value
  1138. var prevID=newElement.attr("data-id");
  1139. // add the new data-id value
  1140. newElement.attr("data-id", newElementID);
  1141. // add element "before insert" hook
  1142. if(typeof(globalContactsExtAddElemBeforeInsert)=='function')
  1143. globalContactsExtAddElemBeforeInsert(newElement);
  1144. // add the new element (with enabled "add" button) + store the reference to the current element
  1145. var tmpRef=inputElementID.parent().after(newElement);
  1146. // enable the "del" button on this and the previous element
  1147. tmpRef.next().addBack().find(inputDelClassSelector).css('visibility', '');
  1148. // now we need a reference to the new element
  1149. var tmpRef=tmpRef.next();
  1150. // CUSTOM PLACEHOLDER
  1151. // enable custom placeholder support (it is enabled only if needed)
  1152. tmpRef.find('input[data-type="value"][placeholder], input[data-type="date_value"][placeholder],textarea[data-type="value"][placeholder]').placeholder();
  1153. // enable autosize for textarea elements
  1154. tmpRef.find('textarea[data-type="value"]').autosize({defaultStyles: {height: '64', overflow: '', 'overflow-y': '', 'word-wrap': '', resize: 'none'}, callback: function(){checkContactFormScrollBar();}});
  1155. //bind datepicker
  1156. if(tmpRef.find('input[data-type="date_value"]').hasClass('hasDatepicker'))
  1157. tmpRef.find('input[data-type="date_value"]').removeClass('hasDatepicker');
  1158. if(tmpRef.find('input[data-type="date_value"]').parent().find('img').css('display')!='none')
  1159. tmpRef.find('input[data-type="date_value"]').parent().find('img').css('display','none')
  1160. tmpRef.find('input[data-type="date_value"]').focus(function(){initDatePicker($(this));});
  1161. // bind events
  1162. var tmp_arr=['[data-type="\\%phone"]', '[data-type="\\%email"]', '[data-type="\\%url"]', '[data-type="\\%date"]', '[data-type="\\%person"]', '[data-type="\\%im"]', '[data-type="\\%profile"]', '[data-type="\\%address"]'];
  1163. if(tmp_arr.indexOf(inputParentSelector)!=-1)
  1164. {
  1165. tmpRef.find('[data-type="\\%add"] input').data('customSelector', inputParentSelector).click(function(){add_element($(this).parent(), $(this).data('customSelector'), $(this).data('customSelector'), '[data-type="\\%add"]','[data-type="\\%del"]', globalABEditorCounter[$(this).data('customSelector')]++);checkContactFormScrollBar();});
  1166. tmpRef.find('[data-type="\\%del"] input').data('customSelector', inputParentSelector).click(function(){del_element($(this).parent(), $(this).data('customSelector'), '[data-type="\\%add"]','[data-type="\\%del"]');checkContactFormScrollBar();});
  1167. if(typeof globalContactAutoExpand=='undefined' || globalContactAutoExpand!=false)
  1168. {
  1169. tmpRef.find('input[type="text"]').bind('keyup', function() {
  1170. var el = $(this);
  1171. var row = el.closest('tr[data-type^="%"]');
  1172. var isLast = row.attr('data-type')!==row.next().attr('data-type');
  1173. if(isLast && el.val()) {
  1174. row.find('[data-type="\\%add"] input').trigger('click');
  1175. }
  1176. });
  1177. }
  1178. // one special thing for address
  1179. if(inputParentSelector=='[data-type="\\%address"]' && tmpRef.attr('data-type')=='%address')
  1180. tmpRef.find('[data-type="country_type"]').change(function(){set_address_country(this);checkContactFormScrollBar();});
  1181. }
  1182. if(inputParentSelector=='[data-type="\\%address"]')
  1183. {
  1184. // execute the "autoselect"
  1185. var tmp=inputElementID.closest(inputParentSelector).next();
  1186. var tmp_select=tmp.find('[data-autoselect]').attr('data-autoselect');
  1187. if(tmp_select!=null)
  1188. {
  1189. tmp.find('[data-type="country_type"]').children('[data-type="'+jqueryEscapeSelector(tmp_select)+'"]').prop('selected', true);
  1190. tmp.find('[data-autoselect]').change();
  1191. }
  1192. }
  1193. tmpRef.find('[data-type="custom_value"]').bind('keyup change', function(){
  1194. $(this).parent().find('[data-type="invalid"]').css('display', (vCard.pre['custom_type'].test($(this).val()) ? 'none' : 'inline'));
  1195. });
  1196. if(typeof(globalContactsExtAddElemAfterInsert)=='function')
  1197. globalContactsExtAddElemAfterInsert(tmpRef, inputDelClassSelector, prevID);
  1198. return true;
  1199. }
  1200. function del_element(inputElementID, inputParentSelector, inputAddClassSelector, inputDelClassSelector)
  1201. {
  1202. // all elements except the last can be removed
  1203. if(inputElementID.closest(inputParentSelector).siblings(inputParentSelector).length>0)
  1204. {
  1205. inputElementID.closest(inputParentSelector).remove();
  1206. // enable the "add" button on last element
  1207. $(inputParentSelector).last().find(inputAddClassSelector).css('visibility', '');
  1208. // hide the "del" button if only one element is present (we maybe change this in future)
  1209. if($(inputParentSelector).length==1)
  1210. $(inputParentSelector).last().find(inputDelClassSelector).css('visibility', 'hidden');
  1211. }
  1212. else // currently not used because the "-" button is hidden on the last element (we maybe change this in future)
  1213. inputElementID.closest(inputParentSelector).find('input[data-type="value"]').val('');
  1214. }
  1215. /* BEGIN image manipulation */
  1216. function process_image(event)
  1217. {
  1218. event.stopPropagation();
  1219. event.preventDefault();
  1220. // allow image manipulation only if the editor is in "edit" state
  1221. if($('#vCardEditor').attr('data-editor-state')!="edit")
  1222. return false;
  1223. if(typeof event.originalEvent.dataTransfer!='undefined')
  1224. var files=event.originalEvent.dataTransfer.files; // fileList object from drag&drop
  1225. else
  1226. var files=event.originalEvent.target.files; // fileList object from input type file
  1227. // files is a FileList of File objects. List some properties.
  1228. for(var i=0;i<files.length;i++) // we handle only the first picture here ... (see below)
  1229. {
  1230. // only process image files
  1231. if(!files[i].type.match(/image/i))
  1232. continue;
  1233. // do not accept images bigger than 64KiB
  1234. // if(files[i].size>65536)
  1235. // continue;
  1236. // show the image "delete" button
  1237. $('#reset_img').css('display', 'inline');
  1238. // remove the template related to previous image (start with clean one)
  1239. vCard.tplM['contentline_PHOTO'][0]=null;
  1240. var reader=new FileReader();
  1241. // closure to capture the file information.
  1242. reader.onload=(function(theFile){
  1243. return function(e){
  1244. //escape(files[i].name), files[i].type, files[i].size, files[i].lastModifiedDate
  1245. var newImg=new Image();
  1246. newImg.src=e.target.result;
  1247. newImg.onload=function(){
  1248. loadImage(this);
  1249. };
  1250. };
  1251. })(files[i]);
  1252. reader.readAsDataURL(files[i]);
  1253. break; // we handle only the first picture here ...
  1254. }
  1255. $('#photoURL, #photoURLHidden').val('');
  1256. }
  1257. /* END image manipulation */
  1258. function hideNotVisibleMessage()
  1259. {
  1260. globalAddressbookList.contactToReload=null;
  1261. animate_message('#ABInMessageEditBox', '#ABInMessageTextEditBox', 0, '-=');
  1262. $('#ABInMessageEditBox').css('display','');
  1263. }
  1264. function initSearchCardDav()
  1265. {
  1266. if(globalQs==null)
  1267. {
  1268. $('#SearchBox').find('input[data-type="search"]').keyup(function(){
  1269. globalAddressbookList.contactToReload=null
  1270. });
  1271. globalQs=$('#SearchBox').find('input[data-type="search"]').quicksearch(globalAddressbookList.contacts,
  1272. {
  1273. delay: 250,
  1274. hide: function(){
  1275. var tmp=$(this)[0];
  1276. if(!tmp.headerOnly)
  1277. tmp.search_hide=true;
  1278. },
  1279. show: function(){
  1280. var tmp=$(this)[0];
  1281. if(!tmp.headerOnly)
  1282. tmp.search_hide=false;
  1283. },
  1284. prepareQuery: function (val){
  1285. return val.multiReplace(globalSearchTransformAlphabet).toLowerCase().split(' ');
  1286. },
  1287. onBefore: function(){
  1288. if($('#SearchBox').find('input[data-type="search"]').val()=='')
  1289. $('#SearchBox').find('img[data-type="reset"]').css('display','none');
  1290. else
  1291. $('#SearchBox').find('img[data-type="reset"]').css('display','');
  1292. },
  1293. onAfter: function(){
  1294. globalAddressbookList.applyABFilter(dataGetChecked('#ResourceCardDAVList'),false);
  1295. // XXX maybe this was the reason for data-filter-url?
  1296. // globalAddressbookList.applyABFilter(globalRefAddContact.attr('data-filter-url'),false);
  1297. // maybe useful for somebody
  1298. // if((selected_contact=globalRefABListTable.find('.ablist_item_selected')).length==1)
  1299. // globalRefABList.scrollTop(globalRefABList.scrollTop()+selected_contact.offset().top-globalRefABList.offset().top-globalRefABList.height()*globalKBNavigationPaddingRate);
  1300. }
  1301. });
  1302. }
  1303. }
  1304. function initKbAddrNavigation()
  1305. {
  1306. $(document.documentElement).keyup(function(event)
  1307. {
  1308. if(typeof globalActiveApp=='undefined' || globalActiveApp!='CardDavMATE')
  1309. return true;
  1310. if(globalActiveApp=='CardDavMATE' && globalObjectLoading==true)
  1311. {
  1312. event.preventDefault();
  1313. return true;
  1314. }
  1315. //if($('#SystemCardDavMATE').css('display')!='none' && $('#ABListLoader').css('display')=='none' && $('#ABListOverlay').css('display')=='none' && !$('input[data-type="search"]').is(':focus'))
  1316. /* XXX - System display:none changes */
  1317. if($('#SystemCardDavMATE').css('visibility')!='hidden' && isCardDAVLoaded && $('#ABListOverlay').css('display')=='none' && !$('input[data-type="search"]').is(':focus'))
  1318. {
  1319. // 37 = left, 38 = up, 39 = right, 40 = down
  1320. var selected_contact=null, next_contact=null;
  1321. if((selected_contact=globalRefABListTable.find('.ablist_item_selected')).length==1)
  1322. {
  1323. if(event.keyCode == 38 && (next_contact=selected_contact.prevAll('.ablist_item').filter(':visible').first()).attr('data-id')!=undefined || event.keyCode == 40 && (next_contact=selected_contact.nextAll('.ablist_item').filter(':visible').first()).attr('data-id')!=undefined)
  1324. globalAddressbookList.loadContactByUID(next_contact.attr('data-id'));
  1325. }
  1326. }
  1327. });
  1328. $(document.documentElement).keydown(function(event)
  1329. {
  1330. if(typeof globalActiveApp=='undefined' || globalActiveApp!='CardDavMATE')
  1331. return true;
  1332. if(globalActiveApp=='CardDavMATE' && globalObjectLoading==true)
  1333. {
  1334. event.preventDefault();
  1335. return true;
  1336. }
  1337. //if($('#SystemCardDavMATE').css('display')!='none' && $('#ABListLoader').css('display')=='none' && $('#ABListOverlay').css('display')=='none' && !$('input[data-type="search"]').is(':focus'))
  1338. /* XXX - System display:none changes */
  1339. if($('#SystemCardDavMATE').css('visibility')!='hidden' && isCardDAVLoaded && $('#ABListOverlay').css('display')=='none' && !$('input[data-type="search"]').is(':focus'))
  1340. {
  1341. // 37 = left, 38 = up, 39 = right, 40 = down
  1342. var selected_contact=null, next_contact=null;
  1343. if((selected_contact=globalRefABListTable.find('.ablist_item_selected')).length==1)
  1344. {
  1345. var wrapperRef = $('.ablist_table_wrapper');
  1346. if(event.keyCode == 38 && (next_contact=selected_contact.prevAll('.ablist_item').filter(':visible').first()).attr('data-id')!=undefined || event.keyCode == 40 && (next_contact=selected_contact.nextAll('.ablist_item').filter(':visible').first()).attr('data-id')!=undefined)
  1347. {
  1348. switch(event.keyCode)
  1349. {
  1350. case 38:
  1351. event.preventDefault();
  1352. if(wrapperRef.scrollTop()>wrapperRef.scrollTop()+next_contact.offset().top-wrapperRef.offset().top-wrapperRef.height()*globalKBNavigationPaddingRate)
  1353. wrapperRef.scrollTop(wrapperRef.scrollTop()+next_contact.offset().top-wrapperRef.offset().top-wrapperRef.height()*globalKBNavigationPaddingRate);
  1354. else if(wrapperRef.scrollTop()<wrapperRef.scrollTop()+next_contact.offset().top+next_contact.height()-wrapperRef.offset().top-wrapperRef.height()*(1-globalKBNavigationPaddingRate)) /* contact invisible (scrollbar moved) */
  1355. wrapperRef.scrollTop(wrapperRef.scrollTop()+next_contact.offset().top+next_contact.height()-wrapperRef.offset().top-wrapperRef.height()*(1-globalKBNavigationPaddingRate));
  1356. else
  1357. return false;
  1358. break;
  1359. case 40:
  1360. event.preventDefault();
  1361. if(wrapperRef.scrollTop()<wrapperRef.scrollTop()+next_contact.offset().top+next_contact.height()-wrapperRef.offset().top-wrapperRef.height()*(1-globalKBNavigationPaddingRate)) /* contact invisible (scrollbar moved) */
  1362. wrapperRef.scrollTop(wrapperRef.scrollTop()+next_contact.offset().top+next_contact.height()-wrapperRef.offset().top-wrapperRef.height()*(1-globalKBNavigationPaddingRate));
  1363. else if(wrapperRef.scrollTop()>wrapperRef.scrollTop()+next_contact.offset().top-wrapperRef.offset().top-wrapperRef.height()*globalKBNavigationPaddingRate)
  1364. wrapperRef.scrollTop(wrapperRef.scrollTop()+next_contact.offset().top-wrapperRef.offset().top-wrapperRef.height()*globalKBNavigationPaddingRate);
  1365. else
  1366. return false;
  1367. break;
  1368. default:
  1369. break;
  1370. }
  1371. }
  1372. else // no previous contact and up pressed || no next contact and down pressed
  1373. {
  1374. switch(event.keyCode)
  1375. {
  1376. case 38:
  1377. wrapperRef.scrollTop(0);
  1378. break;
  1379. case 40:
  1380. wrapperRef.scrollTop(wrapperRef.prop('scrollHeight'));
  1381. break;
  1382. default:
  1383. break;
  1384. }
  1385. }
  1386. }
  1387. }
  1388. });
  1389. }
  1390. function initDatePicker(inputObject)
  1391. {
  1392. if(!inputObject.hasClass('hasDatepicker'))
  1393. {
  1394. inputObject.datepicker({
  1395. disabled: inputObject.prop('readonly') || inputObject.prop('disabled'),
  1396. showMonthAfterYear: true,
  1397. prevText: '',
  1398. nextText: '',
  1399. monthNamesShort: ['01','02','03','04','05','06','07','08','09','10','11','12'],
  1400. dateFormat: globalSettings.datepickerformat.value,
  1401. defaultDate: '-'+Math.round(30*365.25-1),
  1402. minDate: '-120y',
  1403. maxDate: '+0',
  1404. yearRange: 'c-120:+0',
  1405. firstDay: globalSettings.datepickerfirstdayofweek.value,
  1406. weekendDays: globalSettings.weekenddays.value,
  1407. changeMonth: true,
  1408. changeYear: true,
  1409. showAnim: '',
  1410. afterUpdate: function(inst)
  1411. {
  1412. /*************************** BAD HACKS SECTION ***************************/
  1413. // IE and FF datepicker selectbox problem fix
  1414. if($.browser.msie || $.browser.mozilla)
  1415. {
  1416. var calendar=inst.dpDiv;
  1417. setTimeout(function(){
  1418. if($.browser.msie && parseInt($.browser.version, 10)==10) /* IE 10 */
  1419. calendar.find('select').css({'padding-top': '1px', 'padding-left': '0px', 'padding-right': '0px'});
  1420. var newSVG=$(SVG_select).attr('data-type', 'select_icon').css({'pointer-events': 'none', 'z-index': '1', 'display': 'inline', 'margin-left': '-19px', 'vertical-align': 'top', 'background-color': '#ffffff'}); // background-color = stupid IE9 bug
  1421. calendar.find('select').after($($('<div>').append($(newSVG).clone()).html()));
  1422. },1);
  1423. }
  1424. else if(navigator.platform.toLowerCase().indexOf('win')==0 && $.browser.webkit && !!window.chrome) /* Chrome on Windows */
  1425. {
  1426. var calendar=inst.dpDiv;
  1427. setTimeout(function(){ calendar.find('select').css({'padding-left': '0px', 'padding-right': '13px'}); },1);
  1428. }
  1429. /*************************** END OF BAD HACKS SECTION ***************************/
  1430. },
  1431. beforeShow: function(input, inst) // set the datepicker value if the date is out of range (min/max)
  1432. {
  1433. inst.dpDiv.removeClass('ui-datepicker-simple');
  1434. var valid=true;
  1435. try {var currentDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, inputObject.val())}
  1436. catch (e) {valid=false}
  1437. if(valid==true && currentDate!=null)
  1438. {
  1439. var minDateText=inputObject.datepicker('option', 'dateFormat', globalSettings.datepickerformat.value).datepicker('option', 'minDate');
  1440. var maxDateText=inputObject.datepicker('option', 'dateFormat', globalSettings.datepickerformat.value).datepicker('option', 'maxDate');
  1441. var minDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, minDateText);
  1442. var maxDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, maxDateText);
  1443. if(currentDate<minDate)
  1444. inputObject.val(minDateText);
  1445. else if(currentDate>maxDate)
  1446. inputObject.val(maxDateText);
  1447. }
  1448. // Timepicker hack (prevent IE to re-open the datepicker on date click + focus)
  1449. var index=inputObject.attr("data-type");
  1450. var d = new Date();
  1451. if(globalTmpTimePickerHackTime[index]!=undefined && d.getTime()-globalTmpTimePickerHackTime[index]<200)
  1452. return false;
  1453. },
  1454. onClose: function(dateText, inst) // set the datepicker value if the date is out of range (min/max) and reset the value to proper format (for example 'yy-mm-dd' allows '2000-1-1' -> we need to reset the value to '2000-01-01')
  1455. {
  1456. var valid=true;
  1457. try {var currentDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, dateText)}
  1458. catch (e) {valid=false}
  1459. if(valid==true && currentDate!=null)
  1460. {
  1461. var minDateText=inputObject.datepicker('option', 'dateFormat', globalSettings.datepickerformat.value).datepicker('option', 'minDate');
  1462. var maxDateText=inputObject.datepicker('option', 'dateFormat', globalSettings.datepickerformat.value).datepicker('option', 'maxDate');
  1463. var minDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, minDateText);
  1464. var maxDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, maxDateText);
  1465. if(currentDate<minDate)
  1466. inputObject.val(minDateText);
  1467. else if(currentDate>maxDate)
  1468. inputObject.val(maxDateText);
  1469. else
  1470. inputObject.val($.datepicker.formatDate(globalSettings.datepickerformat.value, currentDate));
  1471. }
  1472. // Timepicker hack (prevent IE to re-open the datepicker on date click + focus)
  1473. var index=inputObject.attr("data-type");
  1474. var d = new Date();
  1475. globalTmpTimePickerHackTime[index]=d.getTime();
  1476. inputObject.focus();
  1477. if(inputObject.closest('tr').attr('data-attr-name')==='X-ABDATE') {
  1478. inputObject.trigger('keyup');
  1479. }
  1480. }
  1481. });
  1482. inputObject.mousedown(function(){
  1483. if(inputObject.datepicker('widget').css('display')=='none')
  1484. inputObject.datepicker('show');
  1485. else
  1486. inputObject.datepicker('hide');
  1487. });
  1488. inputObject.on('keydown', function(event){
  1489. // show datepicker on keydown (up/down/left/right) but only if it not causes cursor position move
  1490. if(this.selectionStart!=undefined && this.selectionStart!=-1)
  1491. if(((event.which==38 || event.which==37) && this.selectionStart==0) || ((event.which==40 || event.which==39) && this.selectionStart==$(this).val().length))
  1492. {
  1493. if(inputObject.datepicker('widget').css('display')=='none')
  1494. inputObject.datepicker('show');
  1495. else
  1496. inputObject.datepicker('hide');
  1497. }
  1498. });
  1499. inputObject.blur(function(event){
  1500. // handle onblur event because datepicker can be already closed
  1501. // note: because onblur is called more than once we can handle it only if there is a value change!
  1502. var valid=true;
  1503. try {var currentDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, inputObject.val())}
  1504. catch (e) {valid=false}
  1505. if(valid==true && inputObject.val()!=$.datepicker.formatDate(globalSettings.datepickerformat.value, currentDate))
  1506. {
  1507. var minDateText=inputObject.datepicker('option', 'dateFormat', globalSettings.datepickerformat.value).datepicker('option', 'minDate');
  1508. var maxDateText=inputObject.datepicker('option', 'dateFormat', globalSettings.datepickerformat.value).datepicker('option', 'maxDate');
  1509. var minDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, minDateText);
  1510. var maxDate=$.datepicker.parseDate(globalSettings.datepickerformat.value, maxDateText);
  1511. if(currentDate<minDate)
  1512. inputObject.val(minDateText);
  1513. else if(currentDate>maxDate)
  1514. inputObject.val(maxDateText);
  1515. else
  1516. inputObject.val($.datepicker.formatDate(globalSettings.datepickerformat.value, currentDate));
  1517. }
  1518. });
  1519. inputObject.on('keyup change', function(){
  1520. if(!$(this).prop('readonly') && !$(this).prop('disabled'))
  1521. {
  1522. var valid=true;
  1523. if($(this).val()!='')
  1524. {
  1525. try {$.datepicker.parseDate(globalSettings.datepickerformat.value, $(this).val())}
  1526. catch (e) {valid=false}
  1527. }
  1528. if(valid)
  1529. $(this).parent().find('img').css('display','none');
  1530. else
  1531. $(this).parent().find('img').css('display','inline');
  1532. }
  1533. });
  1534. // show the datepicker after the initialization
  1535. inputObject.datepicker('show');
  1536. }
  1537. }
  1538. function checkForVcardGroups(contactUID)
  1539. {
  1540. if($('#vCardEditor').attr('data-url')==contactUID)
  1541. {
  1542. var collUID= contactUID.replace(RegExp('[^/]*$'),'');
  1543. var select_elem=$('#vCardEditor').find('[data-attr-name="_DEST_"]').find('[data-type="'+jqueryEscapeSelector(collUID)+'"]');
  1544. if(select_elem.length==1)
  1545. {
  1546. var vGroupC = globalAddressbookList.getMyContactGroups(contactUID).length;
  1547. if(vGroupC>1)
  1548. select_elem.text(localization[globalInterfaceLanguage].txtVcardGroupsTextMulti.replace('%coll%',globalResourceCardDAVList.getCollectionByUID(collUID).displayvalue).replace('%n%',vGroupC));
  1549. else if(vGroupC==1)
  1550. select_elem.text(localization[globalInterfaceLanguage].txtVcardGroupsTextSingle.replace('%coll%',globalResourceCardDAVList.getCollectionByUID(collUID).displayvalue));
  1551. }
  1552. }
  1553. }
  1554. function checkContactFormScrollBar()
  1555. {
  1556. var baseWidth = 582;
  1557. var scrollWidth = $('#EditorBox').length ? $('#ABContact').outerWidth() - $('#EditorBox').outerWidth() : 0;
  1558. var previousWidth = parseInt($('#ABList').css('right'), 10);
  1559. var newWidth = baseWidth+scrollWidth;
  1560. if(previousWidth===newWidth)
  1561. return true;
  1562. $('.collection_d, #SearchBox, #ABList').css('right', newWidth);
  1563. $('#ABListOverlay').css('right', newWidth+1);
  1564. $('.contact_d, #ABMessage, #ABContactOverlay').width(newWidth);
  1565. $('#ABContactColor').css('right', newWidth-3);
  1566. $('#ABContact').width(newWidth-3);
  1567. var columnLengths = [];
  1568. for(var i=0; i<getDataColumnCount(); i++) {
  1569. columnLengths.push([]);
  1570. }
  1571. globalRefABListTable.children('.ablist_item:visible').each(function() {
  1572. $(this).children().slice(globalFixedContactDataColumnsCount).each(function(ind) {
  1573. columnLengths[ind].push($(this).text().length);
  1574. });
  1575. });
  1576. setDataColumnsWidth(columnLengths);
  1577. }
  1578. function extendDestSelect(selGroup)
  1579. {
  1580. if($('#vCardEditor').attr('data-editor-state')=='edit')
  1581. return false;
  1582. var dest = $('[data-attr-name="_DEST_"]');
  1583. $('#ExtendedDest').remove();
  1584. var extendedDest = $('<div id="ExtendedDest">');
  1585. var destSelected = dest.children(':selected');
  1586. var header = null;
  1587. var headerShown = false;
  1588. var currentGroups = typeof $('#vCardEditor').attr('data-vcard-uid')=='undefined' ? [] : globalAddressbookList.getMyContactGroups($('#vCardEditor').attr('data-url'));
  1589. dest.parent().after(extendedDest);
  1590. for(var i=0; i<globalResourceCardDAVList.collections.length; i++) {
  1591. var resource = globalResourceCardDAVList.collections[i];
  1592. if(typeof resource.headerOnly!='undefined' && resource.headerOnly) {
  1593. header = resource;
  1594. headerShown = false;
  1595. }
  1596. else if(typeof resource.makeLoaded!='undefined' && resource.makeLoaded) {
  1597. if(!headerShown) {
  1598. $('<div>').addClass('extended_dest_header').text(header.displayvalue).appendTo(extendedDest);
  1599. headerShown = true;
  1600. }
  1601. var itemEl = $('<div>').addClass('extended_dest_item');
  1602. var resourceEl = $('<div>').addClass('extended_dest_resource').text(resource.displayvalue);
  1603. var groupContEl = $('<div>').addClass('extended_dest_group_container');
  1604. $('<input>').attr({'type':'checkbox','data-id':resource.uid})
  1605. .prop('checked',resource.uid==destSelected.attr('data-type'))
  1606. .change(function(){
  1607. if($(this).prop('checked')) {
  1608. var newCollection = globalResourceCardDAVList.getCollectionByUID($(this).attr('data-id'));
  1609. $(this).parent().parent().siblings().find('input[type="checkbox"]').prop('checked',false);
  1610. dest.children('[data-type="'+newCollection.uid+'"]').prop('selected',true).text(newCollection.displayvalue);
  1611. $('#ABContactColor').css('background-color',newCollection.color);
  1612. }
  1613. else
  1614. $(this).prop('checked',true);
  1615. })
  1616. .prependTo(resourceEl);
  1617. $('<div>').addClass('extended_dest_resource_color').css('background-color',resource.color).prependTo(resourceEl);
  1618. for(var j=0; j<globalAddressbookList.vcard_groups[resource.uid].length; j++) {
  1619. var group = globalAddressbookList.vcard_groups[resource.uid][j];
  1620. var groupEl = $('<div>').addClass('extended_dest_group').text(group.displayvalue);
  1621. $('<input>').attr({'type':'checkbox','data-id':group.uid})
  1622. .prop('checked',currentGroups.indexOf(group.uid)!=-1 || typeof selGroup!= 'undefined' && selGroup==group.uid)
  1623. .change(function(){
  1624. var groupCount = $(this).parent().parent().find('input[type="checkbox"]:checked').length;
  1625. var newCollectionUID = $(this).parent().parent().prev().children('input[type="checkbox"]').attr('data-id');
  1626. var newCollection = globalResourceCardDAVList.getCollectionByUID(newCollectionUID);
  1627. if(groupCount>1)
  1628. dest.children('[data-type="'+newCollectionUID+'"]').text(localization[globalInterfaceLanguage].txtVcardGroupsTextMulti.replace('%coll%',newCollection.displayvalue).replace('%n%',groupCount));
  1629. else if(groupCount==1)
  1630. dest.children('[data-type="'+newCollectionUID+'"]').text(localization[globalInterfaceLanguage].txtVcardGroupsTextSingle.replace('%coll%',newCollection.displayvalue));
  1631. else
  1632. dest.children('[data-type="'+newCollectionUID+'"]').text(newCollection.displayvalue);
  1633. if($(this).prop('checked')) {
  1634. $(this).parent().parent().prev().children('input[type="checkbox"]').prop('checked',true);
  1635. $(this).parent().parent().parent().siblings().find('input[type="checkbox"]').prop('checked',false);
  1636. dest.children('[data-type="'+newCollectionUID+'"]').prop('selected',true);
  1637. $('#ABContactColor').css('background-color',newCollection.color);
  1638. }
  1639. })
  1640. .prependTo(groupEl);
  1641. $('<div>').addClass('extended_dest_group_color').css('background-color',group.color).prependTo(groupEl);
  1642. groupEl.appendTo(groupContEl);
  1643. }
  1644. resourceEl.appendTo(itemEl);
  1645. groupContEl.appendTo(itemEl);
  1646. itemEl.appendTo(extendedDest);
  1647. }
  1648. }
  1649. dest.mousedown(function(e){
  1650. e.stopPropagation();
  1651. e.preventDefault();
  1652. this.blur();
  1653. if(extendedDest.height()>0) {
  1654. dest.removeClass('inverse_select');
  1655. /*************************** BAD HACKS SECTION ***************************/
  1656. if($.browser.msie || $.browser.mozilla)
  1657. {
  1658. var newSVG=$(SVG_select).attr('data-type', 'select_icon').css({'pointer-events': 'none', 'z-index': '1', 'display': 'inline', 'margin-left': '-19px', 'vertical-align': 'top', 'background-color': '#ffffff'}); // background-color = stupid IE9 bug
  1659. dest.parent().find('svg[data-type="select_icon"]').replaceWith($('<div>').append($(newSVG).clone()).html());
  1660. }
  1661. /*************************** END OF BAD HACKS SECTION ***************************/
  1662. extendedDest.animate({'height':0},200);
  1663. $('html').unbind('mousedown');
  1664. }
  1665. else {
  1666. dest.addClass('inverse_select');
  1667. /*************************** BAD HACKS SECTION ***************************/
  1668. if($.browser.msie || $.browser.mozilla)
  1669. {
  1670. var newSVG=$(SVG_select_inv).attr('data-type', 'select_icon').css({'pointer-events': 'none', 'z-index': '1', 'display': 'inline', 'margin-left': '-19px', 'vertical-align': 'top', 'background-color': '#ffffff'}); // background-color = stupid IE9 bug
  1671. dest.parent().find('svg[data-type="select_icon"]').replaceWith($('<div>').append($(newSVG).clone()).html());
  1672. }
  1673. /*************************** END OF BAD HACKS SECTION ***************************/
  1674. extendedDest.animate({'height':164},200);
  1675. $('html').mousedown(function(e){
  1676. if(e.target.id=='ExtendedDest' || $.contains(document.getElementById('ExtendedDest'),e.target))
  1677. return true;
  1678. dest.removeClass('inverse_select');
  1679. /*************************** BAD HACKS SECTION ***************************/
  1680. if($.browser.msie || $.browser.mozilla)
  1681. {
  1682. var newSVG=$(SVG_select).attr('data-type', 'select_icon').css({'pointer-events': 'none', 'z-index': '1', 'display': 'inline', 'margin-left': '-19px', 'vertical-align': 'top', 'background-color': '#ffffff'}); // background-color = stupid IE9 bug
  1683. dest.parent().find('svg[data-type="select_icon"]').replaceWith($('<div>').append($(newSVG).clone()).html());
  1684. }
  1685. /*************************** END OF BAD HACKS SECTION ***************************/
  1686. extendedDest.animate({'height':0},200);
  1687. $('html').unbind('mousedown');
  1688. });
  1689. }
  1690. });
  1691. }
  1692. /*
  1693. $(document).on("mouseover", "#vCardEditor .ablist_item", function() {
  1694. if(!$(this).is('.ui-draggable') && (typeof globalDisableDragAndDrop=='undefined' || globalDisableDragAndDrop!=true))
  1695. {
  1696. $(this).draggable({
  1697. delay: 250,
  1698. revert: 'invalid',
  1699. scroll: false,
  1700. opacity: 0.8,
  1701. stack: '#SystemCardDavMATE',
  1702. containment: '#SystemCardDavMATE',
  1703. appendTo: 'body',
  1704. start: function( event, ui ){
  1705. // disallow on read-only collection
  1706. if(globalResourceCardDAVList.getCollectionPrivByUID($(this).attr('data-id').replace(RegExp('[^/]*$'),''))==true)
  1707. return false;
  1708. },
  1709. helper: function(){
  1710. $('#ResourceCardDAVList').find('.resourceCardDAV.ui-droppable').droppable( 'option', 'accept', false);
  1711. $('#ResourceCardDAVList').find('.group.ui-droppable').droppable( 'option', 'accept', false);
  1712. $('#ResourceCardDAVList').find('.resourceCardDAV[data-id!='+jqueryEscapeSelector($(this).attr('data-id').replace(RegExp('[^/]+$'),''))+'].ui-droppable').droppable( 'option', 'accept', '.ablist_item');
  1713. var myContactGroups=globalAddressbookList.getMyContactGroups($(this).attr('data-id'));
  1714. $('#ResourceCardDAVList').find('.group[data-id^='+jqueryEscapeSelector($(this).attr('data-id').replace(RegExp('[^/]+$'),''))+'].ui-droppable').not('.resourceCardDAV_selected').each(function(index, element){
  1715. if(myContactGroups.indexOf($(element).attr('data-id'))==-1)
  1716. $(element).droppable( 'option', 'accept', '.ablist_item');
  1717. });
  1718. var tmp=$(this).clone();
  1719. tmp.addClass('ablist_item_dragged');
  1720. // we cannot use .css() here, because we need to add !important (problem with Gecko based browsers)
  1721. var tmp_style='max-width: '+$(this).outerWidth()+'px;';
  1722. if($(this).css('background-image')!='none')
  1723. tmp_style+='background-image: url(images/company_s_w.svg) !important;';
  1724. tmp.attr('style', tmp_style);
  1725. return tmp;
  1726. }
  1727. });
  1728. }
  1729. });
  1730. */
  1731. function setDataColumnsWidth(cache) {
  1732. if(!globalRefABListTableCols && !globalRefABListInnerTableCols) {
  1733. return true;
  1734. }
  1735. // remove gutter
  1736. $('.ablist_table_gutter').remove();
  1737. // clear old column widths
  1738. globalRefABListTableCols.width('');
  1739. globalRefABListInnerTableCols.width('');
  1740. // use cached column values to compute new column widths
  1741. var characterWidth = 9; // gross approximation
  1742. var lastColumn = null;
  1743. var lastInnerColumn = null;
  1744. var scrollWidth = $('.ablist_table_wrapper').innerWidth() - globalRefABListTable.outerWidth();
  1745. var reservedWidth = 0;
  1746. globalRefABListTable.children('.ablist_item').first().children().slice(0, globalFixedContactDataColumnsCount).each(function() {
  1747. reservedWidth += $(this).width();
  1748. });
  1749. var availableWidth;
  1750. var maxWidth;
  1751. availableWidth = maxWidth = globalRefABList.innerWidth() - reservedWidth - scrollWidth;
  1752. cache.every(function(lengths, index) {
  1753. // var maxLength = Math.max.apply(null, lengths);
  1754. lengths.sort(function(a, b) {
  1755. return a - b;
  1756. });
  1757. var maxLength = lengths[Math.max(Math.min(Math.ceil(lengths.length * globalContactDataMinVisiblePercentage), lengths.length) - 1, 0)];
  1758. var column = globalRefABListTableCols.eq(index + globalFixedContactDataColumnsCount);
  1759. var innerColumn = globalRefABListInnerTableCols.eq(index + globalFixedContactDataColumnsCount);
  1760. var columnWidth = Math.max(maxLength * characterWidth, getDataColumnMinWidthAtIndex(index));
  1761. // exit early if there is not enough space for the column
  1762. if(columnWidth > availableWidth) {
  1763. // if exiting at the very first column, mark it as the last visible one anyway
  1764. // this will ensure that it gets to occupy what width there is available later on
  1765. if(!lastColumn) {
  1766. lastColumn = column;
  1767. }
  1768. if(!lastInnerColumn) {
  1769. lastInnerColumn = innerColumn;
  1770. }
  1771. return false;
  1772. }
  1773. // dont show column if no data are present
  1774. if(columnWidth && lengths[lengths.length - 1]>0) {
  1775. lastColumn = column;
  1776. lastInnerColumn = innerColumn;
  1777. availableWidth -= columnWidth;
  1778. column.width(columnWidth);
  1779. innerColumn.width(columnWidth);
  1780. }
  1781. return true;
  1782. });
  1783. // set the last visible column to occupy the rest of the available table width
  1784. if(lastColumn && lastInnerColumn) {
  1785. lastColumn.width(lastColumn.width() + availableWidth);
  1786. lastInnerColumn.width(lastInnerColumn.width() + availableWidth);
  1787. }
  1788. // if scrollbar present, create gutter
  1789. if(scrollWidth) {
  1790. $('<col class="ablist_table_gutter">').width(scrollWidth).insertAfter(lastColumn);
  1791. $('<th class="ablist_table_gutter">').insertAfter($('.ablist_table_header').children().eq(lastColumn.index()));
  1792. }
  1793. }
  1794. function getDataColumnCount() {
  1795. return globalSettings.collectiondisplay.value.length;
  1796. }
  1797. function isDataColumnDefined(column) {
  1798. var re = RegExp('(?:^|[^\\\\]){'+column+'(?:\\[.*?\\])*'+'}', 'i');
  1799. return globalSettings.collectiondisplay.value.some(function(col) {
  1800. if(col.hasOwnProperty('value')) {
  1801. var values = col.value;
  1802. if($.isPlainObject(values)) {
  1803. return values.company.some(function(value) {
  1804. return re.test(value)
  1805. }) || values.personal.some(function(value) {
  1806. return re.test(value)
  1807. });
  1808. }
  1809. return values.some(function(value) {
  1810. return re.test(value)
  1811. });
  1812. }
  1813. return false;
  1814. });
  1815. }
  1816. function getContactDataColumns(isCompany) {
  1817. return $.map(globalSettings.collectiondisplay.value, function(col) {
  1818. var value = col.value;
  1819. if($.isPlainObject(value)) {
  1820. if(isCompany && value.hasOwnProperty('company')) {
  1821. return [value.company];
  1822. }
  1823. if(!isCompany && value.hasOwnProperty('personal')) {
  1824. return [value.personal];
  1825. }
  1826. }
  1827. return [value];
  1828. });
  1829. }
  1830. function getDataColumnLabelAtIndex(index) {
  1831. if(globalSettings.collectiondisplay.value[index].hasOwnProperty('label')) {
  1832. var label = globalSettings.collectiondisplay.value[index].label;
  1833. if($.isPlainObject(label)) {
  1834. return getDataColumnLabel(label[globalInterfaceLanguage] || '');
  1835. }
  1836. else {
  1837. return getDataColumnLabel(label);
  1838. }
  1839. }
  1840. }
  1841. function getDataColumnLabel(formatString) {
  1842. var result = '';
  1843. var variableParts = null;
  1844. var re = RegExp('(?:^|[^\\\\])({(.*?[^\\\\])})');
  1845. while(variableParts = formatString.match(re)) {
  1846. var value = localization[globalInterfaceLanguage][globalContactDataColumnLabelVars[variableParts[2]]] || '';
  1847. formatString = formatString.replace(variableParts[1], value);
  1848. }
  1849. return formatString;
  1850. }
  1851. function getDataColumnMinWidthAtIndex(index) {
  1852. return 100;
  1853. }
  1854. function setContactDataColumn(contact, column, value, filterData) {
  1855. var column = column.toUpperCase();
  1856. if(globalContactDataColumnDefs.hasOwnProperty(column) && value) {
  1857. var property = globalContactDataColumnDefs[column].property;
  1858. if(!contact.hasOwnProperty(property)) {
  1859. contact[property] = [];
  1860. }
  1861. var data = {};
  1862. for(var name in filterData) {
  1863. var filterProperty = globalContactDataColumnDefs[column].filterProperities[name];
  1864. data[filterProperty] = filterData[name];
  1865. }
  1866. if($.isArray(value)) {
  1867. value = value.join(', ');
  1868. }
  1869. data.value = value;
  1870. contact[property].push(data);
  1871. }
  1872. }
  1873. function getContactDataColumn(contact, variables) {
  1874. var result = '';
  1875. var variableParts = null;
  1876. var re = RegExp('(?:^|[^\\\\])({(.*?[^\\\\])})');
  1877. variables.forEach(function(formatString) {
  1878. var matched = false;
  1879. while(variableParts = formatString.match(re)) {
  1880. var value = getContactDataColumnVariable(contact, variableParts[2]);
  1881. formatString = formatString.replace(variableParts[1], value);
  1882. matched = matched || value!=='';
  1883. }
  1884. if(matched) {
  1885. result += formatString;
  1886. }
  1887. });
  1888. return result;
  1889. }
  1890. function getContactDataColumnVariable(contact, variable) {
  1891. var parts = variable.match(/^(.*?)(\[.*\])*$/);
  1892. var attr = parts[1].toUpperCase();
  1893. if(parts && attr && globalContactDataColumnDefs.hasOwnProperty(attr)) {
  1894. var property = globalContactDataColumnDefs[attr].property;
  1895. if(contact.hasOwnProperty(property)) {
  1896. var re = RegExp('\\[(.*?[^\\\\])\\]');
  1897. var numeral = 0;
  1898. var filterStr = parts[2] ? parts[2].toUpperCase() : '';
  1899. var filters = [];
  1900. var matches = contact[property];
  1901. while(filterStr) {
  1902. var match = filterStr.match(re);
  1903. if(match===null) {
  1904. break;
  1905. }
  1906. filters.push(match[1].replaceAll('\\[', '[').replaceAll('\\]', ']'));
  1907. filterStr = filterStr.replace(match[0], '');
  1908. }
  1909. filters.forEach(function(filterEl) {
  1910. if(filterEl[0]===':') {
  1911. numeral = parseInt(filterEl.slice(1), 10);
  1912. }
  1913. else {
  1914. var filterParts = filterEl.splitCustom('=');
  1915. var filterType = filterParts[0];
  1916. var filterValue = filterParts[1];
  1917. if(filterType && filterValue && globalContactDataColumnDefs[attr].hasOwnProperty('filterProperities') && globalContactDataColumnDefs[attr].filterProperities.hasOwnProperty(filterType)) {
  1918. var filterProperty = globalContactDataColumnDefs[attr].filterProperities[filterType];
  1919. matches = matches.filter(function(matchEl) {
  1920. return matchEl[filterProperty].indexOf(filterValue)>-1;
  1921. });
  1922. }
  1923. }
  1924. });
  1925. if(!isNaN(numeral) && numeral>-1 && numeral<matches.length) {
  1926. return matches[numeral].value;
  1927. }
  1928. }
  1929. }
  1930. return '';
  1931. }
  1932. function getParamsFromContentlineParse(vcard, parsed, primaryParam, customParam, dataTypeRegister, preserveCase) {
  1933. var params = [];
  1934. if(primaryParam && parsed[3]) {
  1935. var parsed_paramArr = vcardSplitValue(parsed[3], ';');
  1936. parsed_paramArr.forEach(function(el) {
  1937. if(el) {
  1938. var elParts = el.split('=');
  1939. if(elParts[0].toUpperCase()===primaryParam) {
  1940. var val = elParts[1];
  1941. if(!preserveCase) {
  1942. val = val.toUpperCase();
  1943. }
  1944. params.push(humanizeVcardDataTypes(dataTypeRegister, val));
  1945. }
  1946. }
  1947. });
  1948. }
  1949. if(customParam && parsed[1]) {
  1950. var vcard_element_related = null;
  1951. var re = RegExp('\r\n'+parsed[1].replace('.','\\.'+customParam+':(.*)')+'\r\n', 'im');
  1952. while((vcard_element_related = vcard.match(re))!=null) {
  1953. var val = vcard_element_related[1];
  1954. if(!preserveCase) {
  1955. val = val.toUpperCase();
  1956. }
  1957. params.push(humanizeVcardDataTypes(dataTypeRegister, vcardUnescapeValue(val)));
  1958. vcard = vcard.replace(vcard_element_related[0], '\r\n');
  1959. }
  1960. }
  1961. return params;
  1962. }
  1963. function humanizeVcardDataTypes(register, type) {
  1964. if(register && dataTypes[register].hasOwnProperty(type.toLowerCase())) {
  1965. matched = type.match(/^_\$!<(.*)>!\$_$/i);
  1966. if(matched) {
  1967. return matched[1];
  1968. }
  1969. }
  1970. return type;
  1971. }
  1972. function showPhotoBox(e) {
  1973. if($('#photoBox').is(':visible'))
  1974. hidePhotoBox();
  1975. else
  1976. {
  1977. e.stopPropagation();
  1978. $('#photoArrow, #photoBox').css('display', 'block');
  1979. $('#photoURL').focus();
  1980. $('html').bind('click.photo', function(e) {
  1981. if(!$.contains(document.getElementById('photoBox'), e.target)) {
  1982. hidePhotoBox();
  1983. }
  1984. });
  1985. }
  1986. }
  1987. function hidePhotoBox() {
  1988. $('#photoURL').val($('#photoURLHidden').val());
  1989. $('#photoBoxContent').find('[data-type="invalid"]').css('display', 'none');
  1990. $('#photoURL').removeClass('invalid');
  1991. $('#photoBox').css('display','none');
  1992. $('#photoArrow').css('display','none');
  1993. $('html').unbind('click.photo');
  1994. }