Переопределение js (Решено)

Задача 1.
В файле /engine/lib/internal/template/js/blocks.js есть код, добавляющий класс active иконке обновления блока («прямой эфир» и «блоги»).
В шаблоне используются иконки (точнее шрифт) font-awesome, поэтому необходимо переопределить класс active на класс fa-spin (вращение).

Решение:
— в template.js шаблона перед вызовом функции инициализации блоков добавим опцию:
ls.blocks.options.update_active = 'fa-spin';

— затем переопределим ее с новой опцией:
ls.blocks.init = function(block,params) {
	params=params || {};
	$('.js-block-'+block+'-item').click(function(){
		ls.blocks.load(this, block);
		return false;
	});
	if (params.group_items) {
		this.initNavigation(block,params.group_min);
	}

	var $this=this;
	$('.js-block-'+block+'-update').click(function(){
		$(this).addClass($this.options.update_active);
		ls.blocks.load($this.getCurrentItem(block), block);
		setTimeout( function() { $(this).removeClass($this.options.update_active); }.bind(this), 600 );
	});
};


Задача 2.
В стандартном функционале при добавлении в избранное js движка добавляет к иконке избранного в футере топика класс active, и это легко можно задействовать при использовании спрайтов, указав координаты «активной» иконки. В нашем примере используется иконки font-awesome, поэтому класс active нам не подходит. Хотя vOFFka в своих шаблонах выкрутился по-другому, задав иконке с классом active желтый цвет.
Т.е. нам нужно при добавлении в избранное менять класс иконки избранного с fa-star-o (звездочка с контуром) на fa-star (залитая звездочка).
Также необходимо при добавлении/удалении в избранное соответственно менять title иконке (Добавить в избранное/Удалить из избранного).

Решение:
Окончание процесса добавления/удаления избранного в движке помечено js-хуком.
В template.js шаблона Synio я нашел применение этого хука (удаляет нулевое значение числа добавлений в избранное) и решил его дополнить:
// избранное
ls.hook.add('ls_favourite_toggle_after',function(idTarget,objFavourite,type,params,result){
	$('#fav_count_'+type+'_'+idTarget).text((result.iCount>0) ? result.iCount : '');

	// меняем иконку
	$('#fav_topic_'+idTarget).toggleClass('fa-star').toggleClass('fa-star-o');
	// Для всех типов объектов, добавляемых в избранное (например, + камменты), следует писать так
	// this.objFavourite.toggleClass('fa-star').toggleClass('fa-star-o');
	// или так
	// $('#fav_'+type+'_'+idTarget).toggleClass('fa-star').toggleClass('fa-star-o');

	// меняем title иконке
	if (result.bState) {
		this.objFavourite.attr('title', 'Удалить из избранного');
	} else {
		this.objFavourite.attr('title', 'Добавить в избранное');
	}
});


P.S.:
Вероятно, вышеизложенное гораздо проще реализовать правками непосредственно в файлах движка, но это может привести к проблемам совместимости.

Большое спасибо ort , PSNet (статья) и tema_mak за помощь в решении задач!

29 комментариев

avatar
1. Если методы template.js применяются после template/js/blocks.js, то просто:
$('.your_selector').removeClass('active').addClass('fa-spin');


2. Никак. Только переопределить желаемую функцию на свою, убрав этим нежелательный функционал. Ну или изначально изменить blocks.js под свои потребности.

ИМХО.
avatar
2. Как в пределах настроек скина запретить загрузку какого-либо участка js из движка (например this.initNavigation из blocks.js)?

Не пробовал сам.

Можно в конфиге шаблона не подключать blocks.js из engine. Создать в шаблоне копию, вырезать/переделать ненужно, и подключить ее.
avatar
Можно в конфиге шаблона не подключать blocks.js из engine.
js движка подключаются в глобальном конфиге
avatar
Не совсем, оно подключается так

$config['head']['default']['js'] = Config::Get('head.default.js');


Соответственно можно эту строку удалить, и добавить нужно с глобального конфига.
avatar
Т.е. добавить все, кроме blocks.js. А его уже подключить из шаблонного каталога.
avatar
Отвечая первым комментарием — не совсем разобрался с вопросом.
В общем, сделал бы как написал выше makenskiy . Отключил в конфиге загрузку родного blocks.js.
И сделал бы свой blocks.js.
Это проще и легче в дальнейшей поддержке.
avatar
Как вариант поискать про хуки js на этом сайте и в нужные места попробовать заинжектить банальные ретурны, что бы прервать выполнение стандартной функции.
Это геморнее и более накладно в плане производительности, но зато оставляет больше совмести с движком/щаблоном.
avatar
Вот про это и ищу…
А почему производительность пострадает?
avatar
1. Таскается туда-сюда ненужные код.
2. Время выполнения хука.
avatar
Вот ссылка. Там смотреть в сторону маркеров.

