Вызов окна MODx.Window на ExtJs

Решил разобраться, почему криво работает вызов окна MODx.Window при разработке в админке, используя modExtra. Проблема в следующем — при первом вызове окно открывается в нормальном виде

При последующих вызовах получаю такое окно

Честно говоря, я не понимаю, почему происходит такая фигня.
Вот пример вызова окна в modExtra, который я использую
createItem: function (btn, e) {
	var w = MODx.load({
		xtype: 'modextra-item-window-create',
		id: Ext.id(),
		listeners: {
			success: {
				fn: function () {
					this.refresh();
				}, scope: this
			}
		}
	});
	w.reset();
	w.setValues({active: true});
	w.show(e.target);
},
В исходниках MODX используется такой же код. Также работает и Tickets. А у меня не хочет работать и все тут. До сегодняшнего дня поступал просто — закрывал окно методом close(), который уничтожает окно (стандартно вызывается hide(), скрывающий окно). Но тут возникает неприятный момент — при закрытии через close() не работает анимация (через hide(), окно как бы растворяется). Поэтому решил найти причину, чтобы красиво закрывать окно.
А пока копался, обнаружил, что такой код вызывает распухание DOMa — метод hide() скрывает окно (выставляет visibility: hidden). И при повторном вызове ExtJs создает новое окно (про старое-то он не знает). И вот так закрывая-открывая окно, получаем куча скрытых окошек в DOMе плюс разные служебные элементы ExtJS. Решая эту проблему, я попутно решил и описанную выше с кривыми окошками.
Измененный код
if (!this.createWindow) {
	this.createWindow= MODx.load({
		xtype: 'dmodextra-item-window-create',
		id: Ext.id(),
		listeners: {
			success: {
				fn: function () {
					this.refresh();
				}, scope: this
			}
		}
	});
}
this.createWindow.reset();
this.createWindow.setValues({active: true});
this.createWindow.show(e.target);

Теперь всегда используется уже созданное окно, а не создается новое. Обе проблема решены, но я все равно не понимаю, почему, например, у Tickets окна вызываются нормально, у меня нет, хотя в точности всё до запятой совпадает. Видимо есть какая-то мелкая мелочь, которая ускользнула от моего пристального внимания.
Сергей Шлоков
24 августа 2015, 15:11
modx.pro
2 184
0
Поблагодарить автора Отправить деньги

Комментарии: 24

Василий Наумкин
24 августа 2015, 18:22
0
Видимо есть какая-то мелкая мелочь, которая ускользнула от моего пристального внимания.
Одинаковые идентификаторы.

Такое дублирование элементов в ExtJS всегда бывает, если у них одинаковые id. Если у полей твоей формы указаны id и они не нужны тебе, на самом деле, то убирай их нафиг — пусть ExtJS сгенерирует уникальные автоматически.

