4

I made a page with multiple elements that use the contenteditable property. I added the functionality that when you tab to the next element, the text is auto-selected (using a little plug-in I found on this answer).

But then if you tabbed to an element that was off the screen, the window didn't auto-scroll to show the element (at least in Chrome). So I used the focus event and .animate() to jump to the element.

And now my issue is that I don't want to jump to the element if it is clicked on instead of tabbed to. It gets annoying when the element is already in view, but then jumps to the top of the page when you click on it. Here is a fiddle to look at.

This is the code I'm using:

$.fn.selectText = function(){
    var doc = document;
    var element = this[0];
    if (doc.body.createTextRange) {
        var range = document.body.createTextRange();
        range.moveToElementText(element);
        range.select();
    } else if (window.getSelection) {
        var selection = window.getSelection();        
        var range = document.createRange();
        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);
    }
};

$(document).on('focus', '.content', function(e) {
    var top = $(this).offset().top - 100;
    $(this).selectText();
    $('body').animate({
         scrollTop: top
     }, 25);
    return true;
});

I've tried using stopPropagation() and preventDefault() and changing around the binding order but to no avail. What's the best way to ignore this focus event on click but not on tab? Or is there a way to restore the original auto-scroll functionality?

Community
  • 1
  • 1
musicnothing
  • 3,977
  • 24
  • 43
  • 1
    You may already know this but FWIW, `e.preventDefault();` + `e.stopPropagation();` is the same as `return false`. See [this css-tricks article](http://css-tricks.com/return-false-and-prevent-default/) – cssyphus Jun 17 '13 at 21:35

2 Answers2

3

use jQuery's .stopPropagation() on your click event:

$('.content').click(function(e){
    e.stopPropagation();
});

EDIT: I've updated the jsFiddle using .mouseenter() and .mouseleave() to set an ignore flag.

Yotam Omer
  • 15,310
  • 11
  • 62
  • 65
  • One issue is that these elements will be added dynamically, so if I use `$('.content')` as the selector, the newly added elements won't get the binding. – musicnothing Jun 17 '13 at 21:35
  • Yes.. I've seen that.. have you considered using `.mouseenter()` and `.mouseleave()`? [jsFiddle](http://jsfiddle.net/Jvm3x/) – Yotam Omer Jun 17 '13 at 21:37
  • Excellent. Not the answer I expected but it does exactly what I'm looking for. You ought to edit your answer to include that. – musicnothing Jun 17 '13 at 21:44
1

I can't reproduce the behaviour that it 'jumps' on Firefox, but I can offer you a hint: the focus event is triggered before the click event. You can find this out by adding a console.log('click'); in the click-eventhandler and a console.log('focus'); in the focus event-handler.

But be aware, that not all browser seem to have the same event-order, so on FF it might be focus first, then click, but the IE might behave different for example. More on this here: What is the event precedence in JavaScript?

And here is even more about event order and your possibilities to interact: You can choose to set your event-listener to the bubble-phase or the capturing-phase. More on this here: http://www.quirksmode.org/js/events_order.html#link4

Community
  • 1
  • 1
Zim84
  • 3,404
  • 2
  • 35
  • 40
  • By "jump" I just mean when `.animate()` brings it into view. The event ordering is helpful to know. It appears that in Chrome the focus IS being triggered first, rendering a `return false;` useless. – musicnothing Jun 17 '13 at 21:39