owncloud /
contacts
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | Modernizr.load({ |
||
| 2 | test: Modernizr.input.placeholder, |
||
| 3 | nope: [ |
||
| 4 | OC.filePath('contacts', 'css', 'placeholder_polyfill.min.css'), |
||
| 5 | OC.filePath('contacts', 'js', 'placeholder_polyfill.jquery.min.combo.js') |
||
| 6 | ] |
||
| 7 | }); |
||
| 8 | |||
| 9 | (function($) { |
||
| 10 | $.QueryString = (function(a) { |
||
| 11 | if (a === '') {return {};} |
||
| 12 | var b = {}; |
||
| 13 | for (var i = 0; i < a.length; ++i) |
||
| 14 | { |
||
| 15 | var p=a[i].split('='); |
||
| 16 | if (p.length !== 2) { |
||
| 17 | continue; |
||
| 18 | } |
||
| 19 | b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, ' ')); |
||
| 20 | } |
||
| 21 | return b; |
||
| 22 | })(window.location.search.substr(1).split('&')); |
||
| 23 | })(jQuery); |
||
| 24 | |||
| 25 | var utils = {}; |
||
| 26 | |||
| 27 | /** |
||
| 28 | * utils.isArray |
||
| 29 | * |
||
| 30 | * Best guess if object is an array. |
||
| 31 | */ |
||
| 32 | utils.isArray = function(obj) { |
||
| 33 | // do an instanceof check first |
||
| 34 | if (obj instanceof Array) { |
||
| 35 | return true; |
||
| 36 | } |
||
| 37 | // then check for obvious falses |
||
| 38 | if (typeof obj !== 'object') { |
||
| 39 | return false; |
||
| 40 | } |
||
| 41 | if (utils.type(obj) === 'array') { |
||
| 42 | return true; |
||
| 43 | } |
||
| 44 | return false; |
||
| 45 | }; |
||
| 46 | |||
| 47 | utils.isInt = function(s) { |
||
| 48 | return typeof s === 'number' && (s.toString().search(/^-?[0-9]+$/) === 0); |
||
| 49 | }; |
||
| 50 | |||
| 51 | utils.isUInt = function(s) { |
||
| 52 | return typeof s === 'number' && (s.toString().search(/^[0-9]+$/) === 0); |
||
| 53 | }; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * utils.type |
||
| 57 | * |
||
| 58 | * Attempt to ascertain actual object type. |
||
| 59 | */ |
||
| 60 | utils.type = function(obj) { |
||
| 61 | if (obj === null || typeof obj === 'undefined') { |
||
| 62 | return String (obj); |
||
| 63 | } |
||
| 64 | return Object.prototype.toString.call(obj) |
||
| 65 | .replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase(); |
||
| 66 | }; |
||
| 67 | |||
| 68 | utils.moveCursorToEnd = function(el) { |
||
| 69 | if (typeof el.selectionStart === 'number') { |
||
| 70 | el.selectionStart = el.selectionEnd = el.value.length; |
||
| 71 | } else if (typeof el.createTextRange !== 'undefined') { |
||
| 72 | el.focus(); |
||
| 73 | var range = el.createTextRange(); |
||
| 74 | range.collapse(false); |
||
| 75 | range.select(); |
||
| 76 | } |
||
| 77 | }; |
||
| 78 | |||
| 79 | Array.prototype.clone = function() { |
||
| 80 | return this.slice(0); |
||
| 81 | }; |
||
| 82 | |||
| 83 | Array.prototype.clean = function(deleteValue) { |
||
| 84 | var arr = this.clone(); |
||
| 85 | for (var i = 0; i < arr.length; i++) { |
||
| 86 | if (arr[i] === deleteValue) { |
||
| 87 | arr.splice(i, 1); |
||
| 88 | i--; |
||
| 89 | } |
||
| 90 | } |
||
| 91 | return arr; |
||
| 92 | }; |
||
| 93 | |||
| 94 | // Keep it DRY ;) |
||
| 95 | var wrongKey = function(event) { |
||
| 96 | return ((event.type === 'keydown' || event.type === 'keypress') |
||
| 97 | && (event.keyCode !== 32 && event.keyCode !== 13)); |
||
| 98 | }; |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Simply notifier |
||
| 102 | * Arguments: |
||
| 103 | * @param string message - The text message to show. |
||
| 104 | * @param int timeout - The timeout in seconds before the notification disappears. Default 10. |
||
| 105 | * @param function timeouthandler - A function to run on timeout. |
||
| 106 | * @param function clickhandler - A function to run on click. If a timeouthandler is given it will be cancelled on click. |
||
| 107 | * @param object data - An object that will be passed as argument to the timeouthandler and clickhandler functions. |
||
| 108 | * @param bool cancel - If set cancel all ongoing timer events and hide the notification. |
||
| 109 | */ |
||
| 110 | OC.notify = function(params) { |
||
| 111 | var self = this; |
||
| 112 | if(!self.notifier) { |
||
| 113 | self.notifier = $('#notification'); |
||
| 114 | self.notifier.on('click', function() { $(this).fadeOut();}); |
||
| 115 | } |
||
| 116 | if(params.cancel) { |
||
| 117 | self.notifier.off('click'); |
||
| 118 | for(var id in self.notifier.data()) { |
||
| 119 | if($.isNumeric(id)) { |
||
| 120 | clearTimeout(parseInt(id)); |
||
| 121 | } |
||
| 122 | } |
||
| 123 | self.notifier.text('').fadeOut().removeData(); |
||
| 124 | } |
||
| 125 | if(params.message) { |
||
| 126 | self.notifier.text(params.message).fadeIn().css('display', 'inline'); |
||
| 127 | } |
||
| 128 | |||
| 129 | var timer = setTimeout(function() { |
||
| 130 | self.notifier.fadeOut(); |
||
| 131 | if(params.timeouthandler && $.isFunction(params.timeouthandler)) { |
||
| 132 | params.timeouthandler(self.notifier.data(dataid)); |
||
| 133 | self.notifier.off('click'); |
||
| 134 | self.notifier.removeData(dataid); |
||
| 135 | } |
||
| 136 | }, params.timeout && $.isNumeric(params.timeout) ? parseInt(params.timeout)*1000 : 10000); |
||
| 137 | var dataid = timer.toString(); |
||
| 138 | if(params.data) { |
||
| 139 | self.notifier.data(dataid, params.data); |
||
| 140 | } |
||
| 141 | if(params.clickhandler && $.isFunction(params.clickhandler)) { |
||
| 142 | self.notifier.on('click', function() { |
||
| 143 | clearTimeout(timer); |
||
| 144 | self.notifier.off('click'); |
||
| 145 | params.clickhandler(self.notifier.data(dataid)); |
||
| 146 | self.notifier.removeData(dataid); |
||
| 147 | }); |
||
| 148 | } |
||
| 149 | }; |
||
| 150 | |||
| 151 | (function(window, $, OC) { |
||
| 152 | 'use strict'; |
||
| 153 | |||
| 154 | OC.Contacts = OC.Contacts || { |
||
| 155 | init:function() { |
||
| 156 | if(oc_debug === true) { |
||
| 157 | $.error = console.error; |
||
| 158 | } |
||
| 159 | var self = this; |
||
| 160 | |||
| 161 | this.lastSelectedContacts = []; |
||
| 162 | this.scrollTimeoutMiliSecs = 100; |
||
| 163 | this.isScrolling = false; |
||
| 164 | this.cacheElements(); |
||
| 165 | this.storage = new OC.Contacts.Storage(); |
||
| 166 | this.addressBooks = new OC.Contacts.AddressBookList( |
||
| 167 | this.storage, |
||
| 168 | $('#app-settings-content'), |
||
| 169 | $('#addressBookTemplate') |
||
| 170 | ); |
||
| 171 | this.otherBackendConfig = new OC.Contacts.OtherBackendConfig( |
||
| 172 | this.storage, |
||
| 173 | this.addressBooks, |
||
| 174 | $('#addressBookConfigTemplate') |
||
| 175 | ); |
||
| 176 | this.contacts = new OC.Contacts.ContactList( |
||
| 177 | this.storage, |
||
| 178 | this.addressBooks, |
||
| 179 | this.$contactList, |
||
| 180 | this.$contactListItemTemplate, |
||
| 181 | this.$contactDragItemTemplate, |
||
| 182 | this.$contactFullTemplate, |
||
| 183 | this.detailTemplates |
||
| 184 | ); |
||
| 185 | this.groups = new OC.Contacts.GroupList( |
||
| 186 | this.storage, |
||
| 187 | this.$groupList, |
||
| 188 | this.$groupListItemTemplate |
||
| 189 | ); |
||
| 190 | self.groups.loadGroups(function() { |
||
| 191 | self.loading(self.$navigation, false); |
||
| 192 | }); |
||
| 193 | // Hide the list while populating it. |
||
| 194 | this.$contactList.hide(); |
||
| 195 | $.when(this.addressBooks.loadAddressBooks()).then(function(addressBooks) { |
||
| 196 | var deferreds = $(addressBooks).map(function(/*i, elem*/) { |
||
| 197 | return self.contacts.loadContacts(this.getBackend(), this.getId(), this.isActive()); |
||
| 198 | }); |
||
| 199 | // This little beauty is from http://stackoverflow.com/a/6162959/373007 ;) |
||
| 200 | $.when.apply(null, deferreds.get()).then(function() { |
||
| 201 | self.contacts.setSortOrder(contacts_sortby); |
||
| 202 | self.$contactList.show(); |
||
| 203 | $(document).trigger('status.contacts.loaded', { |
||
| 204 | numcontacts: self.contacts.length |
||
| 205 | }); |
||
| 206 | self.loading(self.$rightContent, false); |
||
| 207 | // TODO: Move this to event handler |
||
| 208 | self.groups.selectGroup({id:contacts_lastgroup}); |
||
| 209 | var id = $.QueryString.id; // Keep for backwards compatible links. |
||
| 210 | if(!id) { |
||
| 211 | id = window.location.hash.substr(1); |
||
| 212 | } |
||
| 213 | console.log('Groups loaded, id from url:', id); |
||
| 214 | if(id) { |
||
| 215 | self.openContact(id); |
||
| 216 | } |
||
| 217 | if(!contacts_properties_indexed) { |
||
| 218 | // Wait a couple of mins then check if contacts are indexed. |
||
| 219 | setTimeout(function() { |
||
| 220 | $.when($.post(OC.generateUrl('apps/contacts/indexproperties/{user}/', {user: OC.currentUser}))) |
||
| 221 | .then(function(response) { |
||
| 222 | if(!response.isIndexed) { |
||
| 223 | OC.notify({message:t('contacts', 'Indexing contacts'), timeout:20}); |
||
| 224 | } |
||
| 225 | }); |
||
| 226 | }, 10000); |
||
| 227 | } else { |
||
| 228 | console.log('contacts are indexed.'); |
||
| 229 | } |
||
| 230 | }).fail(function(response) { |
||
| 231 | console.warn(response); |
||
| 232 | self.$rightContent.removeClass('loading'); |
||
| 233 | var message = t('contacts', 'Unrecoverable error loading address books: {msg}', {msg:response.message}); |
||
| 234 | OC.dialogs.alert(message, t('contacts', 'Error.')); |
||
| 235 | }); |
||
| 236 | }).fail(function(response) { |
||
| 237 | console.log(response.message); |
||
| 238 | $(document).trigger('status.contacts.error', response); |
||
| 239 | }); |
||
| 240 | $(OC.Tags).on('change', this.groups.categoriesChanged); |
||
| 241 | this.bindEvents(); |
||
| 242 | this.$toggleAll.show(); |
||
| 243 | this.hideActions(); |
||
| 244 | $('.hidden-on-load').removeClass('hidden-on-load'); |
||
| 245 | }, |
||
| 246 | loading:function(obj, state) { |
||
| 247 | $(obj).toggleClass('loading', state); |
||
| 248 | }, |
||
| 249 | /** |
||
| 250 | * Show/hide elements in the header |
||
| 251 | * @param act An array of actions to show based on class name e.g ['add', 'delete'] |
||
| 252 | */ |
||
| 253 | hideActions:function() { |
||
| 254 | this.showActions(false); |
||
| 255 | }, |
||
| 256 | showActions:function(act) { |
||
| 257 | console.log('showActions', act); |
||
| 258 | //console.trace(); |
||
| 259 | this.$headeractions.children().hide(); |
||
| 260 | if(act && act.length > 0) { |
||
| 261 | this.$contactList.addClass('multiselect'); |
||
| 262 | this.$contactListHeader.find('.actions').css('display', ''); |
||
| 263 | this.$contactListHeader.find('.action').css('display', 'none'); |
||
| 264 | this.$contactListHeader.find('.name').attr('colspan', '5'); |
||
| 265 | this.$contactListHeader.find('.info').css('display', 'none'); |
||
| 266 | this.$contactListHeader.find('.'+act.join(',.')).css('display', ''); |
||
| 267 | } else { |
||
| 268 | this.$contactListHeader.find('.actions').css('display', 'none'); |
||
| 269 | this.$contactListHeader.find('.action').css('display', ''); |
||
| 270 | this.$contactListHeader.find('.name').attr('colspan', '1'); |
||
| 271 | this.$contactListHeader.find('.info').css('display', ''); |
||
| 272 | this.$contactList.removeClass('multiselect'); |
||
| 273 | } |
||
| 274 | }, |
||
| 275 | showAction:function(act, show) { |
||
| 276 | this.$contactListHeader.find('.' + act).toggle(show); |
||
| 277 | }, |
||
| 278 | cacheElements: function() { |
||
| 279 | var self = this; |
||
| 280 | this.detailTemplates = {}; |
||
| 281 | // Load templates for contact details. |
||
| 282 | // The weird double loading is because jquery apparently doesn't |
||
| 283 | // create a searchable object from a script element. |
||
| 284 | $.each($($('#contactDetailsTemplate').html()), function(idx, node) { |
||
| 285 | var $node = $(node); |
||
| 286 | if($node.is('div')) { |
||
| 287 | var $tmpl = $(node.innerHTML); |
||
| 288 | self.detailTemplates[$tmpl.data('element')] = $node; |
||
| 289 | } |
||
| 290 | }); |
||
| 291 | this.$groupListItemTemplate = $('#groupListItemTemplate'); |
||
| 292 | this.$contactListItemTemplate = $('#contactListItemTemplate'); |
||
| 293 | this.$contactDragItemTemplate = $('#contactDragItemTemplate'); |
||
| 294 | this.$contactFullTemplate = $('#contactFullTemplate'); |
||
| 295 | this.$contactDetailsTemplate = $('#contactDetailsTemplate'); |
||
| 296 | this.$rightContent = $('#app-content'); |
||
| 297 | this.$navigation = $('#app-navigation'); |
||
| 298 | //this.$header = $('#contactsheader'); |
||
| 299 | this.$groupList = $('#grouplist'); |
||
| 300 | this.$contactList = $('#contactlist'); |
||
| 301 | this.$contactListHeader = $('#contactsHeader'); |
||
| 302 | this.$sortOrder = this.$contactListHeader.find('.action.sort'); |
||
| 303 | this.$sortOrder.val(contacts_sortby||'fn'); |
||
| 304 | this.$headeractions = this.$groupList.find('.contact-actions'); |
||
| 305 | this.$toggleAll = this.$contactListHeader.find('.toggle'); |
||
| 306 | this.$groups = this.$contactListHeader.find('.groups'); |
||
| 307 | this.$ninjahelp = $('#ninjahelp'); |
||
| 308 | this.$firstRun = $('#firstrun'); |
||
| 309 | this.$settings = $('#app-settings'); |
||
| 310 | }, |
||
| 311 | // Build the select to add/remove from groups. |
||
| 312 | buildGroupSelect: function() { |
||
| 313 | // If a contact is open we know which categories it's in |
||
| 314 | if(this.currentid) { |
||
| 315 | var contact = this.contacts.findById(this.currentid); |
||
| 316 | if(contact === null) { |
||
| 317 | return false; |
||
| 318 | } |
||
| 319 | this.$groups.find('optgroup,option:not([value="-1"])').remove(); |
||
| 320 | var addopts = '', rmopts = ''; |
||
| 321 | $.each(this.groups.categories, function(i, category) { |
||
| 322 | if(contact.inGroup(category.name)) { |
||
| 323 | rmopts += '<option value="' + category.id + '">' + category.name + '</option>'; |
||
| 324 | } else { |
||
| 325 | addopts += '<option value="' + category.id + '">' + category.name + '</option>'; |
||
| 326 | } |
||
| 327 | }); |
||
| 328 | if(addopts.length) { |
||
| 329 | $(addopts).appendTo(this.$groups) |
||
| 330 | .wrapAll('<optgroup data-action="add" label="' + t('contacts', 'Add to...') + '"/>'); |
||
| 331 | } |
||
| 332 | if(rmopts.length) { |
||
| 333 | $(rmopts).appendTo(this.$groups) |
||
| 334 | .wrapAll('<optgroup data-action="remove" label="' + t('contacts', 'Remove from...') + '"/>'); |
||
| 335 | } |
||
| 336 | } else if(this.contacts.getSelectedContacts().length > 0) { // Otherwise add all categories to both add and remove |
||
| 337 | this.$groups.find('optgroup,option:not([value="-1"])').remove(); |
||
| 338 | var addopts = '', rmopts = ''; |
||
| 339 | $.each(this.groups.categories, function(i, category) { |
||
| 340 | rmopts += '<option value="' + category.id + '">' + category.name + '</option>'; |
||
| 341 | addopts += '<option value="' + category.id + '">' + category.name + '</option>'; |
||
| 342 | }); |
||
| 343 | $(addopts).appendTo(this.$groups) |
||
| 344 | .wrapAll('<optgroup data-action="add" label="' + t('contacts', 'Add to...') + '"/>'); |
||
| 345 | $(rmopts).appendTo(this.$groups) |
||
| 346 | .wrapAll('<optgroup data-action="remove" label="' + t('contacts', 'Remove from...') + '"/>'); |
||
| 347 | } else { |
||
| 348 | // 3rd option: No contact open, none checked, just show "Add group..." |
||
| 349 | this.$groups.find('optgroup,option:not([value="-1"])').remove(); |
||
| 350 | } |
||
| 351 | $('<option value="add">' + t('contacts', 'Add group...') + '</option>').appendTo(this.$groups); |
||
| 352 | this.$groups.val(-1); |
||
| 353 | }, |
||
| 354 | bindEvents: function() { |
||
| 355 | var self = this; |
||
| 356 | |||
| 357 | // Should fix Opera check for delayed delete. |
||
| 358 | $(window).unload(function (){ |
||
| 359 | $(window).trigger('beforeunload'); |
||
| 360 | }); |
||
| 361 | |||
| 362 | this.hashChange = function() { |
||
| 363 | console.log('hashchange', window.location.hash); |
||
| 364 | var id = String(window.location.hash.substr(1)); |
||
| 365 | if(id && id !== self.currentid && self.contacts.findById(id) !== null) { |
||
| 366 | self.openContact(id); |
||
| 367 | } else if(!id && self.currentid) { |
||
| 368 | self.closeContact(self.currentid); |
||
| 369 | } |
||
| 370 | }; |
||
| 371 | |||
| 372 | // This apparently get's called on some weird occasions. |
||
| 373 | //$(window).bind('popstate', this.hashChange); |
||
| 374 | $(window).bind('hashchange', this.hashChange); |
||
| 375 | |||
| 376 | // App specific events |
||
| 377 | $(document).bind('status.contact.deleted', function(e, data) { |
||
| 378 | var id = String(data.id); |
||
| 379 | if(id === self.currentid) { |
||
| 380 | delete self.currentid; |
||
| 381 | } |
||
| 382 | console.log('contact', data.id, 'deleted'); |
||
| 383 | // update counts on group lists |
||
| 384 | self.groups.removeFromAll(data.id, true, true); |
||
| 385 | }); |
||
| 386 | |||
| 387 | $(document).bind('status.contact.added', function(e, data) { |
||
| 388 | self.currentid = String(data.id); |
||
| 389 | self.buildGroupSelect(); |
||
| 390 | self.hideActions(); |
||
| 391 | }); |
||
| 392 | |||
| 393 | // Keep error messaging at one place to be able to replace it. |
||
| 394 | $(document).bind('status.contacts.error', function(e, data) { |
||
| 395 | var message = data.message; |
||
| 396 | console.warn(message); |
||
| 397 | //console.trace(); |
||
| 398 | OC.notify({message:message}); |
||
| 399 | }); |
||
| 400 | |||
| 401 | $(document).bind('status.contact.enabled', function(e, enabled) { |
||
| 402 | console.log('status.contact.enabled', enabled); |
||
| 403 | /*if(enabled) { |
||
| 404 | self.showActions(['back', 'download', 'delete', 'groups']); |
||
| 405 | } else { |
||
| 406 | self.showActions(['back']); |
||
| 407 | }*/ |
||
| 408 | }); |
||
| 409 | |||
| 410 | $(document).bind('status.contacts.count', function(e, response) { |
||
| 411 | console.log('Num contacts:', response.count); |
||
| 412 | if(response.count > 0) { |
||
| 413 | self.$contactList.show(); |
||
| 414 | self.$firstRun.hide(); |
||
| 415 | } |
||
| 416 | }); |
||
| 417 | |||
| 418 | $(document).bind('status.contacts.loaded status.contacts.deleted', function(e, response) { |
||
| 419 | console.log('status.contacts.loaded', response); |
||
| 420 | if(response.error) { |
||
| 421 | $(document).trigger('status.contacts.error', response); |
||
| 422 | console.log('Error loading contacts!'); |
||
| 423 | } else { |
||
| 424 | if(response.numcontacts === 0) { |
||
| 425 | self.$contactList.hide(); |
||
| 426 | self.$firstRun.show(); |
||
| 427 | } else { |
||
| 428 | self.$contactList.show(); |
||
| 429 | self.$firstRun.hide(); |
||
| 430 | $.each(self.addressBooks.addressBooks, function(idx, addressBook) { |
||
| 431 | console.log('addressBook', addressBook); |
||
| 432 | if(!addressBook.isActive()) { |
||
| 433 | self.contacts.showFromAddressbook(addressBook.getId(), false); |
||
| 434 | } |
||
| 435 | }); |
||
| 436 | } |
||
| 437 | } |
||
| 438 | }); |
||
| 439 | |||
| 440 | $(document).bind('status.contact.currentlistitem', function(e, result) { |
||
| 441 | //console.log('status.contact.currentlistitem', result, self.$rightContent.height()); |
||
| 442 | if(self.dontScroll !== true) { |
||
| 443 | if(result.pos > self.$rightContent.height()) { |
||
| 444 | self.$rightContent.scrollTop(result.pos - self.$rightContent.height() + result.height); |
||
| 445 | } |
||
| 446 | else if(result.pos < self.$rightContent.offset().top) { |
||
| 447 | self.$rightContent.scrollTop(result.pos); |
||
| 448 | } |
||
| 449 | } else { |
||
| 450 | setTimeout(function() { |
||
| 451 | self.dontScroll = false; |
||
| 452 | }, 100); |
||
| 453 | } |
||
| 454 | self.currentlistid = result.id; |
||
| 455 | }); |
||
| 456 | |||
| 457 | $(document).bind('status.nomorecontacts', function(e, result) { |
||
| 458 | console.log('status.nomorecontacts', result); |
||
| 459 | self.$contactList.hide(); |
||
| 460 | self.$firstRun.show(); |
||
| 461 | }); |
||
| 462 | |||
| 463 | $(document).bind('status.visiblecontacts', function(e, result) { |
||
| 464 | console.log('status.visiblecontacts', result); |
||
| 465 | // TODO: To be decided. |
||
| 466 | }); |
||
| 467 | |||
| 468 | $(document).bind('request.openurl', function(e, data) { |
||
| 469 | switch(data.type) { |
||
| 470 | case 'url': |
||
| 471 | var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!-\/]))?/; |
||
| 472 | //if(new RegExp("[a-zA-Z0-9]+://([a-zA-Z0-9_]+:[a-zA-Z0-9_]+@)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?").test(data.url)) { |
||
| 473 | if(regexp.test(data.url)) { |
||
| 474 | var newWindow = window.open(data.url,'_blank'); |
||
| 475 | newWindow.focus(); |
||
| 476 | } else { |
||
| 477 | $(document).trigger('status.contacts.error', { |
||
| 478 | error: true, |
||
| 479 | message: t('contacts', 'Invalid URL: "{url}"', {url:data.url}) |
||
| 480 | }); |
||
| 481 | } |
||
| 482 | break; |
||
| 483 | case 'email': |
||
| 484 | var regexp = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; |
||
| 485 | if(regexp.test(data.url)) { |
||
| 486 | console.log('success'); |
||
| 487 | var url = 'mailto:' + data.url; |
||
| 488 | try { |
||
| 489 | var mailer = window.open(url, 'Mailer'); |
||
| 490 | } catch(e) { |
||
| 491 | console.log('There was an error opening a mail composer.', e); |
||
| 492 | } |
||
| 493 | setTimeout(function(){ |
||
| 494 | try { |
||
| 495 | if(mailer.location.href === url || mailer.location.href.substr(0, 6) === 'about:') { |
||
| 496 | mailer.close(); |
||
| 497 | } |
||
| 498 | } catch(e) { |
||
| 499 | console.log('There was an error opening a mail composer.', e); |
||
| 500 | } |
||
| 501 | }, 1000); |
||
| 502 | } else { |
||
| 503 | $(document).trigger('status.contacts.error', { |
||
| 504 | error: true, |
||
| 505 | message: t('contacts', 'Invalid email: "{url}"', {url:data.url}) |
||
| 506 | }); |
||
| 507 | } |
||
| 508 | break; |
||
| 509 | case 'adr': |
||
| 510 | var address = data.url.filter(function(n) { |
||
| 511 | return n; |
||
| 512 | }); |
||
| 513 | var newWindow = window.open('http://open.mapquest.com/?q='+address, '_blank'); |
||
| 514 | newWindow.focus(); |
||
| 515 | break; |
||
| 516 | } |
||
| 517 | }); |
||
| 518 | |||
| 519 | // A contact id was in the request |
||
| 520 | $(document).bind('request.loadcontact', function(e, result) { |
||
| 521 | console.log('request.loadcontact', result); |
||
| 522 | if(self.numcontacts) { |
||
| 523 | self.openContact(result.id); |
||
| 524 | } else { |
||
| 525 | // Contacts are not loaded yet, try again. |
||
| 526 | console.log('waiting for contacts to load'); |
||
| 527 | setTimeout(function() { |
||
| 528 | $(document).trigger('request.loadcontact', { |
||
| 529 | id: result.id |
||
| 530 | }); |
||
| 531 | }, 1000); |
||
| 532 | } |
||
| 533 | }); |
||
| 534 | |||
| 535 | $(document).bind('request.contact.move', function(e, data) { |
||
| 536 | console.log('contact', data, 'request.contact.move'); |
||
| 537 | self.addressBooks.moveContact(data.contact, data.from, data.target); |
||
| 538 | }); |
||
| 539 | |||
| 540 | $(document).bind('request.contact.setasfavorite', function(e, data) { |
||
| 541 | console.log('contact', data.id, 'request.contact.setasfavorite'); |
||
| 542 | self.groups.setAsFavorite(data.id, data.state); |
||
| 543 | }); |
||
| 544 | |||
| 545 | $(document).bind('request.contact.addtogroup', function(e, data) { |
||
| 546 | self.groups.addTo(data.id, data.groupid, function(response) { |
||
| 547 | console.log('contact', data.id, 'request.contact.addtogroup', response); |
||
| 548 | }); |
||
| 549 | }); |
||
| 550 | |||
| 551 | $(document).bind('request.contact.removefromgroup', function(e, data) { |
||
| 552 | console.log('contact', data.id, 'request.contact.removefromgroup'); |
||
| 553 | self.groups.removeFrom(data.id, data.groupid); |
||
| 554 | }); |
||
| 555 | |||
| 556 | $(document).bind('request.contact.export', function(e, data) { |
||
| 557 | console.log('request.contact.export', data); |
||
| 558 | document.location.href = OC.generateUrl('apps/contacts/addressbook/{backend}/{addressBookId}/contact/{contactId}/export', data); |
||
| 559 | }); |
||
| 560 | |||
| 561 | $(document).bind('request.contact.close', function(e, data) { |
||
| 562 | var id = String(data.id); |
||
| 563 | console.log('contact', data.id, 'request.contact.close'); |
||
| 564 | self.closeContact(id); |
||
| 565 | }); |
||
| 566 | |||
| 567 | $(document).bind('request.contact.open', function(e, data) { |
||
| 568 | var id = String(data.id); |
||
| 569 | console.log('contact', data.id, 'request.contact.open'); |
||
| 570 | self.openContact(id); |
||
| 571 | }); |
||
| 572 | |||
| 573 | $(document).bind('request.contact.delete', function(e, data) { |
||
| 574 | var id = String(data.contactId); |
||
| 575 | console.log('contact', data, 'request.contact.delete'); |
||
| 576 | self.closeContact(id); |
||
| 577 | self.contacts.delayedDelete(data); |
||
| 578 | self.$contactList.removeClass('dim'); |
||
| 579 | self.hideActions(); |
||
| 580 | }); |
||
| 581 | |||
| 582 | $(document).bind('request.contact.merge', function(e, data) { |
||
| 583 | console.log('contact','request.contact.merge', data); |
||
| 584 | var merger = self.contacts.findById(data.merger); |
||
| 585 | var mergees = []; |
||
| 586 | if(!merger) { |
||
| 587 | $(document).trigger('status.contacts.error', { |
||
| 588 | message: t('contacts', 'Merge failed. Cannot find contact: {id}', {id:data.merger}) |
||
| 589 | }); |
||
| 590 | return; |
||
| 591 | } |
||
| 592 | $.each(data.mergees, function(idx, id) { |
||
| 593 | var contact = self.contacts.findById(id); |
||
| 594 | if(!contact) { |
||
| 595 | console.warn('cannot find', id, 'by id'); |
||
| 596 | } |
||
| 597 | mergees.push(contact); |
||
| 598 | }); |
||
| 599 | if(!merger.merge(mergees)) { |
||
| 600 | $(document).trigger('status.contacts.error', { |
||
| 601 | message: t('contacts', 'Merge failed.') |
||
| 602 | }); |
||
| 603 | return; |
||
| 604 | } |
||
| 605 | merger.saveAll(function(response) { |
||
| 606 | if(response.error) { |
||
| 607 | $(document).trigger('status.contacts.error', { |
||
| 608 | message: t('contacts', 'Merge failed. Error saving contact.') |
||
| 609 | }); |
||
| 610 | return; |
||
| 611 | } else { |
||
| 612 | if(data.deleteOther) { |
||
| 613 | self.contacts.delayedDelete(mergees); |
||
| 614 | } |
||
| 615 | console.log('merger', merger); |
||
| 616 | self.openContact(merger.getId()); |
||
| 617 | } |
||
| 618 | }); |
||
| 619 | }); |
||
| 620 | |||
| 621 | $(document).bind('request.select.contactphoto.fromlocal', function(e, contact) { |
||
| 622 | console.log('request.select.contactphoto.fromlocal', contact); |
||
| 623 | $('#contactphoto_fileupload').trigger('click', contact); |
||
| 624 | }); |
||
| 625 | |||
| 626 | $(document).bind('request.select.contactphoto.fromcloud', function(e, metadata) { |
||
| 627 | console.log('request.select.contactphoto.fromcloud', metadata); |
||
| 628 | OC.dialogs.filepicker(t('contacts', 'Select photo'), function(path) { |
||
| 629 | self.cloudPhotoSelected(metadata, path); |
||
| 630 | }, false, 'image', true); |
||
| 631 | }); |
||
| 632 | |||
| 633 | $(document).bind('request.edit.contactphoto', function(e, metadata) { |
||
| 634 | console.log('request.edit.contactphoto', metadata); |
||
| 635 | self.editCurrentPhoto(metadata); |
||
| 636 | }); |
||
| 637 | |||
| 638 | $(document).bind('request.groups.reload', function(e, result) { |
||
| 639 | console.log('request.groups.reload', result); |
||
| 640 | self.groups.loadGroups(function() { |
||
| 641 | self.groups.triggerLastGroup(); |
||
| 642 | }); |
||
| 643 | }); |
||
| 644 | |||
| 645 | $(document).bind('status.group.groupremoved', function(e, result) { |
||
| 646 | console.log('status.group.groupremoved', result); |
||
| 647 | if(parseInt(result.groupid) === parseInt(self.currentgroup)) { |
||
| 648 | self.contacts.showContacts([]); |
||
| 649 | self.currentgroup = 'all'; |
||
| 650 | } |
||
| 651 | $.each(result.contacts, function(idx, contactid) { |
||
| 652 | var contact = self.contacts.findById(contactid); |
||
| 653 | |||
| 654 | // Test if valid because there could be stale ids in the tag index. |
||
| 655 | if(contact) { |
||
| 656 | contact.removeFromGroup(result.groupname); |
||
| 657 | } |
||
| 658 | }); |
||
| 659 | }); |
||
| 660 | |||
| 661 | $(document).bind('status.group.grouprenamed', function(e, result) { |
||
| 662 | console.log('status.group.grouprenamed', result); |
||
| 663 | $.each(result.contacts, function(idx, contactid) { |
||
| 664 | var contact = self.contacts.findById(contactid); |
||
| 665 | if(!contact) { |
||
| 666 | console.warn('Couldn\'t find contact', contactid); |
||
| 667 | return true; // continue |
||
| 668 | } |
||
| 669 | contact.renameGroup(result.from, result.to); |
||
| 670 | }); |
||
| 671 | }); |
||
| 672 | |||
| 673 | $(document).bind('status.group.contactremoved', function(e, result) { |
||
| 674 | console.log('status.group.contactremoved', result, self.currentgroup, result.groupid); |
||
| 675 | var contact = self.contacts.findById(result.contactid); |
||
| 676 | if(contact) { |
||
| 677 | if(contact.inGroup(result.groupname)) { |
||
| 678 | contact.removeFromGroup(result.groupname); |
||
| 679 | } |
||
| 680 | if(parseInt(self.currentgroup) === parseInt(result.groupid)) { |
||
| 681 | console.log('Hiding', contact.getId()); |
||
| 682 | contact.hide(); |
||
| 683 | } |
||
| 684 | } |
||
| 685 | }); |
||
| 686 | |||
| 687 | $(document).bind('status.group.contactadded', function(e, result) { |
||
| 688 | console.log('status.group.contactadded', result); |
||
| 689 | var contact = self.contacts.findById(result.contactid); |
||
| 690 | if(contact) { |
||
| 691 | if(!contact.inGroup(result.groupname)) { |
||
| 692 | contact.addToGroup(result.groupname); |
||
| 693 | } |
||
| 694 | if(parseInt(self.currentgroup) === parseInt(result.groupid)) { |
||
| 695 | console.log('Showing', contact.getId()); |
||
| 696 | contact.show(); |
||
| 697 | } |
||
| 698 | if(self.currentgroup === 'uncategorized') { |
||
| 699 | console.log('Hiding', contact.getId()); |
||
| 700 | contact.hide(); |
||
| 701 | } |
||
| 702 | } |
||
| 703 | }); |
||
| 704 | |||
| 705 | // Group sorted, save the sort order |
||
| 706 | $(document).bind('status.groups.sorted', function(e, result) { |
||
| 707 | console.log('status.groups.sorted', result); |
||
| 708 | $.when(self.storage.setPreference('groupsort', result.sortorder)).then(function(response) { |
||
| 709 | if(response.error) { |
||
| 710 | $(document).trigger('status.contacts.error', { |
||
| 711 | message: response ? response.message : t('contacts', 'Network or server error. Please inform administrator.') |
||
| 712 | }); |
||
| 713 | } |
||
| 714 | }) |
||
| 715 | .fail(function(response) { |
||
| 716 | console.log(response.message); |
||
| 717 | $(document).trigger('status.contacts.error', response); |
||
| 718 | done = true; |
||
| 719 | }); |
||
| 720 | }); |
||
| 721 | // Group selected, only show contacts from that group |
||
| 722 | $(document).bind('status.group.selected', function(e, result) { |
||
| 723 | console.log('status.group.selected', result); |
||
| 724 | self.currentgroup = result.id; |
||
| 725 | // Close any open contact. |
||
| 726 | if(self.currentid) { |
||
| 727 | var id = self.currentid; |
||
| 728 | self.closeContact(id); |
||
| 729 | self.jumpToContact(id); |
||
| 730 | } |
||
| 731 | self.$toggleAll.show(); |
||
| 732 | self.hideActions(); |
||
| 733 | if(result.type === 'category' || result.type === 'fav') { |
||
| 734 | self.contacts.showContacts(result.contacts); |
||
| 735 | } else if(result.type === 'shared') { |
||
| 736 | self.contacts.showFromAddressbook(self.currentgroup, true, true); |
||
| 737 | } else if(result.type === 'uncategorized') { |
||
| 738 | self.contacts.showUncategorized(); |
||
| 739 | } else { |
||
| 740 | self.contacts.showContacts(self.currentgroup); |
||
| 741 | } |
||
| 742 | $.when(self.storage.setPreference('lastgroup', self.currentgroup)).then(function(response) { |
||
| 743 | if(response.error) { |
||
| 744 | $(document).trigger('status.contacts.error', response); |
||
| 745 | } |
||
| 746 | }) |
||
| 747 | .fail(function(response) { |
||
| 748 | console.log(response.message); |
||
| 749 | $(document).trigger('status.contacts.error', response); |
||
| 750 | done = true; |
||
| 751 | }); |
||
| 752 | self.$rightContent.scrollTop(0); |
||
| 753 | }); |
||
| 754 | // mark items whose title was hid under the top edge as read |
||
| 755 | /*this.$rightContent.scroll(function() { |
||
| 756 | // prevent too many scroll requests; |
||
| 757 | if(!self.isScrolling) { |
||
| 758 | self.isScrolling = true; |
||
| 759 | var num = self.$contactList.find('tr').length; |
||
| 760 | //console.log('num', num); |
||
| 761 | var offset = self.$contactList.find('tr:eq(' + (num-20) + ')').offset().top; |
||
| 762 | if(offset < self.$rightContent.height()) { |
||
| 763 | console.log('load more'); |
||
| 764 | self.contacts.loadContacts(num, function() { |
||
| 765 | self.isScrolling = false; |
||
| 766 | }); |
||
| 767 | } else { |
||
| 768 | setTimeout(function() { |
||
| 769 | self.isScrolling = false; |
||
| 770 | }, self.scrollTimeoutMiliSecs); |
||
| 771 | } |
||
| 772 | //console.log('scroll, unseen:', offset, self.$rightContent.height()); |
||
| 773 | } |
||
| 774 | });*/ |
||
| 775 | $('#contactphoto_fileupload').on('click', function(event, contact) { |
||
| 776 | console.log('contact', contact); |
||
| 777 | var metaData = contact.metaData(); |
||
| 778 | var url = OC.generateUrl( |
||
| 779 | 'apps/contacts/addressbook/{backend}/{addressBookId}/contact/{contactId}/photo', |
||
| 780 | {backend: metaData.backend, addressBookId: metaData.addressBookId, contactId: metaData.contactId} |
||
| 781 | ); |
||
| 782 | $(this).fileupload('option', 'url', url); |
||
| 783 | }).fileupload({ |
||
| 784 | singleFileUploads: true, |
||
| 785 | multipart: false, |
||
| 786 | dataType: 'json', |
||
| 787 | type: 'PUT', |
||
| 788 | dropZone: null, pasteZone: null, |
||
| 789 | acceptFileTypes: /^image\//, |
||
| 790 | add: function(e, data) { |
||
| 791 | var file = data.files[0]; |
||
| 792 | if (file.type.substr(0, 6) !== 'image/') { |
||
| 793 | $(document).trigger('status.contacts.error', { |
||
| 794 | error: true, |
||
| 795 | message: t('contacts', 'Only images can be used as contact photos') |
||
| 796 | }); |
||
| 797 | return; |
||
| 798 | } |
||
| 799 | if (file.size > parseInt($(this).siblings('[name="MAX_FILE_SIZE"]').val())) { |
||
| 800 | $(document).trigger('status.contacts.error', { |
||
| 801 | error: true, |
||
| 802 | message: t( |
||
| 803 | 'contacts', |
||
| 804 | 'The size of "{filename}" exceeds the maximum allowed {size}', |
||
| 805 | {filename: file.name, size: $(this).siblings('[name="max_human_file_size"]').val()} |
||
| 806 | ) |
||
| 807 | }); |
||
| 808 | return; |
||
| 809 | } |
||
| 810 | data.submit(); |
||
| 811 | }, |
||
| 812 | start: function(e, data) { |
||
| 813 | console.log('fileupload.start',data); |
||
| 814 | }, |
||
| 815 | done: function (e, data) { |
||
| 816 | console.log('Upload done:', data); |
||
| 817 | self.editPhoto( |
||
| 818 | data.result.metadata, |
||
| 819 | data.result.tmp |
||
| 820 | ); |
||
| 821 | }, |
||
| 822 | fail: function(e, data) { |
||
| 823 | console.log('fail', data); |
||
| 824 | var response = self.storage.formatResponse(data.jqXHR); |
||
| 825 | $(document).trigger('status.contacts.error', response); |
||
| 826 | } |
||
| 827 | }); |
||
| 828 | |||
| 829 | this.$rightContent.bind('drop dragover', function (e) { |
||
| 830 | e.preventDefault(); |
||
| 831 | }); |
||
| 832 | |||
| 833 | this.$ninjahelp.find('.close').on('click keydown',function(event) { |
||
| 834 | if(wrongKey(event)) { |
||
| 835 | return; |
||
| 836 | } |
||
| 837 | self.$ninjahelp.hide(); |
||
| 838 | }); |
||
| 839 | |||
| 840 | this.$toggleAll.on('change', function(event) { |
||
| 841 | event.stopPropagation(); |
||
| 842 | event.preventDefault(); |
||
| 843 | var isChecked = $(this).is(':checked'); |
||
| 844 | self.setAllChecked(isChecked); |
||
| 845 | if(self.$groups.find('option').length === 1) { |
||
| 846 | self.buildGroupSelect(); |
||
| 847 | } |
||
| 848 | if(isChecked) { |
||
| 849 | self.showActions(['toggle', 'add', 'download', 'groups', 'delete', 'favorite', 'merge']); |
||
| 850 | } else { |
||
| 851 | self.hideActions(); |
||
| 852 | } |
||
| 853 | }); |
||
| 854 | |||
| 855 | this.$contactList.on('change', 'input:checkbox', function(/*event*/) { |
||
| 856 | var selected = self.contacts.getSelectedContacts(); |
||
| 857 | var id = String($(this).val()); |
||
| 858 | // Save list of last selected contact to be able to select range |
||
| 859 | $(this).is(':checked') && self.lastSelectedContacts.indexOf(id) === -1 |
||
| 860 | ? self.lastSelectedContacts.push(id) |
||
| 861 | : self.lastSelectedContacts.splice(self.lastSelectedContacts.indexOf(id), 1); |
||
| 862 | |||
| 863 | if(selected.length > 0 && self.$groups.find('option').length === 1) { |
||
| 864 | self.buildGroupSelect(); |
||
| 865 | } |
||
| 866 | if(selected.length === 0) { |
||
| 867 | self.hideActions(); |
||
| 868 | } else if(selected.length === 1) { |
||
| 869 | self.showActions(['toggle', 'add', 'download', 'groups', 'delete', 'favorite']); |
||
| 870 | } else { |
||
| 871 | self.showActions(['toggle', 'add', 'download', 'groups', 'delete', 'favorite', 'merge']); |
||
| 872 | } |
||
| 873 | }); |
||
| 874 | |||
| 875 | this.$contactList.on('click', 'label:not([for=select_all])', function(/*event*/) { |
||
| 876 | var $input = $(this).prev('input'); |
||
| 877 | $input.prop('checked', !$input.prop('checked')); |
||
| 878 | $input.trigger('change'); |
||
| 879 | return false; // Prevent opening contact |
||
| 880 | }); |
||
| 881 | |||
| 882 | // Add title to names that would elliptisized (is that a word?) |
||
| 883 | this.$contactList.on('mouseenter', '.nametext', function() { |
||
| 884 | var $this = $(this); |
||
| 885 | |||
| 886 | if($this.width() > $this.parent().width() && !$this.attr('title')) { |
||
| 887 | $this.attr('title', $this.text()); |
||
| 888 | } |
||
| 889 | }); |
||
| 890 | |||
| 891 | this.$sortOrder.on('change', function() { |
||
| 892 | $(this).blur().addClass('loading'); |
||
| 893 | contacts_sortby = $(this).val(); |
||
| 894 | self.contacts.setSortOrder(); |
||
| 895 | $(this).removeClass('loading'); |
||
| 896 | self.storage.setPreference('sortby', contacts_sortby); |
||
| 897 | }); |
||
| 898 | |||
| 899 | // Add to/remove from group multiple contacts. |
||
| 900 | this.$groups.on('change', function() { |
||
| 901 | var $opt = $(this).find('option:selected'); |
||
| 902 | var action = $opt.parent().data('action'); |
||
| 903 | var groupName, groupId, buildnow = false; |
||
| 904 | |||
| 905 | var contacts = self.contacts.getSelectedContacts(); |
||
| 906 | var ids = $.map(contacts, function(c) {return c.getId();}); |
||
| 907 | |||
| 908 | self.setAllChecked(false); |
||
| 909 | self.$toggleAll.prop('checked', false); |
||
| 910 | if(!self.currentid) { |
||
| 911 | self.hideActions(); |
||
| 912 | } |
||
| 913 | |||
| 914 | if($opt.val() === 'add') { // Add new group |
||
| 915 | action = 'add'; |
||
| 916 | console.log('add group...'); |
||
| 917 | self.$groups.val(-1); |
||
| 918 | self.addGroup(function(response) { |
||
| 919 | if(!response.error) { |
||
| 920 | groupId = response.id; |
||
| 921 | groupName = response.name; |
||
| 922 | self.groups.addTo(ids, groupId, function(result) { |
||
| 923 | if(!result.error) { |
||
| 924 | $.each(ids, function(idx, id) { |
||
| 925 | // Delay each contact to not trigger too many ajax calls |
||
| 926 | // at a time. |
||
| 927 | setTimeout(function() { |
||
| 928 | var contact = self.contacts.findById(id); |
||
| 929 | if(contact === null) { |
||
| 930 | return true; |
||
| 931 | } |
||
| 932 | contact.addToGroup(groupName); |
||
| 933 | // I don't think this is used... |
||
| 934 | if(buildnow) { |
||
| 935 | self.buildGroupSelect(); |
||
| 936 | } |
||
| 937 | }, 1000); |
||
| 938 | }); |
||
| 939 | } else { |
||
| 940 | $(document).trigger('status.contacts.error', result); |
||
| 941 | } |
||
| 942 | }); |
||
| 943 | } else { |
||
| 944 | $(document).trigger('status.contacts.error', response); |
||
| 945 | } |
||
| 946 | }); |
||
| 947 | return; |
||
| 948 | } |
||
| 949 | |||
| 950 | groupName = $opt.text(), groupId = $opt.val(); |
||
| 951 | |||
| 952 | if(action === 'add') { |
||
| 953 | self.groups.addTo(ids, $opt.val(), function(result) { |
||
| 954 | console.log('after add', result); |
||
| 955 | if(!result.error) { |
||
| 956 | $.each(result.ids, function(idx, id) { |
||
| 957 | // Delay each contact to not trigger too many ajax calls |
||
| 958 | // at a time. |
||
| 959 | setTimeout(function() { |
||
| 960 | console.log('adding', id, 'to', groupName); |
||
| 961 | var contact = self.contacts.findById(id); |
||
| 962 | if(contact === null) { |
||
| 963 | return true; |
||
| 964 | } |
||
| 965 | contact.addToGroup(groupName); |
||
| 966 | // I don't think this is used... |
||
| 967 | if(buildnow) { |
||
| 968 | self.buildGroupSelect(); |
||
| 969 | } |
||
| 970 | }, 1000); |
||
| 971 | }); |
||
| 972 | } else { |
||
| 973 | var msg = result.message ? result.message : t('contacts', 'Error adding to group.'); |
||
| 974 | $(document).trigger('status.contacts.error', {message:msg}); |
||
| 975 | } |
||
| 976 | }); |
||
| 977 | if(!buildnow) { |
||
| 978 | self.$groups.val(-1).hide().find('optgroup,option:not([value="-1"])').remove(); |
||
| 979 | } |
||
| 980 | } else if(action === 'remove') { |
||
| 981 | self.groups.removeFrom(ids, $opt.val(), false, function(result) { |
||
| 982 | console.log('after remove', result); |
||
| 983 | if(!result.error) { |
||
| 984 | var groupname = $opt.text(), groupid = $opt.val(); |
||
| 985 | $.each(result.ids, function(idx, id) { |
||
| 986 | var contact = self.contacts.findById(id); |
||
| 987 | if(contact === null) { |
||
| 988 | return true; |
||
| 989 | } |
||
| 990 | contact.removeFromGroup(groupname); |
||
| 991 | if(buildnow) { |
||
| 992 | self.buildGroupSelect(); |
||
| 993 | } |
||
| 994 | }); |
||
| 995 | } else { |
||
| 996 | var msg = result.message ? result.message : t('contacts', 'Error removing from group.'); |
||
| 997 | $(document).trigger('status.contacts.error', {message:msg}); |
||
| 998 | } |
||
| 999 | }); |
||
| 1000 | if(!buildnow) { |
||
| 1001 | self.$groups.val(-1).hide().find('optgroup,option:not([value="-1"])').remove(); |
||
| 1002 | } |
||
| 1003 | } // else something's wrong ;) |
||
| 1004 | self.setAllChecked(false); |
||
| 1005 | }); |
||
| 1006 | |||
| 1007 | this.$contactList.on('mouseenter', 'tr.contact', function(event) { |
||
| 1008 | if ($(this).data('obj').hasPermission(OC.PERMISSION_DELETE)) { |
||
| 1009 | var $td = $(this).find('td').filter(':visible').last(); |
||
| 1010 | $('<a />').addClass('icon-delete svg delete action').appendTo($td); |
||
| 1011 | } |
||
| 1012 | }); |
||
| 1013 | |||
| 1014 | this.$contactList.on('mouseleave', 'tr.contact', function(event) { |
||
| 1015 | $(this).find('a.delete').remove(); |
||
| 1016 | }); |
||
| 1017 | |||
| 1018 | // Prevent Firefox from selecting the table-cell |
||
| 1019 | this.$contactList.mousedown(function (event) { |
||
| 1020 | if (event.ctrlKey || event.metaKey || event.shiftKey) { |
||
| 1021 | event.preventDefault(); |
||
| 1022 | } |
||
| 1023 | }); |
||
| 1024 | |||
| 1025 | $(window).on('click', function(event) { |
||
| 1026 | if(!$(event.target).is('a[href^="mailto"]')) { |
||
| 1027 | return; |
||
| 1028 | } |
||
| 1029 | console.log('mailto clicked', $(event.target)); |
||
| 1030 | |||
| 1031 | $(document).trigger('request.openurl', { |
||
| 1032 | type: 'email', |
||
| 1033 | url: $(event.target).attr('href').substr(7) |
||
| 1034 | }); |
||
| 1035 | |||
| 1036 | event.stopPropagation(); |
||
| 1037 | event.preventDefault(); |
||
| 1038 | }); |
||
| 1039 | |||
| 1040 | // Contact list. Either open a contact or perform an action (mailto etc.) |
||
| 1041 | this.$contactList.on('click', 'tr.contact', function(event) { |
||
| 1042 | if($(event.target).is('input') || $(event.target).is('a[href^="mailto"]')) { |
||
| 1043 | return; |
||
| 1044 | } |
||
| 1045 | // Select a single contact or a range of contacts. |
||
| 1046 | if(event.ctrlKey || event.metaKey || event.shiftKey) { |
||
| 1047 | event.stopPropagation(); |
||
| 1048 | event.preventDefault(); |
||
| 1049 | self.dontScroll = true; |
||
| 1050 | var $input = $(this).find('input:checkbox'); |
||
| 1051 | var index = self.$contactList.find('tr.contact:visible').index($(this)); |
||
| 1052 | if(event.shiftKey && self.lastSelectedContacts.length > 0) { |
||
| 1053 | self.contacts.selectRange( |
||
| 1054 | $(this).data('id'), |
||
| 1055 | self.lastSelectedContacts[self.lastSelectedContacts.length-1] |
||
| 1056 | ); |
||
| 1057 | } else { |
||
| 1058 | self.contacts.setSelected($(this).data('id'), !$input.prop('checked')); |
||
| 1059 | } |
||
| 1060 | return; |
||
| 1061 | } |
||
| 1062 | if($(event.target).is('a.mailto')) { |
||
| 1063 | $(document).trigger('request.openurl', { |
||
| 1064 | type: 'email', |
||
| 1065 | url: $.trim($(this).find('.email').text()) |
||
| 1066 | }); |
||
| 1067 | return; |
||
| 1068 | } |
||
| 1069 | if($(event.target).is('a.delete')) { |
||
| 1070 | $(document).trigger('request.contact.delete', { |
||
| 1071 | contactId: $(this).data('id') |
||
| 1072 | }); |
||
| 1073 | return; |
||
| 1074 | } |
||
| 1075 | self.openContact(String($(this).data('id'))); |
||
| 1076 | }); |
||
| 1077 | |||
| 1078 | this.$settings.find('#app-settings-header').on('click keydown',function(event) { |
||
| 1079 | if(wrongKey(event)) { |
||
| 1080 | return; |
||
| 1081 | } |
||
| 1082 | var bodyListener = function(e) { |
||
| 1083 | if(self.$settings.find($(e.target)).length === 0) { |
||
| 1084 | self.$settings.switchClass('open', ''); |
||
| 1085 | } |
||
| 1086 | }; |
||
| 1087 | if(self.$settings.hasClass('open')) { |
||
| 1088 | self.$settings.switchClass('open', ''); |
||
| 1089 | $('body').unbind('click', bodyListener); |
||
| 1090 | } else { |
||
| 1091 | self.$settings.switchClass('', 'open'); |
||
| 1092 | $('body').bind('click', bodyListener); |
||
| 1093 | } |
||
| 1094 | }); |
||
| 1095 | |||
| 1096 | var addContact = function() { |
||
| 1097 | if(self.contacts.addressBooks.count() > 0){ |
||
| 1098 | console.log('add'); |
||
| 1099 | if(self.currentid) { |
||
| 1100 | if(self.currentid === 'new') { |
||
| 1101 | return; |
||
| 1102 | } else { |
||
| 1103 | var contact = self.contacts.findById(self.currentid); |
||
| 1104 | if(contact) { |
||
| 1105 | contact.close(true); |
||
| 1106 | } |
||
| 1107 | } |
||
| 1108 | } |
||
| 1109 | self.currentid = 'new'; |
||
| 1110 | // Properties that the contact doesn't know |
||
| 1111 | console.log('addContact, groupid', self.currentgroup); |
||
| 1112 | var groupprops = { |
||
| 1113 | favorite: false, |
||
| 1114 | groups: self.groups.categories, |
||
| 1115 | currentgroup: {id:self.currentgroup, name:self.groups.nameById(self.currentgroup)} |
||
| 1116 | }; |
||
| 1117 | self.$firstRun.hide(); |
||
| 1118 | self.$contactList.show(); |
||
| 1119 | self.tmpcontact = self.contacts.addContact(groupprops); |
||
| 1120 | self.tmpcontact.prependTo(self.$contactList.find('tbody')).show().find('.fullname').focus(); |
||
| 1121 | self.$rightContent.scrollTop(0); |
||
| 1122 | self.hideActions(); |
||
| 1123 | }else{ |
||
| 1124 | OC.dialogs.alert(t('contacts','Please create an addressbook first'),t('contacts','Contacts')); |
||
| 1125 | } |
||
| 1126 | }; |
||
| 1127 | |||
| 1128 | this.$firstRun.on('click keydown', '.import', function(event) { |
||
| 1129 | event.preventDefault(); |
||
| 1130 | event.stopPropagation(); |
||
| 1131 | self.$settings.find('.settings').click(); |
||
| 1132 | }); |
||
| 1133 | |||
| 1134 | this.$firstRun.on('click keydown', '.add-contact', function(event) { |
||
| 1135 | if(wrongKey(event)) { |
||
| 1136 | return; |
||
| 1137 | } |
||
| 1138 | addContact(); |
||
| 1139 | }); |
||
| 1140 | |||
| 1141 | this.$groupList.on('click keydown', '.add-contact', function(event) { |
||
| 1142 | if(wrongKey(event)) { |
||
| 1143 | return; |
||
| 1144 | } |
||
| 1145 | addContact(); |
||
| 1146 | }); |
||
| 1147 | |||
| 1148 | this.$contactListHeader.on('click keydown', '.delete', function(event) { |
||
| 1149 | if(wrongKey(event)) { |
||
| 1150 | return; |
||
| 1151 | } |
||
| 1152 | console.log('delete'); |
||
| 1153 | if(self.currentid) { |
||
| 1154 | console.assert(typeof self.currentid === 'string', 'self.currentid is not a string'); |
||
| 1155 | contactInfo = self.contacts[self.currentid].metaData(); |
||
| 1156 | self.contacts.delayedDelete(contactInfo); |
||
| 1157 | } else { |
||
| 1158 | self.contacts.delayedDelete(self.contacts.getSelectedContacts()); |
||
| 1159 | } |
||
| 1160 | self.hideActions(); |
||
| 1161 | }); |
||
| 1162 | |||
| 1163 | this.$contactListHeader.on('click keydown', '.download', function(event) { |
||
| 1164 | if(wrongKey(event)) { |
||
| 1165 | return; |
||
| 1166 | } |
||
| 1167 | |||
| 1168 | var doDownload = function(contacts) { |
||
| 1169 | // Only get backend, addressbookid and contactid |
||
| 1170 | contacts = $.map(contacts, function(c) {return c.metaData();}); |
||
| 1171 | var targets = {}; |
||
| 1172 | // Try to shorten request URI |
||
| 1173 | $.each(contacts, function(idx, contact) { |
||
| 1174 | if(!targets[contact.backend]) { |
||
| 1175 | targets[contact.backend] = {}; |
||
| 1176 | } |
||
| 1177 | if(!targets[contact.backend][contact.addressBookId]) { |
||
| 1178 | targets[contact.backend][contact.addressBookId] = []; |
||
| 1179 | } |
||
| 1180 | targets[contact.backend][contact.addressBookId].push(contact.contactId); |
||
| 1181 | }); |
||
| 1182 | targets = JSON.stringify(targets); |
||
| 1183 | var url = OC.generateUrl('apps/contacts/exportSelected?t={t}', {t:targets}); |
||
| 1184 | //console.log('export url', url); |
||
| 1185 | document.location.href = url; |
||
| 1186 | }; |
||
| 1187 | var contacts = self.contacts.getSelectedContacts(); |
||
| 1188 | console.log('download', contacts.length); |
||
| 1189 | |||
| 1190 | // The 300 is just based on my little testing with Apache2 |
||
| 1191 | // Other web servers may fail before. |
||
| 1192 | if(contacts.length > 300) { |
||
| 1193 | OC.notify({ |
||
| 1194 | message:t('contacts', 'You have selected over 300 contacts.\nThis will most likely fail! Click here to try anyway.'), |
||
| 1195 | timeout:5, |
||
| 1196 | clickhandler:function() { |
||
| 1197 | doDownload(contacts); |
||
| 1198 | } |
||
| 1199 | }); |
||
| 1200 | } else { |
||
| 1201 | doDownload(contacts); |
||
| 1202 | } |
||
| 1203 | }); |
||
| 1204 | |||
| 1205 | this.$contactListHeader.on('click keydown', '.merge', function(event) { |
||
| 1206 | if(wrongKey(event)) { |
||
| 1207 | return; |
||
| 1208 | } |
||
| 1209 | console.log('merge'); |
||
| 1210 | self.mergeSelectedContacts(); |
||
| 1211 | }); |
||
| 1212 | |||
| 1213 | this.$contactListHeader.on('click keydown', '.favorite', function(event) { |
||
| 1214 | if(wrongKey(event)) { |
||
| 1215 | return; |
||
| 1216 | } |
||
| 1217 | |||
| 1218 | var contacts = self.contacts.getSelectedContacts(); |
||
| 1219 | |||
| 1220 | self.setAllChecked(false); |
||
| 1221 | self.$toggleAll.prop('checked', false); |
||
| 1222 | if(!self.currentid) { |
||
| 1223 | self.hideActions(); |
||
| 1224 | } |
||
| 1225 | |||
| 1226 | $.each(contacts, function(idx, contact) { |
||
| 1227 | if(!self.groups.isFavorite(contact.getId())) { |
||
| 1228 | self.groups.setAsFavorite(contact.getId(), true, function(result) { |
||
| 1229 | if(result.status !== 'success') { |
||
| 1230 | $(document).trigger('status.contacts.error', {message: |
||
| 1231 | t('contacts', |
||
| 1232 | 'Error setting {name} as favorite.', |
||
| 1233 | {name:contact.getDisplayName()}) |
||
| 1234 | }); |
||
| 1235 | } |
||
| 1236 | }); |
||
| 1237 | } |
||
| 1238 | }); |
||
| 1239 | |||
| 1240 | self.hideActions(); |
||
| 1241 | }); |
||
| 1242 | |||
| 1243 | this.$contactList.on('mouseenter', 'td.email', function(event) { |
||
| 1244 | if($.trim($(this).text()).length > 3) { |
||
| 1245 | $(this).find('.mailto').css('display', 'inline-block'); //.fadeIn(100); |
||
| 1246 | } |
||
| 1247 | }); |
||
| 1248 | this.$contactList.on('mouseleave', 'td.email', function(event) { |
||
| 1249 | $(this).find('.mailto').fadeOut(100); |
||
| 1250 | }); |
||
| 1251 | |||
| 1252 | $('body').on('touchmove', function(event) { |
||
| 1253 | event.preventDefault(); |
||
| 1254 | }); |
||
| 1255 | |||
| 1256 | $(document).on('keyup', function(event) { |
||
| 1257 | if(!$(event.target).is('body') || event.isPropagationStopped()) { |
||
| 1258 | return; |
||
| 1259 | } |
||
| 1260 | var keyCode = Math.max(event.keyCode, event.which); |
||
| 1261 | // TODO: This should go in separate method |
||
| 1262 | console.log(event, keyCode + ' ' + event.target.nodeName); |
||
| 1263 | /** |
||
| 1264 | * To add: |
||
| 1265 | * Shift-a: add addressbook |
||
| 1266 | * u (85): hide/show leftcontent |
||
| 1267 | * f (70): add field |
||
| 1268 | */ |
||
| 1269 | switch(keyCode) { |
||
| 1270 | case 13: // Enter? |
||
| 1271 | console.log('Enter?'); |
||
| 1272 | if(!self.currentid && self.currentlistid) { |
||
| 1273 | self.openContact(self.currentlistid); |
||
| 1274 | } |
||
| 1275 | break; |
||
| 1276 | case 27: // Esc |
||
| 1277 | if(self.$ninjahelp.is(':visible')) { |
||
| 1278 | self.$ninjahelp.hide(); |
||
| 1279 | } else if(self.currentid) { |
||
| 1280 | self.closeContact(self.currentid); |
||
| 1281 | } |
||
| 1282 | break; |
||
| 1283 | case 46: // Delete |
||
| 1284 | if(event.shiftKey) { |
||
| 1285 | self.contacts.delayedDelete(self.currentid); |
||
| 1286 | } |
||
| 1287 | break; |
||
| 1288 | case 40: // down |
||
| 1289 | case 74: // j |
||
| 1290 | console.log('next'); |
||
| 1291 | if(!self.currentid && self.currentlistid) { |
||
| 1292 | self.contacts.contacts[self.currentlistid].next(); |
||
| 1293 | } |
||
| 1294 | break; |
||
| 1295 | case 65: // a |
||
| 1296 | if(event.shiftKey) { |
||
| 1297 | console.log('add group?'); |
||
| 1298 | break; |
||
| 1299 | } |
||
| 1300 | addContact(); |
||
| 1301 | break; |
||
| 1302 | case 38: // up |
||
| 1303 | case 75: // k |
||
| 1304 | console.log('previous'); |
||
| 1305 | if(!self.currentid && self.currentlistid) { |
||
| 1306 | self.contacts.contacts[self.currentlistid].prev(); |
||
| 1307 | } |
||
| 1308 | break; |
||
| 1309 | case 34: // PageDown |
||
| 1310 | case 78: // n |
||
| 1311 | console.log('page down'); |
||
| 1312 | break; |
||
| 1313 | case 79: // o |
||
| 1314 | console.log('open contact?'); |
||
| 1315 | break; |
||
| 1316 | case 33: // PageUp |
||
| 1317 | case 80: // p |
||
| 1318 | // prev addressbook |
||
| 1319 | //OC.contacts.contacts.previousAddressbook(); |
||
| 1320 | break; |
||
| 1321 | case 82: // r |
||
| 1322 | console.log('refresh - what?'); |
||
| 1323 | break; |
||
| 1324 | case 63: // ? German. |
||
| 1325 | if(event.shiftKey) { |
||
| 1326 | self.$ninjahelp.toggle('fast'); |
||
| 1327 | } |
||
| 1328 | break; |
||
| 1329 | case 171: // ? Danish |
||
| 1330 | case 191: // ? Standard qwerty |
||
| 1331 | self.$ninjahelp.toggle('fast').position({my: 'center', at: 'center', of: '#content'}); |
||
| 1332 | break; |
||
| 1333 | } |
||
| 1334 | |||
| 1335 | }); |
||
| 1336 | |||
| 1337 | // find all with a title attribute and tipsy them |
||
| 1338 | $('.tooltipped.downwards:not(.onfocus)').tipsy({gravity: 'n'}); |
||
| 1339 | $('.tooltipped.upwards:not(.onfocus)').tipsy({gravity: 's'}); |
||
| 1340 | $('.tooltipped.rightwards:not(.onfocus)').tipsy({gravity: 'w'}); |
||
| 1341 | $('.tooltipped.leftwards:not(.onfocus)').tipsy({gravity: 'e'}); |
||
| 1342 | $('.tooltipped.downwards.onfocus').tipsy({trigger: 'focus', gravity: 'n'}); |
||
| 1343 | $('.tooltipped.rightwards.onfocus').tipsy({trigger: 'focus', gravity: 'w'}); |
||
| 1344 | }, |
||
| 1345 | mergeSelectedContacts: function() { |
||
| 1346 | var contacts = this.contacts.getSelectedContacts(); |
||
| 1347 | this.$rightContent.append('<div id="merge_contacts_dialog"></div>'); |
||
| 1348 | if(!this.$mergeContactsTmpl) { |
||
| 1349 | this.$mergeContactsTmpl = $('#mergeContactsTemplate'); |
||
| 1350 | } |
||
| 1351 | var $dlg = this.$mergeContactsTmpl.octemplate(); |
||
| 1352 | var $liTmpl = $dlg.find('li').detach(); |
||
| 1353 | var $mergeList = $dlg.find('.mergelist'); |
||
| 1354 | $.each(contacts, function(idx, contact) { |
||
| 1355 | var $li = $liTmpl |
||
| 1356 | .octemplate({idx: idx, id: contact.getId(), displayname: contact.getDisplayName()}); |
||
| 1357 | if(!contact.data.thumbnail) { |
||
| 1358 | $li.addClass('thumbnail'); |
||
| 1359 | } else { |
||
| 1360 | $li.css('background-image', 'url(data:image/png;base64,' + contact.data.thumbnail + ')'); |
||
| 1361 | } |
||
| 1362 | if(idx === 0) { |
||
| 1363 | $li.find('input:radio').prop('checked', true); |
||
| 1364 | } |
||
| 1365 | $mergeList.append($li); |
||
| 1366 | }); |
||
| 1367 | $('#merge_contacts_dialog').html($dlg).ocdialog({ |
||
| 1368 | modal: true, |
||
| 1369 | closeOnEscape: true, |
||
| 1370 | title: t('contacts', 'Merge contacts'), |
||
| 1371 | height: 'auto', width: 'auto', |
||
| 1372 | buttons: [ |
||
| 1373 | { |
||
| 1374 | text: t('contacts', 'Merge contacts'), |
||
| 1375 | click:function() { |
||
| 1376 | // Do the merging, use $(this) to get dialog |
||
| 1377 | var contactid = $(this).find('input:radio:checked').val(); |
||
| 1378 | var others = []; |
||
| 1379 | var deleteOther = $(this).find('#delete_other').prop('checked'); |
||
| 1380 | console.log('Selected contact', contactid, 'Delete others', deleteOther); |
||
| 1381 | $.each($(this).find('input:radio:not(:checked)'), function(idx, item) { |
||
| 1382 | others.push($(item).val()); |
||
| 1383 | }); |
||
| 1384 | console.log('others', others); |
||
| 1385 | $(document).trigger('request.contact.merge', { |
||
| 1386 | merger: contactid, |
||
| 1387 | mergees: others, |
||
| 1388 | deleteOther: deleteOther |
||
| 1389 | }); |
||
| 1390 | |||
| 1391 | $(this).ocdialog('close'); |
||
| 1392 | }, |
||
| 1393 | defaultButton: true |
||
| 1394 | }, |
||
| 1395 | { |
||
| 1396 | text: t('contacts', 'Cancel'), |
||
| 1397 | click:function() { |
||
| 1398 | $(this).ocdialog('close'); |
||
| 1399 | return false; |
||
| 1400 | } |
||
| 1401 | } |
||
| 1402 | ], |
||
| 1403 | close: function(/*event, ui*/) { |
||
| 1404 | $(this).ocdialog('destroy').remove(); |
||
| 1405 | $('#merge_contacts_dialog').remove(); |
||
| 1406 | }, |
||
| 1407 | open: function(/*event, ui*/) { |
||
| 1408 | $dlg.find('input').focus(); |
||
| 1409 | } |
||
| 1410 | }); |
||
| 1411 | }, |
||
| 1412 | addGroup: function(cb) { |
||
| 1413 | var self = this; |
||
| 1414 | this.$rightContent.append('<div id="add_group_dialog"></div>'); |
||
| 1415 | if(!this.$addGroupTmpl) { |
||
| 1416 | this.$addGroupTmpl = $('#addGroupTemplate'); |
||
| 1417 | } |
||
| 1418 | this.$contactList.addClass('dim'); |
||
| 1419 | var $dlg = this.$addGroupTmpl.octemplate(); |
||
| 1420 | $('#add_group_dialog').html($dlg).ocdialog({ |
||
| 1421 | modal: true, |
||
| 1422 | closeOnEscape: true, |
||
| 1423 | title: t('contacts', 'Add group'), |
||
| 1424 | height: 'auto', width: 'auto', |
||
| 1425 | buttons: [ |
||
| 1426 | { |
||
| 1427 | text: t('contacts', 'OK'), |
||
| 1428 | click:function() { |
||
| 1429 | var name = $(this).find('input').val(); |
||
| 1430 | if(name.trim() === '') { |
||
| 1431 | return false; |
||
| 1432 | } |
||
| 1433 | self.groups.addGroup( |
||
| 1434 | {name:$dlg.find('input:text').val()}, |
||
| 1435 | function(response) { |
||
| 1436 | if(typeof cb === 'function') { |
||
| 1437 | cb(response); |
||
| 1438 | } else { |
||
| 1439 | if(response.error) { |
||
| 1440 | $(document).trigger('status.contacts.error', response); |
||
| 1441 | } |
||
| 1442 | } |
||
| 1443 | }); |
||
| 1444 | $(this).ocdialog('close'); |
||
| 1445 | }, |
||
| 1446 | defaultButton: true |
||
| 1447 | }, |
||
| 1448 | { |
||
| 1449 | text: t('contacts', 'Cancel'), |
||
| 1450 | click:function() { |
||
| 1451 | $(this).ocdialog('close'); |
||
| 1452 | return false; |
||
| 1453 | } |
||
| 1454 | } |
||
| 1455 | ], |
||
| 1456 | close: function(/*event, ui*/) { |
||
| 1457 | $(this).ocdialog('destroy').remove(); |
||
| 1458 | $('#add_group_dialog').remove(); |
||
| 1459 | self.$contactList.removeClass('dim'); |
||
| 1460 | }, |
||
| 1461 | open: function(/*event, ui*/) { |
||
| 1462 | $dlg.find('input').focus(); |
||
| 1463 | } |
||
| 1464 | }); |
||
| 1465 | }, |
||
| 1466 | setAllChecked: function(checked) { |
||
| 1467 | var selector = checked ? 'input:checkbox:visible:not(checked)' : 'input:checkbox:visible:checked'; |
||
| 1468 | $.each(this.$contactList.find(selector), function() { |
||
| 1469 | $(this).prop('checked', checked); |
||
| 1470 | }); |
||
| 1471 | this.lastSelectedContacts = []; |
||
| 1472 | }, |
||
| 1473 | jumpToContact: function(id) { |
||
| 1474 | this.$rightContent.scrollTop(this.contacts.contactPos(id)); |
||
| 1475 | }, |
||
| 1476 | closeContact: function(id) { |
||
| 1477 | $(window).unbind('hashchange', this.hashChange); |
||
| 1478 | if(this.currentid === 'new') { |
||
| 1479 | this.tmpcontact.slideUp().remove(); |
||
| 1480 | this.$contactList.show(); |
||
| 1481 | } else { |
||
| 1482 | var contact = this.contacts.findById(id); |
||
| 1483 | if(contact) { |
||
| 1484 | // Only show the list element if contact is in current group |
||
| 1485 | var showListElement = contact.inGroup(this.groups.nameById(this.currentgroup)) |
||
| 1486 | || ['all', 'fav', 'uncategorized'].indexOf(this.currentgroup) !== -1 |
||
| 1487 | || (this.currentgroup === 'uncategorized' && contact.groups().length === 0); |
||
| 1488 | contact.close(showListElement); |
||
| 1489 | } |
||
| 1490 | } |
||
| 1491 | delete this.currentid; |
||
| 1492 | this.hideActions(); |
||
| 1493 | this.$groups.find('optgroup,option:not([value="-1"])').remove(); |
||
| 1494 | if(this.contacts.length === 0) { |
||
| 1495 | $(document).trigger('status.nomorecontacts'); |
||
| 1496 | } |
||
| 1497 | window.location.hash = ''; |
||
| 1498 | $(window).bind('hashchange', this.hashChange); |
||
| 1499 | }, |
||
| 1500 | openContact: function(id) { |
||
| 1501 | var self = this, contact; |
||
| 1502 | if(typeof id === 'undefined' || id === 'undefined') { |
||
| 1503 | console.warn('id is undefined!'); |
||
| 1504 | console.trace(); |
||
| 1505 | } |
||
| 1506 | console.log('Contacts.openContact', id, typeof id); |
||
| 1507 | if(this.currentid && this.currentid !== id) { |
||
| 1508 | this.closeContact(this.currentid); |
||
| 1509 | } |
||
| 1510 | contact = this.contacts.findById(id); |
||
| 1511 | if (!contact) { |
||
| 1512 | console.warn('Contact', id, 'not found. Possibly deleted'); |
||
| 1513 | return; |
||
| 1514 | } |
||
| 1515 | this.currentid = id; |
||
| 1516 | this.hideActions(); |
||
| 1517 | // If opened from search we can't be sure the contact is in currentgroup |
||
| 1518 | if(!contact.inGroup(this.groups.nameById(this.currentgroup)) |
||
| 1519 | && ['all', 'fav', 'uncategorized'].indexOf(this.currentgroup) === -1 |
||
| 1520 | ) { |
||
| 1521 | this.groups.selectGroup({id:'all'}); |
||
| 1522 | } |
||
| 1523 | $(window).unbind('hashchange', this.hashChange); |
||
| 1524 | console.assert(typeof this.currentid === 'string', 'Current ID not string:' + this.currentid); |
||
| 1525 | // Properties that the contact doesn't know |
||
| 1526 | var groupprops = { |
||
| 1527 | favorite: this.groups.isFavorite(this.currentid), |
||
| 1528 | groups: this.groups.categories, |
||
| 1529 | currentgroup: {id:this.currentgroup, name:this.groups.nameById(this.currentgroup)} |
||
| 1530 | }; |
||
| 1531 | if(!contact) { |
||
| 1532 | console.warn('Error opening', this.currentid); |
||
| 1533 | $(document).trigger('status.contacts.error', { |
||
| 1534 | message: t('contacts', 'Could not find contact: {id}', {id:this.currentid}) |
||
| 1535 | }); |
||
| 1536 | this.currentid = null; |
||
| 1537 | return; |
||
| 1538 | } |
||
| 1539 | var $contactelem = contact.renderContact(groupprops); |
||
| 1540 | var $listElement = contact.getListItemElement(); |
||
| 1541 | console.log('selected element', $listElement); |
||
| 1542 | window.location.hash = this.currentid; |
||
| 1543 | $contactelem.insertAfter($listElement).show().find('.fullname').focus(); |
||
| 1544 | // Remove once IE8 is finally obsoleted in oC. |
||
| 1545 | if (!OC.Util.hasSVGSupport()) { |
||
| 1546 | OC.Util.replaceSVG($contactelem); |
||
| 1547 | } |
||
| 1548 | self.jumpToContact(self.currentid); |
||
| 1549 | $listElement.hide(); |
||
| 1550 | setTimeout(function() { |
||
| 1551 | $(window).bind('hashchange', self.hashChange); |
||
| 1552 | }, 500); |
||
| 1553 | }, |
||
| 1554 | update: function() { |
||
| 1555 | console.log('update'); |
||
| 1556 | }, |
||
| 1557 | cloudPhotoSelected:function(metadata, path) { |
||
| 1558 | var self = this; |
||
| 1559 | console.log('cloudPhotoSelected', metadata); |
||
| 1560 | var url = OC.generateUrl( |
||
| 1561 | 'apps/contacts/addressbook/{backend}/{addressBookId}/contact/{contactId}/photo/cacheFS', |
||
| 1562 | {backend: metadata.backend, addressBookId: metadata.addressBookId, contactId: metadata.contactId} |
||
| 1563 | ); |
||
| 1564 | var jqXHR = $.getJSON(url, {path: path}, function(response) { |
||
| 1565 | console.log('response', response); |
||
| 1566 | response = self.storage.formatResponse(jqXHR); |
||
| 1567 | if(!response.error) { |
||
| 1568 | self.editPhoto(metadata, response.data.tmp); |
||
| 1569 | } else { |
||
| 1570 | $(document).trigger('status.contacts.error', response); |
||
| 1571 | } |
||
| 1572 | }).fail(function(response) { |
||
| 1573 | response = self.storage.formatResponse(jqXHR); |
||
| 1574 | console.warn('response', response); |
||
| 1575 | $(document).trigger('status.contacts.error', response); |
||
| 1576 | }); |
||
| 1577 | }, |
||
| 1578 | editCurrentPhoto:function(metadata) { |
||
| 1579 | var self = this; |
||
| 1580 | var url = OC.generateUrl( |
||
| 1581 | 'apps/contacts/addressbook/{backend}/{addressBookId}/contact/{contactId}/photo/cacheCurrent', |
||
| 1582 | {backend: metadata.backend, addressBookId: metadata.addressBookId, contactId: metadata.contactId} |
||
| 1583 | ); |
||
| 1584 | console.log('url', url); |
||
| 1585 | var jqXHR = $.getJSON(url, function(response) { |
||
| 1586 | response = self.storage.formatResponse(jqXHR); |
||
| 1587 | if(!response.error) { |
||
| 1588 | self.editPhoto(metadata, response.data.tmp); |
||
| 1589 | } else { |
||
| 1590 | $(document).trigger('status.contacts.error', response); |
||
| 1591 | } |
||
| 1592 | }).fail(function(response) { |
||
| 1593 | response = self.storage.formatResponse(jqXHR); |
||
| 1594 | console.warn('response', response); |
||
| 1595 | $(document).trigger('status.contacts.error', response); |
||
| 1596 | }); |
||
| 1597 | }, |
||
| 1598 | editPhoto:function(metadata, tmpkey) { |
||
| 1599 | console.log('editPhoto', metadata, tmpkey); |
||
| 1600 | $('.tipsy').remove(); |
||
| 1601 | // Simple event handler, called from onChange and onSelect |
||
| 1602 | // event handlers, as per the Jcrop invocation below |
||
| 1603 | var showCoords = function(c) { |
||
| 1604 | $('#x').val(c.x); |
||
| 1605 | $('#y').val(c.y); |
||
| 1606 | $('#w').val(c.w); |
||
| 1607 | $('#h').val(c.h); |
||
| 1608 | }; |
||
| 1609 | |||
| 1610 | var clearCoords = function() { |
||
| 1611 | $('#coords input').val(''); |
||
| 1612 | }; |
||
| 1613 | |||
| 1614 | var self = this; |
||
| 1615 | if(!this.$cropBoxTmpl) { |
||
| 1616 | this.$cropBoxTmpl = $('#cropBoxTemplate'); |
||
| 1617 | } |
||
| 1618 | var $container = $('<div />').appendTo($('#content')); |
||
| 1619 | var $dlg = this.$cropBoxTmpl.octemplate().prependTo($container); |
||
| 1620 | |||
| 1621 | $.when(this.storage.getTempContactPhoto( |
||
| 1622 | metadata.backend, |
||
| 1623 | metadata.addressBookId, |
||
| 1624 | metadata.contactId, |
||
| 1625 | tmpkey |
||
| 1626 | )) |
||
| 1627 | .then(function(image) { |
||
| 1628 | var x = 5, y = 5, w = Math.min(image.width, image.height), h = w; |
||
| 1629 | //$dlg.css({'min-width': w, 'min-height': h}); |
||
| 1630 | console.log(x,y,w,h); |
||
| 1631 | $(image).attr('id', 'cropbox').prependTo($dlg).show() |
||
| 1632 | .Jcrop({ |
||
| 1633 | onChange: showCoords, |
||
| 1634 | onSelect: showCoords, |
||
| 1635 | onRelease: clearCoords, |
||
| 1636 | //maxSize: [w, h], |
||
| 1637 | bgColor: 'black', |
||
| 1638 | bgOpacity: .4, |
||
|
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
Loading history...
|
|||
| 1639 | boxWidth: 400, |
||
| 1640 | boxHeight: 400, |
||
| 1641 | setSelect: [ x, y, w-10, h-10 ], |
||
| 1642 | aspectRatio: 1 |
||
| 1643 | }); |
||
| 1644 | $container.ocdialog({ |
||
| 1645 | modal: true, |
||
| 1646 | closeOnEscape: true, |
||
| 1647 | title: t('contacts', 'Edit profile picture'), |
||
| 1648 | height: image.height+100, width: image.width+20, |
||
| 1649 | buttons: [ |
||
| 1650 | { |
||
| 1651 | text: t('contacts', 'Crop photo'), |
||
| 1652 | click:function() { |
||
| 1653 | self.savePhoto($(this), metadata, tmpkey, function() { |
||
| 1654 | $container.ocdialog('close'); |
||
| 1655 | }); |
||
| 1656 | }, |
||
| 1657 | defaultButton: true |
||
| 1658 | } |
||
| 1659 | ], |
||
| 1660 | close: function(/*event, ui*/) { |
||
| 1661 | $(this).ocdialog('destroy').remove(); |
||
| 1662 | $container.remove(); |
||
| 1663 | }, |
||
| 1664 | open: function(/*event, ui*/) { |
||
| 1665 | showCoords({x:x,y:y,w:w-10,h:h-10}); |
||
| 1666 | } |
||
| 1667 | }); |
||
| 1668 | }) |
||
| 1669 | .fail(function() { |
||
| 1670 | console.warn('Error getting temporary photo'); |
||
| 1671 | }); |
||
| 1672 | }, |
||
| 1673 | savePhoto:function($dlg, metaData, key, cb) { |
||
| 1674 | var coords = {}; |
||
| 1675 | $.each($dlg.find('#coords').serializeArray(), function(idx, coord) { |
||
| 1676 | coords[coord.name] = coord.value; |
||
| 1677 | }); |
||
| 1678 | |||
| 1679 | $.when(this.storage.cropContactPhoto( |
||
| 1680 | metaData.backend, metaData.addressBookId, metaData.contactId, key, coords |
||
| 1681 | )) |
||
| 1682 | .then(function(response) { |
||
| 1683 | $(document).trigger('status.contact.photoupdated', { |
||
| 1684 | id: response.data.id, |
||
| 1685 | thumbnail: response.data.thumbnail |
||
| 1686 | }); |
||
| 1687 | }) |
||
| 1688 | .fail(function(response) { |
||
| 1689 | console.log('response', response); |
||
| 1690 | if(!response || !response.message) { |
||
| 1691 | $(document).trigger('status.contacts.error', { |
||
| 1692 | message:t('contacts', 'Network or server error. Please inform administrator.') |
||
| 1693 | }); |
||
| 1694 | } else { |
||
| 1695 | $(document).trigger('status.contacts.error', response); |
||
| 1696 | } |
||
| 1697 | }) |
||
| 1698 | .always(function() { |
||
| 1699 | cb(); |
||
| 1700 | }); |
||
| 1701 | } |
||
| 1702 | }; |
||
| 1703 | })(window, jQuery, OC); |
||
| 1704 | |||
| 1705 | $(document).ready(function() { |
||
| 1706 | |||
| 1707 | $.getScript(OC.generateUrl('apps/contacts/ajax/config.js')) |
||
| 1708 | .done(function() { |
||
| 1709 | OC.Contacts.init(); |
||
| 1710 | }) |
||
| 1711 | .fail(function(jqxhr, settings, exception) { |
||
| 1712 | console.log('Failed loading settings.', jqxhr, settings, exception); |
||
| 1713 | }); |
||
| 1714 | |||
| 1715 | }); |
||
| 1716 |