Newbie needs help inserting html into a js string

Hi all,

I’m not a js person so I think this is an easy question. I have this string in a .js file:

html += `
                <li><span draggable="true"><a class="drag">[${v.name}]</a>&nbsp;=&nbsp;${v.value?v.value:v.desc}</span></li>			
			`

After the ?, for that last “v.desc” I need to add this span around that:

<span class="onscreenTips>x</span>

The “x” is where v.desc would be.

Would appreciate some guidance.

Thanks,

You can drop an anonymous function in there to return the appropriate HTML:

html += `
  <li>
    <span draggable="true">
      <a class="drag">[${v.name}]</a>
      &nbsp;=&nbsp;${v.value ? v.value : () => `<span class="onscreenTips>${v.desc}</span>`}
    </span>
</li>`;

Thanks but that’s not giving me what I want. I think I just need to know how to concatenate the existing code. Really, really basic. :slight_smile:

Let me show you more of the code - this is actually within a function:

_getHtmlForPanel: function() {
		let html = `<ul id="${customFormVariables.constants.PANEL_UL_LIST_ID}"><h4>Provider Variables</h4>`;
		customFormVariables.allVariables.forEach(function(v) {
			html += `
                <li><span draggable="true"><a class="drag">[${v.name}]</a>&nbsp;=&nbsp;${v.value?v.value:v.desc}</span></li>				
		});
		html += '</ul>';
		return html;
	},

The variable list it’s reading from is like this:

