Доброго времени суток, уважаемое сообщество... 

Сей пост про использование стандартной библиотеки всплывающих окон PopupWindow. 

Для начала тем, кто еще не знаком, стоит познакомиться с официальной  документацией  и с  постом

Итак ... 

Была у меня задача - сделать аяксовую сменую 3-х отображений списка товаров инфоблока. Об этом писать не буду. Тут достаточно изучить  пост  . Это успешно было реализовано. Все обрадовались, попили пива ... А дальше начали детально все тестировать и обнаружили, что стандартная всплывашка, которая появилась в eshop и реализованная через JCCatalogSection после аякс-показа элемента - просто не отрабатывает. Потратил часа 4 - так и не разобрался, что же нужно сделать, чтобы работала ... Посему, решил сделать свою. 

Создал отдельный js-файл, подключил его сразу в хедере (знаю, что можно было подключить и только на тех страницах, где это нужно, но не стал уже заморачиваться.... хотя стоило бы:) ), а также подключил в хедере popup-библиотеку (jquery был уже подключен. Если у вас не подключен - его тоже нужно): 

CJSCore::Init(array("popup"));

Представляю вашему вниманию текст данного файла: 

BX.ready(function(){
    var Confirmer = new BX.PopupWindow("add_basket-confirm", null, {
     content: '<div id="mainshadow"></div>'+'<h3>Товар успешно добавлен в корзину</h3>',
     titleBar: {content: BX.create("span", {html: 'Товар добавлен в корзину', 'props': {'className': 'access-title-bar'}})},
     zIndex: 0,
     autoHide : true,
      offsetTop : 1,
      offsetLeft : 0,
      lightShadow : true,
      closeIcon : true,
      closeByEsc : true,
     draggable: {restrict: false},
     overlay: {backgroundColor: 'black', opacity: '80' },  /* затемнение фона */
     buttons: [
      new BX.PopupWindowButton({
          text: "Перейти в корзину",
          className: "popup-window-button-accept",
          events: {click: function(){
           location.href="/personal/cart/";
          }}
      }),
      new BX.PopupWindowButton({
          text: "Продолжить покупки",
          className: "webform-button-link-cancel",
          events: {click: function(){
           this.popupWindow.close(); // закрытие окна
          }}
      })
     ]
    });

    function PAIAddToBasket(PRODUCT_ID,QntTy){
     $.post('/basketchange.php',
      {
          itemID: PRODUCT_ID,
          quantity:  QntTy
      },
      function(data){
          $('div#basket-line').html(data);
          Confirmer.show();
      }
     );
    }

    $('div.bx_content_section').on('click','.buy_btn',function(){
     var PRODUCT_ID = $(this).attr('product_id');
     var QntTy = 1;
     PAIAddToBasket(PRODUCT_ID,QntTy);
     return false;
    });

});

и в подвале помещаем див: 

<div id="add_basket-confirm"></div>

ну и последний штрих: во всех видах отображения у ссылок, отвечающих за добавление товара в корзину, добавляем класс "buy_btn". Примерно вот так: 

<a class="buy_btn" href="#" product_id="<?=$arItem['ID']?>" > В корзину </a>

обычно в атрибут "product_id" помещаю ID товара, который нужно добавить в корзину. Не совсем корректно, но ничего умнее пока не придумал:) 

Суть скрипта: вешаем на ссылку с классом buy_btn обработчик, который получает ID товара и количество единиц, которое нужно добавить (в данном случае - всегда 1 :) )и это все передаем в функцию, которая делает аякс- запрос к файлу, добавляющему товар в корзину (этот файл возвращает обратно компонент "Ссылка на корзину", который также обновляем при добавлении товара в корзину) и вызывает всплывашку. 

P.S. Если не хотите портить дефолтные стили у шаблонов от eshop - просто удалите атрибут ID у ссылок добавления в корзину:) 

UPDATE 2014-09-22

Увидел еще одну штуку: если нужно какое-то событие после показа popup-окна, то добавляется еще один параметр, описывающий события popup: 

