Replace "strings" with HTML code in contentEditable div - javascript

Idea
I'm making a configuration editor for a game, and I want to replace some of the strings with HTML code tooltips that would summarize what the command does, such as gravity or ammo.
I've tried data.replace(replacet, replacew), both (replace this) and (replace with) being array of strings and no, its not working.
JavaScript
function updateStrings() {
var replacet = "sv_cheats ";
var replacew = " <mark>sv_cheats</mark> ";
var data = document.getElementById('data').innerHTML;
document.getElementById('data').innerHTML = data.replace(replacet, replacew);
}
document.addEventListener('onkeydown', document.getElementById('data'), updateStrings());
Point
This code I'd say roughly works, but the caret position is set to 0 (beginning) on every key press as the JavaScript tries to append every character given at the first position which clearly is not supposed to be happening.
Question is are there any frameworks that do this automatically? I'd want something like in VS Code when if you hover over a function it tells you the parameters and such, something like that would be awesome to have!
Thanks!

Related

Chrome Address Bar Javascript produces different effect than Console

Trying something new, I was attempting to highlight text on this wikia page using javascript within the address bar (i.e. using "javascript:[code]").
When running the following code sample through Chrome's console, it produces the desired effect. When running it from the address bar, it results in only the affected text -- the rest of the page body is removed.
javascript:txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;index = txt.innerHTML.indexOf(", but")+2;txt.innerHTML = txt.innerHTML.substring(0,index)+"<span style='background-color:yellow;'>"+txt.innerHTML.substring(index,index+40)+"</span>"+txt.innerHTML.substring(index+40);
Note: if you want to try this you will have to manually type javascript: into the address bar before pasting the code, as Chrome automatically removes it.
I'm curious as to why this would be, and also if there is a way to stop the address bar from removing the rest of the page body. Can anyone offer insight?
Thanks.
The quick solution to the problem you're experiencing is to add false; to the end of your query. This will prevent Chrome from removing the text from your page and should give you the result you expect.
Here's the fixed code:
javascript:txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;index = txt.innerHTML.indexOf(", but")+2;txt.innerHTML = txt.innerHTML.substring(0,index)+"<span style='background-color:yellow;'>"+txt.innerHTML.substring(index,index+40)+"</span>"+txt.innerHTML.substring(index+40);false;
To fully answer the question, let me quickly explain what is happening. I'll start by splitting up your JS a bit to make it easier to read.
txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;
index = txt.innerHTML.indexOf(", but")+2;
txt.innerHTML = txt.innerHTML.substring(0,index) +
"<span style='background-color:yellow;'>" +
txt.innerHTML.substring(index,index+40) +
"</span>"+txt.innerHTML.substring(index+40);
What you'll note is that the final statement is an assignment operation. In JavaScript the result of an assignment operation is the value of the assignment. In other words, if we say return x = 1 we will both set the value of x to 1 and return the value 1.
This brings us to the reason why Chrome is replacing your page content. The JavaScript you're providing is returning the content of the txt element (the paragraph you're deciding to highlight) and this is then being treated as the content of your new page, the same way that visiting data:text/plain,hello world or javascript:"hello world" in your browser will show the text "hello world"even though you haven't explicitly visited a website.
To fix this, you can return a falsey value in JavaScript - this means any one of the following:
0
false
[]
null
undefined
Hence, adding false; at the end of your JavaScript will have Chrome run the code but not show the resulting text and will prevent it from changing the page content on you unexpectedly.

How do I pull contents from a .txt file and display a random line of it in HTML?

