AXForum  
Вернуться   AXForum > Блоги > CRM, SharePoint и Черная Магия
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

Добро пожаловать в мой блог! Изначально он не задумывался как блог CRM разработчика, но жизнь сама внесла нужные коррективы. Тут я публикою все свои наблюдения относительно обозначенных в заголовке систем. Если Вы найдете в нем что-то интересное для Вас, как для заказчика, то буду рад сотрудничать с Вами! В моей компетенции 100% задач по MS CRM 3.0/4.0/2011:
  • Консалтинг
  • Проектирование
  • Разработка
  • Обучение


MVP 2010, 2011
Оценить эту запись

Полезный Popup. Часть 1. Упрощение создания Звонков.

Запись от Артем Enot Грунин размещена 29.03.2010 в 14:53

Доброго времени суток, коллеги. Не успел опубликовать данный пост до отпуска, хотя может быть оно и к лучшему, так как описанное в нем решение имеет ряд "дефектов", о которых позже...

Недавно на одном из проектов возникла задача: упростить ввод данных при создании действий типа Звонок: автоматически заполнять поле "Номер телефона" при выборе адресата. Задача, в общем-то, типовая, даже тривиальная. Сложность реализации заключалась лишь в визуальной части: заказчик просил отображать диалог выбора, на случай, если у Контакта, например, будет заполнено несколько полей с номерами телефонов – мобильный и рабочий. От реализации задачи удалось отбрехаться: мол, создавайте звонки из записи клиента, тогда, во-первых, отработает сопоставление атрибутов, а во-вторых, будет лишний повод просмотреть карточку и заполнить пару лишних полей.
Тем не менее, задача с визуальной частью показалась мне интересной, и я постарался реализовать подобное для саморазвития. В результате родился такой код:

Form OnLoad:
Код:
var oTelField = crmForm.all.phonenumber;
var oTelPopUp = new PhoneNumberPopUP(oTelField);

