I have a simple widget, and want to load it on different sites. I've read this article and tried to make a solution with AJAX - setting response type to document .
Everything seems ok on first look - slider items loaded, styling is ok. But slider does not start to roll. Seems javascript does not start to run. Pervious/Next buttons also not working.
Below code describes what I've tried so far.
Widget - I used twig for templating, however it is not important. And that produces a carousel/slider like this.
<div class="slider-items-holder">
<div class="control-btns">
<ul><li><strong>Slider</strong></li>
<li></li>
<li></li>
</ul>
</div>
<div class="content-wrapper">
<ul>
{% for job in jobs %}
<li>
<div class="job-spotlight">
<h4>{{ job.title }}<span class="job-type part-time">{{ job.type }}</span></h4>
<span><a target="_blank" href="{{ job.loc_statecode }}">
<i class="marker"></i> {{ job.loc_state }}</a>
</span>
<span><i class="user"></i>{{ job.company }}</span>
<p>{{ job.detail|striptags }} ... </p>
Apply For This Job
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
<link rel="stylesheet" type="text/css" href="css/styles.css">
<script src="js/script.js"></script>
JS
function fetch_jobs_widget(selector) {
var url = "http://localhost:9874";
var t = "/static";
var js_template = '<script type="text/javascript" src="'+url+'/js/script.js"></script>';
var css_template = '<link rel="stylesheet" type="text/css" href="'+url+'/css/styles.css">'
var xhr = new XMLHttpRequest();
xhr.open("GET", url+t, true);
xhr.responseType = 'document';
xhr.onload = function(e) {
container(selector).innerHTML = "";
var doc = e.target.response;
var widgetFragment = document.createDocumentFragment();
widgetFragment.appendChild(doc.querySelector(".my-slider"));
container(selector).appendChild(widgetFragment);
container(selector).innerHTML += css_template;
container(selector).innerHTML += js_template;
}
xhr.send();
}
HTML - And I want to use that widget on that page.
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="textwidget jobs-plugin-carousel">
</div>
<script type="text/javascript" src="widgets.js"></script>
<script type="text/javascript">fetch_jobs_widget('.textwidget');</script>
</body>
</html>
I have also tried to load HTML/CSS/JS at once but I've came up with the same result.
UPDATE
JS code for slider
//script.js
(function () {
var mySlider, cWrapper, ul, li;
var current = 0;
var timeOut = 3000;
var intervalHandler;
var automaticStart = true;
init();
function init() {
mySlider = document.querySelector(".my-slider");
cWrapper = document.querySelector(".my-slider > .content-wrapper");
ul = document.getElementById("slider-items-holder");
li = ul.querySelectorAll("li");
if (!mySlider || !cWrapper || !ul || !li.length)
return;
ul.style.width = cWrapper.offsetWidth * li.length;
ul.style.height = cWrapper.offsetHeight;
bindEvents();
startSlider();
}
function startSlider() {
if (automaticStart)
intervalHandler = setInterval(next, timeOut);
}
function next() {
if (current + 1 >= li.length) {
current = -1;
}
ul.style.marginLeft = '-' + (li[0].offsetWidth * ++current);
}
function prev() {
if (current - 1 < 0) {
current = li.length;
}
ul.style.marginLeft = '-' + (li[0].offsetWidth * --current);
}
function bindEvents() {
mySlider.addEventListener('mouseover', function () {
clearInterval(intervalHandler);
});
mySlider.addEventListener('mouseout', startSlider);
var prevBtn = document.querySelector(".my-slider > .control-btns a.prev");
var nextBtn = document.querySelector(".my-slider > .control-btns a.next");
if (prevBtn)
prevBtn.addEventListener('click', prev);
if (nextBtn)
nextBtn.addEventListener('click', next);
}
})();
As I see your slider closely I found that you have this line
ul = document.getElementById("slider-items-holder");
which try to find an element with ID "slider-items-holder" but in your slider template you don't have this id for your ul element. So add this id to your second ul element.
Edit
The way you add your JavaScript file dynamically is wrong. You need to add your script to head tag to your html page like this
var myScript= document.createElement('script');
myScript.type = 'text/javascript';
myScript.src = 'http://localhost:9874/js/script.js';
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(myScript);
Related
I and my course mate are trying to write a code where when the order button is clicked it should save on local storage and redirect to an order page.
So far when we click on order it is not registered in the application/local storage section of the google developer tool and thus does not redirect to a new page.
We put an eventlistener to show a console.log for when we click, just to be sure the buttons are in order(this part is not important).
We also used an online javascript validator to eliminate typos and errors.
Also do we need any specific code on the order.html file to interface with local storage?
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>grc</title>
<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
<header>
<nav>
<ul>
<li>Home</li>
<li>Groceries</li>
<li>Contact</li>
</ul>
</nav>
</header>
<main>
<aside><img class="imgclass1" src="images/rounded logo.png" alt="Grocer Nigeria"></aside>
<article class="preinventory">
<section class="columns-desktop">
<div class="inventory">
<img class="sales" src="images/tomato.jpg" alt="Tomato"/>
<div class="columns">
<div class="title">Tomato</div>
<div class="Price">$100</div>
</div>
<p class="Desc"> Our Tomato2</p>
<button data-order="Tomato2">Order</button>
</div>
<div class="inventory">
<img class="sales" src="images/tomato.jpg" alt="Tomato"/>
<div class="columns">
<div class="title">Tomato</div>
<div class="Price">$100</div>
</div>
<p class="desc"> Our Tomato</p>
<button data-order="Tomato">Order</button>
</div>
</section>
</article>
</main>
<footer>
<nav>
<ul>
<li>Home</li>
<li>Groceries</li>
<li>Contact</li>
</ul>
</nav>
</footer>
<script type="text/javascript">
window.addEventListener("DOMcontentLoaded", function(e){
const orderButtons= document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button){
button.addEventListener("click",function(e){
const button= e.currentTarget;
const container= button.parentNode;
const order={
id:button.getAttribute("data-order"),
title: container.querySelector(".title").innerText,
price1: container.querySelector(".Price").innerText,
desc:container.querySelector(".desc").innerText
};
localStorage.setItem('order', JSON.stringify(order));
const url = window.location.href.replace("grc.html","order.html");
window.location.href = url;
});
});
});
window.addEventListener("DOMcontentLoaded", function(e){
console.log("The page is loaded.");
});
const orderButtons= document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button){
button.addEventListener("click", function(e){
console.log("The button was clicked.");
});
});
</script>
</body>
</html>
**Below is what I see when I run the live server**
<!-- Code injected by live-server -->
<script type="text/javascript">
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function() {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
head.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
head.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function(msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
console.log('Live reload enabled.');
})();
}
// ]]>
</script>
</body>
</html>
The issue here is that the event DOMContentLoaded does not fire.
Here is how I have used the load event instead; for redirection, I have simply used URL search params (because I don't know what your other html file looks like) although you may use your other html document instead.
The snippet is below
However note: Stackoverflow will not allow the JavaScript to run, and will throw a securityError. To run this code you must save it on your computer or use a jsFiddle
function continue_ordering() {
alert("Now continue with order");
};
window.addEventListener("load", function(e) {
const orderButtons = document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button) {
button.addEventListener("click", function(e) {
const button = e.currentTarget;
const container = button.parentNode;
const id = button.getAttribute("data-order");
const order = {
id,
title: container.querySelector(".title").innerText,
price1: container.querySelector(".price").innertext,
desc: container.querySelector(".desc").innerText
};
localStorage.setItem("order-" + id, JSON.stringify(order));
window.location.search = "?ordering=true&order-id=" + id;
});
});
});
window.addEventListener("load", function(e) {
if (window.location.search.search("ordering=true") != -1) {
console.log("User is ordering");
const params = new URLSearchParams(location.search)
const id = params.get("order-id");
if (!id || id == null) throw "There is no order id, error. Remove the ?ordering=true from the url and try again.";
const order_info = JSON.parse(localStorage.getItem("order-" + id));
if (!order_info) throw "Order information is not present: try ordering again. Remove the ?ordering=true from the url";
console.log("Order info is:\n", order_info);
document.getElementById("ordering").removeAttribute("hidden");
return;
};
document.getElementById("make-order").removeAttribute("hidden");
});
const orderButtons = document.querySelectorAll("button[data-order]");
orderButtons.forEach(function(button) {
button.addEventListener("click", function(e) {
console.log("The button was clicked.");
});
});
<div id="make-order" hidden>
<button data-order="test">Order</button>
<div class="title">This is the title</div>
<div class="price">130 USD</div>
<div class="desc">Lorem</div>
</div>
<div id="ordering" hidden>
<h1>
You are ordering.
<br> Choose
Stop ordering Or Continue with order
</h1>
</div>
The DOMcontentLoaded event has already fired by the time that code hooks it.
Check this post;
Code inside DOMContentLoaded event not working
I received this code from another user in this forum.
Issue: As seen in the below screenshot, the search results (or data) starts to appear when you click or start typing in the search box or else only the search box loads without the data.
Requirement: I want to display the results (or data) as the page loads.
The code is given below
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<style>
.nav-link {
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<ul class="nav nav-tabs">
<li class="nav-item">
<div class="nav-link"id="search-link">Search</div>
</li>
</ul>
<div id="app"></div>
<!-- Content here -->
</div>
<!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
<script>
var data;
function loadView(options){
var id = typeof options.id === "undefined" ? "app" : options.id;
var cb = typeof options.callback === "undefined" ? function(){} : options.callback;
google.script.run.withSuccessHandler(function(html){
document.getElementById("app").innerHTML = html;
typeof options.params === "undefined" ? cb() : cb(options.params);
})[options.func]();
}
function setDataForSearch(){
google.script.run.withSuccessHandler(function(dataReturned){
data = dataReturned.slice();
}).getDataForSearch();
}
function search(){
var searchinput = document.getElementById("searchinput").value.toString().toLowerCase().trim();
var searchWords = searchinput.split(/\s+/);
var searchColumns = [0,1,2,3,4,5,6,7];
// and or
var resultsArray = data.filter(function(r){
return searchWords.every(function(word){
return searchColumns.some(function(colIndex){
return r[colIndex].toString().toLowerCase().indexOf(word) !== -1
});
});
});
var searchResultsBox = document.getElementById("searchResults");
var templateBox = document.getElementById("rowTemplate");
var template = templateBox.content;
searchResultsBox.innerHTML = "";
resultsArray.forEach(function(r){
var tr = template.cloneNode(true);
var hinmokuColumn = tr.querySelector(".hinmoku");
var buhinCodeuColumn = tr.querySelector(".buhinCode");
var buhinNameColumn = tr.querySelector(".buhinName");
var hitsuyoColumn = tr.querySelector(".hitsuyo");
var genkaColumn = tr.querySelector(".genka");
var kobaiColumn = tr.querySelector(".kobai");
var sagakuColumn = tr.querySelector(".sagaku");
var kenshoColumn = tr.querySelector(".kensho");
hinmokuColumn.textContent = r[0];
buhinCodeuColumn.textContent = r[1];
buhinNameColumn.textContent = r[2];
hitsuyoColumn.textContent = r[3];
genkaColumn.textContent = r[4];
kobaiColumn.textContent = r[5];
sagakuColumn.textContent = r[6];
kenshoColumn.textContent = r[7];
searchResultsBox.appendChild(tr);
});
}
function loadSearchView(){
loadView({func:"loadSearchView", callback: setDataForSearch});
}
window.addEventListener("load", loadSearchView);
function inputEventHandler(e){
if (e.target.matches("#searchinput")){
search();
}
}
document.getElementById("app").addEventListener("input",inputEventHandler);
document.getElementById("app").addEventListener("click",inputEventHandler);
</script>
</body>
</html>
server-side code
function getDataForSearch(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("TableData");
return ws.getRange(2, 1, ws.getLastRow(),8).getValues();
}
I need to know what modification needs to be done in the code?
I tried document.getElementById("app").addEventListener("load",inputEventHandler);
but it didn't work.
is there any other event listeners available that will load the search results (or data) (without taking any action on the site, i mean without clicking or typing in the search box)?
Thanks in advance.
Edit: loadsearchview function file code
function loadSearchView(){
return loadPartialHTML_("search");
}
You could use addEventListener with DOMContentLoaded to call a function when all the HTML is loaded and the DOM tree is built. For your particular situation, here's how I managed:
First I need to load data into data variable and call the loadSearchView() function when the page loads:
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", function () {
google.script.run.withSuccessHandler(function (r) {
data = r;
loadSearchView();
}).getDataForSearch();
});
} else {
google.script.run.withSuccessHandler(function (r) {
data = r;
loadSearchView();
}).getDataForSearch();
}
Then I need to load the search view, but instead of calling setDataForSearch, I implemented another function to call functions after this view is loaded. This might be useful if you want to call more than one function after the searchView loads. So basically the code would be like this:
function loadSearchView() {
loadView({ func: "loadSearchView", callback: afterSearchViewLoads });
}
function afterSearchViewLoads(){
loadDataWhenPageLoads();
}
function loadDataWhenPageLoads(){
var resultArray = data;
var searchResultsBox = document.getElementById("searchResults");
var templateBox = document.getElementById("rowTemplate");
var template = templateBox.content;
searchResultsBox.innerHTML = "";
resultsArray.forEach(function (r) {
var tr = template.cloneNode(true);
var hinmokuColumn = tr.querySelector(".hinmoku");
var buhinCodeuColumn = tr.querySelector(".buhinCode");
var buhinNameColumn = tr.querySelector(".buhinName");
var hitsuyoColumn = tr.querySelector(".hitsuyo");
var genkaColumn = tr.querySelector(".genka");
var kobaiColumn = tr.querySelector(".kobai");
var sagakuColumn = tr.querySelector(".sagaku");
var kenshoColumn = tr.querySelector(".kensho");
hinmokuColumn.textContent = r[0];
buhinCodeuColumn.textContent = r[1];
buhinNameColumn.textContent = r[2];
hitsuyoColumn.textContent = r[3];
genkaColumn.textContent = r[4];
kobaiColumn.textContent = r[5];
sagakuColumn.textContent = r[6];
kenshoColumn.textContent = r[7];
searchResultsBox.appendChild(tr);
});
}
Hope this can solve your problem!
AddEventListener when you click enter key in keyboard will help you. Link: EventListener Enter Key
Also addEventListener "change" will help you.
edit
If you want your data to load when page is loaded use one of those ways:
window.onload = function() {
Search();
} // way one
window.onload = Search(); //way two
<body onclick="Search()"> // way three
JS code
var response = document.querySelector('#name').value;
localStorage.getItem('li')
localStorage.setItem('li', response)
document.addEventListener("DOMContentLoaded", () => {
document.querySelector('#submit').disabled = true;
document.querySelector('#name').onkeyup = () => {
// checking whether the input bar is empty or not
if (document.querySelector('#name').value.length > 0)
document.querySelector('#submit').disabled = false;
else document.querySelector('#submit').disabled = true;
};
window.onload = () => {
document.querySelector('form').onsubmit = () => {
//Crearting a list item
const li = document.createElement('li');
li.innerHTML = localStorage.getItem('id')
//Appending it to the unordered list
document.querySelector('.unordered').append(li);
//Clear input feild
document.querySelector('#name').value = "";
document.querySelector('#submit').disabled = true;
//Stop form from submitting
return false;
};
};
});
HTML Code
{% extends "base.html" %}
{% block head %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<title>Creating new channel</title>
<link rel="stylesheet" href="{{url_for('static', filename = 'css/main.css')}}" />
<script src="{{url_for('static', filename = 'js/button.js')}}"></script>
{% endblock %}
{% block body %}
<img src="{{url_for('static', filename = 'images/Logo.png')}}">
<div class="form-div">
<form class="form-group">
<input type="text" id="name" class="form-control" placeholder="Create Channel" autocomplete="off" /><br />
<button type="submit" class="btn btn-success" id="submit">Create Channel</button>
</form>
<ol class="unordered"></ol>
</div>
{% endblock %}
</html>
I am trying to create a todo list and so, for storing the data permanently, even when the browser is shut, i am using local storage. But when i have used local storage in this it isn't working(when i refresh the page, all the contents is erased).In the console when i ran the query localstorage.getItem('li') and then localstorage.setItem('li', response) then it is showing the value entered by the user but is unable to store it permanently. So is my code wrong or there are any logical errors.
You're writing li.innerHTML = localStorage.getItem('id') inside document.querySelector('form').onsubmit. So this will be executed only when the form is submitted. To show it normally, you'll have to take it out of this function and put in in window.load.
Something like this:
window.onload = () => {
const li = document.createElement('li');
li.innerHTML = localStorage.getItem('id') ?
localStorage.getItem('id') : "";
document.querySelector('.unordered').append(li);
document.querySelector('form').onsubmit = () => {
//Crearting a list item
const li = document.createElement('li');
li.innerHTML = localStorage.getItem('id');
...
};
};
I am working on the tablet's display of a Pepper robot; I have a functional HTML index page comprising a list of questions—each question redirects to its respective HTML when clicked on—, 2 volume buttons and 2 other buttons—one that pops up an instruction image and the other one that closes the index page and gets back to the splash screen, which when clicked upon, reveals the index page. So far everything is working. The issue is that when I click a question—I get redirected to its HTML page, but then I get stuck there, as neither the 2 volume buttons nor the 2 other buttons work;
I made sure to include the following in each HTML page:
<script type="text/javascript" src="/libs/qimessaging/2/qimessaging.js"></script>
<script type="text/javascript" src="faq.js"></script>
I also reused the same JavaScript functions that worked for the index page.
I commented out some line:
btnPrevious.addEventListener('click', goToPreviousPage);
because I noticed it prevented the splash screen from disappearing when clicked on—i.e., the visibility attribute stays on visible instead of switching to hidden thus revealing the index page, but still, the 3 remaining buttons don't work anyway.
Here is my faq.js code:
/* global QiSession */
var serviceName = 'ADFAQ';
var volumeUpEvent = serviceName + '/VolumeUp';
var volumeDownEvent = serviceName + '/VolumeDown';
var volumeData = serviceName + '/Volume';
/* Clickable buttons */
var btnReturn = document.getElementById('return');
var btnHelp = document.getElementById('call_help');
var btnPrevious = document.getElementById('previous_page');
var btnVolUp = document.getElementById('volume-up');
var btnVolDown = document.getElementById('volume-down');
/* Help image and splash screen */
var helper = document.getElementById('helper');
var img = document.getElementById('click_on_me');
var memory;
var volume;
var audioDevice;
QiSession(connected, disconnected);
function connected (s) {
console.log('QiSession connected');
var questions = document.getElementById('questions');
/* Associating buttons to their respective functions */
btnHelp.addEventListener('click', showHelper);
btnReturn.addEventListener('click', closeQuestions);
//btnPrevious.addEventListener('click', goToPreviousPage);
btnVolUp.addEventListener('click', raiseVolume);
btnVolDown.addEventListener('click', lowerVolume);
img.addEventListener('click', loadQuestions);
questions.addEventListener('click', clickOnQuestion);
s.service('ALMemory').then(function (m) {
m.subscriber(serviceName + '/DialogEnded').then(function (subscriber) {
subscriber.signal.connect(hideQuestions);
});
m.subscriber(serviceName + '/Pepper').then(function (subscriber) {
subscriber.signal.connect(displayPepperHTML)
});
m.subscriber(serviceName + '/RaiseVolume').then(function (subscriber) {
subscriber.signal.connect(raiseVolume);
});
m.subscriber(serviceName + '/LowerVolume').then(function (subscriber) {
subscriber.signal.connect(lowerVolume);
});
memory = m;
});
s.service('ALAudioDevice').then(function (a) {
a.getOutputVolume().then(assignVolume);
audioDevice = a
});
}
function disconnected () {
console.log('QiSession disconnected');
}
function assignVolume(value){
volume = value;
}
function raiseVolume (event) {
var changed = 0;
if(volume < 100) {
volume = Math.min(volume + 5, 100);
audioDevice.setOutputVolume(volume);
changed = 1;
}
memory.insertData(volumeData, volume);
memory.raiseEvent(volumeUpEvent, changed);
}
function lowerVolume (event) {
var changed = 0;
if(volume > 30) {
volume = Math.max(volume - 5, 0);
audioDevice.setOutputVolume(volume);
changed = 1;
}
memory.insertData(volumeData, volume);
memory.raiseEvent(volumeDownEvent, changed);
}
function showHelper (event) {
if (btnHelp.innerHTML === '?') {
helper.style.opacity = '1';
helper.style.zIndex = '1';
btnHelp.innerHTML = '←';
} else {
helper.style.opacity = '0';
helper.style.zIndex = '-1';
btnHelp.innerHTML = '?';
}
btnHelp.blur();
}
function loadQuestions (event) {
memory.raiseEvent(serviceName + '/LoadQuestions', 1);
img.style.visibility = 'hidden';
}
function goToPreviousPage () {
window.location.href = "index.html";
}
function displayPepperHTML() {
window.location.href = "pepper.html";
}
function closeQuestions (event) {
if(location.href != "index.html")
{window.location.href = "index.html";}
memory.raiseEvent(serviceName + '/CloseQuestions', 1);
btnReturn.blur();
}
function hideQuestions (data) {
if (data !== 0) {
img.style.visibility = 'visible';
helper.style.opacity = '0';
btnHelp.innerHTML = '?';
}
}
function clickOnQuestion (event) {
memory.raiseEvent(serviceName + '/' + event.target.id, 1);
}
Here is my non-functioning pepper.html code:
<!DOCTYPE html>
<html lang="fr">
<head>
<title>Pepper</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=1280, user-scalable=no" />
<link type="text/css" rel="stylesheet" href="css/style.css" />
<link type="text/css" rel="stylesheet" href="css/faq.css" />
</head>
<body>
<header>
<h1>Bla bla bla</h1>
<span class="buttons">
<button id="previous_page" class="button-help"> ← </button>
<button id="return" class="button-return">X</button>
</span>
<div id="helper" class="pop-up">
<img src="img/interactionscreen_frf.png" alt="Bla bla bla">
</div>
</header>
<ul id="questions">
<p>
Bla bla bla
</p>
<div class="volume-part">
<div id="volume-up" class="Click-me">+</div>
<img src="img/speaker.png" alt="Bla bla bla" style="vertical-align: middle;">
<div id="volume-down" class="Click-me">-</div>
</div>
</ul>
<script type="text/javascript" src="/libs/qimessaging/2/qimessaging.js"></script>
<script type="text/javascript" src="faq.js"></script>
</body>
</html>
Thank you for your help.
I am expecting the pepper.html page to respond to both the volume and ← and X buttons, as the index.html should, since they use the exact same Javascript.
I was able to find some workaround: creating one JavaScript file for each HTML page, this is redundant and non-optimal I know, but at least it works.
This also made me realize that the commented-out line was blocking the program because the index.html page doesn't use the previous_page button, that's what led me to make a JS file for each HTML page.
If anybody has any other suggestions I am all ears.
Edit: I reduced the number of JS scripts to only 2. One for the index.html and the other for the identically-structured html pages of the other questions.
Everytime the extension refreshes it duplicates the entire feed.json. How do I prevent this and only add new items from feed.json (when that is updated) on top of the old ones? Also how do I only set the badgeText when new items have been added?
Here's what I got so far:
background.html
<html>
<head>
<script type="text/javascript">
var fetchFreq = 30000; // how often we fetch new items (30s)
var req; // request object
var unreadCount = 0; // how many unread items we have
var items; // all currently fetched items
getItems();
setInterval(getItems, fetchFreq);
function getItems() {
req = new XMLHttpRequest();
req.open('GET', 'http://siteurl.com/feed.json');
req.onload = processItems;
req.send();
}
function processItems() {
var res = JSON.parse(req.responseText);
unreadCount += res.length;
if (unreadCount > 0) {
chrome.browserAction.setBadgeBackgroundColor({
color: [255, 0, 0, 255]
});
chrome.browserAction.setBadgeText({text: '' + unreadCount});
}
items = res.concat(items);
}
</script>
</head>
</html>
popup.html
<html>
<head>
<link rel="stylesheet" href="popup.css" />
<script src="util.js"></script>
<script>
var bg; // background page
// timeline attributes
var timeline;
var template;
var link;
var image;
var author;
var content;
onload = setTimeout(init, 0); // workaround for http://crbug.com/24467
// initialize timeline template
function init() {
chrome.browserAction.setBadgeText({text: ''});
bg = chrome.extension.getBackgroundPage();
bg.unreadCount = 0;
timeline = document.getElementById('timeline');
template = xpath('//ol[#id="template"]/li', document);
link = xpath('//div[#class="thumbnail"]/a', template);
image = xpath('img', link);
author = xpath('//div[#class="text"]/a', template);
content = xpath('//div[#class="text"]/span', template);
update();
}
// update display
function update() {
var user;
var item;
for (var i in bg.items) {
user = bg.items[i];
// thumbnail
link.title = user.name;
link.href = openInNewTab(profileurl);
image.src = user.thumbnail;
image.alt = user.name;
// text
author.href = openInNewTab(profileurl);
author.innerHTML = user.name;
content.innerHTML = linkify(bg.items[i].profileurl);
// copy node and update
item = template.cloneNode(true);
timeline.appendChild(item);
}
}
</script>
</head>
<body>
<div id="body">
<div id="title">
<h2>Chrome Extension</h2>
</div>
<ol id="timeline" />
</div>
<ol id="template">
<li>
<div class="thumbnail">
<a>
<img />
</a>
</div>
<div class="text">
<a></a>
<span></span>
</div>
<div class="clear"></div>
</li>
</ol>
</body>
</html>
feed.json
{
"name":"John Doe",
"about":"I am me",
"thumbnail":"http://thumbnail.jpg",
"profileurl":"http://siteurl.com/profileurl.php"
}
Thanks in advance. The extension's purpose is to fetch new items from feed.json and show in the popup.html. Think of it like a feed reader for new twitter tweets.
I know it seems fine now, but having a single global req object is probably not as safe as having one for each request.
You don't seem to ever be clearing the items. Your popup and background should communicate. The background should hold the new and old feeds separately and when the popup shows them, should release them.
Consider, for example, holding the old items in an array, and the new ones in a separate array. And then when the popup shows the new feeds to the user it can call bg.clearItems() which will copy the new ones into the array of the old ones, and then on the next request the new items are put into the now-empty new items array.