Being a noob at HTML, I only know a solution to this in C#. I'm just trying to separate each line of the .txt so I can randomly pull lines from it and display them when a button is pressed. In addition, rather than using a submit button, I wanted to create a div of my own styled button for the user to press. (Which I know how to do) and use a jQuery 'on click'.
I'm a little unsure how to describe exactly what I'm trying to do, but I hope I did it well enough.
Thank you guys in advance.
Note This is the C# I used to create a relatively simple Trivia game. In a separate Trivia.cs I had split the question and answers from each other (In the .txt they were separated by an *)
I'm not sure if this will help guide anyone, however.
static List GetTriviaList()
{
//Get Contents from the file. Remove the special char "\r". Split on each line. Convert to a list.
List contents = File.ReadAllText("trivia.txt").Replace("\r", "").Split('\n').ToList();
//Each item in list "contents" is now one line of the Trivia.txt document.
//make a new list to return all trivia questions
List<Trivia> returnList = new List<Trivia>();
// TODO: go through each line in contents of the trivia file and make a trivia object.
// add it to our return list.
// Example: Trivia newTrivia = new Trivia("what is my name?*question");
//Return the full list of trivia questions
foreach (var item in contents)
{
Trivia bestTrivia = new Trivia(item);
returnList.Add(bestTrivia);
}
return returnList;
}
Here's a working Plunker showing how you could do it with just JavaScript (using the jQuery library).
http://plnkr.co/edit/BUCZOKd0MFDsa2jdMkJs?p=preview
The basic process is as follows:
Fetch the text file from the server
Split it into an array of lines
When the user clicks the button, generate a random number
Display the line corresponding to the random number
Here's the JavaScript for that (see the Plunker above for full source):
var lines;
var randomNumber;
var lastRandomNumber;
$(document.body).ready(function () {
// load the trivia from the server
$.ajax({
url: 'trivia.txt'
}).done(function(content) {
// normalize the line breaks, then split into lines
lines = content.replace(/\r\n|\r/g, '\n').trim().split('\n');
// only set up the click handler if there were lines found
if (lines && lines.length) {
$('#showLine').on('click', function () {
// loop to prevent repeating the last random number
while (randomNumber === lastRandomNumber) {
randomNumber = parseInt(Math.random() * lines.length);
// check to prevent infinite loop
if (lines.length === 1) { break; }
}
// keep track of the last random number
lastRandomNumber = randomNumber;
// show the corresponding line
$('#trivia').text(lines[randomNumber]);
});
}
});
});
UPDATE: Added some explanatory comments to the JavaScript (updated above and in the Plunker). Also added a check to prevent getting the same random line twice in a row.
I strongly suggest you to use server-side language, like PHP. Otherwise you will not be able to read only one word or string from the file. The javascript works in browser and to parse a file, as a first step, it would need the file fully loaded into the browser.
PS
Based on the task I would not recommend you to use JQuery or Javascript. Most likely this task would mean a protection, as in early years, this way was used to activate a copy of purchased software.
Presumably, the soft was bought with instruction and the activation algorithm demand word from instruction pointing page number, row number and number of the word in a row. In the case of Javascript - all this mechanism would be working on client site. It would need to load the file fully and parse it in browser where every one would debug it and extract the secret text fully. It would be an easy to crack protection.

Javascript Bookmarklet Unresponsive

Javascript newb here. Creating a bookmarklet to automate a simple task at work. Mostly a learning exercise. It will scan a transcript on CNN.com, for instance: (http://transcripts.cnn.com/TRANSCRIPTS/1302/28/acd.01.html). It will grab the lead stories at the top of the page, the name and title of the guests on the show, and format them so that they can be copy pasted into another document.
I've come up with a simple version that includes some jQuery that grabs the subheading and then uses a regular expression to find the names of the guests (it will also exclude everything between (begin videoclip) and (end videoclip), but I haven't gotten that far yet. It then alerts them (will eventually print them in a pop-up window, alert is just for troubleshooting purposes).
I'm using http://benalman.com/code/test/jquery-run-code-bookmarklet/ to create the bookmarklet. My problem is that once the bookmarklet is created it is completely unresponsive. Click on it and nothing happens. I've tried minimizing the code first with no result. My guess is that cnn.com's javascript is conflicting with mine but I'm not sure how to get around that. Or do I need to include some code to load and store the text on the current page? Here's the code (I've included comments, but I took these out when I used the bookmarklet generator.) Thanks for any help!
//Grabs the subheading
var leadStories=$(".cnnTransSubHead").text();
//Scans the webpage for guest name and title. Includes a regular expression to find any
//string that starts with a capital letter, includes a comma, and ends in a colon.
var scanForGuests=/[A-Z ].+,[A-Z0-9 ].+:/g;
//Joins the array created by scanForGuests with a semicolon instead of a comma
var guests=scanForGuests.join(‘; ‘);
//Creates an alert in the proper format including stories and guests.
alert(“Lead Stories: “ + leadStories + “. ” + guests + “. SEE TRANSCRIPT FIELD FOR FULL TRANSCRIPT.“)
Go to the page. Open up developer tools (ctrl+shift+j in chrome) and paste your code in the console to see what's wrong.
The $ in var leadStories = $(".cnnTransSubHead").text(); is from jQuery and the link provided does not have jQuery loaded into the page.
On any modern browser you should be able to achieve the same results without jQuery:
var leadStories = document.getElementsByClassName('cnnTransSubHead')
.map(function(el) { return el.innerText } );
next we have:
var scanForGuests=/[A-Z ].+,[A-Z0-9 ].+:/g;
var guests=scanForGuests.join('; ');
scanForGuests IS a regular expression, you never actually matched it to anything - so .join() is going to throw an error. I'm not exactly sure what you're trying to do. Are you trying to scan the full text of the page for that regex? In that case something like this would be your best bet
document.body.innerText.match(scanForGuests);
keep in mind that while innerText removes html markup, it's far from perfect and what pops up in it is very much at the mercy of how the page's html is structured. That said, on my quick test it seems to work.
Finally, for something like this you should use an immediately invoked function or you're sticking all your variables into the global context.
So putting it all together you get something like this:
(function() {
var leadStories = document.getElementsByClassName('cnnTransSubHead')
.map(function(el) { return el.innerText } );
var scanForGuests=/[A-Z ].+,[A-Z0-9 ].+:/g;
var guests = document.body.innerText.match(scanForGuests).join("; ");
alert("Leads: " + leadStories + " Guests: " + guests);
})();

