Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 10.11.2014, 22:07
Кандидат Javascript-наук
Отправить личное сообщение для vuler Посмотреть профиль Найти все сообщения от vuler
 
Регистрация: 16.02.2012
Сообщений: 109

Вопрос по эвенту во встроенной функции.
Добрый день.
Решил немного упростить код, скрывания объектов, но тут появилась небольшая загвоздка.
Вот код.
$('.js_show_sferi').on('click',sferi_change_visible);

function sferi_change_visible(e){
		sferi_block=$(this).parent().find('.sferi_block_wrap').children();
		sferi_block.stop();
		if (sferi_block.is(':visible'))
			sferi_block.fadeOut(1000);
		else {
			//e.preventDefault();
			sferi_block.fadeIn(1000);
			sferi_block.hide_by_click();
			}
}

jQuery.fn.hide_by_click=function(){
	array_list=$('body').data('hide_by_click_list');
	if (!full_null(array_list)){
		array_list.push($(this));
	}else{
		array_list=[$(this)];
	}
	$('body').data('hide_by_click_list',array_list);
	//setTimeout(function(){
		$('body').on('click',function (event){
			//if (event.isDefaultPrevented()==true) return;
			array_list=$('body').data('hide_by_click_list');
			array_list[0].remove();
			})	
	//},300);
}

Тут для теста.Объект не стирается, а удаляется. Проблема в том, что объект появляется и одновременно удаляется. Т.е.
$('.js_show_sferi').on('click',sferi_change_visibl e) срабатывает и за ним сразу задается обработчик и запускается $('body').on('click',function (event). Т.е. объект появляется и удаляется одновременно.
Нашел 2 варианта решения. -
1) добавить. e.preventDefault(); в основную функцию и event.isDefaultPrevented()во встроеную. Так все работает, но проблема в том, что прописывать e.preventDefault(); приходится прописывать в основной фунции, чего мне бы не хотелось. Нужно чтобы просто в коде можно запускать метод .hide_by_click(); и не заботится больше ни о чем. Встроенная функция jQuery.fn.hide_by_click=function(e) - эвент не обрабатывает, выдает ошибку. Возможно как-нибудь это обойти?
2) Вариант более тупой - через таймаут.
Ответить с цитированием
  #2 (permalink)  
Старый 11.11.2014, 02:12
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,070

vuler,
а макет сделать? и ещё раз попробовать обьяснить попроще что творите и что не получается
Ответить с цитированием
  #3 (permalink)  
Старый 11.11.2014, 13:40
Кандидат Javascript-наук
Отправить личное сообщение для vuler Посмотреть профиль Найти все сообщения от vuler
 
Регистрация: 16.02.2012
Сообщений: 109

Да в принципе подправил код. Кому интересно, можно вместе улучшить код.
К любому элементу на страницы применяем метод .hide_by_click(e); и при клике в любою область отличную от этого элемента - он будет скрываться с экрана(нужно для всплывающих окон и меню). Не нравится мне, что в этот метод нужно передавать обязательно event, во внутрь самой функции поместить не удается.
Вот сам код этой функции:
jQuery.fn.hide_by_click=function(e){
	e.preventDefault();
	array_list=$('body').data('hide_by_click_list');
	if (array_list instanceof Array){
		for (key in array_list){
			if (array_list[key]==$(this)) return;
		}
		array_list.push($(this));
	}else{
		array_list=[$(this)];
	}
	$('body').data('hide_by_click_list',array_list);
	$('body').off('click.hide_by_click');
	$('body').on('click.hide_by_click',function (event){
			if (event.isDefaultPrevented()==true) return;
			array_list=$('body').data('hide_by_click_list');
			for (key in array_list){
				array_list[key].stop();
				if(!$(event.target).closest(array_list[key]).length){
					array_list[key].fadeOut();
					array_list.splice(key,1);}
			}
			if (full_null(array_list))
				$('body').off('click.hide_by_click');
			else
				$('body').data('hide_by_click_list',array_list);
			})	
}

Она запоминает все элементы конторые нужно скрыть в переменной 'hide_by_click_list' у элемента body. При клике на любую область, она перебирает все элементы из этого списка и если клик не был по нему - он удаляется. В конце, если список hide_by_click_list пуст, то обработчик удаляется с body.
Также для точности прменяю следующую функцию.
function full_null(elem){//Проверка на полный ноль. отстутсвие или несуществование.
	if (elem=='undefined' || elem==null || elem==""){
		return true;
	}else return false;
}

Разные браузеры по разному видят переменные, если их нет, кто-то undefined, кто-то null, поэтому приходится применять эту конструкцию. Может есть попроще вариант?
Ответить с цитированием
  #4 (permalink)  
Старый 11.11.2014, 13:58
Профессор
Отправить личное сообщение для tsigel Посмотреть профиль Найти все сообщения от tsigel
 
Регистрация: 12.12.2012
Сообщений: 1,398

function full_null(elem){//Проверка на полный ноль. отстутсвие или несуществование.
	if (elem=='undefined' || elem==null || elem==""){
		return true;
	}else return false;
}

Можно заменить на:

function full_null(elem){
  return !(!!elem);
}
Ответить с цитированием
  #5 (permalink)  
Старый 11.11.2014, 16:09
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,070

jQuery plugin Скрытие по клику вне элемента
vuler,
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
    .orange {
    background: #FFCC00;
  }
  .orange + div{
    display: block;
  }
  span {
     cursor: pointer;
  }

  </style>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script>
     jQuery.fn.hide_by_click = (function() {
         var arrSelector = [];

         $(document).on('click', function(event) {
             $.map(arrSelector, function(el) {
                 if (event.target != el && !$(el).has(event.target).length) $(el).fadeOut()
             })

         });
         return function(add) {
             this.each(function(indx, el) {
                 if (add) arrSelector.push(el);
                 else {
                     var indx = $.inArray(el, arrSelector);
                     if (indx != -1) arrSelector.splice(indx, 1)
                 }
             });
             return this
         }
     }())

     $(function() {

         $(".block_info_main span").hide_by_click(true); //добавить все span для контроля
         $(".orange").hide_by_click(false); // убрать оранжевый из списка слежения
     });
  </script>
</head>

<body>
<div class='block_info_main' id='test'>1111


<div class='first'>
<span class='info orange'>Информация</span>
<div class='main'>
<span class='info_show show '>текст1</span>
</div>
</div>
<div class='first'>
<span class='info'>Информация2</span>
<div class='main'>
<span class='info_show '><b style="color: rgb(51, 51, 255)">текст2</b></span>
</div>
</div>
<div class='first'>
<span class='info'>Информация3</span>
<div class='main'>
<span class='info_show '>текст3</span>
</div>
</div>

</div>


</body>

</html>
Ответить с цитированием
  #6 (permalink)  
Старый 11.11.2014, 16:25
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,070

дубль два добавлено отключение слежения при пустом списке.
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
    .orange {
    background: #FFCC00;
  }
  .orange + div{
    display: block;
  }
  span {
     cursor: pointer;
  }

  </style>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script>
     jQuery.fn.hide_by_click = (function() {
         var arrSelector = [],
         tracking = function(event) {
             $.map(arrSelector, function(el) {
                 if (event.target != el && !$(el).has(event.target).length) $(el).fadeOut()
             })

         }
         return function(add) {
            $(document).off({'click' : tracking });
             this.each(function(indx, el) {
                 if (add) arrSelector.push(el);
                 else {
                     var indx = $.inArray(el, arrSelector);
                     if (indx != -1) arrSelector.splice(indx, 1)
                 }
             });
            arrSelector.length && $(document).on({'click' : tracking });
            return this
         }
     }())

     $(function() {

         $(".block_info_main span").hide_by_click(true); //добавить все span для контроля
         $(".orange").hide_by_click(false); // убрать оранжевый из списка слежения
     });
  </script>
</head>

<body>
<div class='block_info_main' id='test'>1111


<div class='first'>
<span class='info orange'>Информация</span>
<div class='main'>
<span class='info_show show '>текст1</span>
</div>
</div>
<div class='first'>
<span class='info'>Информация2</span>
<div class='main'>
<span class='info_show '><b style="color: rgb(51, 51, 255)">текст2</b></span>
</div>
</div>
<div class='first'>
<span class='info'>Информация3</span>
<div class='main'>
<span class='info_show '>текст3</span>
</div>
</div>

</div>


</body>

</html>
Ответить с цитированием
  #7 (permalink)  
Старый 11.11.2014, 18:26
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,070

