Home > OS >  Why is my .focus() going to the beginning of my `contenteditable` `div`?
Why is my .focus() going to the beginning of my `contenteditable` `div`?

Time:10-31

I am creating a book writing website, mostly in php. I have a jQuery function that when the "New Chapter" button is clicked triggers an AJAX function as well as some other JS/jQuery events. Part of those events is that it should focus() my cursor to the END of the <div> and then focus the cursor to the end of it.

For whatever reason, after it appends the information, it moves my cursor to the beginning of the <div>

HTML

<section>
    <aside>
        <h3>Table of Contents</h3>
        <ul id='toc_base'><?php json_toc($meta); ?></ul>
    </aside>
    <article>
        <div contenteditable='false' id='metadata'>
            <?php
            $bookTitle = htmlspecialchars($bookTitle);
            $author = htmlspecialchars($meta->book->metadata->author);
            $startyear = htmlspecialchars($meta->book->metadata->startyear);
            $isbn = ($meta->book->metadata->isbn != "" && $meta->book->metadata->isbn != null)
                ? htmlspecialchars($meta->book->metadata->isbn)
                : "Not Listed";
            $endyear = ($meta->book->metadata->endyear != "" && $meta->book->metadata->endyear != null)
                ? htmlspecialchars($meta->book->metadata->endyear)
                : "TBD";

            echo "Title: $bookTitle | Written By: $author | ISBN: $isbn<br />Start Year: $startyear | End Year: $endyear";
            ?>
        </div>
        <nav style='grid-column: 1 / span 10'>
            <button style='font-weight:bold' id='bold'>B</button>
            <button style='font-style:italic' id='italic'>I</button>
            <button style='text-decoration:underline' id='underline'>U</button>
            &nbsp;
<!-- BUTTON IS HERE -->
            <button style='font-weight:bold' onclick='addChapter()'>Chapter Title</button>
<!-- BUTTON ENDS HERE -->
            <button class='tooltip'>
                <i ></i>
                <span class='tooltiptext'>Add new character to the panel on the right.</span>
            </button>
            &nbsp;
            <button class='tooltip' onclick='autosave()'>
                <i ></i>
                <span class='tooltiptext'>Be like Jesus - Save!</span>
            </button>
            &nbsp;
            <button class='tooltip'>
                <i ></i>
                <span >Edit metadata such as author information, and ISBN.</span>
            </button>
            <div id='update'>...Saved...</div>
        </nav>
<!-- CONTENT IS HERE -->
        <div contenteditable='true' id='content' type='text' autocomplete='off'></div>
<!-- CONTENT ENDS HERE -->
    </article>
    <aside>
        <h3>Characters</h3>
        <ul id='char_base'><?php json_characters($meta); ?></ul>
    </aside>
</section>

jQuery and JS

function addChapter() {
    var end;
    let chapter = prompt("New Chapter Name?");
    if (chapter != null) {
        $.get("editor.php?newchapter="   chapter, function (data, status) {
            $("#toc_base").html("<li>"   chapter   "</li>");
            $("#content").append("[b]"   chapter   "[/b]\n\n");

            var div = document.getElementById('content');
            div.focus();
        });
    }
}

Errors/Exceptions
There are no errors or exceptions displayed on the page or the console_log.

What I've Done
I did check a number of SO questions and all of them seemed to say to just use focus(), which, I have (in many different ways). I've tried it in a timeout function, which did the exact same thing as above. I did it in jQuery: $("#update").focus(); and there was no difference.

Browser
Chrome Version 107.0.5304.62 (Official Build) (64-bit)

What I'm Hoping to Avoid
I'd like to avoid using textarea if possible. All the extra white-space it has the potential to create when using php is just annoying. I can do it if necessary, but I'd like to stay away from it.

SMALL CHANGE TO WHAT'S HAPPENING
If I were to manually move the cursor to the end after one input of the chapter title, then add a second, it focuses at the beginning of the most recent append.

CodePudding user response:

I've given up on trying to get <div contenteditable='true'> to do what I want. I've changed it to <textarea> - I then updated my jQuery:

function addChapter() {
    let chapter = prompt("New Chapter Name?");
    if (chapter != null) {
        let temp = $("#content").val();
        $("#toc_base").append("<li>"   chapter   "</li>");
        $("#content").val(temp   "[b]"   chapter   "[/b]\r\n\r\n");

        $.get("editor.php?newchapter="   chapter, function (data, status) { });

    }
    $("#content").focus();
}

This does appear to do what I want. I'm not happy that I need to save all the text to a var and then set the val() to the original new.

If anyone has any ways to do this better, or with the <div> that I originally had, please let me know.


I was finally able to figure out how to do this...

HTML/PHP

<div id='content_container_1'>
    <div id='content_container_2'>
        <div contenteditable="true" id='content'><?php echo $book->content->writing; ?></div>
    </div>
</div>

CSS

#content_container_1 {
    height:80vh;
    width: 100%; 
    overflow:auto;
    border: 1px solid black;
    background-color: white;
}

#content_container_2 {
    min-height:100%;
    display:table;
}

#content {
    width:273px;
    font-size: 18px;
    font-weight: normal;
    line-height: 18px;
    outline: none;
    vertical-align: middle;
    display: table-cell;
    position: relative;
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    user-select: text;
    word-wrap: break-word;
    overflow:hidden;
}

JS

$(document).ready(function () {
    $("#content").focus();   /** <---- This part ---->
    setInterval(autosave, 30000); //ignore
    $("#update").removeClass("visible"); //ignore
});
  • Related