events: {
     onPopupClose: function () {
                    console.debug('onPopupClose event');
                },
    onAfterPopupShow: function () {
        BX.ajax.post(
            'GetFolder(); ?>/popup.php',
            {
                lang: BX.message('LANGUAGE_ID'),
                site_id: BX.message('SITE_ID') || '',
                arParams: curSetParams
 },
            BX.delegate(function (result) {
                    this.setContent(result);
                    BX("CatalogSetConstructor_" + element_id).style.left = (window.innerWidth - BX("CatalogSetConstructor_" + element_id).offsetWidth) / 2 + "px";
                    var popupTop = document.body.scrollTop + (window.innerHeight - BX("CatalogSetConstructor_" + element_id).offsetHeight) / 2;
                    //BX("CatalogSetConstructor_" + element_id).style.top = popupTop > 0 ? popupTop + "px" : 0;
 },
                this)
        );
    }
} 

Это увидел в компоненте catalog.set.constructor. Оставил так, как было в исходнике. Суть: сначала в попапе показывается прелоадер, а при открытии из файла popup.php тянется содержимое попапа ... Но, конечно же, можно сделать еще кучу других очень полезных фишек, используя данный метод ...

UPDATE 2017-09-26

Если вам нужно вывести во всплывашке что-то, загруженное по аяксу - есть 2 варианта рещения:

  • Если текст должне подтягиваться каждый раз перед показом - значит подгружать текст нужно перед показом его пользователю. Т.е. функция установки данных должна вызываться перед показом popup-а.
  • Содержимое попапа должно получаться по аяксу, но один раз на страницу - тогда получение данных по аяксу лучшу сделать перед определением самого popup-а.

Для примера рассмотрю второй вариант. Итак, в html-структуре создаем контейнер, из которого всплывашка будет получать данные:

<div id="popup_container"></div>

И начало для popup тогда примет вид:

