I have a series of pages on my site that utilize JavaScript to show a title based on the variable defined in the page.
Basic HTML
<h1 id="pageTitle"></h1>
<script> var page = "start";</script>
<!-- Rest of the page... -->
Separate JavaScript File
var startText = "Hello!";
var middleText = "This is a page";
var endText = "Example";
if(page == 'start'){
$('#pageTitle').html(startText);
}
if(page == 'middle'){
$('#pageTitle').html(middleText);
}
if(page == 'end'){
$('#pageTitle').html(endText);
}
This follows a simple pattern that does the job fine, but can get tedious as the website grows. Is there a cleaner way to get the same result?
Instead of defining a JS variable in every page I suggest to attach a data-* attribute to the title tag like :
<h1 id="pageTitle" data-page="start"></h1>
Then in your separate JS file, you could create an object contains the list of title and use the data-page attributes as a key like :
var titles = {
"start": "Hello!",
"middle": "This is a page",
"end": "Example"
}
var title_element = $("#pageTitle");
var key = title_element.data('page');
title_element.text(titles[key]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="pageTitle" data-page="middle"></h1>
Use an object reference the key...
var messages = {
"foo" : "bar",
"hello" : "world"
}
function setMessage(key) {
document.querySelector("#out").innerHTML = messages[key];
}
setMessage("hello");
<div id="out"></div>
A cleaner way could be to organize the titles in a dictionary.
var titles = {
"start": "Hello!",
"middle": "This is a page",
"end": "Example"
}
$('#pageTitle').html(titles[page]);
It's always a good idea to organize your code into modular functions. This will help keep your code maintainable.
function init(title) {
document.querySelector("#pageTitle").innerHTML = getTitleHtml(title);
}
function getTitleHtml(title) {
const titleMap = {
start: "Hello",
middle: "This is a page",
end: "Example"
};
return titleMap[title];
}
var title = "end";
init(title);
<h1 id="pageTitle"></h1>
Related
This is my first post, hoping someone can help me:
I wish to build a web project, where all the HTML elements are stored in database and taken from it to build the web page.
i found a problem with the buttons, i cannot find a way to store the function for a button, i´m using Jquery to build the elements, for now the test element definitions are simulated in some arrays i left at the start of my Js file, the only way i can make the buttons to work is if the functions are hardcoded in the Js file, is there a way for me to bring the functions from database too? and having them in an array?
this is my project sample:
HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!--script src="functions.js"></script-->
<script src="system.js"></script>
<!--script src="elements.js"></script-->
</head>
<body>
<body onload="addElements()">
<div id="div1"></div>
</body>
</html>
JS File
/**
VARIABLE DEFINITIONS
THESE ARE SUPPOSED TO COME FROM A DATABASE
STILL UNKNOWN HOW TO BRING THE FUNCTIONS, AS STRING THEY ARE NOT ALLOWED. FOR NOW THERE ARE TEST FUNCTIONS.
**/
let buttonIds = ['btn1', 'btn2'];
let buttonText = ['Show Text', 'Show HTML'];
let buttonFunc = [alert1, alert2];
//let buttonFunc = ['alert("Hi");', 'alert("Hello");'];
let paragraphs = ['This is some <b>bold</b> text in a paragraph.', 'another <b>bold</b> test'];
//HELPER FUNCTIONS
// **** THESE ARE SUPPOSED TO COME FROM DATABASE, UNKNOWN HOW TO DO IT. ****
function alert1() {
alert("Hi");
}
function alert2(){
alert("Hello");
}
function addElements(){
for(var p=0; p<paragraphs.length; p++){ addParagraphs('#div1', paragraphs[p]); }
for(var i=0; i<buttonIds.length; i++) { createButton( '#div1', buttonIds[i] , buttonText[i]); }
}
// ANY ELEMENTS FUNCTION IS DEFINED HERE ONCE THE PAGE IS LOADED.
$(document).ready(function(){
for(var x=0;x<buttonIds.length; x++){ activateButton(buttonIds[x], buttonFunc[x]); }
});
//HELPER FUNCTIONS USED TO BUILD THE HTML ELEMENTS ON THE MAIN PAGE.
function addParagraphs(location, text){
$(location).append('<p id="test">'+text+'</p>');
}
function createButton(location, id, text){
var definition;
definition = "<button id="+id+">"+text+"</button>";
$(location).append(definition);
}
function activateButton(buttonId, functionName){
var composedId = "#"+buttonId;
$(composedId).click(functionName);
}
You can generate Javascript file serverside with all the funcions you need.
Supposing Node.js you can do something like this:
expressApp.get("some.js", (req, res) => {
getDataFromDatabase() // depends on your database
.then(data => {
let body = 'function your_fn () { alert("'+ JSON.stringify(data) +'")}';
res.send(body);
})
});
One approach is use an object to store the functions in javascript and use property names stored in db to associate which function to use for which element.
Without knowing more about your use case it is hard to really help design a proper system to use
Following is a very basic example
// functions stored in js file
const funcs = {
f1: function(e){ console.log('func one called , id = ', this.id)},
f2: function(e){ console.log('func 2 called , id = ', this.id)}
}
// data from database
const elems = [
{id: 1, className: 'one', func:'f1', text:'Item 1'},
{id: 1, className: 'two', func:'f2', text:'Item 2'}
]
elems.forEach(e => {
const $el= $('<div>', {id: e.id, class: e.className, text:e.text, click: funcs[e.func]})
$('body').append($el);
});
div {margin:1em;}
.one {color:red;}
.two {color:green;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<strong>Click on items</strong><br><br>
I'm new to web development and can't seem to find this specific task anywhere on this site, only things related to dynamic changes while using a page. Basically, I want the contents of the tag in my part of my html document to always be different when loading/refreshing the page; I want to store some kind of array of strings in JS, and have the page, upon loading the html, pick one of these strings to insert into the tag.
This will result in every time I refresh the page, the title on the tab is different, and will not change unless I refresh again.
Can anyone point me to how I might do this? Completely stuck, and out of ideas after my window.onload didn't work.
EDIT: I have tried this code based on what I found on this site, but the title didn't change; and I'm not sure why.
var titles = ['rainy skies == best', 'now with more bugs!', 'c > java'];
window.onload = function() {
document.title = titles[(Math.random() * 10) % 2];
$('meta[name="description"]').attr("content", 'My website!');
};
(This is then linked into the html page as per usual)
You can add a little piece of Javascript. It will be executed each time the page loads and can change the page title dynamically.
<script>
var titles = ['asdf', 'qwer', 'uiop']
var title = titles[Math.floor(Math.random() * titles.length)] // pick random item
document.title = title
</script>
The usage of a backend language like PHP can solve the issue too, but this is much simpler.
Server-side example. Define a list of titles, pick a random one, and output it in the title attribute.
Get random item from array
PHP
<?php
$titles = ['title1', 'title2', 'title3'];
?>
<html lang="">
<head>
<title><?php echo $titles[array_rand($titles)]; ?></title>
</head>
...
</html>
You should use document.title to change the title in the tab of the website.
const strings = ["bar", "foo", "banana", "apple", "orange", "red", "green", "blue", "brown", "gray"];
window.onload = () => {
let random = Math.floor(Math.random() * strings.length);
// example with a div
document.getElementById("my-span").innerHTML = strings[random];
// example with page title
// document.title = strings[random];
};
<span id="my-span"></span>
HTML:
<head>
<title id="title"></title>
</head>
Javascript:
window.onload = function() {
var titles = ['rainy skies == best', 'now with more bugs!', 'c > java'];
var random = Math.floor(Math.random() * titles.length);
var titleElement = document.getElementById('title')
titleElement.innerHTML = titles[random];
}
EDIT: innerHTML instead of html
I'm trying to get an image from a Wikipedia article. I have the title of the article but it seems like I need to know the pageid to access the thumbnail. How do I get the pageid from the title?
My JavaScript code:
$.getJSON("http://en.wikipedia.org/w/api.php?action=query&titles=" + article + "&prop=pageimages&format=json&pithumbsize=350", function (data) {
imageURL = data.query.pages[/* pageid */].thumbnail.source;
});
Here's what I'm parsing (example for article = "Car"):
{"query":{"pages":{"13673345":{"pageid":13673345,"ns":0,"title":"Car","thumbnail":{"source":"http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Benz-velo.jpg/100px-Benz-velo.jpg","width":100,"height":80},"pageimage":"Benz-velo.jpg"}}}}
^ It seems like I first need to know that it's the 13673345 index.
OP asks how to "access the thumbnail", i.e., the URL within the returned data. He did not ask how to access the full image behind the thumbnail ... which is something other answers address.
OP's problem is that the data is keyed to the page ID. In fact, the query could return more than one article in which case there would be multiple page IDs and thumbnails.
The following query returns the data used in the code snippet:
http://en.wikipedia.org/w/api.php?action=query&titles=Stack_Overflow&prop=pageimages&format=json&pithumbsize=350
And OP can extract the page IDs using this code:
var pageid = [];
for( var id in data.query.pages ) {
pageid.push( id );
}
Run the code snippet below to test.
<html>
<body>
<img id="thumbnail"/>
<script type="text/javascript">
var data = {
"query":
{
"normalized": [
{
"from": "Stack_Overflow",
"to": "Stack Overflow"
}],
"pages":
{
"21721040":
{
"pageid": 21721040,
"ns": 0,
"title": "Stack Overflow",
"thumbnail":
{
"source": "http://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Stack_Overflow_homepage.png/350px-Stack_Overflow_homepage.png",
"width": 350,
"height": 185
},
"pageimage": "Stack_Overflow_homepage.png"
}
}
}
};
// get the page IDs
var pageid = [];
for( var id in data.query.pages ) {
pageid.push( id );
}
// display the thumbnail using a page ID
document.getElementById('thumbnail').src = data.query.pages[ pageid[0] ].thumbnail.source;
</script>
</body>
</html>
Just build your JSON object with JSON.parse so you have an object that looks like:
var response = {
query: {
pages: {
"13673345":{
pageid: 13673345,
ns: 0,
title: "Car",
thumbnail: {
source: "http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Benz-velo.jpg/100px-Benz-velo.jpg",
width: 100,
height: 80
},
pageimage: "Benz-velo.jpg"
}
}
}
};
And then you can clearly see you don't need pageid in the slightest, you just need to process the correct "pages" object.
In this case there's only one, but even if there would be multiple, just run through Object.keys for the response.query.pages object:
var pages = response.query.pages;
var propertyNames = Object.keys(pages);
propertyNames.forEach(function(propertyName) {
var page = pages[propertyName];
var thumbnail = page.thumbnail.src;
var imgURL = thumbnail.replace("/thumb/",'').replace(/\.(jpg|png).*/,".$1");
doSomethingWith(imgURL);
});
(note the file extension regexp, which we do because who says all images are jpg? Better to pick jpg and png, since those are the two prevailing image formats on the web)
I am learning JavaScript.
I am trying toggle the text on a page using the replaceChild() method. I came up with the code below. I don't understand why it will not work. Pls help.
<html>
<head>
<script>
function toggleText() {
var be= document.getElementById("main");
var b4= be.getElementsByTagName("h1");
var l8 = document.createElement("h1").innerHTML="After";
var l88 = document.createElement("h1").innerHTML="Before";
if (b4[0].innerHTML=="Before"){
be.replaceChild(l8,b4[0])
}
if (b4[0].innerHTML=="After") {
be.replaceChild(l88,b4[0]);
}
}
</script>
</head>
<body>
<div id="main" onclick="toggleText()">
<h1>Before</h1>
</div>
</body>
</html>
As CBrone wrote, you have to create h1 instance first, store it to variable and then call innerHML on the variable.
Another problem is if structure. First you replace the element and then test the same element for another condition and do another operation. In this case is better to use if ... else if ... statement instead of if ... if ..., which is the root of your problem.
Here is working toggleText function
function toggleText() {
var be= document.getElementById("main");
var b4= be.getElementsByTagName("h1");
var l8 = document.createElement("h1");
l8.innerHTML="After";
var l88 = document.createElement("h1");
l88.innerHTML="Before";
if (b4[0].innerHTML == "Before")
{
be.replaceChild(l8, b4[0]);
}
else if (b4[0].innerHTML=="After")
{
be.replaceChild(l88, b4[0]);
}
}
Here is working fiddle
In addition to what’s been said in comments already:
var l8 = document.createElement("h1").innerHTML="After";
var l88 = document.createElement("h1").innerHTML="Before";
After this your variables do not contain references to the created elements, but the string values that you assigned to their innterHTML. (The result of an assignment operation is the assigned value.) And trying to pass text values instead of element references to replaceChild afterwards must fail for that reason.
Do this in two steps – create the elements first and save their reference into the variables – and then manipulate their innerHTML afterwards.
var l8 = document.createElement("h1");
l8.innerHTML="After";
var l88 = document.createElement("h1");
var l88 = .innerHTML="Before";
(And maybe use better suited variable names, because if you keep your current “naming scene” up you’ll get confused sooner or later.)
May I suggest the following, for better readability:
<html>
<head>
<script>
function toggleText() {
var be= document.getElementById("main");
var b4= be.getElementsByTagName("h1")[0];
if (b4.innerHTML=="Before") {
b4.innerHTML = "After";
}
else if (b4.innerHTML=="After") {
b4.innerHTML = "Before";
}
}
</script>
</head>
<body>
<div id="main" onclick="toggleText()">
<h1>Before</h1>
</div>
</body>
</html>
I am trying to build a template builder using http://ejohn.org/blog/javascript-micro-templating
My html has this script tag
<script type="text/html" id="item_tmpl">
<div>
<div class="grid_1 alpha right">
</div>
<div class="grid_6 omega contents">
<p><b><%=AdTitle%>:</b> <%=AdTitle%></p>
</div>
</div>
</script>
<script src="${URLUtils.staticURL('/js/shoptheAd.js')}"type="text/javascript"></script>
The Script contains the following code
(function(app){
if (app) {
var cache = {};
this.tmpl = function tmpl(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
// Provide some basic currying to the user
return data ? fn( data ) : fn;
};
var sitecoresuggestions = {
"suggestions": [
{
"AdTitle": "CheckAd",
"AdDescription": "",
"AdImageUrl": "http://demo-kiehls.loreal.photoninfotech.com/~/media/Advertisement Images/emma-watson-3.ashx",
"Count": 2,
"Hit": 0
},
{
"AdTitle": "CheckAd",
"AdDescription": "",
"AdImageUrl": "http://demo-kiehls.loreal.photoninfotech.com/~/media/Advertisement Images/kate2.ashx",
"Count": 2,
"Hit": 0
}
]
} ;
var show_user = tmpl("item_tmpl"), html = "";
for ( var i = 0; i < sitecoresuggestions.suggestions.length; i++ ) {
html += show_user( sitecoresuggestions.suggestions[i] );
}
console.log(html);
} else {
// namespace has not been defined yet
alert("app namespace is not loaded yet!");
}
})(app);
When the show_user = tmpl("item_tmpl") is executed
i get the error TypeError: document.getElementById(...) is null
on debugging i have figured out that due to some reason
<script type="text/html" id="item_tmpl">
<div>
<div class="grid_1 alpha right">
</div>
<div class="grid_6 omega contents">
<p><b><%=AdTitle%>:</b> <%=AdTitle%></p>
</div>
</div>
</script>
does not get loaded in the browser any ideas why it is not getting loaded even though it is included inside the head tag or any other pointers for the cause of the error
Per the post:
Quick tip: Embedding scripts in your page that have a unknown content-type (such is the case here - >the browser doesn't know how to execute a text/html script) are simply ignored by the browser - and >by search engines and screenreaders. It's a perfect cloaking device for sneaking templates into >your page. I like to use this technique for quick-and-dirty cases where I just need a little >template or two on the page and want something light and fast.
So the page doesn't actually render the HTML, and I would assume you would only have reference to it in the page so that you can extract and apply to other objects or items. And as the blogger states you would use it like:
var results = document.getElementById("results");
results.innerHTML = tmpl("item_tmpl", dataObject);