Я этим механизмом в плагине я так вмешивался в работу кнопки «Загрузить» для изображений.
avatar
Да… Запутался я…
Вы не могли бы привести пример?:
здесь вместо добавления/удаления
класса active добавлять/удалять класс fa-spin
— или др. пример — здесь вместо добавления/удаления класса active менять его (fa-star-o или fa-star)
avatar
— здесь вместо добавления/удаления
класса active добавлять/удалять класс fa-spin

Так как тут нет точки встраивания для js-хука, то возможно спасет где-то в своем js прописать
ls.blocks.init = function(block,params) {
...
}


И еще раз её вызвать. Как минимум переопределятся обработкчики для
$('.js-block-'+block+'-update')
avatar
— или др. пример — здесь вместо добавления/удаления класса active менять его (fa-star-o или fa-star)

ls.hook.inject (
	[ls.favourite,'toggle'], 
	" код... ",
	'toggleBefore'
);
avatar
а, так как задача выполнить код вместо родного, то завершить его нужно
return false;


Выполняться он будет после (точне на месте) конструкции
ls.hook.marker('toggleBefore');


Соответвенно ваша задача переписать то, что идет после.
avatar
Показал бы кто пример использования ls.hook.marker…
avatar
Ну собственно выше
avatar
обновил топик
avatar
Вторая задача (заменить добавляемый класс active на fa-spin) пока не решилась.

А если вот так?

ls.hook.inject (
	[ls.favourite,'toggle'], 
	"ls.ajax(this.options.type[type].url, params, function(result) {
			$(this).trigger('toggle',[idTarget,objFavourite,type,params,result]);
			if (result.bStateError) {
				ls.msg.error(null, result.sMsg);
			} else {
				ls.msg.notice(null, result.sMsg);
				this.objFavourite.removeClass(this.options.active);
				if (result.bState) {
					this.objFavourite.removeClass('fa-star-o');
					this.objFavourite.addClass('fa-star');
					this.showTags(type,idTarget);
				} else {
					this.objFavourite.removeClass('fa-star');
					this.objFavourite.addClass('fa-star-o');
					this.hideTags(type,idTarget);
				}
				ls.hook.run('ls_favourite_toggle_after',[idTarget,objFavourite,type,params,result],this);
			}
		}.bind(this));
		return false;",
	'toggleBefore'
);
avatar
Точнее лучше так:

ls.hook.inject (
	[ls.favourite,'toggle'], 
	"ls.ajax(this.options.type[type].url, params, function(result) {
			$(this).trigger('toggle',[idTarget,objFavourite,type,params,result]);
			if (result.bStateError) {
				ls.msg.error(null, result.sMsg);
			} else {
				ls.msg.notice(null, result.sMsg);
				this.objFavourite.removeClass(this.options.active);
				if (result.bState) {
					this.objFavourite.removeClass('fa-star-o');
					this.objFavourite.addClass('fa-star');
					this.showTags(type,idTarget);
				} else {
					this.objFavourite.removeClass('fa-star');
					this.objFavourite.addClass('fa-star-o');
					this.hideTags(type,idTarget);
				}
			}
		}.bind(this));
		return false;",
	'toggleBefore'
);


Что бы после измененного кода не дернуть чужой хук.
avatar
А, блин. Порядок задач же поменялся =)
avatar
В block.js косяк с опцией active — она есть, но не используется.
Для решения можно переопределить весь метод github.com/livestreet/livestreet/blob/1.0.3/engine/lib/internal/template/js/blocks.js#L131 с заменой явного класса на опцию, а затем переопределить эту опцию на нужный класс.
  • ort
  • 0
avatar
Т.е. нужно в template.js переписать это, добавив опцию и заменив класс на опцию?

Опцию active в этом случае переопределится только в init? (чтобы в других местах оставалось active: 'active')
avatar
я погорячился — опция active используется, но для другого
нужно сделать как выше написал, только не переопределять текущую опцию, а добавить новую, например, update_active
avatar
Примерно так будет работать?:
ls.blocks.options.update_active = 'fa-spin';
ls.blocks.init() {
    var $this=this; 
    $('.js-block-'+block+'-update').click(function(){ 
        $(this).addClass(this.options.update_active); 
        ls.blocks.load($this.getCurrentItem(block), block); 
        setTimeout( function() { $(this).removeClass(this.options.update_active); }.bind(this), 600 ); 
    }); 
};
avatar
не работает, к сожалению…
avatar
ls.blocks.init() {

заменить на
ls.blocks.init = function(block,params) {
		params=params || {};
		$('.js-block-'+block+'-item').click(function(){
			ls.blocks.load(this, block);
			return false;
		});
		if (params.group_items) {
			this.initNavigation(block,params.group_min);
		}

И этот код должен быть прописан до инициализации js блоков (вызова ls.blocks.init() ).
avatar
можно ли тут использовать принцип наследования, чтобы не переписывать всю функцию?
avatar
и this.options.update_active заменить на $this.options.update_active
avatar
Большое спасибо!!!
Обновил топик…
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.