BX.ready(function(){
	BX.ajax.insertToNode('/ajax_path.php', BX('popup_container'));
    var Confirmer = new BX.PopupWindow("add_basket-confirm", null, {
     content: BX('popup_container'),
.....

Благодаря тому, что контент залили в контейнер мы до определения всплывашки - центрирование произойдет автоматически. Если же нужно контент подтягивать перед самим показом всплывашки - значит для контейнера, в который заливаем данные по аяксу, нужно обязательно задать в стилях ширину, т.к. центр рассчитывается библиотекой на основании ширины этого контейнера.

UPDATE 2020-11-29

Пример использования библиотеки для создания формы обратной связи с простейшей превалидацией полей:

BX.ready(function(){
	var formReviewErrors = false;
	var popupFields = BX.create({
		tag: 'form',
		props: {
			className: 'formFieldsContainer',
			action: '/ajax/',
			id: 'reviewContainerForm', 
			method:'post'
		},
		children: [
			BX.create({
				tag: 'input',
				props: {
					name: 'sessid',
					type: 'hidden', 
					value: BX.bitrix_sessid()
				}
			}),
			BX.create({
				tag: 'input',
				props: {
					name: 'action',
					type: 'hidden', 
					value: 'addReview'
				}
			}),
			BX.create({
				tag:'div',
				props: {
					className: "form-group"
				},
				children: [
					BX.create({
						tag: 'label',
						props: {for: 'reviewName'},
						text: 'Ваше имя'
					}),
					BX.create({
						tag: 'input',
						props: {
							id: 'reviewName',
							type:'text',
							className:'form-control',
							placeholder:'Ваше имя',
							name:'reviewName'
						},
						events: {
							change: function (){
								if(
									this.value.length<=0 || 
									!/[а-яА-ЯЁё]/.test(this.value)
								){
									BX.adjust(BX(this),{
										props:{className: "form-control invalid"}
									});
									return false;
								} else {
									BX.adjust(BX(this),{
										props:{className: "form-control"}
									});
									return true;
								}
							},
							input: function (){
								if(this.value.length<=0 || 
									!/[а-яА-ЯЁё]/.test(this.value)
								){
									BX.adjust(BX(this),{
										props:{className: "form-control invalid"}
									});
									return false;
								} else {
									BX.adjust(BX(this),{
										props:{className: "form-control"}
									});
									return true;
								}
							}
						}
					}),
				]
			}),
			BX.create({
				tag:'div',
				props: {
					className: "form-group"
				},
				children: [
					BX.create({
						tag: 'label',
						props: {for: 'reviewText'},
						text: 'Ваш отзыв'
					}),
					BX.create({
						tag: 'textarea',
						props: {
							id: 'reviewText',
							name: 'reviewText',
							rows:3,
							className:'form-control'},
						events: {
							change: function (){
								if(this.value.length<=0 || 
									!/[а-яА-ЯЁё]/.test(this.value)){
									BX.adjust(BX(this),{
										props:{className: "form-control invalid"}
									});
									return false;
								} else {
									BX.adjust(BX(this),{
										props:{className: "form-control"}
									});
									return true;
								}
							},
							input: function (){
								if(this.value.length<=0 || 
									!/[а-яА-ЯЁё]/.test(this.value)){
									BX.adjust(BX(this),{
										props:{className: "form-control invalid"}
									});
									return false;
								} else {
									BX.adjust(BX(this),{
										props:{className: "form-control"}
									});
									return true;
								}
							}
						}
					}),
				]
			}),
		]
	});
	var addReviewForm = new BX.PopupWindow("addReviewForm", null, {
		content: popupFields,
		titleBar: {content: BX.create("div", {
			html: 'Оставить отзыв о работе', 
			props: {'className': 'access-title-bar'}
		})},
		zIndex: 0,
		autoHide : true,
		offsetTop : 1,
		offsetLeft : 0,
		lightShadow : true,
		closeIcon : true,
		closeByEsc : true,
		draggable: {restrict: false},
		overlay: {backgroundColor: 'black', opacity: '80' },
		buttons: [
			new BX.PopupWindowButton({
				id: 'reviewSuccessBtn',
				text: "Оставить отзыв",
				className: "btn btn-success",
				events: {
					click: function (){
						BX.fireEvent(BX('reviewName'),'change');
						BX.fireEvent(BX('reviewText'),'change');

						if(BX.findChildren(
							BX('reviewContainerForm'),{class:'invalid'},true
						).length>0){
							return false;
						} else {
							BX.ajax.submitAjax(BX('reviewContainerForm'),
								{
									method: 'POST',
									dataType: 'json',
									onsuccess: function(data){
										if(data.SUCCESS_ID!==undefined){
											BX.adjust(BX('reviewContainerForm'),{
												html:'Ваш отзыв будет опубликован после проверки модератором!'
											});
											BX.cleanNode(BX('reviewSuccessBtn'),true);
										} else if(data.ERROR!==undefined){
											alert(data.ERROR); // TODO: реализовать вывод тут же в форме
										}
									},
									onfailure: function(data){
										console.debug('error');
										console.debug(data);
									}
								});
						}

					}
				}
			})
		]
	});
	let ReviewsBtnContainer = BX('addRewiewBtnContainer');
	let Btn = BX.create({
		tag: "button",
		props: {className: "btn btn-info btn-large"},
		text: 'Оставить отзыв',
		events: {
			click: function () {
				addReviewForm.show();
			}
		}
	});
	BX.append(Btn,ReviewsBtnContainer);

});

Если в процессе работы со всплывашкой ее ширины меняется - сталкиваемсяс проблемой отсутствия центрированности окна. Чтобы отцентрировать окно после изменения его ширины, необходимо вызвать функцию центрирования:

Confirmer.adjustPosition();
Количество показов: 51136


Реклама: ООО 'КвикСофт'. ИНН 7734706120. ERID: CQH36pWzJqCRJ4UXKvMNSFqMsX7dYBaPEMRX5odpmNzefp
Реклама: ООО "Таймвеб". ИНН 7840339881. ERID: CQH36pWzJqCRJ4UXUsMHpqiAFXGXsNMKwFXHih2J7kSZMP

Разработка сайта

Подайте заявку на разработку сайта на базе готового решения от компании 1С-Битрикс или одного из партнеров компании. Максимально подробно опишите, чему будет посвящен сайт, если это интернет-магазин - что он будет продавать, нужна ли мультиязычность, будут ли разные типы цен (розница, опт, крупный опт), будет ли интеграция с 1С, будет ли выгрузка товаров на различные торговые площадки...

Сопровождение сайта

Вы можете подать заявку на сопровождение вашего сайта на базе 1С-Битрикс. Сопровождение включает в себя: проверка актуальности обновлений сайта, проверка актуальности резервной копии, консультации по сайту. Опишите в заявке, какие еще объемы планируются на сопровождении и на какой срок вы планируете заключить договор на сопровождение - мы подберем подходящий вам бюджет на сопровождение

Работы по сайту

Вы можете подать заявку на выполнение определенного объема работ по сайту. Опишите в заявке объем работ. Это может быть разработка какого-то нового функционала, доработки по имеющемуся функционалу, доработки под требования сео-специалистов. На основании заявки вам будет сформирован бюджет работ, а также названы сроки на выполнение тех или иных работ.