Изменение размера элемента при клике
Доброго времени суток! 3 дня не ем и не сплю пытаюсь сделать такую вещь:
есть элемент, при клике на него необходимо сделать увеличение его размеров, и уменьшение при очередном клике. НО! необходимо также сделать уменьшение, если человек щелкнул мышью вне этого элемента на экране. Все это должно работать одновременно. Сейчас код выглядит примерно так: $('.float').click(function() { $('.float').toggleClass('size'); }); При клике добавляю/убираю класс с увеличенным размером. Как сделать еще клик со свободной областью ума не приложу. Если делать общий клик по документу то он перебивает клик по селектору. Помогите пожалуйста! Заранее благодарен! |
Вероятно не самый лучший вариант..
<style> .float{height: 20px;background: yellow} .size{height:100px} </style> <div class="float"></div> <script> (function(){ var onDocumentClick = function() { setTimeout(function(){ element.addEventListener('click', onElementClick); }); document.removeEventListener('click', onDocumentClick); element.classList.remove('size'); }; var onElementClick = function() { setTimeout(function(){ document.addEventListener('click', onDocumentClick); }); element.removeEventListener('click', onElementClick); element.classList.add('size'); }; var element = document.querySelector('.float'); element.addEventListener('click', onElementClick); })(); </script> |
Спасибо за решение, буду сидеть разбираться... делаю на jquery, поэтому для чистого js нужно немного вникнуть.
|
Единственное, что возможно вызывает непонимание - это setTimeout в onElementClick.
Без него, событие тут же отрабатывает на документе и логика ломается. Вместо setTimeout() можно просто остановить всплытие события: event.stopPropagation(); Причем в обработчике onDocumentClick setTimeout лишний - его можно удалить. |
еще решение
<body> <style> .float { height: 20px; background: yellow } .size { height:100px } </style> <div class="float"></div> <script> (function () { var element = document.querySelector('.float'); document.onclick = function (e) { var target = e && e.target || e.srcElement; element.classList[target.className == 'float' ? 'add' : 'remove']('size'); return false; } })(); </script> </body> |
Забыл отметить что addEventListener нету в IE8, а classList - нету даже в IE9, и в старых версиях других браузеров. (но для всего этого есть костыли (polyfills))
Poznakomlus, твой вариант на мой взгляд, ибо нерационально - ловить все клики, когда есть возможность ловить не все. |
|
Цитата:
<head> <style> .float { height: 20px; background: yellow } .size { height:100px } </style> </head> <body> <a href="http://mail.ru">Mail.ru</a> <div class="float"></div> <script> (function () { var element = document.querySelector('.float'); document.onclick = function (event) { event = event || window.event; var target = event.target || event.srcElement; element.className = 'float' + (target.className == 'float' ? ' size' : ''); return target.tagName == 'A'; } })(); </script> </body> http://learn.javascript.ru/play/7BWXn Поправил исходя из советов danik.js ниже |
<зануда_mode>
1) Элемент <style> не должен быть внутри <body> (разве что с атрибутом scoped) 2) Твой скрипт отключит переход по ссылкам, так как ты предотвращаешь действие по умолчанию 3) Нет смысла переобъявлять переменную event (она уже объявлена как параметр) </зануда_mode> |
Цитата:
Можешь открыть инспектор и убедиться в этом. Хотя в общем то ничто не мешает поместить его в любое место скриптом в уже сформированном DOM-е. Между прочим, такая запись будет правильной: <style>/* тут стили */</style> <div>тут содержимое body</div> Браузер автоматом сформирует <head> и <body>, причем ошибок парсинга не возникнет, в отличие от твоего варианта. |
Цитата:
|
Цитата:
<head> <style> .float { height: 20px; background: yellow; } .size { height:100px } </style> </head> <body> <a href="http://mail.ru">Mail.ru</a> <div class="float"></div> <script> (function () { var element = document.querySelector('.float'); document.onclick = function (event) { event = event || window.event; var target = event.target || event.srcElement; if (target.tagName == "DIV" && (target.className == 'float' || target.className == 'float size')) { element.className = 'float' + (target.className == 'float' ? ' size' : ''); return false; } if (element.className == 'float size') { element.className = 'float'; } } })(); </script> </body> http://learn.javascript.ru/play/FaPQPb |
$('.float').click(function() { $('.float').toggleClass('size'); }); $(document).click(function(event){ if($(event.target).hasClass('float') return; if(!$(event.target).hasClass('size') && $('.float').hasClass('size')){ $('.float').toggleClass('size'); } }); Вообще пробую так как написал выше. Делаю проверку, если клик на элементе, то возврат. Если клик вне элемента и элемент имеет класс size то тогда убирать класс у него. На одном элементе работает такая схема, а когда элементов несколько то беда... Задача была у меня следующая: есть 4 картинки с описанием каждой, при клике на картинку необходимо увеличивать ее размер и показывать описание, мой способ работает если документ один, когда элементов несколько не хочет, плывет css весь( и вообще похоже это все на говнокод) я слабоват еще) |
Мой вариант, переписанный с использованием jQuery и слегка измененный.
<style> .float{height: 20px;background: yellow;margin-bottom:10px;} .size{height:100px} </style> <div class="float"></div> <div class="float"></div> <div class="float"></div> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> (function(){ var $target = null; var skipClick = false; var onDocumentClick = function() { $target.removeClass('size'); $target = null; return false; }; var onElementClick = function() { if (!skipClick) { setTimeout(function(){ $(document).one('click', onDocumentClick); }); skipClick = true; $target = $(this); $target.addClass('size'); return false; } skipClick = false; }; $('.float').click(onElementClick); })(); </script> |
<!DOCTYPE HTML> <head> <style> .float { height: 80px; background: yellow; width:120px; margin: 5px; float: left; } .size { height:160px } </style> </head> <body> <div class="float"> <div>Test</div> </div> <div class="float"></div> <div class="float"></div> <div class="float"></div> <script> (function () { document.onclick = function (event) { event = event || window.event; var target = event.target || event.srcElement, active = this.querySelector('.size'), elCls; while (target != this) { elCls = target.className; elCls == 'float' && (target.className += ' size') || elCls == 'float size' && (target.className = 'float'); target = target.parentNode; } active && (active.className = 'float'); } }()); </script> </body> http://learn.javascript.ru/play/YGn0Sb:dance: А код то становится все короче |
Derekovich, при клике по элементу чередование открытия закрытия - вне элемента все закрываются
<!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style> .float{height: 20px;background: yellow;margin-bottom:10px;} .size{height:100px} </style> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> </script> </head> <body> <div class="float"></div> <div class="float"></div> <div class="float"></div> <script> $('.float').click(function(event) { event.stopPropagation(); $(this).toggleClass('size'); }); $(document).click(function(){ $('.float').removeClass('size'); }); </script> </body> </html> |
Derekovich,
Вариант клик по другому элементу закрывает предыдущий - всё остальное как выше <!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style> .float{height: 20px;background: yellow;margin-bottom:10px;} .size{height:100px} </style> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> </script> </head> <body> <div class="float"></div> <div class="float"></div> <div class="float"></div> <script> var floats = $('.float'); floats.click(function (event) { event.stopPropagation(); floats.not(this).removeClass('size'); $(this).toggleClass('size'); }); $(document).click(function () { floats.removeClass('size'); });</script> </body> </html> |
Derekovich,
Ещё вариант варианта выше ))) <!DOCTYPE HTML> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style> .float{height: 20px;background: yellow;margin-bottom:10px;} .size{height:100px} </style> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> </script> </head> <body> <div class="float"></div> <div class="float"></div> <div class="float"></div> <script> var floats = $('.float'); $(document).click(function (event) { $('.size').not(event.target).removeClass('size'); $(event.target, floats).toggleClass('size'); }); </script> </body> </html> |
В данном примере меняется только добавление/удаление единственного класса к элементу. А вот например как сделать, если есть 3 элемента с разными классами, и при клике должно также отображаться описание текста к картинке. Привожу пример самого блока:
<div class="section_1"> <div class="size_image"><img src="skin/frontend/default/il/images/img1.png" alt="" /></div> <div class="text_img1"> <p>TEXT only for img1</p> </div> </div> Таких картинок на странице 3 штуки, добавляю только в конце класса порядковый номер другой типа class="section_2", class="text_img2" и т.д. Возможно я неправильно сделал разметку, сейчас получается мне нужно для каждого клика необходимо писать обработчик клика, что не есть хорошо. Заранее благодарен! |
Цитата:
|
А как например тогда определить какое описание текста к картинке выводить?
|
Цитата:
|
<p>TEXT only for img1</p>
Текст находится в блоке у каждого элемента. Понимаю что все это не совсем правильно....но... |
Цитата:
|
Я пишу click() для каждого элемента с указанием его в селекторе, все вышепоказанные примеры в селекторе указывают только один класс. У мня же так не получится, я имею 3 блока, у каждого разный класс, в нем есть картинка и описание, в зависимости от клика я отображаю содержимое и увеличиваю картинку. Если например убрать классы которые заканчиваются на 1,2,3, то как пойму, что именно для этого элемента необходимо вывести именно это описание. Поэтому сделал 3 класса, но приходится тогда делать 3 раза обработчик клика, где в селекторе ставлю каждый класс. Как-то так....
|
Цитата:
|
Часовой пояс GMT +3, время: 10:26. |