function PhoneNumberPopUP(oField)
{
    var This = this;
    
    This.EntityLookup = "";
    This.Attributes = [];
    This.Labels = [];
    This.Icons = [];

    var oTelPopup = window.createPopup(); 

    function reRenderControl()
    {
        oField.PhoneNumberPopUP = This;
        
        var oLabel = crmForm.all[oField.id + "_c"];
        oLabel.style.textDecoration = "underline";
        oLabel.style.color = "blue";
        oLabel.attachEvent("onclick", This.showPopUP);

        oTelPopup.document.body.attachEvent("onclick", This.OnPopClick);
    }
    
    // Обработчик popup
    This.showPopUP = function()
    {
        var oPopUpHTML = This.getPopUpHTML();

        oTelPopup.document.body.innerHTML = oPopUpHTML;

        var Width  = oField.offsetWidth;
        // TODO: По длинне записи!
        //var Width = 180;
        var Height = This.Attributes.length * 22;

        var Position = This.getControlPostion(oField);
        var Left = Position.X + 1;
        var Top = Position.Y + 1;

        oTelPopup.show(Left, Top, Width, Height, null);
    }

    This.getPopUpHTML = function()
    {
        var oTelXML = This.fetchAttribData();

        var oXmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        oXmlDoc.async = false;
        oXmlDoc.loadXML(oTelXML);

        var oPopUpHTML = "<table style='width:100%;height:100%;border:1px solid gray;font-family:Tahoma;font-size:11px'>";

        for (var i = 0; i < This.Attributes.length; i++)
        {
            var telName = This.Attributes[i];
            var telNode = oXmlDoc.selectSingleNode("/resultset/result/" + telName);
            var telNum = telNode != null ? telNode.text : "";
            var telLabel = This.Labels[i];
            var telIco = This.Icons[i] == 0 ? "ico_16_4210.gif" : "ico_18_4204.gif";

            oPopUpHTML += "<tr style='cursor:pointer'>" +
                                "<td><img src='/_imgs/" + telIco + "' /></td>" +
                                "<td>" + telLabel + "</td>" +
                                "<td>" + telNum + "</td>" +
                             "</tr>";
        }

        oPopUpHTML += "</table>";



        return oPopUpHTML;
    }

    This.OnPopClick = function(event)
    {
        var phoneRow = event.srcElement;
        while (phoneRow.tagName != "TR")
        {
            phoneRow = phoneRow.parentElement;
        }
        
        var oTelNum = phoneRow.lastChild.innerText;
        oField.DataValue = oTelNum;
    }

    This.getControlPostion = function(control)  
    {       
        var Position = new Object();       
        var controlHeight = control.offsetHeight;       
        var iY = 0, iX = 0;       
        while( control != null )       
        {             
            iY += control.offsetTop;  
            iX += control.offsetLeft;  
            control = control.offsetParent;  
        }       
        Position.X = iX + screenLeft;       
        Position.Y = iY + screenTop + controlHeight;       
        return Position;  
    }

    This.fetchAttribData = function()
    {
        if (This.EntityLookup == null) return;

        var oFetchXML = "<fetch mapping='logical'>" +
                    "<entity name='" + This.EntityLookup.typename + "'>";

        for (var i = 0; i < This.Attributes.length; i++)
        {
            oFetchXML += "<attribute name='" + This.Attributes[i] + "'/>";
        }

        oFetchXML += "<filter type='and'><condition attribute='" + This.EntityLookup.typename + "id' ";
        oFetchXML += "operator='eq' value='" + This.EntityLookup.id + "'/>";
        oFetchXML += "</filter></entity></fetch>";

        oFetchXML = oFetchXML.replace(/</g, '&lt;');
        oFetchXML = oFetchXML.replace(/>/g, '&gt;');

        var oSOAP = "<?xml version='1.0' encoding='utf-8'?>" +
                "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'" +
                        " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" +
                        " xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
                        GenerateAuthenticationHeader() +
                "<soap:Body>" +
                    "<Fetch xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>" +
                        "<fetchXml>" +
                            oFetchXML +
                        "</fetchXml>" +
                    "</Fetch>" +
                "</soap:Body>" +
            "</soap:Envelope>";

        var oXmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        oXmlHttp.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
        oXmlHttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Fetch");
        oXmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        oXmlHttp.setRequestHeader("Content-Length", oSOAP.length);
        oXmlHttp.send(oSOAP);

        var oResponseText = oXmlHttp.responseXML.text;

        return oResponseText;
    }

    reRenderControl();
}
OnChange полей Отправитель и/или Получатель:
Код:
var oTelField = crmForm.all.phonenumber;
var oTelPopUp = oTelField.PhoneNumberPopUP;


var oEntityLookup = null;
var oAttributes = [];
var oLabels = [];
var oIcons = [];

if (event.srcElement.DataValue != null)
{
    oEntityLookup = event.srcElement.DataValue[0];
    
    var oTypeName = oEntityLookup.typename;

    switch (oTypeName)
    {
        case "account":
            {
                oAttributes = new Array("telephone1", "telephone2", "fax");
                oLabels = new Array("Основной", "Дополнителельный", "Факс");
                oIcons = new Array(0, 0, 1);

                break;
            }
        case "contact":
            {

                oAttributes = new Array("telephone1", "telephone2", "mobilephone", "fax");
                oLabels = new Array("Основной", "Дополнителельный", "Мобильный", "Факс");
                oIcons = new Array(0, 0, 0, 1);

                break;            
            }
        case "lead":
            {
                oAttributes = new Array("telephone1", "telephone2", "fax");
                oLabels = new Array("Основной", "Дополнителельный", "Мобильный", "Факс");
                oIcons = new Array(0, 0, 0, 1);

                break;
            }
        case "systemuser":
            {
                oAttributes = new Array("address1_telephone1", "address1_telephone2", "mobilephone", "address1_fax");
                oLabels = new Array("Основной", "Дополнителельный", "Мобильный", "Факс");
                oIcons = new Array(0, 0, 0, 1);

                break;
            }
    }
}