дубль 3 добавлена защита от повторного добавления элемента в список слежения
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
    .orange {
    background: #FFCC00;
  }
  .orange + div{
    display: block;
  }
  span {
     cursor: pointer;
  }

  </style>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script>
     jQuery.fn.hide_by_click = (function() {
         var listSelector = $(),
         tracking = function(event) {
             listSelector.each(function(i,el) {
                 if (event.target != el && !$(el).has(event.target).length) $(el).fadeOut()
             })
         }
         return function(add) {
            $(document).off({'click' : tracking });
             this.each(function(indx, el) {
                listSelector = listSelector[add ? 'add' : 'not'](el);
             });
            listSelector.length && $(document).on({'click' : tracking });
            return this
         }
     }())

     $(function() {
         $(".block_info_main span").hide_by_click(true); //добавить все span для контроля
         $(".orange").hide_by_click(false); // убрать оранжевый из списка слежения
     });
  </script>
</head>

<body>
<div class='block_info_main' id='test'>1111


<div class='first'>
<span class='info orange'>Информация</span>
<div class='main'>
<span class='info_show show '>текст1</span>
</div>
</div>
<div class='first'>
<span class='info'>Информация2</span>
<div class='main'>
<span class='info_show '><b style="color: rgb(51, 51, 255)">текст2</b></span>
</div>
</div>
<div class='first'>
<span class='info'>Информация3</span>
<div class='main'>
<span class='info_show '>текст3</span>
</div>
</div>

</div>


</body>

</html>
Ответить с цитированием
  #8 (permalink)  
Старый 11.11.2014, 18:38
Профессор
Отправить личное сообщение для kostyanet Посмотреть профиль Найти все сообщения от kostyanet
 
Регистрация: 23.10.2010
Сообщений: 2,718

Сообщение от vuler
метод .hide_by_click(e); и при клике в любою область отличную от этого элемента
Значит hide_if_unclick()

Чем-то похоже на теорию несуществования. И на практике применяется?
Ответить с цитированием
  #9 (permalink)  
Старый 11.11.2014, 21:08
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,070

Как написать плагин для jquery или закрыть по клику вне элемента
изменён формат опций, добавлена возможность установить свою функцию исчезновения
<!DOCTYPE HTML>
<html>

<head>
    <title>Untitled</title>
    <meta charset="utf-8">
    <style type="text/css">
        .orange {
            background: #FFCC00;
        }
        .orange + div {
            display: block;
        }
        span {
            cursor: pointer;
        }
        .red {
            background: rgb(255, 20, 20);
        }
    </style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <script>
        jQuery.fn.hide_by_click = (function() {
            var defaults = {
                add: true,
                done: function() {
                    $(this).fadeOut()
                }

            }

            var listSelector = $(),
                tracking = function(event) {
                    listSelector.each(function(i, el) {
                        if (event.target != el && !$(el).has(event.target).length) defaults.done.call(el)
                    })
                }
            return function(options) {
                defaults = $.extend({}, defaults, options);
                $(document).off({
                    'click': tracking
                });
                this.each(function(indx, el) {
                    listSelector = listSelector[defaults.add ? 'add' : 'not'](el);
                });
                listSelector.length && $(document).on({
                    'click': tracking
                });
                return this
            }
        }())

        $(function() {
            $(".block_info_main .info").hide_by_click(); //добавить все span.info для контроля
            $(".orange").hide_by_click({
                'add': true,
                'done': function() {
                    $(this).addClass("red").fadeOut(2000)
                }
            }); // добавить оранжевый, изменить функцию исчезновения
        });
    </script>
</head>

<body>
    <div class='block_info_main' id='test'>1111


        <div class='first'>
            <span class='orange'>Информация</span>
            <div class='main'>
                <span class='info_show show '>текст1</span>
            </div>
        </div>
        <div class='first'>
            <span class='info'>Информация2</span>
            <div class='main'>
                <span class='info_show '><b style="color: rgb(51, 51, 255)">текст2</b></span>
            </div>
        </div>
        <div class='first'>
            <span class='info'>Информация3</span>
            <div class='main'>
                <span class='info_show '>текст3</span>
            </div>
        </div>

    </div>


</body>

</html>

Последний раз редактировалось рони, 28.02.2015 в 21:22.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Скобки после имени функции. В чем разница, если они есть и если их нет? jsuse Общие вопросы Javascript 2 19.11.2011 16:11
Установить имя конструктора Андрей Параничев Общие вопросы Javascript 8 17.11.2011 10:09
динамическое содержимое функции alfmaster Общие вопросы Javascript 2 28.05.2011 17:10
Вопрос по функции Flex Общие вопросы Javascript 3 05.12.2008 04:03