Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content Editable: is there a way to override event fired on first selection (click)? #708

Closed
Asimov77 opened this issue Aug 20, 2014 · 6 comments

Comments

@Asimov77
Copy link

Hi, I noticed there is no way to do such thing: it would be nice to define a custom action when clicking the cell to edit (such as select entire text to edit, modify the text before editing - if text displayed in readonly mode was, for example, an abbreviation -, etc.)

I'd expect to find a property similar to editable_editComplete to be able to bind a custom function to the event.

Additionally, I noticed that when I got no value for a given cell (which means that there is no data for that cell, or an empty string), there is no way to fire the event and edit the empty content. In an application I'm coding I have this exact need and I have to show a placeholder text like '[Edit]' in place of an empty string.

In case one or more of these features are already present I apologize and please let me know where and how they can be implemented.

Thanks in advance.

@Mottie
Copy link
Owner

Mottie commented Aug 21, 2014

Hi @Asimov77!

Yes, you are correct, there is not a callback function included when a content editable element is focused. I have no problem in adding this option.

It can also be accomplished by adding some code within tablesorters initialized callback function. I created (this demo) which included a placeholder widget to add the desired placeholder text and other needed methods to accomplish what you are describing:

CSS

.focused {
    /* important flag needed to override theme styling (just for the demo) */
    color: blue !important;
}

Script

$(function () {

    var emptyText = '[Edit]';

    // add defined placeholder text to any empty cells
    $.tablesorter.addWidget({
        id: "placeholder",
        priority: 50,
        format: function (table, c, wo) {
            c.$tbodies.children().children().each(function () {
                var $this = $(this),
                    txt = $.trim( $this.text() );
                if (txt === '') {
                    $this.text(emptyText);
                }
            });
        }
    });

    $('table').tablesorter({
        theme: 'blue',
        textExtraction: function (node) {
            var txt = $.trim($(node).text());
            return txt === emptyText ? '' : txt;
        },
        widgets: ['zebra', 'placeholder', 'editable'],
        widgetOptions: {
            // or "0-2" (v2.14.2); point to the columns to make
            // editable (zero-based index)
            editable_columns: [0, 1, 2],
            // press enter to accept content, or click outside if false
            editable_enterToAccept: true,
            // accepts any changes made to the table cell automatically (v2.17.6)
            editable_autoAccept: true,
            // auto resort after the content has changed.
            editable_autoResort: false,
            // return a valid string: function(text, original){ return text; }
            editable_validate: null,
            // class name of cell that is not editable
            editable_noEdit: 'no-edit',
            // event fired after the table content has been edited
            editable_editComplete: 'editComplete'
        },
        initialized: function (table) {
            $(table).on('focusin focusout', '[contenteditable]', function (e) {
                var t = this,
                    $this = $(this);
                $this.toggleClass('focused', e.type === 'focusin');
                // select all if it is an "empty" cell
                if ($this.text() === emptyText && e.type === 'focusin') {
                    setTimeout(function(){
                        // select all text in contenteditable
                        // see http://stackoverflow.com/a/6150060/145346
                        var range = document.createRange();
                        range.selectNodeContents(t);
                        var sel = window.getSelection();
                        sel.removeAllRanges();
                        sel.addRange(range);
                    }, 100);
                }
            });
        }
    });

});

@Asimov77
Copy link
Author

Hi @Mottie, first of all many thanks for the quick answer and for your time: I think that your work is amazing and it's a pleasure for me to meet you and talk about this.

Yesterday I managed to accomplish the very same behavior of your demo, but in a very less elegant way: I simply bound a custom function to the cell's inner container onmouseup event, that does the exact same job. Of course I will replace my code with the one from your demo asap.

I would expose these features (and a couple more related to them, even if their job would be easily accomplished manually either in callback functions or outside the widget) with some parameters like:

  • editable_onEdit (function to execute when a cell is selected)
  • editable_cssFocused (css class to apply when a cell is selected (focused))
  • editable_emptyText (string to show as empty text)
  • editable_cssEmptyText (css class to apply to empty cells)
  • editable_selectEmptyTextOnClick (bool)
  • editable_selectNonEmptyTextOnClick (bool)

Implementing editable_cssEmptyText probably implies extra code to add to the content changing handlers, that would have to toggle the class depending on whether cell contains empty data or not, so depending on validation and edit operation outcome, too)

Of course I'm just suggesting some (in my mind) useful features that may extend content editable widget in a more complete and flexible way, but I don't presume this to be the better possible choice, and I may be wrong on some assumption: if somehow you'll find these inputs valuable and decide to introduce them on tablesorter future releases, I'll be very pleased to be a little contributor of a little part of your great project :)

Thanks again for your attention, keep up this really nice work and thanks for that, too. :)

@Mottie
Copy link
Owner

Mottie commented Aug 22, 2014

Nice!

Those are some great suggestions! I need to think about how to integrate the textExtraction requirement to make it all work.... I might have to add a new option to the code to make it easier to automatically replace/add placeholder text in empty cells. Or maybe I do need to create a separate widget that works with the editable one, like the "placeholder" example I have above.

I'll work on adding your suggestions once I catch up with all my other stuff ;)

@Mottie
Copy link
Owner

Mottie commented Aug 26, 2014

@Asimov77 Try this demo... the changes are available in the working branch.

I didn't include anything to add a placeholder since I think this might be better accomplished using the combination of the extra textExtraction code with the placeholder widget shared above. The reason I didn't add it is I think a placeholder message should not require the user to delete or remove the text.

It might be better to create a widget to add an element positioned behind the contenteditable element and shown only if the element is empty and not actively being edited.

@Asimov77
Copy link
Author

Really nice solution Mottie, this surely gives more flexibility to content editable widget.
Very pleased that you found my observations helpful, and thanks again for your time and your work.

@Mottie
Copy link
Owner

Mottie commented Sep 16, 2014

This code is now available in v2.17.8

@Mottie Mottie closed this as completed Sep 16, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants