1 /*********************************************************************************
2 * SugarCRM Community Edition is a customer relationship management program developed by
3 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Affero General Public License version 3 as published by the
7 * Free Software Foundation with the addition of the following permission added
8 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
9 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
10 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
17 * You should have received a copy of the GNU Affero General Public License along with
18 * this program; if not, see http://www.gnu.org/licenses or write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
23 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU Affero General Public License version 3.
29 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
30 * these Appropriate Legal Notices must retain the display of the "Powered by
31 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
32 * technical reasons, the Appropriate Legal Notices must display the words
33 * "Powered by SugarCRM".
34 ********************************************************************************/
37 if(SUGAR.email2.grid) {
38 SUGAR.email2.grid.destroy();
44 var Ck = YAHOO.util.Cookie;
45 var widths = [ 10, 10, 150, 250, 175, 125 ];
47 if (Ck.get("EmailGridWidths")) {
48 for (var i=0; i < widths.length; i++) {
49 widths[i] = Ck.getSub("EmailGridWidths", i+ "", Number);
52 for (var i=0; i < widths.length; i++) {
53 Ck.setSub("EmailGridWidths", i + "", widths[i], {expires: SUGAR.email2.nextYear});
57 // changes "F" to an icon
58 function flaggedIcon(cell, record, column, value) {
60 cell.innerHTML = "<span style='color: #f00; font-weight:bold;'>!</span>";
63 // changes "A" to replied icon
64 function repliedIcon(cell, record, column, value) {
66 cell.innerHTML = "<img src='index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=export.gif' class='image' border='0' width='10' align='absmiddle'>";
69 function attachIcon(cell, record, column, value) {
71 cell.innerHTML = "<img src='index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=attachment.gif' class='image' border='0' width='10' align='absmiddle'>";
78 label: "<h2><img src='index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=attachment.gif' class='image' border='0' width='10' align='absmiddle'></h2>",
83 formatter: attachIcon,
87 label: "<span style='color: #f00; font-weight:bold;'>!</span>",
92 formatter: flaggedIcon,
96 label: "<img src='index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=export.gif' class='image' border='0' width='10' align='absmiddle'>",
101 formatter: repliedIcon,
105 label: app_strings.LBL_EMAIL_FROM,
112 label: app_strings.LBL_EMAIL_SUBJECT,
119 label: mod_strings.LBL_LIST_DATE,
126 label: app_strings.LBL_EMAIL_TO,
162 var dataModel = new YAHOO.util.DataSource(urlBase + "?", {
163 responseType: YAHOO.util.DataSource.TYPE_JSON,
165 resultsList: 'Email',
166 fields: ['flagged', 'status', 'from', 'subject', 'date','to_addrs', 'uid', 'mbox', 'ieId', 'site_url', 'seen', 'type', 'AssignedTo','hasAttach'],
167 metaFields: {total: 'TotalCount', unread:"UnreadCount", fromCache: "FromCache"}
173 action : "EmailUIAjax",
174 emailUIAction : "getMessageList",
177 forceRefresh : "false"
179 if(lazyLoadFolder != null) {
180 params['mbox'] = lazyLoadFolder.folder;
181 params['ieId'] = lazyLoadFolder.ieId;
182 //Check if the folder is a Sugar Folder
183 var test = new String(lazyLoadFolder.folder);
184 if(test.match(/SUGAR\./)) {
185 params['emailUIAction'] = 'getMessageListSugarFolders';
186 params['mbox'] = test.substr(6);
187 params['getUnread'] = 1;
190 //dataModel.initPaging(urlBase, SUGAR.email2.userPrefs.emailSettings.showNumInList);
193 var grid = SUGAR.email2.grid = new YAHOO.SUGAR.SelectionGrid('emailGrid', colModel, dataModel, {
194 MSG_EMPTY: SUGAR.language.get("Emails", "LBL_EMPTY_FOLDER"),
196 paginator: new YAHOO.widget.Paginator({
197 rowsPerPage:parseInt(SUGAR.email2.userPrefs.emailSettings.showNumInList),
198 containers : ["dt-pag-nav"],
199 template: "<div class='pagination'>{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}</div>",
200 firstPageLinkLabel: "<button class='button'><div class='paginator-start'/></button>",
201 previousPageLinkLabel: "<button class='button'><div class='paginator-previous'/></button>",
202 nextPageLinkLabel: "<button class='button'><div class='paginator-next'/></button>",
203 lastPageLinkLabel: "<button class='button'><div class='paginator-end'/></button>"
205 initialRequest:SUGAR.util.paramsToUrl(params),
212 //Override Paging request construction
213 grid.set("generateRequest", function(oState, oSelf) {
214 oState = oState || {pagination:null, sortedBy:null};
215 var sort = (oState.sortedBy) ? oState.sortedBy.key : oSelf.getColumnSet().keys[5].getKey();
216 var dir = (oState.sortedBy && oState.sortedBy.dir === YAHOO.widget.DataTable.CLASS_ASC) ? "asc" : "desc";
217 var startIndex = (oState.pagination) ? oState.pagination.recordOffset : 0;
218 var results = (oState.pagination) ? oState.pagination.rowsPerPage : null;
221 SUGAR.util.paramsToUrl(oSelf.params) +
224 "&start=" + startIndex +
225 ((results !== null) ? "&limit=" + results : "");
230 grid.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
231 oPayload = oPayload || { };
233 oPayload.totalRecords = oResponse.meta.total;
235 if (oResponse.meta.unread != -1) {
236 oPayload.unreadRecords = oResponse.meta.unread;
239 var tabObject = SE.innerLayout.get("tabs")[0];
241 if (this.params.mbox != null) {
242 mboxTitle = this.params.mbox;
244 var tabtext = mboxTitle + " (" + oResponse.meta.total + " " + app_strings.LBL_EMAIL_MESSAGES + " )";
245 tabObject.get("labelEl").firstChild.data = tabtext;
248 var node = SE.tree.getNodeByProperty('id', this.params.ieId) || SE.tree.getNodeByProperty('origText', this.params.mbox);
250 if (oResponse.meta.unread != -1) {
251 node.data.unseen = oResponse.meta.unread;
253 SE.accounts.renderTree();
259 var resize = grid.resizeGrid = function () {
260 SUGAR.email2.grid.set("width", SUGAR.email2.grid.get("element").parentNode.clientWidth + "px");
261 SUGAR.email2.grid.set("height", (SUGAR.email2.grid.get("element").parentNode.clientHeight - 47) + "px");
263 grid.convertDDRows = function() {
264 var rowEl = this.getFirstTrEl();
265 while (rowEl != null) {
266 new this.DDRow(this, this.getRecord(rowEl), rowEl);
267 rowEl = this.getNextTrEl(rowEl);
272 grid.on("columnResizeEvent", function(o) {
273 //Find the index of the column
274 var colSet = SUGAR.email2.grid.getColumnSet().flat;
275 for (var i=0; i < colSet.length; i++) {
276 if (o.column == colSet[i]) {
277 //Store it in the cookie
278 Ck.setSub("EmailGridWidths", i + "", o.width, {expires: SUGAR.email2.nextYear});
284 grid.on("postRenderEvent", function() {this.convertDDRows()}, null, grid);
285 grid.on("rowClickEvent", SUGAR.email2.listView.handleClick);
286 grid.on("rowDblclickEvent", SUGAR.email2.listView.getEmail);
288 SUGAR.email2.listViewLayout.on("render", resize);
291 //Setup the default load parameters
292 SUGAR.email2.grid.params = params;
294 grid.on('postRenderEvent', SUGAR.email2.listView.setEmailListStyles);
295 dataModel.subscribe("requestEvent", grid.disable, grid, true);
296 dataModel.subscribe("responseParseEvent", grid.undisable, grid, true);
303 function initRowDD() {
304 var sg = SUGAR.email2.grid,
305 Dom = YAHOO.util.Dom;
306 sg.DDRow = function(oDataTable, oRecord, elTr) {
307 if(oDataTable && oRecord && elTr) {
308 this.ddtable = oDataTable;
309 this.table = oDataTable.getTableEl();
312 this.newIndex = null;
314 this.initFrame(); // Needed for DDProxy
315 this.invalidHandleTypes = {};
319 YAHOO.extend(sg.DDRow, YAHOO.util.DDProxy, {
320 _resizeProxy: function() {
321 this.constructor.superclass._resizeProxy.apply(this, arguments);
322 var dragEl = this.getDragEl(),
324 var xy = Dom.getXY(el);
326 Dom.setStyle(dragEl, 'height', this.rowEl.offsetHeight + "px");
327 Dom.setStyle(dragEl, 'width', (parseInt(Dom.getStyle(dragEl, 'width'),10) + 4) + 'px');
328 Dom.setXY(dragEl, [xy[0] - 100, xy[1] - 20] );
329 Dom.setStyle(dragEl, 'display', "");
332 startDrag: function(x, y) {
333 //Check if we should be dragging a set of rows rather than just the one.
334 var selectedRows = this.ddtable.getSelectedRows();
335 var iSelected = false;
336 for (var i in selectedRows) {
337 if (this.rowEl.id == selectedRows[i]) {
344 for (var i in selectedRows) {
345 this.rows[i] = this.ddtable.getRecord(selectedRows[i]);
348 this.rows = [this.row];
349 this.ddtable.unselectAllRows();
350 this.ddtable.selectRow(this.row);
353 //Initialize the dragable proxy
354 var dragEl = this.getDragEl();
355 var clickEl = this.getEl();
356 Dom.setStyle(clickEl, "opacity", "0.25");
357 dragEl.innerHTML = "<table><tr>" + clickEl.innerHTML + "</tr></table>";
358 Dom.addClass(dragEl, "yui-dt-liner");
359 Dom.setStyle(dragEl, "opacity", "0.5");
360 Dom.setStyle(dragEl, "height", (clickEl.clientHeight - 2) + "px");
361 Dom.setStyle(dragEl, "backgroundColor", Dom.getStyle(clickEl, "backgroundColor"));
362 Dom.setStyle(dragEl, "border", "2px solid gray");
365 clickValidator: function(e) {
366 if (this.row.getData()[0] == " ")
368 var target = YAHOO.util.Event.getTarget(e);
369 return ( this.isValidHandleChild(target) &&
370 (this.id == this.handleElId || this.DDM.handleWasClicked(target, this.id)) );
373 * This function checks that the target of the drag is a table row in this
374 * DDGroup and simply moves the sourceEL to that location as a preview.
376 onDragOver: function(ev, id) {
377 var node = SUGAR.email2.tree.getNodeByElement(Dom.get(id));
378 if (node && node != this.targetNode) {
379 this.targetNode = node;
380 SUGAR.email2.folders.unhighliteAll();
385 onDragOut: function(e, id) {
386 if (this.targetNode) {
387 SUGAR.email2.folders.unhighliteAll();
388 this.targetNode = false;
391 endDrag: function() {
392 Dom.setStyle(this.getEl(), "opacity", "");
393 Dom.setStyle(this.getDragEl(), "display", "none");
394 if (this.targetNode) {
395 SUGAR.email2.folders.handleDrop(this.rows, this.targetNode);
397 SUGAR.email2.folders.unhighliteAll();
403 function AddressSearchGridInit() {
404 function moduleIcon(elCell, oRecord, oColumn, oData) {
405 elCell.innerHTML = "<img src='index.php?entryPoint=getImage&themeName="+SUGAR.themes.theme_name+"&imageName=" + oData + ".gif' class='image' border='0' width='16' align='absmiddle'>";
407 function selectionCheckBox(elCell, oRecord, oColumn, oData) {
408 elCell.innerHTML = '<input type="checkbox" onclick="SUGAR.email2.addressBook.grid.toggleSelectCheckbox(\'' + oRecord.getId() + '\', this.checked);">';
410 var checkHeader = '<input type="checkbox" ';
411 if (SUGAR.email2.util.isIe()) {
412 checkHeader += 'style="top:-5px" ';
414 checkHeader += 'onclick="SUGAR.email2.addressBook.grid.toggleSelectAll(this.checked);">';
419 formatter: selectionCheckBox,
423 label: mod_strings.LBL_LIST_TYPE,
425 formatter: moduleIcon,
429 label: app_strings.LBL_EMAIL_ADDRESS_BOOK_NAME,
435 label: app_strings.LBL_EMAIL_ADDRESS_BOOK_EMAIL_ADDR,
441 var dataModel = new YAHOO.util.DataSource(urlBase + "?", {
442 responseType: YAHOO.util.XHRDataSource.TYPE_JSON,
444 resultsList: 'Person',
445 fields: ['name', 'email', 'bean_id', 'bean_module'],
446 metaFields: {total: 'TotalCount'}
448 //enable sorting on the server accross all data
454 action : "EmailUIAjax",
455 emailUIAction:"getAddressSearchResults"
457 var rb = document.getElementById('hasRelatedBean').checked;
459 var idx = SUGAR.email2.composeLayout.currentInstanceId;
460 var relatedBeanId = document.getElementById('data_parent_id' + idx).value;
461 var relatedBeanType = document.getElementById('data_parent_type' + idx).value;
462 dataModel.params['related_bean_id'] = relatedBeanId;
463 dataModel.params['related_bean_type'] = relatedBeanType;
464 dataModel.params['person'] = document.getElementById('input_searchPerson').value;
466 SUGAR.email2.addressBook.addressBookDataModel = dataModel;
468 var grid = SUGAR.email2.addressBook.grid = new YAHOO.widget.ScrollingDataTable("addrSearchGrid", colModel, dataModel, {
469 MSG_EMPTY: " ", //SUGAR.language.get("Emails", "LBL_EMPTY_FOLDER"),
471 paginator: new YAHOO.widget.Paginator({
473 containers : ["dt-pag-nav-addressbook"],
474 template: "<div class='pagination'>{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}</div>",
475 firstPageLinkLabel: "<button class='button'><div class='paginator-start'/></button>",
476 previousPageLinkLabel: "<button class='button'><div class='paginator-previous'/></button>",
477 nextPageLinkLabel: "<button class='button'><div class='paginator-next'/></button>",
478 lastPageLinkLabel: "<button class='button'><div class='paginator-end'/></button>"
480 initialRequest:SUGAR.util.paramsToUrl(dataModel.params),
484 //Override Paging request construction
485 grid.set("generateRequest", function(oState, oSelf) {
486 oState = oState || {pagination:null, sortedBy:null};
487 var sort = (oState.sortedBy) ? oState.sortedBy.key : oSelf.getColumnSet().keys[0].getKey();
488 var dir = (oState.sortedBy && oState.sortedBy.dir === YAHOO.widget.DataTable.CLASS_DESC) ? "desc" : "asc";
489 var startIndex = (oState.pagination) ? oState.pagination.recordOffset : 0;
490 var results = (oState.pagination) ? oState.pagination.rowsPerPage : null;
493 SUGAR.util.paramsToUrl(oSelf.getDataSource().params) +
494 "&sort=" + sort + "&dir=" + dir + "&start=" + startIndex +
495 ((results !== null) ? "&limit=" + results : "");
499 grid.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
500 oPayload = oPayload || { };
501 oPayload.totalRecords = oResponse.meta.total;
505 grid.clickToggleSelect= function(args) {
506 var isIE = (args.event.target == null);
507 var targetElement = isIE ? args.event.srcElement : args.event.target;
508 if(targetElement.type == null || targetElement.type != 'checkbox') {
509 SUGAR.email2.addressBook.grid.toggleSelect(args.target.id);
513 grid.reSelectRowsOnRender = function (){
514 var rows = SUGAR.email2.addressBook.grid.getRecordSet().getRecords();
515 for (var i = 0; i < rows.length; i++)
517 var emailAddress = rows[i].getData("email");
518 var alreadyAdded = SUGAR.email2.addressBook.doesEmailAdddressExistInResultTable(emailAddress);
521 rows[i].setData("selected", true);
522 SUGAR.email2.addressBook.grid.selectRow(rows[i]);
526 rows[i].setData("selected", false);
527 SUGAR.email2.addressBook.grid.unselectRow(rows[i]);
531 grid.subscribe("rowMouseoverEvent", grid.onEventHighlightRow);
532 grid.subscribe("rowMouseoutEvent", grid.onEventUnhighlightRow);
533 grid.subscribe("rowClickEvent", grid.clickToggleSelect);
534 grid.subscribe("postRenderEvent", grid.reSelectRowsOnRender);
537 dataModel.subscribe("requestEvent", grid.disable, grid, true);
538 dataModel.subscribe("responseParseEvent", grid.undisable, grid, true);
540 grid.toggleSelectCheckbox = function(id,checked){
541 var row = SUGAR.email2.addressBook.grid.getRecord(id);
542 row.setData("checked",checked);
544 grid.toggleSelect = function(id, checked) {
545 var row = SUGAR.email2.addressBook.grid.getRecord(id);
546 checked = row.getData("selected");
549 SUGAR.email2.addressBook.grid.selectRow(row);
550 SE.addressBook.insertContactRowToResultTable(id,null)
553 SUGAR.email2.addressBook.grid.unselectRow(row);
554 SE.addressBook.removeRowFromGridResults(id,row.getData("email"));
556 row.setData("selected", !checked);
559 grid.toggleSelectAll = function(checked) {
560 rows = SUGAR.email2.addressBook.grid.getRecordSet().getRecords();
561 for (var i = 0; i < rows.length; i++) {
562 if (typeof(rows[i]) != "undefined")
563 rows[i].setData("checked", checked);
565 var checkBoxes = SUGAR.email2.addressBook.grid.get("element").getElementsByTagName('input');
566 for (var i = 0; i < checkBoxes.length; i++) {
567 checkBoxes[i].checked = checked;
571 //Initialize the grid result table.
572 AddressSearchResultsGridInit();
578 * Initalize the results table for the address book selection.
581 function AddressSearchResultsGridInit()
584 /* Full name sort function to compare by last name if available */
585 var fullNameSort = function(a, b, desc) {
586 // Deal with empty values
587 if(!YAHOO.lang.isValue(a))
588 return (!YAHOO.lang.isValue(b)) ? 0 : 1;
589 else if(!YAHOO.lang.isValue(b))
592 var aNames = a.getData("name").split(' ');
593 var bNames = b.getData("name").split(' ');
595 var aSortField = (aNames.length == 2) ? aNames[1] : a.getData("name");
596 var bSortField = (bNames.length == 2) ? bNames[1] : b.getData("name");
598 return YAHOO.util.Sort.compare(aSortField,bSortField, desc);
602 var typeDdOptions = [app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_TO.replace(/:$/,'') ,
603 app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_CC.replace(/:$/,''),
604 app_strings.LBL_EMAIL_ADDRESS_BOOK_ADD_BCC.replace(/:$/,'')];
606 var ColumnDefs = [{key:'type',label:app_strings.LBL_EMAIL_ADDRESS_BOOK_ADRRESS_TYPE, width: 60, sortable: true, editor: new YAHOO.widget.RadioCellEditor({radioOptions:typeDdOptions,disableBtns:true})},
607 {key:'name',label:app_strings.LBL_EMAIL_ACCOUNTS_NAME,width: 280,sortable: true, sortOptions:{sortFunction:fullNameSort}}];
609 var myDataSource = new YAHOO.util.DataSource([]);
610 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
611 myDataSource.responseSchema = {
612 fields: ["name","type","email_address","display_email_address","bean_id","idx"]
615 var gridResults = SUGAR.email2.addressBook.gridResults = new YAHOO.widget.ScrollingDataTable("addrSearchResultGrid", ColumnDefs, myDataSource, {
616 width: "350px",height: "250px", MSG_EMPTY: " "});
618 var highlightEditableCell = function(oArgs) {
619 var elCell = oArgs.target;
620 if(YAHOO.util.Dom.hasClass(elCell, "yui-dt-editable")) {
621 this.highlightCell(elCell);
625 gridResults.subscribe("cellMouseoverEvent", highlightEditableCell);
626 gridResults.subscribe("cellMouseoutEvent", gridResults.onEventUnhighlightCell);
627 gridResults.subscribe("cellClickEvent", gridResults.onEventShowCellEditor);
628 gridResults.subscribe("rowMouseoverEvent", gridResults.onEventHighlightRow);
629 gridResults.subscribe("rowMouseoutEvent", gridResults.onEventUnhighlightRow);
631 //Setup the context menus
632 var onContextMenuClick = function(p_sType, p_aArgs, p_myDataTable) {
633 var task = p_aArgs[1];
636 var elRow = this.contextEventTarget;
637 elRow = p_myDataTable.getTrEl(elRow);
644 var oRecord = p_myDataTable.getRecord(elRow);
645 p_myDataTable.deleteRow(elRow);
646 SUGAR.email2.addressBook.grid.reSelectRowsOnRender();
651 var contextMenu = new YAHOO.widget.ContextMenu("contextmenu",
652 {trigger:gridResults.getTbodyEl()});
653 contextMenu.addItem(app_strings.LBL_EMAIL_DELETE);
654 contextMenu.render("addrSearchResultGrid");
655 contextMenu.clickEvent.subscribe(onContextMenuClick, gridResults);