Drawing links among words in a web page - javascript

I would like to know if something like this (see the picture above) is possible in HTML/CSS/Javascript and if so, what are the frameworks/technology that I should look at.
I have a text in a HTML page and I would like to highlight some words in it using different colours according to different meanings (let's say 3 types, 'name of software': blue, 'numbers': grey, 'name of people: 'red'). Then, an this is the tricky part for me, I would like to draw directed arrows among these highlighted words in a way that resizing the window will automatically keep anchored the arrows regardless to the changed position of the words.
Right now I am solving the highlighting part using a particular tag for the words to be highlighted and an ad-hoc CSS decorator with the property background colour accordingly set. The linking part is literally a mystery for me.
I thank you all for your help,
michele.
PS. I would prefer doing that on the client side.

You need to do loads of JavaScript code for this but I will simply tell you the steps. To achive your goal you need to:
parse every word in your paragraph by using split() method.
var words = yourparagraph.split(" ");
create an array that contains called name_of_software and push the software names in this array.
do the very above thing for people names and call the array people_names.
var name_of_software = ["html", "css", "javascript"];
var people_names = ["michele", "george", "john"];
create corresponding css for the highlightings.
span.red { background: red; overflow: hidden; display: block; }
span.grey { background: grey; overflow: hidden; display: block; }
span.blue { background: blue; overflow: hidden; display: block; }
Do a loop like this:
.
for(var i = 0; i < words.length; i++)
{
if($.inArray(words[i].toLowerCase(), name_of_software)) {
// The word is a name of a software. Give blue class.
} else if($.inArray(words[i].toLowerCase(), people_names)) {
// The word is a name of a person. Give red class.
} else if(isNaN(words[i])) {
// The word is a number. Give grey class.
}
}
I didn't test it or create a working version of it. Hope this steps will guide you to achive your goal.

Related

Adding CSS classes and media to an empty div and append

