Back

Custom Field: Linking to different Content

Description

This custom code was contributed by our dotCMS friend at the Dept Agency, Daniel Patterson.  It shows how you can create a field in dotCMS that can link to other content objects and then store that relation as a reusable json object for consumption by your implementation.

To use - create a custom field called link and then add this code in the custom field code screen.  It gives you the ability to browse for content to link to, add styling to it and then save all the properties to the content store.

Code

## first we get the content (we have access to all our
## velocity tools, including any custom ones that have been written

#set($content = $dotcontent.find($request.getParameter("inode")))

## then we write some ugly js to get and set the values on the edit content form -
## the dom.id of the hidden field that stores the value is just the velocity variable name
## so watch out for js variable scope issues
##<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<script src="https://kit.fontawesome.com/e3a489020b.js" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>

<script>
    var cstLinkObject = {
        url: "",
        external: false,
        icon: "",
        iconAlign: "left",
        linkStyles: "",
        target: "",
        linkText: ""
    };

    dojo.require('dotcms.dijit.FileBrowserDialog');
    jQuery.noConflict();
    function browseItems() {
        fileSelector.show();
    }

    function addItemLink(item) {
        if(item.type == "file_asset"){
            cstLinkObject.url = item.path + item.fileName;
        }else if(item.type == "htmlpage"){
            cstLinkObject.url = item.pageURI;
        }
        document.getElementById("link").value = JSON.stringify(cstLinkObject);
        dijit.byId("customValue").textbox.value = cstLinkObject.url;
    }

    function internalClicked(x){
        document.getElementById("externalInfo").style.visibility = "hidden";
        dijit.byId("btnBrowsePages").domNode.style.visibility = "";
        dijit.byId("customValue").textbox.readOnly = true;
        cstLinkObject.external = false;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }
        dijit.byId("radioExt").set("checked", "");
    }

    function externalClicked(x){
        document.getElementById("externalInfo").style.visibility = "";
        dijit.byId("btnBrowsePages").domNode.style.visibility = "hidden";
        dijit.byId("customValue").textbox.readOnly = false;
        cstLinkObject.external = true;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }
        dijit.byId("radioInt").set("checked", "");
    }

    function urlEntered(x){
        cstLinkObject.url = x.target.value;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }else{
            document.getElementById("link").value = "";
        }
    }

    function iconSelected(x){
        cstLinkObject.icon = x.target.value;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }
    }

    function alignSelected(x){
        cstLinkObject.iconAlign = x.target.value;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }
    }

    function stylesEntered(x){
        cstLinkObject.linkStyles = x.target.value;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }
    }

    function targetSelected(x){
        cstLinkObject.target = x.target.value;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }
    }

    function textEntered(x){
        cstLinkObject.linkText = x.target.value;
        if (cstLinkObject.url){
            document.getElementById("link").value = JSON.stringify(cstLinkObject);
        }
    }

    jQuery(document).ready(function() {
        let json = jQuery.getJSON("https://affectionate-goldberg-c98fd0.netlify.com/fontawesome.json", function (data) {
            var ics = document.getElementById("linkIcon");
            for (var i = 0; i < data.length; i++) {
                var faObj = data[i];
                var opt = new Option(faObj.iconUnicode + " " + faObj.iconName, faObj.iconName);
                opt.classList.add("iconSelectOption");
                ics.options[ics.options.length] = opt;
            }

            for (var i = 0; i < ics.length; i++) {
                var o = ics[i];
                o.innerHTML = o.innerHTML.replace(/\&amp;/gi, "&");
            }

            if(document.getElementById("link").value){
                cstLinkObject = JSON.parse(document.getElementById("link").value);
                dijit.byId("customValue").textbox.value = cstLinkObject.url;

                if (cstLinkObject.external == true){
                    dijit.byId("radioInt").set("checked", "");
                    dijit.byId("radioExt").set("checked", "checked");
                }else{
                    dijit.byId("radioExt").set("checked", "");
                    dijit.byId("radioInt").set("checked", "checked");
                }

                document.getElementById("linkStyles").value = cstLinkObject.linkStyles;
                document.getElementById("linkIcon").value = cstLinkObject.icon;
                document.getElementById("linkIconAlign").value = cstLinkObject.iconAlign;
                document.getElementById("linkTarget").value = cstLinkObject.target;
                document.getElementById("linkText").value = cstLinkObject.linkText;

            }

            if(dijit.byId("radioInt").checked == false && dijit.byId("radioExt").checked == false){
                dijit.byId("radioExt").checked = true
            }

            if(dijit.byId("radioInt").checked)
            {
                document.getElementById("externalInfo").style.visibility = "hidden";
                dijit.byId("btnBrowsePages").domNode.style.visibility = "";
                dijit.byId("customValue").textbox.readOnly = true;
            }
            else{
                document.getElementById("externalInfo").style.visibility = "";
                dijit.byId("btnBrowsePages").domNode.style.visibility = "hidden";
                dijit.byId("customValue").textbox.readOnly = false;
            }

            document.getElementById("customValue").addEventListener("input", urlEntered);
            document.getElementById("linkIcon").addEventListener("change", iconSelected);
            document.getElementById("linkIconAlign").addEventListener("change", alignSelected);
            document.getElementById("linkStyles").addEventListener("input", stylesEntered);
            document.getElementById("linkTarget").addEventListener("change", targetSelected);
            document.getElementById("linkText").addEventListener("input", textEntered);
        });
    });


