Replace portions of URLs from variables and display them as plain text?

Twine Version: version 2.3.16
Story Format: SugarCube 2.36.1

Hello, everyone. I have some variables that take URL addresses. I would like to replace part of the URL and show them as plain text in a passage. I tried changing the format style and disabled it using this in the stylesheet:

a.disabled {
  pointer-events: none;
  cursor: default;
  text-decoration: none;
  color: #FFF
}

And something like this in the passage to replace parts of the URL:

<a href="link.html" class="disabled" >$link</a>
<p id="demo"><<print $link>></p>

<script>
let text = document.getElementById("demo").innerHTML; 
document.getElementById("demo")= text.replace("/option1/", "/option2/");
</script>

You can see that $link is printed twice. The first one comes as plain text, but nothing has been replaced. The second link, which is actually addressed in the script, comes as an active hyperlink, but same URL, although different destination. Or, in other words, the target has been successfully replaced, it’s just that the output is still the original URL, and it is still clickable. Are there any suggestions you recommend?

Thank you.

1 Like

note: You haven’t include an example of the value being stored within the $link Story Variable, which may be helpful. I will assume it’s something like the following based on the contents of your example.

<<set $link to "./option1/link.html">>

I must admit I don’t fully understand your question, but I can comment on the JavaScript you’re using and how you are calling it.

While the contents of a Passage is being processed any HTML elements that are generated are attached to a HTML Node based “buffer” until the entirety of the content has being processed, after which the “buffer” is attached to the Document Object Model of the current web-page.

Because of this “buffering” behaviour DOM functions like getElementById() wont find the element they are searching for because by default they are executed before that element has been added to the DOM. This means you need to use some method to delay that execution, one such being the [<<done>>](http://www.motoslave.net/sugarcube/2/docs/#macros-macro-done) macro.

You are also executing the same document.getElementById("demo") search twice, which is both unnecessary as the same element is returned each time, and inefficient as DOM searching is not a cheap action.

The following example may achieve the outcome you wanted…

<a href="link.html" class="disabled" >$link</a>
<p id="demo"><<print $link>></p>

<<done>>
	<<script>>
		let el = document.getElementById("demo");
		el.innerHTML = el.innerHTML.replace("/option1/", "/option2/");
	<</script>>
<</done>>

note: You will notice I replaced your usage of a <script> HTML element to execute the JavaScript, with a <<script>> macro call.

2 Likes

Hi, Greyelf,

Thank you for your help. Here’s what I want to achieve:

  1. Passage 1 has a textbox.
  2. A user enters a URL address. Let’s say https://www.example.com/option1/example
  3. The user clicks next to go to passage 2.
  4. Passage 2 shows the URL changed to https://www.example.com/option2/example in plain and non-clickable text.

I tried the script you provided, but the outcome is still the same I had before:

Passage 2 keeps showing https://www.example.com/option1/example as a formatted and clickable URL and only its destination changes to https://www.example.com/option2/example.

The destination is not seen on the passage, but by clicking or hovering on the URL, one can see that /option1/ has been replaced by /option2/

Note: I put my links as a preformatted text because, as a new member, Infiction doesn’t let me add more than two links per post.

1 Like

The replace function used with a string will only replace the first occurrence which is why the destination of the link changes but not the text. See String.prototype.replace() - JavaScript | MDN
You probably want to use a regex with the g parameter. Try something like:

el.innerHTML = el.innerHTML.replace(/\/option1\//g, "/option2/");
2 Likes

Thank you, Nils Fagerburg. The line you sent has successfully replaced one of the instances for $link. Now I can see the changes. The other instances remain the same, that’s fine, as long as I can have at least one that shows these changes. However, I still cannot disable the link and turn it into plain text. Do you have any suggestions for that?

1 Like

I’m now using a temporary workaround for the remaining issue regarding the plain text. I created a class in the stylesheet to look like plain text. I called my class “white” and, using Grayelf’s script and Nils Fagerburg’s edit, I merged the first two lines in my original script. The output looks like plain text. However, it is not really plain text because if you hover on the printed output, the pointer keeps its appearance of an arrow instead of a text pointer, but I can live with that. Also, the variable $link won’t be affected by the replaced function in all other instances you use it (as already explained by Nils Fagerburg). Here are the modifications. If anyone can produce plain text out of this, has another way to replace variables in all occurrences, or have other ideas, I would appreciate it. Thank you.

<a href="link.html" id="demo" class="disabled white" >$link</a>

<<done>>
	<<script>>
		let el = document.getElementById("demo");
		el.innerHTML = el.innerHTML.replace(/\/option1\//g, "/option2/");
	<</script>>
<</done>>```