class VariablesDefinitionRecipient {
	const VARIABLES = [
		[
			'name' => 'recipientFirstName',
			'desc' => '(Recipient\'s first name, e.g., John)'
		],
		[
			'name' => 'recipientFullName',
			'desc' => '(Recipient\'s full name, e.g., John A. Smith)'
		],
		[
			'name' => 'recipientEmail',
			'desc' => '(Email 1)'
		],
			

When we have that variable in our database, the code displays the ‘name’ value. If not, it displays the ‘desc’ value. I’m trying to style the ‘desc’ value with the “onscreenTips” class.

Here’s a graphic of the desired outcome (i.e., this individual has a value for [providerPhone1] in their DB but not for [providerPhone2]. [providerPhone2] has had the onscreenTips class applied to it’s value.

sitepointjs

Sorry, you lost me.

I’m not sure if this is part of the problem, but the code you posted is not valid JavaScript:

class VariablesDefinitionRecipient {
  const VARIABLES = [
    [
      'name' => 'recipientFirstName',
      'desc' => '(Recipient\'s first name, e.g., John)'
    ],
    ...
]

Is this meant to be JavaScript? If so, you should likely use object notation.

Also, probably a typo, but the _getHtmlForPanel function is missing a backtick.

customFormVariables.allVariables.forEach(function(v) {
  html += `
    <li>
      <span draggable="true">
        <a class="drag">[${v.name}]</a>
        &nbsp;=&nbsp;${v.value?v.value:v.desc}
      </span>
    </li>
  `;  // This is missing in your code
});

Other than that, can you please post enough code that I can recreate your problem on my PC. You can hardcode anything coming from the database.

The VariablesDefinitionRecipient snippet is from a php file - not javascript. I just put it in to help explain how this works. And yes - the backtick is there in the code - me not posting it was just a typo.

I probably don’t understand enough of this to be sure I’m posting all you need. I’m mostly the HTML/CSS person but occasionally, when I need to add some HTML or CSS to something that’s in the js, I try to see if I can figure it out. This one stumped me so mostly, I’m just trying to learn. If it helps, here’s the whole js file:


let customFormVariables = {
	constants: {
        AJAX_TARGET_URL: AJAX_PATH + 'variables/variables.php',
		
		PANEL_DIV_SELECTOR: '#customFormVariablesPanel',
		PANEL_UL_LIST_ID: 'customFormVariables'
	},

	allVariables: [],

	init: function() {
		customFormVariables._getAllVariables();
	},

	_getAllVariables: function(successFunc) {
        $.ajax({
            type: 'POST',
            url: customFormVariables.constants.AJAX_TARGET_URL,
            data: { action: 'get_custom_form_variables' },
            dataType: 'json',
            success:function(res) {
            	customFormVariables.allVariables = res.variables;
            }
        });
	},

	initPanel: function() {
		customFormVariables._createPanel();
		customFormVariables._initDraggableOnPanel();
	},

	_createPanel: function() {
		let panelHtml = customFormVariables._getHtmlForPanel();
		let visibleFormPopup = $(elementGenerator.WINDOW_WRAPPER_DIV_SELECTOR+':visible');
		let panelDiv = visibleFormPopup.find(customFormVariables.constants.PANEL_DIV_SELECTOR);

		panelDiv.html(panelHtml);
	},

	_getHtmlForPanel: function() {
		let html = `<ul id="${customFormVariables.constants.PANEL_UL_LIST_ID}"><h4>Provider Variables</h4>`;

		customFormVariables.allVariables.forEach(function(v) {
			html += `
                <li><span draggable="true"><a class="drag">[${v.name}]</a>&nbsp;=&nbsp;${v.value?v.value:v.desc}</span></li>			
			`
			
			
		});

		html += '</ul>';

		return html;
	},

	_initDraggableOnPanel: function() {
		let varBlocks = $('#'+customFormVariables.constants.PANEL_UL_LIST_ID+' li span[draggable="true"]');

        varBlocks.draggable({
            helper: 'clone',
            cursorAt: { left: 0, top:0 },
            zIndex: 2710,

            stop: function() {
            	let varName = $(this).find('a').text();
            	let dropElement = customFormVariables._getDropElement();
            	if (dropElement)
            		dropElement.val(dropElement.val() + varName);
            }
        });
	},

	_getDropElement: function() {
		let allElementsAtXY = document.elementsFromPoint(event.clientX, event.clientY);

	    for (let i = 0; i < allElementsAtXY.length; i++) {
	        let elObj = $(allElementsAtXY[i]);

	        if (elObj.is('textarea'))
	        	return elObj;

	        if (elObj.is('input[type=text]'))
	        	return elObj;
	    }

	    return undefined;
	}
}

Oops, actually, scratch that. That won’t work. Don’t know what I was thinking there. Sorry…

This is a better solution:

const v = { name: 'foo', desc: 'bar' }
const html = `
  <li>
    <span draggable="true">
      <a class="drag">[${v.name}]</a>
      &nbsp;=&nbsp;${v.value ? v.value : `<span>${v.desc}</span>`}
    </span>
</li>`;

console.log(html);

Produces:

<li>
  <span draggable="true">
    <a class="drag">[foo]</a>
    &nbsp;=&nbsp;<span>bar</span>
  </span>
</li>

Essentially, if I’m understanding this correctly, what I’m trying to do boils down to this snippet:

${v.value?v.value:v.desc}

I THINK what that means is that the variable displays the value (v.value) if it’s there, or if not, then it displays the value and it’s description (v.value:v.desc). What I’m trying to do is add a class of onscreenTips to the v.desc. Or maybe the onscreenTips needs to cover that whole thing (v.value:v.desc). I think if I could just figure out how to concatenate some HTML into there, I’d be OK. But maybe not. Maybe it’s more complex than that.

The code I posted above does that (lol, for real this time).

${v.value ? v.value : `<span class="onscreenTips">${v.desc}</span>`}

And your understanding is correct.

You have a template string: denoted by two backticks:

const html = ``;

Inside the template string, interpolation is done using the ${} syntax.

const name = 'Jim';
const html = `<p>${name}</p>`;
// <p>Jim</p>

Inside the ${}, you then have a ternary conditional: condition ? true branch : false branch.

The condition is evaluated. If it evaluates to true, the code in the true branch is executed, otherwise the code in the false branch. This is a way of adding some logic to string interpolation.

So essentially, if v.value evaluates to true, return v.value. Otherwise return a template string containing v.desc wrapped in a span element.

2 Likes

YES!!! That worked! Thanks so much for taking the time to explain it! I really appreciate your help. :slight_smile:

No worries. And sorry about the initial wrong answer.

No problem! I probably didn’t give you enough info. I’m just happy to know how to do it!

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.