Вопрос

Have several hotspots by ID. The ID specific hotspots show an area (#ID-ed textarea) at mouseover and then hide the textareas at mouseout (note the CSS display:hidden was remarkably faster than hide). Have about 50. I have written this out verbosely - aka a function for every one.

Would like to learn a better, wiser, efficient, and shorter way to do this.

    //// POP 1_1
$('#pop_01_01').hover(
    function() {
    $('#text_01_01.textarea').fadeIn('fast');          
    },
    function() {
    $('#text_01_01.textarea').css({'display':'none'});
    }
);
//// POP 02_01
$('#pop_02_01').hover(
    function() {
    $('#text_02_01.textarea').fadeIn('fast');          
    },
    function() {
    $('#text_02_01.textarea').css({'display':'none'});
    }
);
//// POP 02_01
$('#pop_02_02').hover(
    function() {
    $('#text_02_02.textarea').fadeIn('fast');          
    },
    function() {
    $('#text_02_02.textarea').css({'display':'none'});
    }
);
//// POP 02_03
$('#pop_02_03').hover(
    function() {
    $('#text_02_03.textarea').fadeIn('fast');          
    },
    function() {
    $('#text_02_03.textarea').css({'display':'none'});
    }
);
Это было полезно?

Решение

You can do the following:

  1. Combine all the objects that have this behavior into one jQuery selector so they can all run the same code.
  2. Remove the textarea from the selector since the ids are unqiue anyway so it isn't needed and should be faster without it.
  3. Extract the id you want from the object's id that is being hovered and grab the ending characters so you can use it to create the other id you want.
  4. Use .hide() instead of .css({'display':'none'}); as a built-in shortcut.

Resulting Code:

$('#pop_01_01, #pop_02_01, #pop_02_02').hover(
    function() {$('#text_' + this.id.substr(-5)).fadeIn('fast');},
    function() {$('#text_' + this.id.substr(-5)).hide();}
);

Другие советы

use a function like this:

function makehover(myid)
{
  $('#pop'+myid).hover(
      function() {
      $('#text'+myid+'.textarea').fadeIn('fast');          
      },
      function() {
      $('#text'+myid+'.textarea').css({'display':'none'});
      }
  );

then call

 makehover('_01_01');
 makehover('_02_01');
 makehover('_02_02');

or call via jQuery

 $.each(['_01_01','_02_01','_02_02'],function (a,b) { makehover(b); });

or call via (1.6+ javascript )

 ['_01_01','_02_01','_02_02'].map(function (a) { makehover(a); return a; });

etc.

If you want to do it the jquery way, consider that:

$.fn.makeHover = function() {
    this.each(function() {
        var $el = $(this),
            $textarea = $el.find('textarea');

        $el.hover(
            function() {
                $textarea.fadeIn('fast');
            },
            function() {
                $textarea.hide();
            }
        );
    });
};

$('#pop_01_01, #pop_02_01, #pop_02_02, #pop_02_03').makeHover();

By the way, I'm also caching $el and $textarea to avoid going through the DOM all the time (for performance improvement).

The best way to do this is to reference your items by class instead of id, and store the relevant part (01_01, 01_02, etc) in a data-id attribute instead of in the id.

HTML -
<div class="pop" data-id="_01_01"></div>
<div class="pop" data-id="_02_01"></div>
<div class="pop" data-id="_02_02"></div>

<textarea data-id="_01_01"></textarea>
<textarea data-id="_02_01"></textarea>
<textarea data-id="_02_02"></textarea>

//// All pops
$('.pop').hover(
    function(e) {
      var dataid = $(e.target).attr("data-id");
      $('textarea[data-id="'+dataid+'"]').fadeIn('fast');
    },
    function(e) {
      var dataid = $(e.target).attr("data-id");
      $('textarea[data-id="'+dataid+'"]').hide();
    }
);

Something like that should be able to nicely apply to all your elements, doesn't use a bunch of ugly unnecessary ids, and keeps your data clean and separate from your names.

Fiddle here - http://jsfiddle.net/fGLnB/

$('#pop_01_01, #pop_02_01, #pop_02_02').hover(
    function(){
        id = $(this).attr('id');
        $('#text'+id.substring(3,id.length)).fadeIn('fast');          
    },
    function(){
        id = $(this).attr('id');
        $('#text'+id.substring(3,id.length)).css({'display':'none'});
    }
);

I have ommited ".textarea" class, because ID should be unique so there's no reason to use class additionally

You can do something like:

var hotspots = ['01_01','02_01','02_02'];   
hotspots.forEach(function(i) {
    $('#pop_' + i).hover(
        function() {
        $('#text_' + i + '.textarea').fadeIn('fast');          
        },
        function() {
        $('#text_' + i + '.textarea').css({'display':'none'});
        }
    );
});
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top