Trying to fire off a bunch of onclicks all containing a different number

There is a page I can access that contains a bunch of links like this:
<a href="#" onclick="navigate(___VIEW_RAID_2, {raid_inst_id:556816});return false;">
The number after the raid_inst_id: is always going to be different and there will be multiples on the same page all with different numbers. I'm trying to put together a javascript that will scrape the page for these links, put them in an array and then cycle through clicking them.
Ideally, an alert causing a pause between onclicks would be helpful. I've been unsuccessful so far even trying to gather the numbers and just echoing them out let alone manipulating them.
Any hints or help would be greatly appreciated!
Below is a function I tried putting together just to see if I could capture some of the onclick values for further processing but, this produces nothing...
function closeraids(){
x=document.getElementsByTagName('a');
for(i=0;i<x.length;i++)
{
attnode=x.item(i).getAttributeNode('onclick');
alert("OnClick events are: " + attnode);
}
}
Wow - 4 months later and the same problem still exists. I decided to look into this again only to find my own posted question in my Google search! Does anyone have any thoughts on what could be done here? The function I'm trying to provide will be part of a Chrome extension I already provide to users. It uses a combination of a .js file I host on my webserver and injected html content.
Any help would be appreciated!
Had some fun while making this jsfiddle: http://jsfiddle.net/Ralt/ttkGG/
Mostly because I went onto using almost fully functional style... but well. Onto your question.
I'm using getAttribute('onclick') to get the string in there. It shows something like:
"navigate(___VIEW_RAID_2, {raid_inst_id:553516});return false;"
So I just built the necessary regex to match it, and capture the number after raid_inst_id:
var re = /navigate\(___VIEW_RAID_2, {raid_inst_id:(\d+)}\);return false;/;
It's mostly rewriting the string by escaping the parentheses and putting (\d+) where you want to capture the number. (\d+ is matching a number, () is capturing the matched string.)
Using match(), I can simply get the captured string as the last element. So, rewriting the code in old IE way:
var links = document.getElementsByTagName('a'),
re = /navigate\(___VIEW_RAID_2, {raid_inst_id:(\d+)}\);return false;/;
for (var i = 0, l = links.length; i < l; i++) {
var attribute = links[i].getAttribute('onclick'),
nb;
if (nb = attribute.match(re)) {
alert(nb.pop());
}
}

Adding Javascript variables to HTML elements

