Кастомизация
16
Июн
20

Связанные записи в iFrame

Под связанными записями в данном случаи понимаются связи между объектами 1:N и N:N. Т.е. в результате которых на левой навигационной панели форм создаются кнопки, нажав которые, Вы можете увидеть те самые связанные записи.

Но иногда бывает так, что юзверам и эти клики не осилить 🙂 И они хотят видеть эти связанные записи прямо на форме. Но каким-либо обычным способом (через настройки) их на форму не вынести. Но полно же необычных способов 🙂 И один из них – показать представление связанного объекта в iFrame.

Когда Вы щелкаете по ссылке на левой панели, связанные записи подтягиваются не в новую форму, а в эту же. А если быть совсем точным, то они откроются в iFrame. И чтобы они там появились в iFrame необходимо передать строчку URL с некторыми параметрами:

  • Для системных связей (т.е. тех которые уже были) и для кастомных связей 1:N в строчке URL должны быть следующие параметры: oId, oType, security, tabSet;
  • Для кастомных связей N:N нужен дополнительный параметр: roleOrd.

В качестве примера рассмотрим вынос на форму двух связанных объектов формы Контакты — это Дочерние контакты (1:N) и кастомная связь N:N с объектом Пользователи:

  • Для начала я создал отношение N:N между объектом Контакты и Пользователи. И опубликовал изменения;
  • Теперь нам нужно получить значение параметра tabSet. Для этого откройте запись какого-нибудь контакта и перейдите на левой панели к Дочерние контакты. Далее, «вооружитесь» Internet Explorer Developer Toolbar (в IE8 он уже встроен, вызывается по F12), выберите инструмент Выбрать элементы щелчком (Select Element by Click) в виде стрелки и щелкните по границе области содержащий список представления. Левое нижнее окно, содержащее разметку документа в иерархическом виде, тут же перескочит к элементу по которому Вы щелкнули. Двигаясь вверх по этой иерархической структуре, доберитесь до элемента iframe, в которую входит этот список представления. У тега iframe будет параметр src, который содержит строчку URL (которую мы и будем «искусственно» воссоздавать 🙂 ) В этой строчке URL есть параметр tabSet — скопируйте куда-ниубдь его значение. Аналогичным образом найдите параметр tabSet для другого связанного объекта;


  • Создайте на форме два новых iFrame (один я назвал iFrame_contact, а дугой iFrame_user). В качестве URL укажите about:blank и обязательно снимите у них галку Ограничить использвание сценариев между кадрами;
  • Далее на OnLoad формы вешаем такой код:
    //Первым делом проверяем сохранена ли запись, т.е. есть ли у нее ID'шник - иначе нам нечего будет передавать в iFrame
    if (crmForm.ObjectId != null) {
    	var tabSet = "areaSubConts"; //поменяйте значение на Ваше
    	var id = crmForm.ObjectId;
    	var type = crmForm.ObjectTypeCode;
    	var security = crmFormSubmit.crmFormSubmitSecurity.value;
    	var path = document.location.pathname.substring(0, document.location.pathname.indexOf("edit.aspx")) + "areas.aspx?";
    	//для связей 1:N и для системных связей
    	crmForm.all.IFRAME_contact.src = path + "oId=" + id + "&oType=" + type + "&security=" + security + "&tabSet=" + tabSet;
    
        // вызываем функцию скрывающую лишие отступы и передаем ей имя айфрейма
        FixStylingInFrameSource('IFRAME_contact');
    }
    
    if (crmForm.ObjectId != null) {
    	var tabSet = "areanew_contact_systemuser"; //поменяйте значение на Ваше
    	var id = crmForm.ObjectId;
    	var type = crmForm.ObjectTypeCode;
    	var security = crmFormSubmit.crmFormSubmitSecurity.value;
    	var path = document.location.pathname.substring(0, document.location.pathname.indexOf("edit.aspx")) + "areas.aspx?";
    	//для кастомных связей N:N
    	crmForm.all.IFRAME_user.src = path + "oId=" + id + "&oType=" + type + "&security=" + security + "&roleOrd=1&tabSet=" + tabSet;
    
        // вызываем функцию скрывающую лишие отступы и передаем ей имя айфрейма
        FixStylingInFrameSource('IFRAME_user');
    }
    
    function FixStylingInFrameSource(iframeID) {
    	// Проверяем что контент загрузился в iFrame
    	if (document.getElementById(iframeID).contentWindow.document.readyState != "complete") {
    		// Если еще нет, то перезапускаем функцию через 10 милисекунд
    		window.setTimeout(function() { FixStylingInFrameSource(iframeID) }, 10);
    	} else { // Content window is ready
    		// скрываем лишние отступы        
    		document.getElementById(iframeID).contentWindow.document.body.childNodes[0].style.padding = 0; 
    	}
    }
    

    Первая часть кода передает в iFrame строчку URL для отношения 1:N и системных связей. А вторая соответственно для кастомных отношений N:N. В этом коде Вам необходимо изменить только значение tabSet, на то которое Вы скопироваи при помощие IEDevTool;

  • Сохраняем закрываем и публикуем. Ну, и смотрим на результат!



