Changeset a61bbb2 in github
- Timestamp:
- Mar 26, 2010 12:38:20 PM (3 years ago)
- Branches:
- master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
- Children:
- 0dc5bc8
- Parents:
- c75f8e9
- Files:
-
- 2 added
- 24 edited
-
CHANGELOG (modified) (1 diff)
-
SQL/mysql.initial.sql (modified) (1 diff)
-
SQL/mysql.update.sql (modified) (1 diff)
-
SQL/sqlite.initial.sql (modified) (2 diffs)
-
SQL/sqlite.update.sql (modified) (1 diff)
-
config/db.inc.php.dist (modified) (1 diff)
-
index.php (modified) (1 diff)
-
program/include/rcmail.php (modified) (2 diffs)
-
program/include/rcube_addressbook.php (modified) (3 diffs)
-
program/include/rcube_contacts.php (modified) (6 diffs)
-
program/js/app.js (modified) (31 diffs)
-
program/localization/de_CH/labels.inc (modified) (1 diff)
-
program/localization/de_CH/messages.inc (modified) (1 diff)
-
program/localization/en_US/labels.inc (modified) (2 diffs)
-
program/localization/en_US/messages.inc (modified) (1 diff)
-
program/steps/addressbook/func.inc (modified) (4 diffs)
-
program/steps/addressbook/groups.inc (added)
-
program/steps/mail/autocomplete.inc (modified) (4 diffs)
-
skins/default/addressbook.css (modified) (9 diffs)
-
skins/default/functions.js (modified) (4 diffs)
-
skins/default/images/icons/folders.png (modified) (previous)
-
skins/default/images/icons/groupactions.png (added)
-
skins/default/images/listheader.gif (modified) (previous)
-
skins/default/mail.css (modified) (1 diff)
-
skins/default/templates/addressbook.html (modified) (2 diffs)
-
skins/default/templates/mail.html (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r33e2e42 ra61bbb2 2 2 =========================== 3 3 4 - Added contact groups in address book (not finished yet) 4 5 - Added PageUp/PageDown/Home/End keys support on lists (#1486430) 5 6 - Added possibility to select all messages in a folder (#1484756) -
SQL/mysql.initial.sql
r94fe9ca ra61bbb2 95 95 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; 96 96 97 -- Table structure for table `contactgroups` 98 99 CREATE TABLE `contactgroups` ( 100 `contactgroup_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, 101 `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0', 102 `changed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 103 `del` tinyint(1) NOT NULL DEFAULT '0', 104 `name` varchar(128) NOT NULL DEFAULT '', 105 PRIMARY KEY(`contactgroup_id`), 106 CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`) 107 REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, 108 INDEX `contactgroups_user_index` (`user_id`,`del`) 109 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; 110 111 CREATE TABLE `contactgroupmembers` ( 112 `contactgroup_id` int(10) UNSIGNED NOT NULL, 113 `contact_id` int(10) UNSIGNED NOT NULL DEFAULT '0', 114 `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 115 PRIMARY KEY (`contactgroup_id`, `contact_id`), 116 CONSTRAINT `contactgroup_id_fk_contactgroups` FOREIGN KEY (`contactgroup_id`) 117 REFERENCES `contactgroups`(`contactgroup_id`) ON DELETE CASCADE ON UPDATE CASCADE, 118 CONSTRAINT `contact_id_fk_contacts` FOREIGN KEY (`contact_id`) 119 REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE 120 ) /*!40000 ENGINE=INNODB */; 121 97 122 98 123 -- Table structure for table `identities` -
SQL/mysql.update.sql
rac756e8 ra61bbb2 84 84 ALTER TABLE `identities` ADD INDEX `user_identities_index` (`user_id`, `del`); 85 85 86 CREATE TABLE `contactgroups` ( 87 `contactgroup_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, 88 `user_id` int(10) UNSIGNED NOT NULL DEFAULT '0', 89 `changed` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 90 `del` tinyint(1) NOT NULL DEFAULT '0', 91 `name` varchar(128) NOT NULL DEFAULT '', 92 PRIMARY KEY(`contactgroup_id`), 93 CONSTRAINT `user_id_fk_contactgroups` FOREIGN KEY (`user_id`) 94 REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, 95 INDEX `contactgroups_user_index` (`user_id`,`del`) 96 ) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */; 97 98 CREATE TABLE `contactgroupmembers` ( 99 `contactgroup_id` int(10) UNSIGNED NOT NULL, 100 `contact_id` int(10) UNSIGNED NOT NULL DEFAULT '0', 101 `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 102 PRIMARY KEY (`contactgroup_id`, `contact_id`), 103 CONSTRAINT `contactgroup_id_fk_contactgroups` FOREIGN KEY (`contactgroup_id`) 104 REFERENCES `contactgroups`(`contactgroup_id`) ON DELETE CASCADE ON UPDATE CASCADE, 105 CONSTRAINT `contact_id_fk_contacts` FOREIGN KEY (`contact_id`) 106 REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE ON UPDATE CASCADE 107 ) /*!40000 ENGINE=INNODB */; 108 86 109 /*!40014 SET FOREIGN_KEY_CHECKS=1 */; -
SQL/sqlite.initial.sql
r94fe9ca ra61bbb2 20 20 21 21 -- 22 -- Table structure for table contacts 22 -- Table structure for table contacts and related 23 23 -- 24 24 … … 36 36 37 37 CREATE INDEX ix_contacts_user_id ON contacts(user_id, email); 38 39 40 CREATE TABLE contactgroups ( 41 contactgroup_id integer NOT NULL PRIMARY KEY, 42 user_id integer NOT NULL default '0', 43 changed datetime NOT NULL default '0000-00-00 00:00:00', 44 del tinyint NOT NULL default '0', 45 name varchar(128) NOT NULL default '' 46 ); 47 48 CREATE INDEX ix_contactgroups_user_id ON contactgroups(user_id, del); 49 50 51 CREATE TABLE contactgroupmembers ( 52 contactgroup_id integer NOT NULL, 53 contact_id integer NOT NULL default '0', 54 created datetime NOT NULL default '0000-00-00 00:00:00', 55 PRIMARY KEY (contactgroup_id, contact_id) 56 ); 57 38 58 39 59 -- -------------------------------------------------------- -
SQL/sqlite.update.sql
r94fe9ca ra61bbb2 48 48 DROP INDEX ix_identities_user_id; 49 49 CREATE INDEX ix_identities_user_id ON identities (user_id, del); 50 51 CREATE TABLE contactgroups ( 52 contactgroup_id integer NOT NULL PRIMARY KEY, 53 user_id integer NOT NULL default '0', 54 changed datetime NOT NULL default '0000-00-00 00:00:00', 55 del tinyint NOT NULL default '0', 56 name varchar(128) NOT NULL default '' 57 ); 58 59 CREATE INDEX ix_contactgroups_user_id ON contactgroups(user_id, del); 60 61 CREATE TABLE contactgroupmembers ( 62 contactgroup_id integer NOT NULL, 63 contact_id integer NOT NULL default '0', 64 created datetime NOT NULL default '0000-00-00 00:00:00', 65 PRIMARY KEY (contactgroup_id, contact_id) 66 ); 67 -
config/db.inc.php.dist
r2273d41 ra61bbb2 45 45 $rcmail_config['db_table_contacts'] = 'contacts'; 46 46 47 $rcmail_config['db_table_contactgroups'] = 'contactgroups'; 48 49 $rcmail_config['db_table_contactgroupmembers'] = 'contactgroupmembers'; 50 47 51 $rcmail_config['db_table_session'] = 'session'; 48 52 -
index.php
rf52c936f ra61bbb2 218 218 'addressbook' => array( 219 219 'add' => 'edit.inc', 220 'create-group' => 'groups.inc', 221 'delete-group' => 'groups.inc', 222 'removefromgroup' => 'groups.inc', 223 'add2group' => 'groups.inc', 220 224 ), 221 225 -
program/include/rcmail.php
rd8c440c ra61bbb2 301 301 $list['0'] = array( 302 302 'id' => 0, 303 'name' => rcube_label('personaladrbook'), 303 'name' => rcube_label('personaladrbook'), 304 'groups' => true, 304 305 'readonly' => false, 305 'autocomplete' => in_array('sql', $autocomplete)306 'autocomplete' => in_array('sql', $autocomplete) 306 307 ); 307 308 } … … 310 311 foreach ($ldap_config as $id => $prop) 311 312 $list[$id] = array( 312 'id' => $id, 313 'name' => $prop['name'], 314 'readonly' => !$prop['writable'], 315 'autocomplete' => in_array('sql', $autocomplete) 313 'id' => $id, 314 'name' => $prop['name'], 315 'groups' => false, 316 'readonly' => !$prop['writable'], 317 'autocomplete' => in_array('sql', $autocomplete) 316 318 ); 317 319 } -
program/include/rcube_addressbook.php
r1d786c8 ra61bbb2 30 30 /** public properties */ 31 31 var $primary_key; 32 var $groups = false; 32 33 var $readonly = true; 33 34 var $ready = false; … … 62 63 */ 63 64 abstract function list_records($cols=null, $subset=0); 65 66 /** 67 * List all active contact groups of this source 68 * 69 * @return array Indexed list of contact groups, each a hash array 70 */ 71 function list_groups() { } 64 72 65 73 /** … … 125 133 126 134 /** 135 * Setter for the current group 136 * (empty, has to be re-implemented by extending class) 137 */ 138 function set_group($gid) { } 139 140 /** 127 141 * Create a new contact record 128 142 * -
program/include/rcube_contacts.php
reb27aad ra61bbb2 40 40 var $primary_key = 'contact_id'; 41 41 var $readonly = false; 42 var $groups = true; 42 43 var $list_page = 1; 43 44 var $page_size = 10; 45 var $group_id = 0; 44 46 var $ready = false; 45 47 … … 83 85 84 86 /** 87 * Setter for the current group 88 * (empty, has to be re-implemented by extending class) 89 */ 90 function set_group($gid) 91 { 92 $this->group_id = $gid; 93 } 94 95 96 /** 85 97 * Reset all saved results and search parameters 86 98 */ … … 93 105 } 94 106 107 /** 108 * List all active contact groups of this source 109 * 110 * @param string Search string to match group name 111 * @return array Indexed list of contact groups, each a hash array 112 */ 113 function list_groups($search = null) 114 { 115 $results = array(); 116 $sql_filter = $search ? "AND " . $this->db->ilike('name', '%'.$search.'%') : ''; 117 118 $sql_result = $this->db->query( 119 "SELECT * FROM ".get_table_name('contactgroups')." 120 WHERE del<>1 121 AND user_id=? 122 $sql_filter 123 ORDER BY name", 124 $this->user_id); 125 126 while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { 127 $sql_arr['ID'] = $sql_arr['contactgroup_id']; 128 $results[] = $sql_arr; 129 } 130 131 return $results; 132 } 95 133 96 134 /** … … 110 148 if ($this->result->count) 111 149 { 150 if ($this->group_id) 151 $join = "LEFT JOIN ".get_table_name('contactgroupmembers')." AS rcmgrouplinks". 152 " ON (rcmgrouplinks.contact_id=rcmcontacts.".$this->primary_key.")"; 153 112 154 $start_row = $subset < 0 ? $this->result->first + $this->page_size + $subset : $this->result->first; 113 155 $length = $subset != 0 ? abs($subset) : $this->page_size; 114 156 115 157 $sql_result = $this->db->limitquery( 116 "SELECT * FROM ".$this->db_name." 117 WHERE del<>1 118 AND user_id=?" . 158 "SELECT * FROM ".$this->db_name." AS rcmcontacts ".$join." 159 WHERE rcmcontacts.del<>1 160 AND rcmcontacts.user_id=?" . 161 ($this->group_id ? " AND rcmgrouplinks.contactgroup_id=?" : ""). 119 162 ($this->filter ? " AND (".$this->filter.")" : "") . 120 " ORDER BY name",163 " ORDER BY rcmcontacts.name", 121 164 $start_row, 122 165 $length, 123 $this->user_id); 166 $this->user_id, 167 $this->group_id); 124 168 } 125 169 … … 185 229 function count() 186 230 { 231 if ($this->group_id) 232 $join = "LEFT JOIN ".get_table_name('contactgroupmembers')." AS rcmgrouplinks". 233 " ON (rcmgrouplinks.contact_id=rcmcontacts.".$this->primary_key.")"; 234 187 235 // count contacts for this user 188 236 $sql_result = $this->db->query( 189 "SELECT COUNT(contact_id) AS rows 190 FROM ".$this->db_name." 191 WHERE del<>1 192 AND user_id=?". 237 "SELECT COUNT(rcmcontacts.contact_id) AS rows 238 FROM ".$this->db_name." AS rcmcontacts ".$join." 239 WHERE rcmcontacts.del<>1 240 AND rcmcontacts.user_id=?". 241 ($this->group_id ? " AND rcmgrouplinks.contactgroup_id=?" : ""). 193 242 ($this->filter ? " AND (".$this->filter.")" : ""), 194 $this->user_id); 243 $this->user_id, 244 $this->group_id); 195 245 196 246 $sql_arr = $this->db->fetch_assoc($sql_result); … … 358 408 } 359 409 410 411 /** 412 * Create a contact group with the given name 413 * 414 * @param string The group name 415 * @return False on error, array with record props in success 416 */ 417 function create_group($name) 418 { 419 $result = false; 420 421 $sql_result = $this->db->query( 422 "SELECT * FROM ".get_table_name('contactgroups')." 423 WHERE del<>1 424 AND user_id=? 425 AND name LIKE ?", 426 $this->user_id, 427 $name . '%'); 428 429 // make sure we have a unique name 430 if ($num = $this->db->num_rows($sql_result)) 431 $name .= ' ' . ($num+1); 432 433 $this->db->query( 434 "INSERT INTO ".get_table_name('contactgroups')." (user_id, changed, name) 435 VALUES (".intval($this->user_id).", ".$this->db->now().", ".$this->db->quote($name).")" 436 ); 437 438 if ($insert_id = $this->db->insert_id('contactgroups')) 439 $result = array('id' => $insert_id, 'name' => $name); 440 441 return $result; 442 } 443 444 /** 445 * Delete the given group and all linked group members 446 * 447 * @param string Group identifier 448 */ 449 function delete_group($gid) 450 { 451 $sql_result = $this->db->query( 452 "DELETE FROM ".get_table_name('contactgroupmembers')." 453 WHERE contactgroup_id=?", 454 $gid); 455 456 $sql_result = $this->db->query( 457 "UPDATE ".get_table_name('contactgroups')." 458 SET del=1, changed=".$this->db->now()." 459 WHERE contactgroup_id=?", 460 $gid); 461 462 return $this->db->affected_rows(); 463 } 464 465 /** 466 * Add the given contact records the a certain group 467 * 468 * @param string Group identifier 469 * @param array List of contact identifiers to be added 470 */ 471 function add_to_group($group_id, $ids) 472 { 473 if (!is_array($ids)) 474 $ids = explode(',', $ids); 475 476 $added = 0; 477 478 foreach ($ids as $contact_id) { 479 $sql_result = $this->db->query( 480 "SELECT 1 FROM ".get_table_name('contactgroupmembers')." 481 WHERE contactgroup_id=? 482 AND contact_id=?", 483 $group_id, 484 $contact_id); 485 486 if (!$this->db->num_rows($sql_result)) { 487 $this->db->query( 488 "INSERT INTO ".get_table_name('contactgroupmembers')." (contactgroup_id, contact_id, created) 489 VALUES (".intval($group_id).", ".intval($contact_id).", ".$this->db->now().")" 490 ); 491 if (!$this->db->db_error) 492 $added++; 493 } 494 } 495 496 return $added; 497 } 498 499 500 /** 501 * Remove the given contact records from a certain group 502 * 503 * @param string Group identifier 504 * @param array List of contact identifiers to be removed 505 */ 506 function remove_from_group($group_id, $ids) 507 { 508 if (!is_array($ids)) 509 $ids = explode(',', $ids); 510 511 $sql_result = $this->db->query( 512 "DELETE FROM ".get_table_name('contactgroupmembers')." 513 WHERE contactgroup_id=? 514 AND contact_id IN (".join(',', array_map(array($this->db, 'quote'), $ids)).")", 515 $group_id); 516 517 return $this->db->affected_rows(); 518 } 519 360 520 } -
program/js/app.js
r33e2e42 ra61bbb2 285 285 286 286 case 'addressbook': 287 if (this.gui_objects.folderlist) 288 this.env.contactfolders = $.extend($.extend({}, this.env.address_sources), this.env.contactgroups); 289 287 290 if (this.gui_objects.contactslist) 288 291 { 289 this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, {multiselect:true, draggable:true, keyboard:true}); 292 this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, 293 {multiselect:true, draggable:this.gui_objects.folderlist?true:false, keyboard:true}); 290 294 this.contact_list.row_init = function(row){ p.triggerEvent('insertrow', { cid:row.uid, row:row }); }; 291 295 this.contact_list.addEventListener('keypress', function(o){ p.contactlist_keypress(o); }); … … 307 311 this.contact_list.focus(); 308 312 309 this.gui_objects.folderlist = this.gui_objects.contactslist;313 //this.gui_objects.folderlist = this.gui_objects.contactslist; 310 314 } 311 315 312 316 this.set_page_buttons(); 313 317 314 if (this.env.address_sources && this.env.address_sources[this.env.source] && !this.env.address_sources[this.env.source].readonly) 318 if (this.env.address_sources && this.env.address_sources[this.env.source] && !this.env.address_sources[this.env.source].readonly) { 315 319 this.enable_command('add', 'import', true); 320 this.enable_command('add-group', this.env.address_sources[this.env.source].groups); 321 } 316 322 317 323 if (this.env.cid) … … 326 332 this.enable_command('export', true); 327 333 328 this.enable_command('list', true);334 this.enable_command('list', 'listgroup', true); 329 335 break; 330 336 … … 490 496 case 'menu-open': 491 497 case 'menu-save': 492 this.triggerEvent(command, {props:props}); 493 return false; 494 break; 498 this.triggerEvent(command, {props:props}); 499 return false; 495 500 496 501 case 'open': … … 523 528 this.enable_command('add', 'import', (this.env.address_sources && !this.env.address_sources[props].readonly)); 524 529 } 530 break; 531 532 533 case 'listgroup': 534 this.list_contacts(null, props); 525 535 break; 526 536 … … 970 980 this.add_contact(props); 971 981 break; 972 982 973 983 // quicksearch 974 984 case 'search': … … 989 999 this.list_mailbox(this.env.mailbox); 990 1000 else if (s && this.task == 'addressbook') 991 this.list_contacts(this.env.source); 1001 this.list_contacts(this.env.source, this.env.group); 1002 break; 1003 1004 case 'add-group': 1005 this.add_contact_group(props) 992 1006 break; 993 1007 … … 1192 1206 this.contact_list.blur(); 1193 1207 list = this.contact_list; 1194 model = this.env. address_sources;1208 model = this.env.contactfolders; 1195 1209 } 1196 1210 else if (this.ksearch_value) { … … 1200 1214 // handle mouse release when dragging 1201 1215 if (this.drag_active && model && this.env.last_folder_target) { 1202 var mbox = model[this.env.last_folder_target].id;1203 1216 var target = model[this.env.last_folder_target]; 1217 1204 1218 $(this.get_folder_li(this.env.last_folder_target)).removeClass('droptarget'); 1205 1219 this.env.last_folder_target = null; 1206 1220 list.draglayer.hide(); 1207 1221 1208 if (!this.drag_menu(e, mbox))1209 this.command('moveto', mbox);1222 if (!this.drag_menu(e, target)) 1223 this.command('moveto', target); 1210 1224 } 1211 1225 … … 1219 1233 }; 1220 1234 1221 this.drag_menu = function(e, mbox)1235 this.drag_menu = function(e, target) 1222 1236 { 1223 1237 var modkey = rcube_event.get_modifier(e); 1224 1238 var menu = $('#'+this.gui_objects.message_dragmenu); 1225 1239 1226 if (menu && modkey == SHIFT_KEY ) {1240 if (menu && modkey == SHIFT_KEY && this.commands['copy']) { 1227 1241 var pos = rcube_event.get_mouse_pos(e); 1228 this.env.drag_ mbox = mbox;1242 this.env.drag_target = target; 1229 1243 menu.css({top: (pos.y-10)+'px', left: (pos.x-10)+'px'}).show(); 1230 1244 return true; 1231 1245 } 1246 1247 return false; 1232 1248 }; 1233 1249 … … 1238 1254 menu.hide(); 1239 1255 } 1240 this.command(action, this.env.drag_ mbox);1241 this.env.drag_ mbox= null;1256 this.command(action, this.env.drag_target); 1257 this.env.drag_target = null; 1242 1258 }; 1243 1259 1244 1260 this.drag_start = function(list) 1245 1261 { 1246 var model = this.task == 'mail' ? this.env.mailboxes : this.env. address_sources;1262 var model = this.task == 'mail' ? this.env.mailboxes : this.env.contactfolders; 1247 1263 1248 1264 this.drag_active = true; … … 1485 1501 return (this.env.mailboxes[id] && this.env.mailboxes[id].id != this.env.mailbox && !this.env.mailboxes[id].virtual); 1486 1502 else if (this.task == 'addressbook') 1487 return (id != this.env.source && this.env.address_sources[id] && !this.env.address_sources[id].readonly); 1503 return (id != this.env.source && this.env.contactfolders[id] && !this.env.contactfolders[id].readonly && 1504 !(!this.env.source && this.env.contactfolders[id].group) && 1505 !(this.env.contactfolders[id].type == 'group' && this.env.contactfolders[id].id == this.env.group)); 1488 1506 else if (this.task == 'settings') 1489 1507 return (id != this.env.folder); … … 1785 1803 this.list_mailbox(this.env.mailbox, page); 1786 1804 else if (this.task=='addressbook') 1787 this.list_contacts(this.env.source, page);1805 this.list_contacts(this.env.source, null, page); 1788 1806 } 1789 1807 }; … … 2175 2193 this.move_messages = function(mbox) 2176 2194 { 2195 if (mbox && typeof mbox == 'object') 2196 mbox = mbox.id; 2197 2177 2198 // exit if current or no mailbox specified or if selection is empty 2178 2199 if (!mbox || mbox == this.env.mailbox || (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length))) … … 3098 3119 + (this.env.mailbox ? '&_mbox='+urlencode(this.env.mailbox) : '') 3099 3120 + (this.env.source ? '&_source='+urlencode(this.env.source) : '') 3121 + (this.env.group ? '&_gid='+urlencode(this.env.group) : '') 3100 3122 + (addurl ? addurl : ''), true); 3101 3123 } … … 3209 3231 var pre = this.ksearch_input.value.substring(0, p); 3210 3232 var end = this.ksearch_input.value.substring(p+this.ksearch_value.length, this.ksearch_input.value.length); 3211 var insert = this.env.contacts[id]+', '; 3233 var insert = ''; 3234 3235 // insert all members of a group 3236 if (typeof this.env.contacts[id] == 'object' && this.env.contacts[id].members) { 3237 for (var i=0; i < this.env.contacts[id].members.length; i++) 3238 insert += this.env.contacts[id].members[i] + ', '; 3239 } 3240 else if (typeof this.env.contacts[id] == 'string') 3241 insert = this.env.contacts[id] + ', '; 3242 3212 3243 this.ksearch_input.value = pre + insert + end; 3213 3244 … … 3270 3301 // display search results 3271 3302 if (a_results.length && this.ksearch_input && this.ksearch_value) { 3272 var p, ul, li, s_val = this.ksearch_value;3303 var p, ul, li, text, s_val = this.ksearch_value; 3273 3304 3274 3305 // create results pane if not present … … 3284 3315 3285 3316 // add each result line to list 3286 for (i=0; i<a_results.length; i++) { 3317 for (i=0; i < a_results.length; i++) { 3318 text = typeof a_results[i] == 'object' ? a_results[i].name : a_results[i]; 3287 3319 li = document.createElement('LI'); 3288 li.innerHTML = a_results[i].replace(new RegExp('('+s_val+')', 'ig'), '##$1%%').replace(/</g, '<').replace(/>/g, '>').replace(/##([^%]+)%%/g, '<b>$1</b>');3320 li.innerHTML = text.replace(new RegExp('('+s_val+')', 'ig'), '##$1%%').replace(/</g, '<').replace(/>/g, '>').replace(/##([^%]+)%%/g, '<b>$1</b>'); 3289 3321 li.onmouseover = function(){ ref.ksearch_select(this); }; 3290 3322 li.onmouseup = function(){ ref.ksearch_click(this) }; … … 3364 3396 }; 3365 3397 3366 this.list_contacts = function(src, page)3398 this.list_contacts = function(src, group, page) 3367 3399 { 3368 3400 var add_url = ''; 3369 3401 var target = window; 3370 3402 3403 // currently all groups belong to the local address book 3404 if (group) 3405 src = 0; 3406 3371 3407 if (!src) 3372 3408 src = this.env.source; 3373 3409 3374 if (page && this.current_page ==page && src == this.env.source)3410 if (page && this.current_page == page && src == this.env.source && group == this.env.group) 3375 3411 return false; 3376 3412 … … 3381 3417 this.reset_qsearch(); 3382 3418 } 3419 else if (group != this.env.group) 3420 page = this.env.current_page = 1; 3383 3421 3384 3422 this.select_folder(src, this.env.source); 3423 this.select_folder(group, this.env.group, 'rcmliG'); 3424 3385 3425 this.env.source = src; 3426 this.env.group = group; 3386 3427 3387 3428 // load contacts remotely 3388 3429 if (this.gui_objects.contactslist) 3389 3430 { 3390 this.list_contacts_remote(src, page);3431 this.list_contacts_remote(src, group, page); 3391 3432 return; 3392 3433 } … … 3397 3438 add_url = '&_framed=1'; 3398 3439 } 3440 3441 if (group) 3442 add_url += '&_gid='+group; 3443 if (page) 3444 add_url += '&_page='+page; 3399 3445 3400 3446 // also send search request to get the correct listing … … 3403 3449 3404 3450 this.set_busy(true, 'loading'); 3405 target.location.href = this.env.comm_path +(src ? '&_source='+urlencode(src) : '')+(page ? '&_page='+page : '')+add_url;3451 target.location.href = this.env.comm_path + (src ? '&_source='+urlencode(src) : '') + add_url; 3406 3452 }; 3407 3453 3408 3454 // send remote request to load contacts list 3409 this.list_contacts_remote = function(src, page)3455 this.list_contacts_remote = function(src, group, page) 3410 3456 { 3411 3457 // clear message list first … … 3417 3463 var url = (src ? '_source='+urlencode(src) : '') + (page ? (src?'&':'') + '_page='+page : ''); 3418 3464 this.env.source = src; 3465 this.env.group = group; 3466 3467 if (group) 3468 url += '&_gid='+group; 3419 3469 3420 3470 // also send search request to get the right messages … … 3454 3504 cid = this.contact_list.get_selection().join(','); 3455 3505 3456 if (to != this.env.source && cid && this.env.address_sources[to] && !this.env.address_sources[to].readonly) 3457 this.http_post('copy', '_cid='+urlencode(cid)+'&_source='+urlencode(this.env.source)+'&_to='+urlencode(to)); 3506 if (to.type == 'group') 3507 this.http_post('add2group', '_cid='+urlencode(cid)+'&_source='+urlencode(this.env.source)+'&_gid='+urlencode(to.id)); 3508 else if (to.id != this.env.source && cid && this.env.address_sources[to.id] && !this.env.address_sources[to.id].readonly) 3509 this.http_post('copy', '_cid='+urlencode(cid)+'&_source='+urlencode(this.env.source)+'&_to='+urlencode(to.id)); 3458 3510 }; 3459 3511 … … 3463 3515 // exit if no mailbox specified or if selection is empty 3464 3516 var selection = this.contact_list.get_selection(); 3465 if (!(selection.length || this.env.cid) || !confirm(this.get_label('deletecontactconfirm')))3517 if (!(selection.length || this.env.cid) || (!this.env.group && !confirm(this.get_label('deletecontactconfirm')))) 3466 3518 return; 3467 3519 … … 3491 3543 3492 3544 // send request to server 3493 this.http_post('delete', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source)+'&_from='+(this.env.action ? this.env.action : '')+qs); 3545 if (this.env.group) 3546 this.http_post('removefromgroup', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source)+'&_gid='+urlencode(this.env.group)+qs); 3547 else 3548 this.http_post('delete', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source)+'&_from='+(this.env.action ? this.env.action : '')+qs); 3549 3494 3550 return true; 3495 3551 }; … … 3506 3562 // cid change 3507 3563 if (newcid) { 3508 row.id = 'rcmrow' + newcid;3564 row.id = 'rcmrow' + newcid; 3509 3565 this.contact_list.remove_row(cid); 3510 3566 this.contact_list.init_row(row); 3511 this.contact_list.selection[0] = newcid;3512 row.style.display = '';3567 this.contact_list.selection[0] = newcid; 3568 ow.style.display = ''; 3513 3569 } 3514 3570 … … 3548 3604 this.enable_command('export', (this.contact_list.rowcount > 0)); 3549 3605 }; 3606 3607 3608 this.add_contact_group = function() 3609 { 3610 if (!this.gui_objects.folderlist || !this.env.address_sources[this.env.source].groups) 3611 return; 3612 3613 if (!this.name_input) { 3614 this.name_input = document.createElement('input'); 3615 this.name_input.type = 'text'; 3616 this.name_input.onkeypress = function(e){ return rcmail.add_input_keypress(e); }; 3617 3618 this.gui_objects.folderlist.parentNode.appendChild(this.name_input); 3619 } 3620 3621 this.name_input.select(); 3622 }; 3623 3624 // handler for keyboard events on the input field 3625 this.add_input_keypress = function(e) 3626 { 3627 var key = rcube_event.get_keycode(e); 3628 3629 // enter 3630 if (key == 13) { 3631 var newname = this.name_input.value; 3632 3633 if (newname) { 3634 this.set_busy(true, 'loading'); 3635 this.http_post('create-group', '_source='+urlencode(this.env.source)+'&_name='+urlencode(newname), true); 3636 } 3637 return false; 3638 } 3639 // escape 3640 else if (key == 27) 3641 this.reset_add_input(); 3642 3643 return true; 3644 }; 3645 3646 this.reset_add_input = function() 3647 { 3648 if (this.name_input) { 3649 this.name_input.parentNode.removeChild(this.name_input); 3650 this.name_input = null; 3651 } 3652 }; 3653 3654 // callback for creating a new contact group 3655 this.insert_contact_group = function(prop) 3656 { 3657 this.reset_add_input(); 3658 } 3550 3659 3551 3660 … … 4257 4366 4258 4367 // mark a mailbox as selected and set environment variable 4259 this.select_folder = function(name, old )4368 this.select_folder = function(name, old, prefix) 4260 4369 { 4261 4370 if (this.gui_objects.folderlist) … … 4263 4372 var current_li, target_li; 4264 4373 4265 if ((current_li = this.get_folder_li(old ))) {4374 if ((current_li = this.get_folder_li(old, prefix))) { 4266 4375 $(current_li).removeClass('selected').removeClass('unfocused'); 4267 4376 } 4268 if ((target_li = this.get_folder_li(name ))) {4377 if ((target_li = this.get_folder_li(name, prefix))) { 4269 4378 $(target_li).removeClass('unfocused').addClass('selected'); 4270 4379 } 4271 4380 4272 4381 // trigger event hook 4273 this.triggerEvent('selectfolder', { folder:name, old:old });4382 this.triggerEvent('selectfolder', { folder:name, old:old, prefix:prefix }); 4274 4383 } 4275 4384 }; 4276 4385 4277 4386 // helper method to find a folder list item 4278 this.get_folder_li = function(name) 4279 { 4387 this.get_folder_li = function(name, prefix) 4388 { 4389 if (!prefix) 4390 prefix = 'rcmli'; 4280 4391 if (this.gui_objects.folderlist) 4281 4392 { 4282 4393 name = String(name).replace(this.identifier_expr, '_'); 4283 return document.getElementById( 'rcmli'+name);4394 return document.getElementById(prefix+name); 4284 4395 } 4285 4396 … … 4714 4825 this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0)); 4715 4826 4716 if (response.action == 'list') 4827 if (response.action == 'list') { 4828 this.enable_command('add-group', this.env.address_sources[this.env.source].groups); 4829 // disabeld for now: this.enable_command('rename-group', 'delete-group', this.env.address_sources[this.env.source].groups && this.env.group); 4717 4830 this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount }); 4831 } 4718 4832 } 4719 4833 break; -
program/localization/de_CH/labels.inc
r71e7545 ra61bbb2 215 215 $labels['export'] = 'Exportieren'; 216 216 $labels['exportvcards'] = 'Kontakte im vCard-Format exportieren'; 217 $labels['newcontactgroup'] = 'Neue Adressgruppe erstellen'; 218 $labels['groupactions'] = 'Aktionen fÌr Kontaktgruppen...'; 217 219 $labels['previouspage'] = 'Eine Seite zurÌck'; 218 220 $labels['firstpage'] = 'Erste Seite'; 219 221 $labels['nextpage'] = 'NÀchste Seite'; 220 222 $labels['lastpage'] = 'Letzte Seite'; 223 $labels['group'] = 'Gruppe'; 221 224 $labels['groups'] = 'Gruppen'; 222 225 $labels['personaladrbook'] = 'Persönliches Adressbuch'; -
program/localization/de_CH/messages.inc
r3c9aa23 ra61bbb2 94 94 $messages['selectimportfile'] = 'Bitte wÀhlen Sie eine Datei zum Importieren aus'; 95 95 $messages['addresswriterror'] = 'Das gewÀhlte Adressbuch kann nicht verÀndert werden'; 96 $messages['contactaddedtogroup'] = 'Kontakte wurden dieser Gruppe hinzugefÌgt'; 97 $messages['contactremovedfromgroup'] = 'Kontakte wurden aus dieser Gruppe entfernt'; 96 98 $messages['importwait'] = 'Daten werden importiert, bitte warten...'; 97 99 $messages['importerror'] = 'Import fehlgeschlagen! Die hochgeladene Datei ist nicht im vCard-Format.'; -
program/localization/en_US/labels.inc
rfb7ec57 ra61bbb2 259 259 $labels['export'] = 'Export'; 260 260 $labels['exportvcards'] = 'Export contacts in vCard format'; 261 $labels['newcontactgroup'] = 'Create new contact group'; 262 $labels['groupactions'] = 'Actions for contact groups...'; 261 263 262 264 $labels['previouspage'] = 'Show previous set'; … … 265 267 $labels['lastpage'] = 'Show last set'; 266 268 269 $labels['group'] = 'Group'; 267 270 $labels['groups'] = 'Groups'; 268 271 $labels['personaladrbook'] = 'Personal Addresses'; -
program/localization/en_US/messages.inc
rb1e74ac ra61bbb2 96 96 $messages['selectimportfile'] = 'Please select a file to upload'; 97 97 $messages['addresswriterror'] = 'The selected address book is not writeable'; 98 $messages['contactaddedtogroup'] = 'Successfully added the contacts to this group'; 99 $messages['contactremovedfromgroup'] = 'Successfully remove contacts from this group'; 98 100 $messages['importwait'] = 'Importing, please wait...'; 99 101 $messages['importerror'] = 'Import failed! The uploaded file is not a valid vCard file.'; -
program/steps/addressbook/func.inc
r3704b78 ra61bbb2 40 40 else 41 41 $CONTACTS->set_page(isset($_SESSION['page']) ?$_SESSION['page'] : 1); 42 43 if (!empty($_REQUEST['_gid'])) 44 $CONTACTS->set_group(get_input_value('_gid', RCUBE_INPUT_GPC)); 42 45 43 46 // set message set for search result … … 61 64 $local_id = '0'; 62 65 $current = get_input_value('_source', RCUBE_INPUT_GPC); 63 $line_templ = html::tag('li', array('id' => 'rcmli%s', 'class' => ' %s'),66 $line_templ = html::tag('li', array('id' => 'rcmli%s', 'class' => 'addressbook %s'), 64 67 html::a(array('href' => '%s', 'onclick' => "return ".JS_OBJECT_NAME.".command('list','%s',this)"), '%s')); 65 68 … … 80 83 Q(rcmail_url(null, array('_source' => $id))), $js_id, (!empty($source['name']) ? Q($source['name']) : Q($id))); 81 84 } 85 86 $out .= rcmail_contact_groups(array('items' => true)); 82 87 83 88 $OUTPUT->add_gui_object('folderlist', $attrib['id']); 84 89 85 90 return html::tag('ul', $attrib, $out, html::$common_attrib); 91 } 92 93 94 function rcmail_contact_groups($attrib) 95 { 96 global $CONTACTS, $OUTPUT; 97 98 if (!$attrib['id']) 99 $attrib['id'] = 'rcmgroupslist'; 100 101 $groups = $CONTACTS->list_groups(); 102 $line_templ = html::tag('li', array('id' => 'rcmliG%s', 'class' => 'contactgroup'), 103 html::a(array('href' => '#', 'onclick' => "return ".JS_OBJECT_NAME.".command('listgroup','%s',this)"), '%s')); 104 105 $jsdata = array(); 106 foreach ($groups as $group) { 107 $out .= sprintf($line_templ, $group['ID'], $group['ID'], Q($group['name'])); 108 $jsdata['G'.$group['ID']] = array('id' => $group['ID'], 'name' => $group['name'], 'type' => 'group'); 109 } 110 111 $OUTPUT->set_env('contactgroups', $jsdata); 112 //$OUTPUT->add_gui_object('groupslist', $attrib['id']); 113 114 return $attrib['items'] ? $out : html::tag('ul', $attrib, $out, html::$common_attrib); 86 115 } 87 116 … … 201 230 $OUTPUT->add_handlers(array( 202 231 'directorylist' => 'rcmail_directory_list', 232 // 'groupslist' => 'rcmail_contact_groups', 203 233 'addresslist' => 'rcmail_contacts_list', 204 234 'addressframe' => 'rcmail_contact_frame', -
program/steps/mail/autocomplete.inc
r1b5f98a ra61bbb2 6 6 | | 7 7 | This file is part of the RoundCube Webmail client | 8 | Copyright (C) 2008-20 09, RoundCube Dev Team |8 | Copyright (C) 2008-2010, RoundCube Dev Team | 9 9 | Licensed under the GNU GPL | 10 10 | | … … 24 24 $book_types = (array) $RCMAIL->config->get('autocomplete_addressbooks', 'sql'); 25 25 26 if ($book_types && $search = get_input_value('_search', RCUBE_INPUT_ POST, true)) {26 if ($book_types && $search = get_input_value('_search', RCUBE_INPUT_GPC, true)) { 27 27 28 28 foreach ($book_types as $id) { … … 33 33 while ($sql_arr = $result->iterate()) { 34 34 $contacts[] = format_email_recipient($sql_arr['email'], $sql_arr['name']); 35 if (count($contacts) >= $MAXNUM)35 if (count($contacts) >= $MAXNUM) 36 36 break 2; 37 } 38 } 39 40 // also list matching contact groups 41 if ($abook->groups) { 42 foreach ($abook->list_groups($search) as $group) { 43 $members = array(); 44 $abook->reset(); 45 $abook->set_group($group['ID']); 46 $result = $abook->list_records(array('email','name')); 47 while ($result && ($sql_arr = $result->iterate())) 48 $members[] = format_email_recipient($sql_arr['email'], $sql_arr['name']); 49 50 if (count($members)) { 51 $contacts[] = array('name' => $group['name'] . ' (' . rcube_label('group') . ')', 'members' => $members); 52 if (count($contacts) >= $MAXNUM) 53 break; 54 } 37 55 } 38 56 } 39 57 } 40 58 41 sort($contacts);59 usort($contacts, 'contact_results_sort'); 42 60 } 43 61 … … 45 63 $OUTPUT->send(); 46 64 65 66 function contact_results_sort($a, $b) 67 { 68 $name_a = is_array($a) ? $a['name'] : $a; 69 $name_b = is_array($b) ? $b['name'] : $b; 70 return strcmp(trim($name_a, '" '), trim($name_b, '" ')); 71 } 72 47 73 ?> -
skins/default/addressbook.css
r9224c8a ra61bbb2 5 5 position: absolute; 6 6 top: 45px; 7 left: 2 05px;7 left: 225px; 8 8 height: 35px; 9 9 } … … 77 77 { 78 78 position: absolute; 79 bottom: 16px;80 left: 2 00px;79 bottom: 6px; 80 left: 225px; 81 81 width: 240px; 82 82 height: 20px; … … 95 95 top: 85px; 96 96 right: 20px; 97 bottom: 40px;98 left: 2 05px;99 } 100 101 #directorylist 97 bottom: 30px; 98 left: 225px; 99 } 100 101 #directorylistbox 102 102 { 103 103 position: absolute; 104 104 top: 85px; 105 bottom: 40px;105 bottom: 30px; 106 106 left: 20px; 107 width: 1 75px;107 width: 195px; 108 108 border: 1px solid #999999; 109 109 background-color: #F9F9F9; 110 110 overflow: hidden; 111 } 112 113 #directorylistwarp 114 { 115 position: absolute; 116 top: 20px; 117 bottom: 22px; 118 left: 0; 119 right: 0; 120 overflow: auto; 121 } 122 123 #groups-title 124 { 125 position: absolute; 126 top: 0; 127 left: 0; 128 right: 0; 129 } 130 131 #directorylistbox input 132 { 133 display: absolute; 134 margin: 2px; 135 } 136 137 #directoylistbuttons 138 { 139 display: block; 140 position: absolute; 141 bottom: 0px; 142 left: 0px; 143 right: 0px; 144 height: 22px; 145 border-top: 1px solid #999; 146 background: url('images/listheader.gif') top left repeat-x #CCC; 147 } 148 149 #directoylistbuttons a.button, 150 #directoylistbuttons a.buttonPas 151 { 152 display: block; 153 float: left; 154 width: 34px; 155 height: 22px; 156 padding: 0px; 157 margin: 0; 158 overflow: hidden; 159 background: url('images/icons/groupactions.png') 0 0 no-repeat transparent; 160 opacity: 0.99; /* this is needed to make buttons appear correctly in Chrome */ 161 } 162 163 #directoylistbuttons a.groupactions { 164 background-position: 0 -26px; 165 } 166 167 #directoylistbuttons a.buttonPas { 168 opacity: 0.35; 111 169 } 112 170 … … 119 177 background-color: #F9F9F9; 120 178 overflow: auto; 179 } 180 181 #contactgroupslist 182 { 183 border-top: 1px solid #999; 121 184 } 122 185 … … 137 200 { 138 201 left: 0px; 139 width: 340px;202 width: 280px; 140 203 } 141 204 … … 145 208 } 146 209 147 #directorylist ul210 #directorylist 148 211 { 149 212 list-style: none; … … 153 216 } 154 217 155 #directorylist ul li 156 { 218 #directorylist li 219 { 220 display: block; 157 221 font-size: 11px; 222 background: url(images/icons/folders.png) 5px -108px no-repeat; 158 223 border-bottom: 1px solid #EBEBEB; 159 224 white-space: nowrap; 160 225 } 161 226 162 #directorylist ul li a 163 { 164 display: block; 165 padding-left: 6px; 227 #directorylist li a 228 { 229 cursor: default; 230 display: block; 231 padding-left: 25px; 166 232 padding-top: 2px; 167 233 padding-bottom: 2px; … … 170 236 } 171 237 238 #directorylist li.contactgroup 239 { 240 background-position: 5px -144px; 241 } 242 172 243 #directorylist li.selected 173 244 { … … 202 273 position: absolute; 203 274 top: 0px; 204 left: 555px;275 left: 290px; 205 276 right: 0px; 206 277 bottom: 0px; -
skins/default/functions.js
r39f9d39 ra61bbb2 127 127 function rcube_mail_ui() 128 128 { 129 this.markmenu = $('#markmessagemenu'); 130 this.searchmenu = $('#searchmenu'); 131 this.messagemenu = $('#messagemenu'); 132 this.listmenu = $('#listmenu'); 133 this.dragmessagemenu = $('#dragmessagemenu'); 129 this.popupmenus = { 130 markmenu:'markmessagemenu', 131 searchmenu:'searchmenu', 132 messagemenu:'messagemenu', 133 listmenu:'listmenu', 134 dragmessagemenu:'dragmessagemenu', 135 groupmenu:'groupoptionsmenu' 136 }; 137 138 var obj; 139 for (var k in this.popupmenus) { 140 obj = $('#'+this.popupmenus[k]) 141 if (obj.length) 142 this[k] = obj; 143 } 134 144 } 135 145 136 146 rcube_mail_ui.prototype = { 137 147 148 show_popupmenu: function(obj, refname, show, above) 149 { 150 if (typeof show == 'undefined') 151 show = obj.is(':visible') ? false : true; 152 153 var ref = rcube_find_object(refname); 154 if (show && ref) { 155 var pos = $(ref).offset(); 156 obj.css({ left:pos.left, top:(pos.top + (above ? -obj.height() : ref.offsetHeight)) }); 157 } 158 159 obj[show?'show':'hide'](); 160 }, 161 138 162 show_markmenu: function(show) 139 163 { 140 if (typeof show == 'undefined') 141 show = this.markmenu.is(':visible') ? false : true; 142 143 var ref = rcube_find_object('markreadbutton'); 144 if (show && ref) 145 this.markmenu.css({ left:ref.offsetLeft, top:(ref.offsetTop + ref.offsetHeight) }); 146 147 this.markmenu[show?'show':'hide'](); 164 this.show_popupmenu(this.markmenu, 'markreadbutton', show); 148 165 }, 149 166 150 167 show_messagemenu: function(show) 151 168 { 152 if (typeof show == 'undefined') 153 show = this.messagemenu.is(':visible') ? false : true; 154 155 var ref = rcube_find_object('messagemenulink'); 156 if (show && ref) 157 this.messagemenu.css({ left:ref.offsetLeft, top:(ref.offsetTop + ref.offsetHeight) }); 158 159 this.messagemenu[show?'show':'hide'](); 169 this.show_popupmenu(this.messagemenu, 'messagemenulink', show); 170 }, 171 172 show_groupmenu: function(show) 173 { 174 this.show_popupmenu(this.groupmenu, 'groupactionslink', show, true); 160 175 }, 161 176 … … 268 283 else if (this.dragmessagemenu && this.dragmessagemenu.is(':visible') && !rcube_mouse_is_over(evt, rcube_find_object('dragmessagemenu'))) 269 284 this.dragmessagemenu.hide(); 285 else if (this.groupmenu && this.groupmenu.is(':visible') && target != rcube_find_object('groupactionslink')) 286 this.show_groupmenu(false); 270 287 else if (this.listmenu && this.listmenu.is(':visible') && target != rcube_find_object('listmenulink')) { 271 288 var menu = rcube_find_object('listmenu'); … … 291 308 { 292 309 if (rcube_event.get_keycode(evt) == 27) { 293 if (this.markmenu && this.markmenu.is(':visible')) 294 this.show_markmenu(false); 295 if (this.searchmenu && this.searchmenu.is(':visible')) 296 this.show_searchmenu(false); 297 if (this.messagemenu && this.messagemenu.is(':visible')) 298 this.show_messagemenu(false); 299 if (this.listmenu && this.listmenu.is(':visible')) 300 this.show_listmenu(false); 301 if (this.dragmessagemenu && this.dragmessagemenu.is(':visible')) 302 this.dragmessagemenu.hide(); 310 for (var k in this.popupmenus) { 311 if (this[k] && this[k].is(':visible')) 312 this[k].hide(); 313 } 303 314 } 304 315 } … … 313 324 rcube_event.add_listener({ object:rcmail_ui, method:'body_mouseup', event:'mouseup' }); 314 325 rcube_event.add_listener({ object:rcmail_ui, method:'body_keypress', event:'keypress' }); 315 rcmail.addEventListener('menu-open', 'open_listmenu', rcmail_ui); 316 rcmail.addEventListener('menu-save', 'save_listmenu', rcmail_ui); 317 rcmail.gui_object('message_dragmenu', 'dragmessagemenu'); 318 } 326 if (rcmail.env.task == 'mail') { 327 rcmail.addEventListener('menu-open', 'open_listmenu', rcmail_ui); 328 rcmail.addEventListener('menu-save', 'save_listmenu', rcmail_ui); 329 rcmail.gui_object('message_dragmenu', 'dragmessagemenu'); 330 } 331 } -
skins/default/mail.css
rfb7ec57 ra61bbb2 687 687 #messagelist thead tr td.sortedDESC 688 688 { 689 background-position: 0 -2 0px;689 background-position: 0 -22px; 690 690 } 691 691 -
skins/default/templates/addressbook.html
rd4a2c0c ra61bbb2 5 5 <roundcube:include file="/includes/links.html" /> 6 6 <script type="text/javascript" src="/splitter.js"></script> 7 7 <script type="text/javascript" src="/functions.js"></script> 8 8 <style type="text/css"> 9 <roundcube:if condition="count(env:address_sources) <= 1" />10 #abookcountbar { left: 20px; }11 #addressscreen { left: 20px;12 <roundcube:exp expression="browser:ie ? 'width:expression((parseInt(document.documentElement.clientWidth)-40)+\\'px\\');' : ''" />13 }14 9 #addresslist { width: <roundcube:exp expression="!empty(cookie:addressviewsplitter) ? cookie:addressviewsplitter-5 : 245" />px; } 15 10 #contacts-box { left: <roundcube:exp expression="!empty(cookie:addressviewsplitter) ? cookie:addressviewsplitter+5 : 255" />px; 16 <roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:addressviewsplitter) ? cookie:addressviewsplitter+5 : 255).')+\\'px\\');') : ''" />11 <roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:addressviewsplitter) ? cookie:addressviewsplitter+5 : 255).')+\\'px\\');') : ''" /> 17 12 } 18 <roundcube:else />19 #addresslist { width: <roundcube:exp expression="!empty(cookie:addressviewsplitter) ? cookie:addressviewsplitter-5 : 245" />px; }20 #contacts-box { left: <roundcube:exp expression="!empty(cookie:addressviewsplitter) ? cookie:addressviewsplitter+5 : 255" />px;21 <roundcube:exp expression="browser:ie ? ('width:expression((parseInt(this.parentNode.offsetWidth)-'.(!empty(cookie:addressviewsplitter) ? cookie:addressviewsplitter+5 : 255).')+\\'px\\');') : ''" />22 }23 <roundcube:endif />24 13 </style> 25 14 26 15 </head> 27 <body >16 <body onload="rcube_init_mail_ui()"> 28 17 29 18 <roundcube:include file="/includes/taskbar.html" /> … … 46 35 </div> 47 36 48 <roundcube:if condition="count(env:address_sources) > 1" /> 49 <div id="directorylist"> 37 <div id="directorylistbox"> 50 38 <div id="groups-title" class="boxtitle"><roundcube:label name="groups" /></div> 51 <roundcube:object name="directorylist" id="directories-list" /> 39 <div id="directorylistwarp"> 40 <roundcube:object name="directorylist" id="directorylist" /> 41 <roundcube:object name="groupslist" id="contactgroupslist" /> 52 42 </div> 53 <roundcube:endif /> 43 <div id="directoylistbuttons"> 44 <roundcube:button command="add-group" type="link" title="newcontactgroup" class="buttonPas addgroup" classAct="button addgroup" content=" " /> 45 <roundcube:button name="groupactions" id="groupactionslink" type="link" title="groupactions" class="button groupactions" onclick="rcmail_ui.show_groupmenu();return false" content=" " /> 46 </div> 47 </div> 48 49 <div id="groupoptionsmenu" class="popupmenu"> 50 <ul> 51 <li><roundcube:button command="rename-group" label="rename" classAct="active" /></li> 52 <li><roundcube:button command="delete-group" label="delete" classAct="active" /></li> 53 </ul> 54 </div> 54 55 55 56 <div id="addressscreen"> -
skins/default/templates/mail.html
rfb7ec57 ra61bbb2 120 120 <roundcube:button name="markreadbutton" id="markreadbutton" type="link" class="button markmessage" title="markmessages" onclick="rcmail_ui.show_markmenu();return false" content=" " /> 121 121 <roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button messagemenu" title="messageactions" onclick="rcmail_ui.show_messagemenu();return false" content=" " /> 122 </div> 122 123 123 124 <div id="markmessagemenu" class="popupmenu"> … … 132 133 133 134 <roundcube:include file="/includes/messagemenu.html" /> 134 135 </div>136 135 137 136 <div id="searchmenu" class="popupmenu">
Note: See TracChangeset
for help on using the changeset viewer.