oTelPopUp.EntityLookup = oEntityLookup;
oTelPopUp.Attributes = oAttributes;
oTelPopUp.Labels = oLabels;
oTelPopUp.Icons = oIcons;
Результат работы кода можно увидеть на скриншоте ниже:

Нажмите на изображение для увеличения
Название: popTelNumbers.jpg
Просмотров: 684
Размер:	99.7 Кб
ID:	48

По клику на всплывающем окне соответствующий телефон вставляется в поле Номер телефона.
В ASPX я не силен, поэтому диалог выбора реализовывался как окно «попап». Возможно, такое решение даже более элегантно, так как не загромождает экран и упрощает развертывание. Данная реализация popup работает сугубо под IE, так что для CRM 5.0, которая, как мы надеемся, будет кросс-браузерной его придется переписать.
Все бы ничего, но я, каюсь, запамятовал, что поле «получатель» - PartyList, что обозначает, что получателей может быть несколько. Не знаю, как это выглядит с точки зрения логики, однако система позволяет выбирать сразу несколько получателей разного типа для одного звонка. На какое время я озадачился исправлением своего промаха, что и привело к задержке с публикацией, однако в процессе разработки мне посчастливилось найти иной подход к реализации задачи, о котором я расскажу в следующей части данной эпопеи.

В качестве отправной точки использовались следующие посты:
CRM Custom Tooltip
CRM Lookup Preview

Последний, кстати, и вдохновил на изменение концепции решения с целью сделать его универсальным. Продожение следует.
Размещено в CRM
Просмотров 68506 Комментарии 5
Всего комментариев 5

Комментарии

  1. Старый комментарий
    Добрый день. Подскажите пожалуйста как применить ваше решение чтобы окно с выбором телефонов поднималось по нажатию ISV-кнопки из грида и из формы. Не понятна именна та часть, которая кассаяется привязки попапа к полю Телефон:
    var oTelField = crmForm.all.phonenumber;
    var oTelPopUp = new PhoneNumberPopUP(oTelField);

    function PhoneNumberPopUP(oField)
    {
    ....
    Что в моем случае надо передавать в функцию PhoneNumberPopUP?
    Запись от OlegaN размещена 30.04.2010 в 13:51 OlegaN is offline
  2. Старый комментарий
    Аватар для Артем Enot Грунин
    Решение изначально делалось только для формы. Честно говоря, не понимаю что вы собираетесь заполнять в гриде.
    Запись от Артем Enot Грунин размещена 30.04.2010 в 13:56 Артем Enot Грунин is offline
  3. Старый комментарий
    Я хочу выполнять звонки из карточки/строки Контакта. Для этого планирую сделать ISV кнопку, которая будет получать все телефоы контакта и отображать их в попапе. А при выборе нужного телефона из попапа будет создаваться и открывться карточка Звонка со всеми нужными полями
    Запись от OlegaN размещена 30.04.2010 в 14:04 OlegaN is offline
  4. Старый комментарий
    Аватар для Артем Enot Грунин
    Пишите с нуля - быстрее управитесь. Посмотрите последний пост про группировку в гриде. Там написано как сделать кнопку и привязать к ней меню. По нажатию я, очевидно, искал бы в гриде выбранную строку (строки?):
    Код:
    var selected = crmGrid.innerGrid.selectedRecords[0];
    Вычитывал id объекта и далее все как в примере... Как открывать карточку с заранее заполненными полями можете почитать в одном из моих первых постов.
    Запись от Артем Enot Грунин размещена 30.04.2010 в 14:19 Артем Enot Грунин is offline
  5. Старый комментарий
    Здравствуйте!
    Возможно оффтоп, но может Вы знаете: как на форму звонка подтащить данные из кастомного поля в карточке?
    Запись от lin2nil размещена 14.10.2011 в 16:47 lin2nil is offline
 


Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 12:44.