Еще один скрипт для связи N:N

// Создаем объект N2NViewer и передаем ему имя iFrame'а
var n2nViewer = new N2NViewer('IFRAME_account_association');
n2nViewer.RoleOrder = 1; // используйте iedevtoolber для уточнения этого параметра
/* Имя связи (без слова "area") */ 
n2nViewer.TabsetId  = "gi_account_account";
n2nViewer.Load();

function N2NViewer(iframeId)
{
    if (!document.all[iframeId])
    {
        alert(iframeId + " is missing!");
        return;
    }
 
    var viewer = this;
    var _locAssocObj = null;
 
    viewer.IFRAME = document.all[iframeId];
    viewer.RoleOrder;
    viewer.TabsetId;
 
    viewer.Load = function()
    {
        /* Собираем URL */
        viewer.IFRAME.src = "areas.aspx?oId=" + crmForm.ObjectId + "&oType=" + crmForm.ObjectTypeCode + "&security=" + crmFormSubmit.crmFormSubmitSecurity.value + "&roleOrd=" +         viewer.RoleOrder + "&tabSet=area" + viewer.TabsetId;
        viewer.IFRAME.onreadystatechange = viewer.StateChanged;
    }
 
    viewer.StateChanged = function()
    {
        if (viewer.IFRAME.readyState != 'complete')
        {
            return;
        }
  
        var iframeDoc = viewer.IFRAME.contentWindow.document;
  
        /* Удаляем скроллинг */
        iframeDoc.body.scroll = "no";
        /* Удаляем padding */
        iframeDoc.body.childNodes[0].rows[0].cells[0].style.padding = 0;
  
        /* Сохраняем MS locAssocObj */
        _locAssocObj = locAssocObj;
        /* Переопределяем MS locAssocObj */
        locAssocObj = viewer.locAssocObj;
    }
 
    viewer.locAssocObj = function(iType , sSubType, sAssociationName, iRoleOrdinal)
    {
        /* Открываем Dialog */
        _locAssocObj(iType , sSubType, sAssociationName, iRoleOrdinal);
        /* Обновляем только если iFrame содержит сорректное имя tabset */
        if (sAssociationName == viewer.TabsetId)
        {
            viewer.IFRAME.contentWindow.document.all.crmGrid.Refresh(); 
        }
    }
}
Комментарии (20)
  • Виктор 16.06.2009

    Добрый день! А есть ли способ избавиться от белой рамки в iFrame?

  • Виктор 16.06.2009

    И еще вопрос! Как вывести в iFrame поля связанынх записей, например, description для всех действий журнала?

    P.S. Ни за что ни про что обозвали спам-ботом…

  • slivka_83 16.06.2009

    Здрасьте 🙂

    1. Дописал код — теперь отступы лишние скрываются (и не забудьте в настройках айфрейма убрать границу).

    2. Для действий журнала попробуйте настроить представление таким образом http://mmcrm.ru/?p=878

    3. про бота… Ну наверно Вы не ввели код 🙂 или ввели его не правильно 🙂 🙂 🙂

  • loggerzd 16.06.2009

    Какой Вы молодец! Когда только успеваете всё делать и проверять. Огромное спасибо!
    Может, матпомощь какую оказать надо? 🙂

  • slivka_83 16.06.2009

    Да нет 🙂 не надо 🙂 спасибо 🙂

  • oikcom 16.06.2009

    Здрасте
    А нельзя немного усложнить — подтянуть связанные записи связанной сущности, например есть таблица — отчеты внештатного сотрудника, к этой таблице соответственно привязана таблица контактов, по какому то полю, а можно вытащить на форму таблицы отчеты связанные с сотрудником (контактом) звонки либо задачи?
    Спасибо

  • slivka_83 16.06.2009

    Вот с помощью этого http://mmcrm.ru/?p=866 можно состряпать почти любое представление 🙂

  • oikcom 16.06.2009

    Здравствуйте,
    А можно как то к tabSet добавить один фильтр, т.е. вытащить связанные записи но с одним фильтром по одному полю? т.е. в идеале нужно много вкладок на форме, таким образом чтобы, на каждой было представление одной и той же связи, но с разными значениями фильтра

  • oikcom 16.06.2009

    Поискал по Вашему сайту, нашел еще ресурс http://mmcrm.ru/?p=878, а можно его использовать для того чтобы размножить связанное представление одной кустомной сущности в другой кустомной сущности по фильтру, одного поля. Это может и решит проблему? Т.е. создать динамическое связанное представление в кустомной сущности?

  • slivka_83 16.06.2009

    > А можно как то к tabSet добавить один фильтр, т.е. вытащить связанные записи но с одним фильтром по одному полю?

    Насколько мне известно нет.

    > можно его использовать для того чтобы размножить связанное представление одной кустомной сущности в другой кустомной сущности по фильтру, одного поля. Это может и решит проблему?

    Тоже такого не пробовал 🙂 Единственное что известно мне это использовать http://mmcrm.ru/?p=866 🙂

  • oikcom 16.06.2009

    Срасибо.
    Это я уже заведомо понял, просто в связи с тем, что нужны именно связанные записи, я думал это все можно как то упростить, плюс значений фильтра 12 штук……

  • nibo 16.06.2009

    Подскажите, пожалуйста, а вам не известно что за поле такое crmFormSubmitSecurity? Может его можно как-то генерить самостоятельно? Просто стоит задача показать связанный список с Crm но не в Crm-ной форме.

  • slivka_83 16.06.2009

    Боюсь что не известно. Но наверника какое-нибудь харкодное поле, которой просто так не воспроизвести…

  • nibo 16.06.2009

    Нашел. Это засериализованное значение из перечисления с правами доступа на сущность.

  • slivka_83 16.06.2009

    И с чем его кушать? 🙂 удалось использовать представление CRM вне CRM? 🙂

  • nibo 16.06.2009

    Да в принципе ни с чем не кушать. Ничто не мешает его даже и захардкодить. В нашем случае у нас своя система, которая имеет свою безопасность. Просто замапили наши флаги доступа на CRM-ные, поэтому все оказалось просто. Представление удалось вставить без проблем. Единственно, для представлений N:N пришлось тянуть в наши окна lookup.js и remotecommand.js, но, тем не менее, работает 🙂

  • Dmitry 16.06.2009

    Привет!

    а как вывести связь 1..N для формы с отсутствующей левой частью.

  • slivka_83 16.06.2009

    Добрый день 🙂
    На какой форме? 🙂

  • Константин 16.06.2009

    Добрый день!, спасибо за статью!
    Есть чуть чуть вопросиков, при таком выводе информации в Iframe можно ли убрать верхние кнопки печать слияние и т.д., и второй можно ли допустим при добавление пользователя, что бы окно iframe автоматически обновлялось ?

  • slivka_83 16.06.2009

    Здрасьте. Да, вроде оба вопроса реализуемы. Кнопки можно скрыть добравшись до них по DOM. А обновлять вроде можно через ансапортно стандартные методы (до них тоже нужно добратьсяпо DOM). Вроде раньше встречал как это делается в инете…

*

code