Search code examples
javascriptjqueryjquery-uilightbox

How to simulate an <a> tag with class and data-type after .on("click".... in jQuery


I'm trying to use the venobox lightbox to allow a user to select a user-generated item on a page and edit its contents. The u-g item has a button made with jQueryUI:

<span class='ui-icon ui-icon-pencil'></span>

I want to click on that and have an edit form appear in a venobox lightbox. Venobox offers an iframe option that should do nicely. To call venobox I need to do something like

<a class='venobox_custom' data-type='iframe' href='http://www.sample.com/editform.html'>open iFrame</a>

so I can't just use "window.location = url" How can I specify the class and data-type with the url?

Without much hope, I tried inserting the full anchor text inside the span, but nothing shows up to click and clicking on the button does not invoke venobox.

I've got the .on("click") logic working, just not calling venobox.

Edited, July 27

I've put the code in cut-down form and runable here: http://www.informationtamers.com/venoboxtest/index.html

I've tried both the iframe and inline options, and this code demonstrates them both, but they won't invoke Venobox. There's a hard link as well that shows Venobox working but not in the way I need to use it.

Here is the code:

<!DOCTYPE html>
<html>
     <head>

        <link type="text/css" rel="stylesheet" href="todo.css"/>
        <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
        <!-- venobox is a jquery lightbox plugin -->
        <link rel="stylesheet" href="venobox/venobox.css" type="text/css" media="screen" />

        <title>UG list</title>

    </head>
    <body>
        <p>I've removed as much of the functionality as I can, like getting users' previously-added content from a JSON file, saving it after changes, sanitizing user content, and so on.</p>
        <p>First, add a line by pressing Add.<br/>
        While experimenting with venobox, I've made that generate two lines:
        The first uses venobox's 'inline' option, the second, its 'iframe' option.</p>

        <div id="inputs" class="textIn">
            <form name="checkListForm" >
                <input type="text" id="textEntry" name="userEntry" style="width: 99%; height:25px"/>
            </form>
        </div>
        <div id="controls" style="width: 100%">
            <div id="buttonItem">Add</div>
        </div>
        <ul class="list">

        </ul>
        <p>Once you've added a line, click the blue pencil button that appears on the right of the first line.  This doesn't appear to invoke venobox, although console.log entries show that it's passing through the on-click code.</p>
        <p>Then click the blue pencil button that appears on the right of the second line. This loads editform.html into the browser window directly instead of showing it in a lightbox.  It appears to be treating it as a normal hyperlink.</p>
        <p>The behavior I'm trying to get can be seen if you click this link (uses the 'inline' option):<br/> 
        <center><a class='venobox_custom' data-type='inline' href='#lightboxform'><b>open inline form in lightbox</b></a></center><br/>


        <div id="lightboxform" style="display:none">
            <div class="textIn">
                <form name="editForm" >
                    <input type="text" id="textEdit" name="userEdit" style="width: 99%; height:25px"/>
                </form>
            </div>
            <div id="controls" style="width: 100%">
                <div id="buttonItem">Save changes</div>
            </div>


        <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
        <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
        <!-- Add venobox (a jquery lightbox plugin) -->
        <script type="text/javascript" src="venobox/venobox.min.js"></script>

        <script>

// ƒ to MOVE new user input to a <li> item
            function sendLineToDOM (lineType) {
                var toAdd = $('input[name=userEntry]').val();
                if (toAdd == null || toAdd == "") {
                    console.log('empty');
                }
                else {
                    // two lines generated here while experimenting with venobox
                    // this uses venobox's 'inline' option
                    $('.list').prepend("<li><span class='" + lineType + "'><span class='handle'><span class='ui-icon ui-icon-arrowthick-2-n-s'></span></span>" + "iframe: " + toAdd + "<span class='edit'><a class='venobox_custom' data-type='iframe' href='editform.html'><span class='ui-icon ui-icon-pencil'></span></a></span><span class='delete'><span class='ui-icon ui-icon-trash'></span></span></span></li>");
                    // this uses venobox's 'iframe' option
                    $('.list').prepend("<li><span class='" + lineType + "'><span class='handle'><span class='ui-icon ui-icon-arrowthick-2-n-s'></span></span>" + "inline: " + toAdd + "<span class='edit'><a class='venobox_custom' data-type='inline' href='#lightboxform'><span class='ui-icon ui-icon-pencil'></span></a></span><span class='delete'><span class='ui-icon ui-icon-trash'></span></span></span></li>");
                    // empty text input field once data consumed
                    $('#textEntry').val("");
                    }
                }

// Substantive START
            $(document).ready(function () {
                $('#textEntry').val("Some text or other here.");

console.log('Initialize lightbox plugin');
/* default settings */
                $('.venobox').venobox(); 

                /* open content with custom settings */
                $('.venobox_custom').venobox({
                    framewidth: '300px',
                    frameheight: '250px',
                    border: '6px',
                    bordercolor: '#ba7c36',
                    numeratio: true,
                    infinigall: true
                });

                /* auto-open #firstlink on page load */
                $("#firstlink").venobox().trigger('click');

                // Enable  DRAG  of list items vertically to re-order them
                $(".list").sortable( {  
                    handle: ".handle"
                });

                // DELETE  a line when its red-button trash symbol is clicked on
                $(document).on("click", ".delete", function () 
                {
                    var whichOne = Math.floor( $("span").index(this) / 7 );
                    $( "ul li" ).eq( whichOne ).remove();
                });

                // EDIT  a line when its blue-button pencil symbol is clicked on
                $(document).on("click", ".edit", function () 
                {
console.log('Click on edit button detected for line #:');
                    var whichOne = Math.floor( $("span").index(this) / 7 );
console.log(whichOne);
                    var input = $( 'input[name=userEntry]' );
                    var extractedText = $( "ul li" ).eq(whichOne).text();
// The following was an initial form for user text editing, but for the planned functionality, I want to show the lightbox instead.
                    $('#textEdit').val( extractedText );
console.log(extractedText);
                });

                /* Add a line with text box contents as ACTION text when Action button pressed*/
                $('#buttonItem').click(function () {
console.log('Add Action text on button press');
                    sendLineToDOM ('item');
                });
            });

        </script>
    </body>
</html>

Solution

  • @Niklas gave me a working answer (and improved my code), but at that stage, I hadn't worked out how I was going to pass the data to be edited to the lightbox form. After much trial and searching, I found that this was either not possible or not not withing my grasp, so I'm revisiting this with an eventual full solution in case anyone else is looking for a way to allow users to edit text they've input previously in a lightbox and save it back to the page. (Note that this doesn't include sanitizing user content which would obviously be necessary.)

    The problem was that clicking on the blue edit button immediately launched the Venobox lightbox - there was no opportunity to load the existing data to the input field. I could find no information in the Venobox documentation about how that might be done. In my project there will be many lines of user-entered data, and each has an associated edit button but once the edit lightbox is triggered, it's too late to get the data.

    The solution was a different lightbox jquery plugin: Colorbox. http://www.jacklmoore.com/colorbox/

    This is well-documented. As well as working with hyperlinks, it has a way of calling Colorbox directly, so that I can trigger editing with 'on click', set up the input form data chosen, and jump into colorbox, and do all the other actions needed.

    The code is below, but again, I've put a runable example on line here: http://www.informationtamers.com/colorboxtest/index.html

    I've removed the venobox online code mentioned in my question.

    <!DOCTYPE html>
    <html>
         <head>
    
            <link type="text/css" rel="stylesheet" href="todo.css"/>
            <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
            <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
            <!-- colorbox is a jquery lightbox plugin -->
            <link rel="stylesheet" href="colorbox/colorbox.css" type="text/css" media="screen" />
    
            <title>UG list</title>
    
        </head>
        <body>
            <p>I've removed much of the functionality, like getting users' previously-added content from a JSON file, saving it after changes, sanitizing user content, and so on.</p>
            <p>First, press Add to generate a line, then key in one or two more lines.</p>
    
            <div id="inputs" class="textIn">
                <form name="checkListForm" >
                    <input type="text" id="textEntry" name="userEntry" style="width: 99%; height:25px"/>
                </form>
            </div>
            <div id="controls" style="width: 100%">
                <div id="buttonItem">Add</div>
            </div>
            <ul class="list">
    
            </ul>
            <p>Next, press one of the blue pencil buttons, change the text presented in the lightbox input form, and press Save changes.</p>
    
    
            <p>&nbsp;</p>
            <div style="display:none">
                <div id="lightboxform">
                    <div class="textIn" >
                        <form name="editForm" >
                            <input type="text" id="textEdit" name="userEdit" style="width: 99%; height:25px"/>
                        </form>
                    </div>
                    <div id="controls" style="width: 100%">
                        <center><div id="buttonSaveChange">Save changes</div></center>
                    </div>
                </div>
            </div>
    
            <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
            <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
            <script type="text/javascript" src="colorbox/jquery.colorbox.js"></script> <!-- colorbox is a jquery lightbox plugin -->
    
    
            <script>
    
    // ƒ to add new user input to a <li> item
                function sendLineToDOM (lineType, lineText) {
                    var toAdd = lineText;
                    if (lineText == null || lineText == "") {
                        console.log('empty');
                    }
                    else {
                        var inlineRow = "<li><span class='" + lineType + "'><span class='handle'><span class='ui-icon ui-icon-arrowthick-2-n-s'></span></span>" + lineText + "<span class='edit'><span class='ui-icon ui-icon-pencil'></span></span><span class='delete'><span class='ui-icon ui-icon-trash'></span></span></span></li>";
                        $('.list').prepend(inlineRow);
                        // empty text input field once data consumed
                        $('#textEntry').val("");
                    }
                }
    
    // ƒ to move edited input to appropriate <li> item
                function returnLineToDOM (lineType, lineText) {
                    if (lineText == null || lineText == "") {
                        console.log('empty');
                    }
                    else {
                        var inlineRow = "<li><span class='" + lineType + "'><span class='handle'><span class='ui-icon ui-icon-arrowthick-2-n-s'></span></span>" + lineText + "<span class='edit'><span class='ui-icon ui-icon-pencil'></span></span><span class='delete'><span class='ui-icon ui-icon-trash'></span></span></span></li>";
                        // replace original line
                        $( "ul li" ).eq( whichOne ).replaceWith( inlineRow );
    
                        // empty text input field once data consumed
    console.log('data consumed, empty text input field');
                        $('#textEdit').val("");
                    }
                }
    
    // Substantive START
                $(document).ready(function () {
                    $('#textEntry').val("Some text or other here.");
    
                    /* Define global variables */
                    window.whichOne = 0; // global variable indicating which line selected for edit
                    window.extractedText = ""; // global variable to hold user text selected for edit
    
                    // Enable  DRAG  of list items vertically to re-order them
                    $(".list").sortable( {  
                        handle: ".handle"
                    });
    
                    // DELETE  a line when its red-button trash symbol is clicked on
                    $(document).on("click", ".delete", function () 
                    {
                        var whichOne = Math.floor( $("span").index(this) / 7 );
                        $( "ul li" ).eq( whichOne ).remove();
                    });
    
                    // EDIT  a line when its blue-button pencil symbol is clicked on
                    $(document).on("click", ".edit", function () 
                    {
    console.log('Click on edit button detected for line #:');
                        var whichOne = Math.floor( $("span").index(this) / 7 );
    console.log(whichOne);
                        var input = $( 'input[name=userEntry]' );
                        var extractedText = $( "ul li" ).eq(whichOne).text();
                        $('#textEdit').val( extractedText );
    console.log(extractedText);
                    });
    
                    // Add line w.text box contents as action text when Action button pressed
                    $('#buttonItem').click(function () {
    console.log('Add Action text on button press');
                        sendLineToDOM ('item', $('input[name=userEntry]').val());
                    });
    
                    // EDIT  a line when its blue-button pencil symbol is clicked on
                    $(document).on("click", ".edit", function () {
    console.log('Edit a line');
                        // The divisor in the next expression is the number of <span>s before the 
                        // clicked one in the <li> lines constructed in sendLineToDOM(). This 
                        // works out which blue button has been pressed, and therefore which 
                        // <li> item to edit.
                        whichOne = Math.floor( $("span").index(this) / 7 );
    console.log(whichOne);
                        var input = $( 'input[name=userEntry]' );
                        extractedText = $( "ul li" ).eq(whichOne).text();
    console.log('extracted:' + extractedText );
                        $('#textEdit').val( extractedText );
                        $.colorbox({inline:true, href:"#lightboxform", width:"80%", height:"25%"});
                    });
    
    /* RELOAD edited line on click */
                    // Get the edited user input and replace the old entry with it.
                    $('#buttonSaveChange').click(function () {
    console.log('Replace old entry on button press');
    //                  Save edited text!!!!
                        returnLineToDOM ('item', $('input[name=userEdit]').val());
                        $.colorbox.close()
                    }); 
    
                });
    
            </script>
        </body>
    </html>