I am trying to add a JS script file called chatfunction.js into my index.html in Blazor but it gives me an error that it cannot find a file. My CSS is linked correctly and the HTML and CSS both show up but it does not provide any of the JS functionality that I have implemented.
I am adding it at the bottom of my HTML in index.html like this:
....
<script src="_framework/blazor.webassembly.js"></script>
<script src="chatfunction.js"></script>
</body>
</html>
Here is my project structure
Now when I try compiling it gives me this error:
(JS) File 'C:/Users/darka/source/repos/chatproject/wwwroot/js/mysrc.js' not found.
I don't get why it can't find it and I am confused as to why it thinks my file is mysrc.js as there is no file like that in my project structure.
Any pointers how to fix this?
Here is the layout of my JS file
var botController = (function () {
})();
var uiController = (function () {
})();
var controller = (function (botCntr, uiCntr) {
var $chatCircle,
$chatBox,
$chatBoxClose,
$chatBoxWelcome,
$chatWraper,
$submitBtn,
$chatInput,
$msg;
/*toggle*/
function hideCircle(evt) {
evt.preventDefault();
$chatCircle.hide('scale');
$chatBox.show('scale');
$chatBoxWelcome.show('scale');
}
function chatBoxCl(evt) {
evt.preventDefault();
$chatCircle.show('scale');
$chatBox.hide('scale');
$chatBoxWelcome.hide('scale');
$chatWraper.hide('scale');
}
function chatOpenMessage(evt) {
evt.preventDefault();
$chatBoxWelcome.hide();
$chatWraper.show();
}
//generate messages on submit click
function submitMsg(evt) {
evt.preventDefault();
//1. get input message data
msg = $chatSubmitBtn.val();
//2.if there is no string button send shoudn't work
if (msg.trim() == '') {
return false;
}
//3. add message to bot controller
callbot(msg);
//4. display message to ui controller
generate_message(msg, 'self');
}
function chatSbmBtn(evt) {
if (evt.keyCode === 13 || evt.which === 13) {
console.log("btn pushed");
}
}
/* var input = uiCntr.getInput();*/
/* $chatSubmitBtn.on("click", hideCircle);*/
function init() {
$chatCircle = $("#chat-circle");
$chatBox = $(".chat-box");
$chatBoxClose = $(".chat-box-toggle");
$chatBoxWelcome = $(".chat-box-welcome__header");
$chatWraper = $("#chat-box__wraper");
$chatInput = $("#chat-input__text");
$submitBtn = $("#chat-submit");
//1. call toggle
$chatCircle.on("click", hideCircle);
$chatBoxClose.on("click", chatBoxCl);
$chatInput.on("click", chatOpenMessage);
//2. call wait message from CRM-human
$submitBtn.on("click", chatSbmBtn);
$chatInput.on("keypress", chatSbmBtn);
//6. get message from bot controller-back end
//7. display bot message to ui controller
}
return {
init: init
};
})(botController, uiController);
$('.chat-input__form').on('submit', function (e) {
e.preventDefault();
msg = $('.chat-input__text').val();
$('.chat-logs').append('<div id="cm-msg-0" class="chat-msg background-warning push-right bot"><div class="cm-msg-text">' + msg + '</div><span class="msg-avatar"><img class="chat-box-overlay_robot" src="https://www.meetsource.com//userStyles/images/user.png"></span></div>');
$('.chat-input__text').val('');
});
$(document).ready(controller.init);
function talk() {
var user = document.getElementById("userBox").value;
document.getElementById("userBox").value = "";
document.getElementById("chatLog").innerHTML += user + "<br>";
}
I think your script line needs to be:
<script src="js/chatfunction.js"></script>
Suppose, I have following array of objects successfully sent to handlebars file from my express server:
[
{
"name": "Jon",
"isPositive": true
},
{
"name": "Cercei",
"isPositive": false
}
]
Each time when my button gets clicked, I want to show next element of the array on my view. Is it possible with handlebars? Or do I need something more complex like Vue.js to solve this problem? Here is simple pseudocode I would like to achieve:
<head>
<script>
$(document).ready(() => {
var index = 0;
var currentCharacter = getCurrentCharacter();
start();
});
</script>
</head>
<body>
<h3 id="name"></h3>
<p id="someInfo"> </p>
<button onclick="next()">Next</button>
<script>
function getCurrentCharacter() {
/// somehow access array of objects sent from server
var myCharacters = {{characters}}; // {} used because of handlebars
var character = myCharacters[index];
index += 1;
return character;
}
function start() {
document.getElementById("name").textContent = currentCharacter.name;
/// as you see here, I change my UI based on current object fields/attributes
if (currentCharacter.isPositive) {
document.getElementById("someInfo").style.display = "block";
document.getElementById("someInfo").textContent = "Some text here";
} else {
document.getElementById("someInfo").style.visibility = "hidden";
}
}
function next() {
currentCharacter = getCurrentCharacter();
start();
}
</script>
</body>
Is it possible to have such a logic with handlebars or other templating languages? If they are not build for these purposes, please recommend me another way to solve this problem.
I have an wordpress website which I have to translate to english and spanish. I have created a toggle button to change the content language by setting each language link to a page with different content (i know that is probably dumb) but I just cannot change the language of the sidebars, header and footer. How do I solve this? What can I do so I just have my whole page translated when clicking the button?
Unfortunately I just cannot use any plug-ins, I have to do it completely manually.
to directly change page link to english and spanish mains pages use <base> tag ( see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base )
for texts just add / remove a noDisplay class as appropriate
to keep Language selection for Every page and next connection use LocalStorage -> https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
sample code (I use it in a closure Object)
this is just a start code, you have to complete it for your own app
const LangChooser = (function()
{
const cLangElm = document.querySelectorAll('.cLang')
, langList = ['EN', 'SP'] // english or spanish pages pages
, defLang = 'EN'
, obj_ret = {}
, MemoLang = 'LangChoosed' // name value in local storage
;
let idxLang = langList.indexOf(defLang)
;
function LangdSet(lang)
{
localStorage.setItem(MemoLang, lang )
;
cLangElm.forEach(Elm=>
{
if (Elm.classList.contains(lang))
{ Elm.classList.remove('noDisplay')}
else
{ Elm.classList.add('noDisplay')}
})
}
obj_ret.LangInit = function()
{
let currentLang = localStorage.getItem(MemoLang)
;
if (!currentLang)
{
currentLang = defLang
}
idxLang = langList.indexOf(currentLang)
LangdSet(currentLang)
}
obj_ret.setLang = function(lang)
{
let idx = langList.indexOf(lang)
if (idx<0)
{
throw `${lang} language doesn't exist here !`;
}
idxLang = idx;
LangdSet(lang)
}
obj_ret.toogleNextLang = function()
{
idxLang = ++idxLang %2
LangdSet(langList[idxLang] )
}
obj_ret.getLang = function()
{
return langList[idxLang]
}
return obj_ret
})()
;
function configurePageLang()
{
let currentLang = LangChooser.getLang()
// change bage..
direction.textContent =' base = ' + currentLang
pageLink.href = currentLang + '/'
}
//on load...
LangChooser.LangInit()
configurePageLang()
btLang.onclick=()=>
{
LangChooser.toogleNextLang()
configurePageLang()
}
.noDisplay { display:none }
<base id="pageLink" href="EN/">
<p id="direction"> base = EN </p>
<button id="btLang"> page EN / SP </button>
<p>
a link to page 2
<!-- go to EN/Page2.html or SP/Page2.html -->
</p>
<p class="cLang EN"> This is text in English </p>
<p class="cLang SP noDisplay"> Este es texto en español </p>
I have made an offline web application:
<!DOCTYPE html>
<html dir="rtl">
<head>
<meta charset="utf-8">
<style><!-- some style here --></style>
<script>
var rqid = location.hash.replace('#','');
var js = Math.ceil(rqid / 100);
var id = rqid - ((js - 1) * 100) - 1;
var tg = document.createElement('script')
tg.src = js + '.js'
tg.type = 'text/javascript'
document.head.appendChild(tg);
window.onload = function load() {
var body='<h1>' + title[id] + '</h1> <article>' + content[id] + '</article>';
document.getElementById("body").innerHTML = body;}
</script>
</head>
<body id='body'>
</body>
</html>
The above is the simplified article.html file, which shows articles stored inside external .js files, each with two variables.
1.js contains
title = ['title of article1','title of article2',...,'title of article100'];
content = ['content of article1','content of article2',...,'content of article100'];
2.js contains
title = ['title of article101','title of article102',...,'title of article200'];
content = ['content of article101','content of article102',...,'content of article200'];
For example, article.html#1 loads 1.js into the html, and then shows article1, and article.html#101 loads 2.js and shows article101.
It works fine, but there's a problem with the search engine I have written for this application. The search engine code is quite bulky. Sharing it here will not be possible.
The problem is the identical variables in the .js files, which are overridden one after one.
<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
So, search is done only in 3.js.
The question is: Is it possible to dynamically join title/content arrays in those .js files and have a unified title/content variable like the following, so the search can be performed in all articles?
title = ['title of article1',...,'title of article200'];
content = ['content of article1',...,'content of article200'];
If it is not possible, simply say no but please do not recommend to restructure the stored data.
I would add that the speed/performance is not a problem, in case it is going to be slow.
Here is a simple example of how you could do this without having to restructure your 1.js, 2.js..
For the purpose of this example I've created a pretend fetch, that can get 1.js, & 2.js, if you have any real URL's to test, we should be able to replace the fetch mock with a real one.
const pretenddata = {
"1.js":
`title = ['title of article1','title of article2','title of article100'];
content = ['content of article1','content of article2','content of article100']`,
"2.js": `title = ['title of article101','title of article102','title of article200'];
content = ['content of article101','content of article102','content of article200'];`
};
//lets create a pretend fetch..
function fetch(url) {
function astext() {
return new Promise((resolve) => {
resolve(pretenddata[url]);
});
}
return new Promise((resolve) => {
resolve({text: astext});
});
}
async function test() {
var combined_title = [];
var combined_content = [];
async function getData(url) {
const r = await(await fetch(url)).text();
var d = new Function(`${r}; return [title, content]`)();
combined_title = combined_title.concat(d[0]);
combined_content = combined_content.concat(d[1]);
}
await Promise.all([
getData("1.js"),
getData("2.js")
]);
console.log(combined_title);
console.log(combined_content);
}
test();
When working with globals across multiple files, it is always a good idea to use some kind of globals structure, that way it is much more explicit as to the fact that the data is, in fact, global, and it makes it much less likely to cause issues with scope pollution.
In your case, you can create a basic object called "globals", which will have a title and content property, just like you were with your global variables. In fact, those actually go on the window object by default, so it works exactly the same - just instead of saying window.title, you can say globals.title, etc. The only difference being that the variables will never be accessed accidentally by default scoping.
window.globals = {};
// file1
(function () {
var title = ['title of article1','title of article2','title of article100'];
var content = ['content of article1','content of article2','content of article100'];
globals.title = globals.title ? globals.title.concat(title) : title;
globals.content = globals.content ? globals.content.concat(content) : content;
})();
// file2
(function () {
var title = ['title of article101','title of article102','title of article200'];
var content = ['content of article101','content of article102','content of article200'];
globals.title = globals.title ? globals.title.concat(title) : title;
globals.content = globals.content ? globals.content.concat(content) : content;
})();
// file3
(function () {
var title = ['title of article201','title of article202','title of article300'];
var content = ['content of article201','content of article202','content of article300'];
globals.title = globals.title ? globals.title.concat(title) : title;
globals.content = globals.content ? globals.content.concat(content) : content;
})();
// final results
console.log(globals.title);
console.log(globals.content);
I have this form:
<form id="searchForm" class="search_field" method="get" action="">
...
...
</form>
Then this javascript:
var form = document.getElementById("searchForm");
form.doSearch1.onclick = searchPage;
form.doSearch2.onclick = searchPage;
form.showFeatureChoices.onclick = function( )
{
var cbs = form.featType;
for ( var c = 0; c < cbs.length; ++c )
{
cbs[c].checked = false;
}
document.getElementById("featuresDiv").style.display = "block";
}
function searchPage()
{
var form = document.getElementById("searchForm");
var searchText = form.searchBox.value.replace(/-/g,"");
form.searchBox.value = searchText;
if (searchText != "")
{
// collect features to search for:
var features = [ ];
var featTypes = form.featType;
for ( var f = 0; f < featTypes.length; ++f )
{
if ( featTypes[f].checked ) features.push( featTypes[f].value );
}
featureList = "'" + features.join("','") + "'";
searchMsg("Searching for '" + searchText + "' ...");
// startStatusUpdate(1000);
// findTask.execute(findParams, showResults);
var accord = dijit.byId("accordianContainer");
var resultsPane = dijit.byId("resultsPane");
accord.selectChild(resultsPane,true);
doSearch( searchText, featureList );
}
else
{
searchMsg("No search criteria entered, enter search text");
}
}
If I embed this code in same file as the <form..., it works fine.
If however, I have this js in another file and use as include file:
<script type="text/javascript" src="Views/JS/main.js"></script>
I get following error: "Object required" and it points to these lines:
form.doSearch1.onclick = searchPage;
form.doSearch2.onclick = searchPage;
Any ideas how to fix this?
Just a bit more info, the js code shown above in a file called main.js which is in a folder called JS and Js is in a folder called Views. The
Thanks a lot in advance
When you include the JavaScript code in the same page, where is it in relation to the form element? (Before or after it?) How about when you reference the external JavaScript file?
I'm guessing that in the former case the code is at the end of the file, while in the latter case the script reference tag is at the beginning?
If that's true then what's happening is this code is being executed before the DOM is ready:
var form = document.getElementById("searchForm");
form.doSearch1.onclick = searchPage;
form.doSearch2.onclick = searchPage;
If the form tag hasn't been rendered to the DOM yet then that first line won't find anything, and the subsequent lines will fail as a result. One approach is to put the script reference tags at the end, but that seems like a hack to me. Sometimes there are good reasons to keep them in the page header, not the least of which is cleaner management of the code in many cases. There are other ways to hold off on executing JavaScript code until the DOM is ready.