I'm trying to re-create an Instagram like sort of page with some jQuery included. This is for a course I'm taking, so I'm a student basically.
This particular part of the exercise is asking me to:
- Empty the content of a class div.
- iterate over the media that is given.
- create an empty div and assign two classes, background image and append to the "empty" class.
The code I have so far is the following:
function renderUserMedia (media) {
// The class that is being emptied.
$('.user-media').html('');
// iteration
media.forEach(function (mediaItem) {
// empty div to add to every iterated picture with whatever is needed
var div = $('<div>').addClass('user-media-item u-pull-left').css('background-image', mediaItem).appendTo('.user-media');
});
}
All media is fetched through an API which I have no idea how is being configured (school configuration and what not), and the media is from a "dummy" insta page I guess.
What's happening is that images are not happening on the browser, and I think it has something to do with the .css implementation of the images iterated. The property background-image does not exist in the css file, so there might be something going on.
I have also tried to append to '.user-media' with $('.user-media').append(div); on the next line, but it didn't produce the desired result, which is to have all pictures iterated from forEach with the '.user-media-item' class.
.user-media-item {
margin-right: 10px;
margin-bottom: 10px;
width: 230px;
height: 230px;
overflow: hidden;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
Could someone please help me understand what am I doing wrong?
After having checked everything and not being able to retrieve images, the only needed thing was (thanks to #freedomn-m and #CBroe for directions) to include the actual key that holds the location of the file. In this case a local folder.
function renderUserMedia (media) {
$('.user-media').html('');
media.forEach(function (mediaItem) {
var div = $('<div>').addClass('user-media-item u-pull-left').css('background-image', 'url(' + mediaItem.media_url + ')').appendTo('.user-media');
});
}
In case of using the url key, then we should change to .css('background-image', 'url(' + mediaItem.permalink + ')') as it was showing in the object containing the info of the images.

How to change text to invisible, but still show underline?

I made a studying tool using Javascript and PHP. There's a toggle that shows/hides keywords in a paragraph, so the user can mentally "fill in the blanks".
How I've done this so far is that the all the keywords are underlined, and I use a DOM selector to select all innerHTML in u tags.
<p>
Example sentence, <u>this</u> is a <u>keyword</u>.
</p>
<button onClick='hideKeywords()'>Hide Keywords</button>
<script>
function hideKeywords() {
var x = Array.from(document.getElementsByTagName('u'));
for (var i = 0; i < x.length; i++) {
x[i].style.visibility = "hidden";
}
}
</script>
This works as intended - the "keywords" are blanked out and the flow of the document is unaffected, since the keywords still take up the same space that they would normally take.
One downside is that in paragraphs with particularly long "keywords", the paragraph's line structure is disrupted and it looks like text is just floating randomly in space. This would be fixable if I could somehow change visibility such that the words in the keywords are hidden and the text-decoration (underline) still shows. This retains the line structure.
I thought about using Javascript to replace every character in the keyword with underscores, but two more problems pop up. One thing is that even if the number of characters stay the same, the width might change.. For example, "apple" is not the same physical length as "______". This is not ideal as the document flow would change. A second problem is that I can't think of any way to get the keywords back after converting them into underscores.
One workaround is instead of changing the visibility to "hidden", I could change the background-color to the same color as the text. This blocks out the text, but the line structure and document flow are both preserved. However, I do hope to find a way to implement my original idea, so any suggestion is appreciated!
Update: I would prefer not to add any additional divs to the keywords. The user can add new entries using a rich text editor, so declaring a keyword is as easy as underlining it in the text editor.
You can do it with css adding a pseudo-element and instead of using visibility hidden, using color: transparent, like this:
u{
position:relative;
}
u::after{
content: ' ';
display:block;
position:absolute;
bottom:0;
left:0;
width: 100%;
height:1px;
background-color:#000;
}
And in the script
<script>
function hideKeywords() {
var x = Array.from(document.getElementsByTagName('u'));
for (var i = 0; i < x.length; i++) {
x[i].style.color = "transparent";
}
}
</script>
https://codepen.io/anon/pen/ROoMaM
I would probably implement this using your second method. Set the text colour to the same as the background then add a bottom border to the element. Preserves the spacing and allows you to quickly check if you are right by just highlighting the line. Also, if you give the keyword wrapper element a class you can easily just toggle the color of the hidden text, and retain the underlines so you can see what has changed.
div {
color: black;
}
span {
color: white;
text-decoration: none;
border-bottom: 2px solid green;
}
<div>
This <span>is hidden</span> with an underline
</div>
You'd have to find some way to get the div positioned under the hidden text, but you can use the following code to create a div with the width of the text. I might come back later after answering and find a way to position the div.
In your HTML, let's say you have a phrase, foo bar, that you want hidden. You will assign an id to it with the code: <p id="foo">foo bar</p>
Here is the CSS:
#foo {
position: absolute;
visibility: hidden;
height: auto;
width: auto;
white-space: nowrap;
}
Then in your Javascript, you can use the following code:
var fontSize = 20; //this defines a font size
var foo = document.getElementById("foo");
foo.style.fontSize = fontSize; //this sets the style as the font size
var width = (foo.clientWidth) + "px"
var div = document.createElement("div");
div.style.width = width;
div.style.height = 2px;
div.style.background = "red"; //makes the underline visible
document.getElementById("main").appendChild(div);
From here, you could probably just reposition the div how you want so it appears under the text. This way, the div is the exact length of the text.
An alternative solution would be to use a monospace font and then manually calculuate the width.

Colouring letters, numbers in HTML document

How is it possible to add style (colors) to text in an html document in a letter by letter basis (by numbers and any symbol as well), to each letter a defined color is applied.
Think you have grapheme-color synesthesia, in this case I have, and want to make a text editor with your colors applied to glyphs. Although there are ready programs I want to enjoy doing one myself and practice my JavaScript skills. Later I am planning a reader also.
One way is to wrap every letter in an html element in another element, say a span and apply style by class name being related to the wrapped letters name. I will use same idea also in a React Native app.
Is there any other more efficient or more proper way to achieve this?
Basic regular expression with replace to add spans. You can replace the string with a function so you can do something more dynamic to determine the color.
var ps = document.querySelectorAll("p");
[].forEach.call(ps, function (elem) {
elem.innerHTML = elem.innerHTML.replace(/(\S)/g, "<span>$1</span>");
});
span {
display: inline-block;
border: 1px solid black;
width: 20px; text-align: center;
}
<p>Mary had a slice of bacon. It cost $0.75 and tasted great.</p>
<p>Bill had no bacon. He was sad!</p>
Other than doing the looping and replacing, I do not think there is another way of doing it.
Below is the reference link,
Change this span tag in the referenced example,
ie. instead background give color in style tag
<span style="color:'+bgColor+'">'+ text.charAt(i) +'</span>
and
Change the css background:white
Reference link

Highlight text by keywords which are separated by comma

I would like to split up text by comma - i.e. keywords are as the following:
keyword1, keyword2, keyword3, keyword4
How can I have a the black style element for each and every keyword that is separated by a comma. Is there an easy way to do this? The text is always dynamic, so I never know exactly what those keywords will be and how many. So each keyword should have a box elements around it.
<span class="keyword-option-black">keyword1, keyword2, keyword3, keyword4</span>
.keyword-option-black {
color:white;
background-size:contain;
margin:10px;
padding:5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
background:black;
}
CSS is unable to select text.
In order to highlight the keywords on a page, you need to use programming languages such as JavaScript (for client-side) or PHP (or whatever else for server-side) to wrap the keywords by a wrapper element which has a special CSS style to distinguish the keys.
Here, I implemented the above approach by using jQuery (just to demonstrate):
Working Fiddle
JS part:
// Insert the keywords here,
// you can also get the keys automatically from the DOM if needed
var keywords = ['Google', 'Facebook', 'Social'];
$.each(keywords, function(index, key) {
var $content = $('#content'),
text = $content.html();
$content.html(
text.replace(
new RegExp("("+ key +")", 'ig'), "<span class='highlight'>$1</span>"
)
);
});
And here is the highlight class:
.highlight {
color: white;
background-size: contain;
margin:10px;
padding:5px;
border-radius: 5px;
background: black;
}
HTML and CSS are static. Since you don't know how many keywords are gonna be there, you need something dynamic. Depending on implementation, you can use JavaScript or any Back-end language you are using.
Basically, you want to add a span tag around each keyword and style that span (span in one with class keyword-option-black). So, when you enter keywords to HTML use <span>keywordX</span> in loop that adds elements or, alternatively, add those tags when document loads using JavaScript.
Hope this helps.
Using Django, I did it the following way.
Create a simple CSS class to perform the highlighting.
Create a custom tag that splits up data in template view into <span class="keyword">A</span><span class="keyword">B</span>. It takes the original view output and parses this into a format that already has the spans included.

"Opening"/Divinding an HTML paragraph

This question could be an interesting problem to solve…
On a web page that displays a text, I need a specific behavior : when the user clicks on some special words, an explanation of this word opens just below the clicked word. All the problem is : it should really open below the words, like "opening" the paragraph in two, without making the text that follows to jump to the next line.
I found a solution that works pretty well, using the CSS float property.
You can see it there (would speak more than the code below) : http://jsfiddle.net/3gwzx/3/
The main problem of this solution, is that it uses nested span. And, as span aren't block tags, the padding wouldn't work with them. So, inside the gray box, the text will never have any horizontal padding (vertical padding is ok) - otherwise it changes the size of the box itself - or did I missed something ? - And that's bad. Has anybody got a solution ? Should I rethink the problem in a whole other way ?
Thanks you very, very much !
Here is what the HTML looks like :
<body onload="putListeners()">
<p>This is the normal text here, you cannot click it. But some words needs long
explanations, like this one : <span class="note">click on me
<span class="noteTxt">The explanation begins here <a class="foo" href="bar.html"> and
could have link</a> that one should be able to click.
And the note can be loooong, long, long, very, very long.
</span>
</span>
And here, the text carry on. It could carry on for a long, long time.
And with all the other solutions I tried, this part of the text "jumps" after the note,
on a new line, when it appears. What I like here is that, when you open the note,
it really "open the paragraphs in two". But i cannot give a padding
to those nested span… I should have a div… but you cannot put a div
inside a span !</p>
</body>
Here is the JS
function putListeners() {
//just listens to the text…
var elements = document.getElementsByClassName("note");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener("click", showNote, false);
}
};
function showNote()
{
//content to show
var currentTxt;
//finds the nested noteTxt
for (var i = 0; i < this.childNodes.length; i++) {
if (this.childNodes[i].className == "noteTxt") {
currentTxt = this.childNodes[i];
break;
}
}
//displays it or hides it
if(currentTxt.style.display=="none" || currentTxt.style.display=="")
{
currentTxt.style.display="block";
}
else
{
currentTxt.style.display="none";
}
return true;
};
And, for information, the relevant part of the CSS (you probably figured out what it looks like - complete code in the Jfiddle) :
span.note {
position: static;
}
span.note span.noteTxt {
display: none;
float: left;
color: black;
width: 100%;
background-color: #eaeaea;
}
If you want to change the layout behavior of a tag, in your case <span> you can set css property display: block to change it to a div style layout.
span.asblock {
display: block;
}
this will give you a span that behaves like a div.

Categories