Генератор обработчиков массивов

Пусть есть функция, которая знает как обрабатывать объект. Генератор вернет такую функцию, которая сможет обрабатывать списки таких объектов. Возьмем для примера функцию hide, которая должна скрывать DOM узлы. 
function add_class (node, class_name) {
    var node_classes;

    node_classes = node.className;
    node.className = (node_classes ? node_classes + ' ' : '') + class_name;
}


function remove_class (node, class_name) {
	node.className = node.className.replace(new RegExp(' *' + class_name + ' *', 'g'), '');
}
И превратим их в обработчкики списков с помощью функции ниже: 
function make_iterable (func) {
	var arr_proto;

	// храним ссылку на прототип массива
	arr_proto = Array.prototype;
	return function (el) {
		var res,
			args,
			i;

		// сюда будут складываться результаты множественных вызовов
		res = [];

		// структура типа [undefined, все_кроме_первого_аргумента]
		args = [undefined].concat(arr_proto.slice.call(arguments, 1));

		// проверка на «массивность». Специально сделана, чтобы корректно
		// обработала коллекции типа document.links, document.images
		if ('length' in el) {
			for (i = 0; i < el.length; i += 1) {
				// подменяем в структуре первый элемент на элемент массива
				// [элемент_массива, все_кроме_первого_аргумента]
				args.splice(0,1,el[i]);

				// запоминаем результат вызова обработчика
				// с этим набором аргументов
				res[i] = func.apply(this, args);
			}
		} else {
			// если передался не массив аргументов, вызываем
			// обработчик с указанными аргументами
			res.push(func.apply(this, arguments));
		}

		// массив результатов вызовов обработчика
		return res;
	};
}
Теперь можно подняться на уровень выше, и мыслить категориями коллекций, а не отдельных нод.
var add_class_to_multiple = make_iterable(add_class);

function hide (selector) {
    add_class_to_multiple(document.querySelectorAll(selector), 'hidden');
}
Share
Send
Popular