У полей в окошке комментария, как видно, нигде id не указаны, поэтому их можно открыть сколько угодно и никаких дубликатов.
    Сергей Шлоков
    24 августа 2015, 18:32
    0
    Точно. Выставил вместо статических id динамические
    id: config.id + '-class',
    Теперь работает. Спасибо.
    Но проблема с утечкой (хоть и не большой) в modExtra остается. Есть смысл в репозиторий modExtra писать?
      Василий Наумкин
      24 августа 2015, 18:48
      0
      Даже и не знаю, буду ли я там когда-нибудь что-то менять в ближайшее время.

      Если есть желание, я могу тебя добавить в этот репозиторий, будешь сам принимать коммиты. Идёт?
        Сергей Шлоков
        24 августа 2015, 18:52
        0
        Я готов. Но вряд ли без твоего согласия решусь коммитить. Ведь ежели чего поломается, меня же потом тухлыми помидорами закидают.
        Кстати, там же Илья вроде уже дирижирует.
          Василий Наумкин
          24 августа 2015, 20:25
          0
          Всё, теперь ты можешь одобрять pull-request.

          А Илья просто коммитил, как и все.
            Павел Гвоздь
            24 августа 2015, 22:09
            +1
            Василий, я конечно не в тему поинтересуюсь, но создавать отдельный топик тоже не хочется. Ты как-то писал о том, что в будущем сделаешь курс по ExtJS, я очень жду до сих пор и хотелось бы узнать — а ждать ли вообще?)
              Василий Наумкин
              24 августа 2015, 22:11
              +1
              Да он уже давно был, вроде.

              Для старта должно хватить, а больше ничего на эту тему писать не планирую.
    Сергей Шлоков
    24 августа 2015, 20:10
    0
    Чисто для демонстрации вышеописанного механизма утечки
      Василий Наумкин
      24 августа 2015, 20:24
      0
      Утечка-то где?

      Ну вот захотелось мне открыть 100500 комментов — почему нет?
        Сергей Шлоков
        24 августа 2015, 20:27
        0
        100500 окон одного и того же коммента?
          Василий Наумкин
          24 августа 2015, 20:30
          0
          Why not?

          Не вижу проблемы, серьёзно. Если бы оперативка заканчивалась и браузер вешался — это утечка. А так просто не идеально =)
            Сергей Шлоков
            24 августа 2015, 20:39
            0
            Ну как бы формально это называется утечкой. Я тоже не считаю, что это критично. Я так и написал, что небольшая утечка. В самом MODX при редактировании системных настроек такой же код — и ничего ни у кого не виснет. Но феншуйнее было бы одно окно вызывать.
              Василий Наумкин
              24 августа 2015, 20:46
              0
              Где возможность открытия окошек формально называют утечкой? Утечкой чего, кстати?

              Я вот штук 30 окон наоткрывал, да так и не увидел разницы с потреблении оперативки браузером.

              Дай хоть ссылку почитать, а то утечка не пойми чего происходит, а я и не в курсе.
                Сергей Шлоков
                24 августа 2015, 21:52
                0
                «Доцент, ты, конечно, вор авторитетный», но в чем смысл стеба не пойму. Причем здесь возможность открытия 30 окошек? Я писал про то, что все эти окошки после закрытия остаются в DOMе и больше никогда не используются. Открой еще 30 окошек и у тебя будет 60 окошек. Одно окошко состоит из кучи дивов и разных служебных элементов. DOM разбухает. Вот я про что писал. Ну может это не совсем утечка в формальном смысле, но явно ничего хорошего не получается. Вот несколько раз открыл и закрыл окно

                Про утечки можно почитать на learn.javascript.ru.
                Алексей Карташов
                24 августа 2015, 21:46
                0
                Формально, утечка памяти — это когда сборщик мусора не удаляет из памяти что-то, что по логике должно быть удалено (к примеру, циклические ссылки на объекты или неправильная работа с замыканиями). И с каждой последующей итерацией выполнения кода — память не высвобождается.
                Утечки памяти — это более тонкая материя. А то, что описали вы, формально — это просто баг (или фича) в _логике_ самого приложения.
                  Сергей Шлоков
                  24 августа 2015, 21:58
                  0
                  Ну да, я в курсе, просто обозвал так, чтобы было понятнее. Наверно, зря, ибо Василий прицепился именно к этому слову, хотя я уверен, что он понял в чем суть.
                  Я привел Василию ссылку, где пишут про утечки. Там тоже пишут, что проблемы могут возникнуть, если интерфейс очень сложный. А в обычной жизни ни замыкания, ни jQuery утечки проблем не доставляют.
                  П.С. Я думаю, это не баг и не фича. Это способ программирования. Кто-то считает, что так можно и вреда не будет, кто-то нет. Вот и вся разница. Такой код не приведет к проблемам, иначе уже давно ругались бы при редактировании системных настроек.
                  П.П.С. Мы же вроде на ты уже общались :)
                    Василий Наумкин
                    24 августа 2015, 22:10
                    0
                    Я же уже согласился, что мой код не идеален, но и никакой проблемы я в этом не вижу.

                    В новых виджетах я прибиваю окошки принудительно, сразу после скрытия, примерно так:
                    this.on('hide', function() {
                    	var w = this;
                    	window.setTimeout(function() {
                    		w.close()
                    	}, 300);
                    })
                    И анимация на месте, и лишних элементов не остаётся. Может и в Tickets когда-то это допишу, но не сегодня.
                      Сергей Шлоков
                      24 августа 2015, 23:31
                      0
                      Так и я написал, что это не проблема, чисто ради программного феншуя. А картинка с кодом спрятанных окошек — это окна, которые остаются после редактирования системных настроек. Т.е. ребята из MODx тоже не заморачиваются.
                      Подскажи, если знаешь, как оставить анимацию закрытия у окна, которому сам прописываю только одну кнопку закрытия, вместо стандартных
                      buttons: [{
                      	text: _('close'),
                      	id: 'window-close-btn',
                      	handler: function(){this.hide();},
                      	scope: this
                      }]
                      Кнопка закрывает окно без анимации. Посмотрел в исходниках MODx.Window. Там прописаны 2 кнопки — <Отмена> и <Сохранить>. Причем у кнопки отмены прописан тот же this.hide(). Но анимация работает. А у меня нет.
                        Василий Наумкин
                        25 августа 2015, 06:42
                        +3
                        У меня была подобная проблема при показе нового окошка загрузки в галерее.

                        Решилась она верным открытием, а не свойствами самого окна:
                        var w = MODx.load({
                        	xtype: 'ms2gallery-uploader-window',
                        	record: this.config.record,
                        	listeners: {
                        		success: {fn:function() {this.store.reload()}, scope: this}
                        	}
                        });
                        w.show(Ext.EventObject.target);
                        Весь фокус в последней строке, точнее в Ext.EventObject.target. Попробуй.

                        Вот само окно, если что.
                          Сергей Шлоков
                          25 августа 2015, 07:11
                          0
                          Супер. Вот теперь красиво. Спасибо огромное.
                    Алексей Карташов
                    24 августа 2015, 22:38
                    +1
                    Во времена, когда меня ещё не тошнило от ExtJS'а и я не оставлял попыток познакомиться с ним поближе, я тоже натыкался на описываемое в статье поведение. И мне это тоже жутко не нравилось.
                    Решал это тем, что в методе открытия окна делал проверку на существование этого же окна в dom'е. Если в dom'е оно есть, то делаем hide(), remove(), а потом создаем окошко заново.
                    У окна, соответственно, жестко прописанный id-шник.

                    Как-то так:
                    // ...
                    ,createDiscount: function(btn,e) {
                    	// находим dom-элемент
                    	var w = Ext.getCmp('ms2discount-window-discount-create');
                    	// если есть, скрываем и удаляем
                    	if (w) {w.hide().getEl().remove();}
                    
                    	if (!this.windows.createDiscount) {
                    		this.windows.createDiscount = MODx.load({
                    			xtype: 'ms2discount-window-discount-create'
                    			,id: 'ms2discount-window-discount-create'
                    			,fields: this.getDiscountFields('create', {})
                    			,listeners: {
                    				success: {
                    					fn: function() { this.refresh(); },
                    					scope: this
                    				},
                    				hide: {
                    					fn: function() {
                    						this.getEl().remove()
                    					}
                    				}
                    			}
                    		});
                    	}
                    	this.windows.createDiscount.fp.getForm().reset();
                    	this.windows.createDiscount.show(e.target);
                    }
                      Сергей Шлоков
                      24 августа 2015, 23:13
                      0
                      Я поначалу также хотел сделать, но потом решил, что пусть одно окно будет, нужно просто его запомнить и вызывать.
        Володя
        24 августа 2015, 22:43
        0
        Такое поведение свойственно если жестко задавать id-шники элементам, если обходится без них то данных проблем и не возникнет. В случае чего помогает способ выше от Алексея Карташова.
          Сергей Шлоков
          24 августа 2015, 23:12
          0
          А мое решение, описанное в статье, некорректно?
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          24