So, I have some code that should do four things:
remove the ".mp4" extension from every title
change my video category
put the same description in all of the videos
put the same keywords in all of the videos
Note: All of this would be done on the YouTube upload page. I'm using Greasemonkey in Mozilla Firefox.
I wrote this, but my question is: how do I change the HTML title in the actual HTML page to the new title (which is a Javascript variable)?
This is my code:
function remove_mp4()
{
var title = document.getElementsByName("title").value;
var new_title = title.replace(title.match(".mp4"), "");
}
function add_description()
{
var description = document.getElementsByName("description").value;
var new_description = "Subscribe."
}
function add_keywords()
{
var keywords = document.getElementsByName("keywords").value;
var new_keywords = prompt("Enter keywords.", "");
}
function change_category()
{
var category = document.getElementsByName("category").value;
var new_category = "<option value="27">Education</option>"
}
remove_mp4();
add_description();
add_keywords();
change_category();
Note: If you see any mistakes in the JavaScript code, please let me know.
Note 2: If you wonder why I stored the current HTML values in variables, that's because I think I will have to use them in order to replace HTML values (I may be wrong).
A lot of things have been covered already, but still i would like to remind you that if you are looking for cross browser compatibility innerHTML won't be enough, as you may need innerText too or textContent to tackle some old versions of IE or even using some other way to modify the content of an element.
As a side note innerHTML is considered from a great majority of people as deprecated though some others still use it. (i'm not here to debate about is it good or not to use it but this is just a little remark for you to checkabout)
Regarding remarks, i would suggest minimizing the number of functions you create by creating some more generic versions for editing or adding purposes, eg you could do the following :
/*
* #param $affectedElements the collection of elements to be changed
* #param $attribute here means the attribute to be added to each of those elements
* #param $attributeValue the value of that attribute
*/
function add($affectedElements, $attribute, $attributeValue){
for(int i=0; i<$affectedElements.length; i++){
($affectedElements[i]).setAttribute($attribute, $attributeValue);
}
}
If you use a global function to do the work for you, not only your coce is gonna be easier to maintain but also you'll avoid fetching for elements in the DOM many many times, which will considerably make your script run faster. For example, in your previous code you fetch the DOM for a set of specific elements before you can add a value to them, in other words everytime your function is executed you'll have to go through the whole DOM to retrieve your elements, while if you just fetch your elements once then store in a var and just pass them to a function that's focusing on adding or changing only, you're clearly avoiding some repetitive tasks to be done.
Concerning the last function i think code is still incomplete, but i would suggest you use the built in methods for manipulating HTMLOption stuff, if i remember well, using plain JavaScript you'll find yourself typing this :
var category = document.getElem.... . options[put-index-here];
//JavaScript also lets you create <option> elements with the Option() constructor
Anyway, my point is that you would better use JavaScript's available methods to do the work instead of relying on innerHTML fpr anything you may need, i know innerHTML is the simplest and fastest way to get your work done, but if i can say it's like if you built a whole HTML page using and tags only instead of using various semantic tags that would help make everything clearer.
As a last point for future use, if you're interested by jQuery, this will give you a different way to manipulate your DOM through CSS selectors in a much more advanced way than plain JavaScript can do.
you can check out this link too :
replacement for innerHTML
I assume that your question is only about the title changing, and not about the rest; also, I assume you mean changing all elements in the document that have "title" as name attribute, and not the document title.
In that case, you could indeed use document.getElementsByName("title").
To handle the name="title" elements, you could do:
titleElems=document.getElementsByName("title");
for(i=0;i<titleElems.length;i++){
titleInner=titleElems[i].innerHTML;
titleElems[i].innerHTML=titleInner.replace(titleInner.match(".mp4"), "");
}
For the name="description" element, use this: (assuming there's only one name="description" element on the page, or you want the first one)
document.getElementsByName("description")[0].value="Subscribe.";
I wasn't really sure about the keywords (I haven't got a YouTube page in front of me right now), so this assumes it's a text field/area just like the description:
document.getElementsByName("keywords")[0].value=prompt("Please enter keywords:","");
Again, based on your question which just sets the .value of the category thingy:
document.getElementsByName("description")[0].value="<option value='27'>Education</option>";
At the last one, though, note that I changed the "27" into '27': you can't put double quotes inside a double-quoted string assuming they're handled just like any other character :)
Did this help a little more? :)
Sry, but your question is not quite clear. What exactly is your HTML title that you are referring to?
If it's an element that you wish to modify, use this :
element.setAttribute('title', 'new-title-here');
If you want to modify the window title (shown in the browser tab), you can do the following :
document.title = "the new title";
You've reading elements from .value property, so you should write back it too:
document.getElementsByName("title").value = new_title
If you are refering to changing text content in an element called title try using innerHTML
var title = document.getElementsByName("title").value;
document.getElementsByName("title").innerHTML = title.replace(title.match(".mp4"), "");
source: https://developer.mozilla.org/en-US/docs/DOM/element.innerHTML
The <title> element is an invisible one, it is only displayed indirectly - in the window or tab title. This means that you want to change whatever is displayed in the window/tab title and not the HTML code itself. You can do this by changing the document.title property:
function remove_mp4()
{
document.title = document.title.replace(title.match(".mp4"), "");
}

Categories