</script>
<style>
    .cf-top-gutter{
        margin-top: 10px;
    }
    .stdSelect{
        height: 35px;
        font-size: 14px;
        width: 200px;
    }

    .iconSelect{
        font-family: FontAwesome;
        height: 35px;
        font-size: 17px;
        width: 200px;
    }

    .iconSelectOption{
        font-family: FontAwesome;
    }

    .divTable{
        display: table;
        width: 100%;
    }
    .divTableRow {
        display: table-row;
    }
    .divTableHeading {
        background-color: #EEE;
        display: table-header-group;
    }
    .divTableCell, .divTableHead {
        border: 1px solid #E6E5E5;
        display: table-cell;
        padding: 3px 10px;
    }

    .divTableCellNoBorder, .divTableHeadNoBorder {
        border: none;
        display: table-cell;
        padding: 3px 10px;
    }

    .divTableHeading {
        background-color: #EEE;
        display: table-header-group;
        font-weight: bold;
    }
    .divTableFoot {
        background-color: #EEE;
        display: table-footer-group;
        font-weight: bold;
    }
    .divTableBody {
        display: table-row-group;
    }

    .label-span{
        display: inline-block;
        width: 100px;
        text-align: right;
        padding-right: 7px;
    }

    .label-span-md{
        display: inline-block;
        width: 180px;
        padding-right: 7px;
    }

</style>

<div>
    <div>
        <input id="customValue" name="customValue" data-dojo-type="dijit/form/TextBox" data-dojo-props="placeHolder: 'Enter URL here...'">
    </div>
    <div class="cf-top-gutter">
        <div class="divTable">
            <div class="divTableBody">
                <div class="divTableRow" style="height: 150px; background: #f1f1f1;">
                    <div class="divTableCellNoBorder">
                        <input type="radio" data-dojo-type="dijit/form/RadioButton" name="radioInt" id="radioInt" onClick="internalClicked();" value="internal"/><label for="radioInt">&nbsp; Internal</label> &nbsp;&nbsp;&nbsp;
                        <input type="radio" data-dojo-type="dijit/form/RadioButton" name="radioExt" id="radioExt" onClick="externalClicked();" value="external"/><label for="radioExt">&nbsp; External</label>
                        <div class="cf-top-gutter">
                            <button dojoType="dijit.form.Button" id="btnBrowsePages" onClick="browseItems();return false;" type="button"><i class="fa fa-search"></i> Select Item</button>
                        </div>
                        <div>
                            <span id="externalInfo" class="label-span-md">Please enter a URL above e.g. 'http://www.google.com'/span>
                        </div>
                    </div>
                    <div class="divTableCellNoBorder">
                        <div class="cf-top-gutter">
                            <span class="label-span">Icon Settings: &nbsp;</span>
                            <select class="iconSelect" id="linkIcon" name="linkIcon" >
                                <option value="" style="color:#969595">&#xf067 Add Icon to Link</option>
                            </select>
                            <select id="linkIconAlign" name="linkIcon" class="stdSelect">
                                <option value="left">Left Align</option>
                                <option value="right">Right Align</option>
                            </select>
                        </div>
                        <div class="cf-top-gutter">
                            <span class="label-span">Link Styles: &nbsp;</span>
                            <input id="linkStyles" name="linkStyles" style="width: 404px;" data-dojo-type="dijit/form/TextBox" data-dojo-props="placeHolder: 'Add custom styles classes here...'">
                        </div>
                        <div class="cf-top-gutter">
                            <span class="label-span">Link Text: &nbsp;</span>
                            <input id="linkText" name="linkText" style="width: 404px;" data-dojo-type="dijit/form/TextBox" data-dojo-props="placeHolder: 'Add link text here...'">
                        </div>
                        <div class="cf-top-gutter">
                            <span class="label-span">Link Target: &nbsp;</span>
                            <select class="stdSelect" id="linkTarget" name="linkTarget" style="width: 404px;">
                                <option value="_blank">Display in a new window or tab</option>
                                <option value="_self" selected>Display in the same window</option>
                                <option value="_parent">Display in the parent frame</option>
                                <option value="_top">Display in the full body of the window</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div dojoAttachPoint="fileBrowser" jsId="fileSelector" onFileSelected="addItemLink" dojoType="dotcms.dijit.FileBrowserDialog"></div>
</div>