Вызов окна MODx.Window на ExtJs
Решил разобраться, почему криво работает вызов окна MODx.Window при разработке в админке, используя modExtra. Проблема в следующем — при первом вызове окно открывается в нормальном виде
При последующих вызовах получаю такое окно
Честно говоря, я не понимаю, почему происходит такая фигня.
Вот пример вызова окна в modExtra, который я использую
А пока копался, обнаружил, что такой код вызывает распухание DOMa — метод hide() скрывает окно (выставляет visibility: hidden). И при повторном вызове ExtJs создает новое окно (про старое-то он не знает). И вот так закрывая-открывая окно, получаем куча скрытых окошек в DOMе плюс разные служебные элементы ExtJS. Решая эту проблему, я попутно решил и описанную выше с кривыми окошками.
Измененный код
Теперь всегда используется уже созданное окно, а не создается новое. Обе проблема решены, но я все равно не понимаю, почему, например, у Tickets окна вызываются нормально, у меня нет, хотя в точности всё до запятой совпадает. Видимо есть какая-то мелкая мелочь, которая ускользнула от моего пристального внимания.
При последующих вызовах получаю такое окно
Честно говоря, я не понимаю, почему происходит такая фигня.
Вот пример вызова окна в 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);
Теперь всегда используется уже созданное окно, а не создается новое. Обе проблема решены
Поблагодарить автора
Отправить деньги
Комментарии: 24
Видимо есть какая-то мелкая мелочь, которая ускользнула от моего пристального внимания.Одинаковые идентификаторы.
Такое дублирование элементов в ExtJS всегда бывает, если у них одинаковые id. Если у полей твоей формы указаны id и они не нужны тебе, на самом деле, то убирай их нафиг — пусть ExtJS сгенерирует уникальные автоматически.
У полей в окошке комментария, как видно, нигде id не указаны, поэтому их можно открыть сколько угодно и никаких дубликатов.
Точно. Выставил вместо статических id динамические
Но проблема с утечкой (хоть и не большой) в modExtra остается. Есть смысл в репозиторий modExtra писать?
id: config.id + '-class',
Теперь работает. Спасибо.Но проблема с утечкой (хоть и не большой) в modExtra остается. Есть смысл в репозиторий modExtra писать?
Даже и не знаю, буду ли я там когда-нибудь что-то менять в ближайшее время.
Если есть желание, я могу тебя добавить в этот репозиторий, будешь сам принимать коммиты. Идёт?
Если есть желание, я могу тебя добавить в этот репозиторий, будешь сам принимать коммиты. Идёт?
Я готов. Но вряд ли без твоего согласия решусь коммитить. Ведь ежели чего поломается, меня же потом тухлыми помидорами закидают.
Кстати, там же Илья вроде уже дирижирует.
Кстати, там же Илья вроде уже дирижирует.
Всё, теперь ты можешь одобрять pull-request.
А Илья просто коммитил, как и все.
А Илья просто коммитил, как и все.
Василий, я конечно не в тему поинтересуюсь, но создавать отдельный топик тоже не хочется. Ты как-то писал о том, что в будущем сделаешь курс по ExtJS, я очень жду до сих пор и хотелось бы узнать — а ждать ли вообще?)
Да он уже давно был, вроде.
Для старта должно хватить, а больше ничего на эту тему писать не планирую.
Для старта должно хватить, а больше ничего на эту тему писать не планирую.
Утечка-то где?
Ну вот захотелось мне открыть 100500 комментов — почему нет?
Ну вот захотелось мне открыть 100500 комментов — почему нет?
100500 окон одного и того же коммента?
Why not?
Не вижу проблемы, серьёзно. Если бы оперативка заканчивалась и браузер вешался — это утечка. А так просто не идеально =)
Не вижу проблемы, серьёзно. Если бы оперативка заканчивалась и браузер вешался — это утечка. А так просто не идеально =)
Ну как бы формально это называется утечкой. Я тоже не считаю, что это критично. Я так и написал, что небольшая утечка. В самом MODX при редактировании системных настроек такой же код — и ничего ни у кого не виснет. Но феншуйнее было бы одно окно вызывать.
Где возможность открытия окошек формально называют утечкой? Утечкой чего, кстати?
Я вот штук 30 окон наоткрывал, да так и не увидел разницы с потреблении оперативки браузером.
Дай хоть ссылку почитать, а то утечка не пойми чего происходит, а я и не в курсе.
Я вот штук 30 окон наоткрывал, да так и не увидел разницы с потреблении оперативки браузером.
Дай хоть ссылку почитать, а то утечка не пойми чего происходит, а я и не в курсе.
«Доцент, ты, конечно, вор авторитетный», но в чем смысл стеба не пойму. Причем здесь возможность открытия 30 окошек? Я писал про то, что все эти окошки после закрытия остаются в DOMе и больше никогда не используются. Открой еще 30 окошек и у тебя будет 60 окошек. Одно окошко состоит из кучи дивов и разных служебных элементов. DOM разбухает. Вот я про что писал. Ну может это не совсем утечка в формальном смысле, но явно ничего хорошего не получается. Вот несколько раз открыл и закрыл окно
Про утечки можно почитать на learn.javascript.ru.
Про утечки можно почитать на learn.javascript.ru.
Формально, утечка памяти — это когда сборщик мусора не удаляет из памяти что-то, что по логике должно быть удалено (к примеру, циклические ссылки на объекты или неправильная работа с замыканиями). И с каждой последующей итерацией выполнения кода — память не высвобождается.
Утечки памяти — это более тонкая материя. А то, что описали вы, формально — это просто баг (или фича) в _логике_ самого приложения.
Утечки памяти — это более тонкая материя. А то, что описали вы, формально — это просто баг (или фича) в _логике_ самого приложения.
Ну да, я в курсе, просто обозвал так, чтобы было понятнее. Наверно, зря, ибо Василий прицепился именно к этому слову, хотя я уверен, что он понял в чем суть.
Я привел Василию ссылку, где пишут про утечки. Там тоже пишут, что проблемы могут возникнуть, если интерфейс очень сложный. А в обычной жизни ни замыкания, ни jQuery утечки проблем не доставляют.
П.С. Я думаю, это не баг и не фича. Это способ программирования. Кто-то считает, что так можно и вреда не будет, кто-то нет. Вот и вся разница. Такой код не приведет к проблемам, иначе уже давно ругались бы при редактировании системных настроек.
П.П.С. Мы же вроде на ты уже общались :)
Я привел Василию ссылку, где пишут про утечки. Там тоже пишут, что проблемы могут возникнуть, если интерфейс очень сложный. А в обычной жизни ни замыкания, ни jQuery утечки проблем не доставляют.
П.С. Я думаю, это не баг и не фича. Это способ программирования. Кто-то считает, что так можно и вреда не будет, кто-то нет. Вот и вся разница. Такой код не приведет к проблемам, иначе уже давно ругались бы при редактировании системных настроек.
П.П.С. Мы же вроде на ты уже общались :)
Я же уже согласился, что мой код не идеален, но и никакой проблемы я в этом не вижу.
В новых виджетах я прибиваю окошки принудительно, сразу после скрытия, примерно так:
В новых виджетах я прибиваю окошки принудительно, сразу после скрытия, примерно так:
this.on('hide', function() {
var w = this;
window.setTimeout(function() {
w.close()
}, 300);
})
И анимация на месте, и лишних элементов не остаётся. Может и в Tickets когда-то это допишу, но не сегодня.
Так и я написал, что это не проблема, чисто ради программного феншуя. А картинка с кодом спрятанных окошек — это окна, которые остаются после редактирования системных настроек. Т.е. ребята из MODx тоже не заморачиваются.
Подскажи, если знаешь, как оставить анимацию закрытия у окна, которому сам прописываю только одну кнопку закрытия, вместо стандартных
Подскажи, если знаешь, как оставить анимацию закрытия у окна, которому сам прописываю только одну кнопку закрытия, вместо стандартных
buttons: [{
text: _('close'),
id: 'window-close-btn',
handler: function(){this.hide();},
scope: this
}]
Кнопка закрывает окно без анимации. Посмотрел в исходниках MODx.Window. Там прописаны 2 кнопки — <Отмена> и <Сохранить>. Причем у кнопки отмены прописан тот же this.hide(). Но анимация работает. А у меня нет.
У меня была подобная проблема при показе нового окошка загрузки в галерее.
Решилась она верным открытием, а не свойствами самого окна:
Вот само окно, если что.
Решилась она верным открытием, а не свойствами самого окна:
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. Попробуй.Вот само окно, если что.
Супер. Вот теперь красиво. Спасибо огромное.
Во времена, когда меня ещё не тошнило от ExtJS'а и я не оставлял попыток познакомиться с ним поближе, я тоже натыкался на описываемое в статье поведение. И мне это тоже жутко не нравилось.
Решал это тем, что в методе открытия окна делал проверку на существование этого же окна в dom'е. Если в dom'е оно есть, то делаем hide(), remove(), а потом создаем окошко заново.
У окна, соответственно, жестко прописанный id-шник.
Как-то так:
Решал это тем, что в методе открытия окна делал проверку на существование этого же окна в 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);
}
Я поначалу также хотел сделать, но потом решил, что пусть одно окно будет, нужно просто его запомнить и вызывать.
Такое поведение свойственно если жестко задавать id-шники элементам, если обходится без них то данных проблем и не возникнет. В случае чего помогает способ выше от Алексея Карташова.
А мое решение, описанное в статье, некорректно?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.