ducksboard / gridster.js

gridster.js is a jQuery plugin that makes building intuitive draggable layouts from elements spanning multiple columns
http://gridster.net/
MIT License
6.03k stars 1.2k forks source link

Bug: Widget content cannot be highlighted or properly interacted with when resize enabled. #360

Open dustinbolton opened 10 years ago

dustinbolton commented 10 years ago

When resize is enabled, you cannot highlight text or other data within the widget area. For instance highlighting text to copy or interacting with a WYSIWYG such as Redactor or ckeditor as this related bug report indicates: https://github.com/ducksboard/gridster.js/issues/290

Turning resize off works around the issue but at the cost of this very powerful (and critical for my uses) feature. It seems like clicks are being captured and prevented from functioning whenever resize is enable for some reason.

Is there a workaround for this?

hrosenbauer commented 10 years ago

You should use a certain element of your widget for dragging and set gridster up with http://gridster.net/#widget_selector_opt. Doing so, you have a certain drag-handle but you can still select text in the rest of the widget.

dustinbolton commented 10 years ago

I'm using draggable->handle to set which part lets you pick it up and drag it around. My widget_selector option is the li as that contains all the widget HTML. This works for the widget-title class being draggable and when resize is disabled works 100% as expected. It's tied to whether or not resize is enabled. Here's my code that does not work as expected:

<script>
    $(function(){
        gridster = $(".gridster ul").gridster({
            widget_selector: '.gs-w',
            widget_margins: [10, 10],
            widget_base_dimensions: [140, 140],
            resize: {
                enabled: true
            },
            draggable: {
                handle: '.widget-title'
            }
        }).data('gridster');
    });
</script>

<div class="gridster">
    <ul>
        <li class="gs-w" data-id="1" data-row="1" data-col="2" data-sizex="2" data-sizey="2">
            <div class="widget-title">My widget title</div>
            <div>Cannot hightlight this if resize enabled.</div>
        </li>
    </ul>
</div>
dustinbolton commented 10 years ago

Anyone have any ideas on how to fix this bug? It's critical for my needs and I'm still trying to find a solution to fixing it.

hrosenbauer commented 10 years ago

I copied your code into jsfiddle: http://jsfiddle.net/2s7HY/ I can select the content of the widget using Firefox and Chrome, so your problem might be somewhere else.

dustinbolton commented 10 years ago

I can select the text in that jsfiddle with Firefox but NOT with Chrome. I'm Chrome Version 34.0.1847.137 on OS X 10.9.2. I tested with all Chrome browser plugins disabled as well with the same problem.

hrosenbauer commented 10 years ago

I stand corrected: you are right. This is a bug.

dustinbolton commented 10 years ago

Success! I've been successful in patching this issue. I only had to add a single if-block.

I believe this solves the problem without impacting any other functionality. Around line 787 in fn.ignore_drag I have added a single if-block checking if the current draggable we are dealing with is the resizer (by checking this.options.resize on it). If it is, then we only need to check if it's the handle being dragged. Any other dragging (on the widget, a specific widget dragging handle, etc) will be on another draggable that does not have this.options.resize === true so this will not impact those.

I have tested this with resizing both on and off and all dragging and resizing actions with success.

New function:

    fn.ignore_drag = function(event) {
        if (this.options.handle) { // Widget drag handle.
            return !$(event.target).is(this.options.handle);
        }

        if ($.isFunction(this.options.ignore_dragging)) {
            return this.options.ignore_dragging(event);
        }

        // NEW IF-BLOCK TO FIX DRAGGING WHEN RESIZE ENABLED:
        if (this.options.resize) {
            return ! $(event.target).is(this.options.items);  // Current draggable is the resizer so only need to ignore the resize handle.
        }

        return $(event.target).is(this.options.ignore_dragging.join(', '));
    };
zeroth commented 10 years ago

I got the same problem and you if-block seems to fix the issue thanks a ton, saved lots of time.

josephndenton commented 9 years ago

This also solved the issue for me.

dustinbolton commented 9 years ago

Can this be merged into the official?

rlisowski commented 9 years ago

+1