I'm stuck on how to iterate to the next element based on the condition in a function. Once the user highlights the right word and the message well done gets displayed, it should move on to the next definition/word taken from the array onA. At the bottom, I've put a pseudo code, as I don't know how to access the result of the conditional statement from the function.
var onA = [
{t: "grooming", d: "an activity when someone builds an emotional connection with a child to gain their trust for the purposes of sexual abuse or exploitation."},
{t: "cyberbullying", d: "an activity that involves the use of ICT, particularly mobile phones and the internet, deliberately to upset, threaten and intimidate someone else."}
];
function getSelectionHandler(index) {
return function clickHandler() {
var txt = '';
var feedback = document.querySelector("#onA .feedback");
if (window.getSelection) {
txt = window.getSelection().toString();
} else if (document.selection) {
txt = document.selection.createRange().text;
}
// Display the selected text
document.querySelector("#onA .word").innerHTML = txt;
// Change the type of bootstrap alert depending on success
function feed(oldClass, newClass, message) {
feedback.classList.remove(oldClass);
feedback.classList.add(newClass);
feedback.innerHTML = message.bold();
}
// Check if the selected word is correct
if (txt === onA[index].t) {
feed("alert-warning", "alert-success", "Well done!");
} else {
feed("alert-success", "alert-warning", "Try again!");
}
};
}
var i = 0
while (i<onA.length) {
document.getElementById("onA").onclick = getSelectionHandler(i);
document.querySelector("#onA .def").innerHTML += onA[i].d;
if condition in the if statement above is true:
i++
}
Global variable can be used to record the current state. I just write it bear hand, you have to debug it if necessary.
function getSelectionHandler(){
var txt = '';
var feedback = document.querySelector("#onA .feedback");
if (window.getSelection) {
txt = window.getSelection().toString();
} else if (document.selection) {
txt = document.selection.createRange().text;
}
// Display the selected text
document.querySelector("#onA .word").innerHTML = txt;
// Change the type of bootstrap alert depending on success
function feed(oldClass, newClass, message) {
feedback.classList.remove(oldClass);
feedback.classList.add(newClass);
feedback.innerHTML = message.bold();
}
// Check if the selected word is correct
if (txt === onA[index].t) {
feed("alert-warning", "alert-success", "Well done!");
index++; //increase before showing next or checking end
if (checkEnded()){
//all end, show end msg
feed("alert-warning", "alert-success", "Finish!");
}else {
//show next
showNext();
}
} else {
feed("alert-success", "alert-warning", "Try again!");
}
}
function checkEnded(){
return index >= onA.length;
}
function showNext(){
document.querySelector("#onA .def").innerHTML += onA[index].d; //display next item
}
var index = 0; //global index for selecting from the array
document.getElementById("onA").onclick = function(){getSelectionHandler();} //register hanlder onc time only
document.querySelector("#onA .def").innerHTML += onA[index].d; //display first item
Related
I am trying forever to fix this code: i have a list and i am searching through the list to find students. Once i don't find a student, an error message should appear. At the moment i have a function who searches the student based on text match. I have an if statement inside the function. When the match is found show student and when not, hide all the students. I created a variable 'found' set to 'true' when the student is found. if this is false the message should be appended.
The problem is that both conditions are being executed it seems so if i put found as being false inside the second condition the error message will display every time.
At the moment i have another if which checks if found was false. the problem is it doesn't recognise that it is false...so confusing. Please see screenshot with the console where you can see that although the student is found, the second condition is executed each time... screenshot with the console - second condition is always executed
First condition doesn't execute unless it's true.
Please help as I am trying to investigate this forever and I asked lots of questions here around this issue but with no big results.
Thanks so much,
Alina
var ul = document.getElementsByClassName("student-list");
var li = document.getElementsByTagName("li");
//add search bar
$( ".page-header" ).append('<div class="student-search"></div>');
$( ".student-search" ).append('<input id="input-search" placeholder="Search for students..."/><button id="search">Search</button>');
// append to the .page the container div for the error message
$('.page').append('<div class="error"></div>');
// append to the error div a p with the error message if student is not found
var found = true;
//myFunction
function myFunction() {
var input = document.getElementById("input-search");
var filter = input.value.toUpperCase();
for (var i = 0; i < li.length; i+=1) {
var h = li[i].getElementsByTagName("h3")[0];
if (h.innerHTML.toUpperCase().indexOf(filter) != -1) {
li[i].style.display = "";
console.log('yey found it');
found = true;
} else {
li[i].style.display = "none";
console.log('condtion 2');
}
}
if (found===false) {
$('.error').append('<p>"student not found!"</p>');
}
$('.pagination').hide();
}
//myFunction end
$('#search').on('click', function(){
myFunction();
});
// when the input is empty return to page 1, empty the error div, show pagination,
$('#input-search').on('keyup', function() {
if($(this).val() === '') {
go_to_page(0);
$('.pagination').show();
}
});
I think the function is called more than once judging that 'condition 2' got logged 50 times , and the condition isn't satisfied every time,
To make sure that it doesn't reach the else statement even if the code entered the if statement edit the function to be like this:
function myFunction() {
var input = document.getElementById("input-search");
var filter = input.value.toUpperCase();
found = false
for (var i = 0; i < li.length; i+=1) {
var h = li[i].getElementsByTagName("h3")[0];
if (h.innerHTML.toUpperCase().indexOf(filter) != -1) {
li[i].style.display = "";
console.log('yey found it');
found = true;
} else {
li[i].style.display = "none";
console.log('condtion 2');
}
}
if (found===false) {
$('.error').append('<p>"student not found!"</p>');
}
$('.pagination').hide();
console.log('--------------------------------------');
}
That way you see how many times the function was being called
I'm trying to set a variation of this Javascript: How to detect if a word is highlighted , but I'd like to run the function getSelectedText only if the selected text matches the value of the h1 id
The code I set looks like:
function getSelectedText() {
var x = document.getElementById("titleProduct");
var text = "";
if (typeof window.getSelection === x) {
alert('hey');
text = window.getSelection().toString();
}
return text;
}
function doSomethingWithSelectedText() {
var selectedText = getSelectedText();
if (selectedText) {
document.getElementById("hiddenCTA").className = "visibleCTA";
}
}
var x = document.getElementById("titleProduct");
document.onmouseup = doSomethingWithSelectedText;
I included the alert('hey') inside that if loop to see that is running, just for testing but there is no evidence of it in my tests, nor I can see any errors in the console. The whole code is in http://codepen.io/malditojavi/pen/LWmRvp?editors=1010
In this case, the function should only run if the full string 'Title Of Your Product' is selected, not any other text within the HTML document.
Your if should be:
if (window.getSelection().toString() === x.textContent) {
But it seems your function could just return a boolean indicating if the expected text was matched. As you already know the text in that case, it suffices to return true or false. Here is how I would suggest writing it:
function isSelectedText(txt) {
return window.getSelection().toString().trim() === txt;
}
function doSomethingWhenTextSelected() {
if (isSelectedText(document.getElementById("titleProduct").textContent)) {
document.getElementById("hiddenCTA").className = "visibleCTA";
}
}
document.onmouseup = doSomethingWhenTextSelected;
.hiddenCTA { display: none }
.visibleCTA { display: block }
<h3 id="titleProduct">Title Of Your Product</h3>
hhhh
<div class="hiddenCTA" id="hiddenCTA">Hey, we do price match!</div>
So I am trying to create a button where when the button is pressed it creates a new div string as shown in the node.innerHtml part. Yet this code does not seem to work, and I am not sure why.
This is the html side
<input type = "button" value = "start" onclick="changeOne()">
<div id = "Checkifwon"> Answer </div>
This is the javascript side
function changeOne(){
var node=document.getElementById('Checkifwon');
if(value() ){ //calls if true or false given by the other function
node.innerHTML='<div id =Checkifwon > Sorry you died in one shot</div>';
}
else {
node.innerHTML='<div id =Checkifwon > you lived another day</div>';
}
}
function value(){
var feww = Math.floor(Math.random() *2);
if (feww === 0) {
return false;
}
else {
return true;
}
}
haven't run the code myself and this is not the best way, but try:
function changeOne() {
var node=document.getElementById('Checkifwon');
if(value()){
//calls if true or false given by the other function
node.innerHTML = 'Sorry you died in one shot';
} else {
node.innerHTML = 'you lived another day';
}
}
I'm trying to make the TAB key navigate on my dGrid. I have used as a base the solution found at Dgrid set focus on cell, but there are a couple of issues I'm running into which I couldn't solve so far.
Below you can find the block I'm using now; Not all columns have editors, so for I added a var do the element definition to select the next column instead of doing a right. I also added support for SHIFT+TAB to make backwards navigation possible. MT4.prje.grids[gridId]is the dGrid instance. There might be various on the page.
The grid is created with
MT4.prje.grids[gridId] = new (declare([OnDemandGrid, Keyboard, Selection, CellSelection]))(gridInfo, gridId);
where gridInfo has the column definitions and the store. The store is created as:
new Observable(new Memory({'data': {}, 'idProperty': 'id'}));
The editors are usually TextBox, NumberTextBox and Select dijit widgets, all set to autoSave.
aspect.after(MT4.prje.grids[gridId], "edit", function (promise, cellNode) {
if (promise === null) return;
promise.then(function (widget) {
if (!widget._editorKeypressHandle) {
widget._editorKeypressHandle = on(widget, "keypress", function (e) {
for (var rowId in MT4.prje.grids[gridId].selection) {
break;
}
for (var columnId in MT4.prje.grids[gridId].selection[rowId]) {
break;
}
if (e.charOrCode == keys.TAB) {
e.preventDefault();
var cellToEdit = null,
cellEdited = MT4.prje.grids[gridId].cell(rowId, columnId);
if (e.shiftKey) {
if (cellEdited.column.previousEditor === undefined) {
rowId = parseInt(rowId) - 1;
if (MT4.prje.grids[gridId].row(rowId).element !== null) {
for (var lastColumnId in MT4.prje.grids[gridId].columns) {}
cellToEdit = MT4.prje.grids[gridId].cell(rowId, lastColumnId);
}
} else {
cellToEdit = MT4.prje.grids[gridId].cell(rowId, cellEdited.column.previousEditor);
}
} else {
if (cellEdited.column.nextEditor === undefined) {
var firstColumnId = null;
rowId = parseInt(rowId) + 1;
if (MT4.prje.grids[gridId].row(rowId).element === null) {
var fields = {};
for (var cId in MT4.prje.grids[gridId].columns) {
if ((cId != 'excluir') && (firstColumnId === null)) {
firstColumnId = cId;
}
fields[cId] = '';
}
MT4.prje.addRowToGrid(gridId, fields);
} else {
for (var cId in MT4.prje.grids[gridId].columns) {
if (cId != 'excluir') {
firstColumnId = cId;
break;
}
}
}
cellToEdit = MT4.prje.grids[gridId].cell(rowId, firstColumnId);
} else {
cellToEdit = MT4.prje.grids[gridId].cell(rowId, cellEdited.column.nextEditor);
}
}
if (cellToEdit) {
MT4.prje.grids[gridId].deselect(cellEdited);
MT4.prje.grids[gridId].select(cellToEdit);
MT4.prje.grids[gridId].edit(cellToEdit);
}
}
});
}
});
});
Even ignoring the new line part, there are a couple of errors that happen. First of all, the editor barely pops into existence and them disappears, together with the selection. Sometimes when tabbing to an empty column, the editor will be filled with the values of the previous editor. Is there a way to do it more consistently?
What I'm figuring is that there is a race condition happening on the sharedEditor (they are set to editOn: focus). I tried wrapping the deselect/select on a dojo.on('blur') and emit it. But that doesn't get consistently correct with the dijit/form/Select widgets. Is there a better event that I can call for it?
I also tried changing the final block to:
if (cellToEdit) {
on(cellToEdit.element, 'focus', function(){
MT4.prje.grids[gridId].select(cellToEdit);
});
on(cellEdited.element, 'blur', function(){
MT4.prje.grids[gridId].deselect(cellEdited);
on.emit(cellToEdit.element, 'focus', {'bubble': true, 'cancelable': false});
});
on.emit(cellEdited.element, 'blur', {'bubble': true, 'cancelable': false});
}
But that gives two errors:
If I do make changes to a cell it does not go to the next editor. Does not even select it.
The first time I move from an empty cell to another empty cell it doesn't work either.
Anyone got any ideas?
This fix works on dgrid 0.3.11.
Add to your dgrid's postCreate.
postCreate: function() {
var that = this;
this.inherited(arguments);
this.on('dgrid-datachange', function(evt) {
that._selectedCell = that.cell(evt);
});
aspect.after(this, 'save', function(dfd) {
dfd.then(function() {
var nextCell = that.right(that.cell(that._selectedCell.row.id, that._selectedCell.column.id));
that.edit(nextCell);
// Bonus Fix. Workaround dgrid bug that blocks field text to be selected on focus.
nextCell.element.widget && nextCell.element.widget.textbox && nextCell.element.widget.textbox.select();
});
});
}
I want to create a Google Chrome extension that, among other things, will modify the chat text based on what is inputed. I will add a button next to the video, call, and add people buttons below the name, and when clicked will activate the modifications. I don't want to have to put any more scripts on the page than I have to, so I would like to be able to send the messages the way Gmail would be pressing "return" in the chat box. Also I want to to be able to show that both of the people chatting are using my extension by displaying text in the chat box just like the "This chat is off the record" text is, and possibly if both are using it add extra stuff to the chat. What I tried to do was make an imitation textarea and when the user 'sends' it, grab it and modify it, then insert it into the real one and send the new text. I can change the text but can't seem to send it...
Heres what I have so far, I enclosed everything in a setInterval to check if chat box exists and add appropriate stuff to it:
var chatBtnClone = setInterval(function() {
if ($("body").find(".nH .NG").length > 0) { //if chat is active
var clone = $("body").find(".nH .NG .NJ").first();
if (clone.children()[0].className.indexOf("chat") < 0) { //if already added my class
var clonned = clone.clone();
var clonnedChd = clonned.children().first();
clonnedChd.attr("title", "Start encrypted chat");
clonnedChd.on('click', function() {
console.log("clicked chatBtn!"); //make sure it works
var self = $(this);
if (self[0].className.indexOf("chatEncX") >= 0) { //toggle button pic
self.removeClass('chatEncX').addClass('chatEnc');
self.attr("title", "Stop encrypted chat");
} else {
self.removeClass('chatEnc').addClass('chatEncX');
self.attr("title", "Start encrypted chat");
}
});
clone.parent().prepend(clonned);
clonned.find('.NK').removeClass("NK-Y8").addClass("chatEncX");
}
var chatBoxs = $('body').find(".nn .AD");
var chatArea = chatBoxs.first().find(".nH textarea"); //get chat textareas
if (chatArea.length === 1) {
var clonChatArea = chatArea.first().clone();
clonChatArea.removeAttr("id");
chatArea.first().parent().append(clonChatArea);
// chatArea.first().hide();
var chatTextDiv = chatBoxs.first().find(".jp .nH .nH").first();
clonChatArea.focusin(function() {
chatTextDiv.removeClass("gv").addClass("f7");
});
clonChatArea.focusout(function() {
chatTextDiv.removeClass("f7").addClass("gv");
});
clonChatArea.on('keyup', function(event) {
var self = this;
//console.log(this.style.height); //make sure height it working
if (self.scrollHeight === 38) {
self.style.overflowY = "hidden";
self.style.height = "36px";
} else if (self.scrollHeight === 47) {
self.style.height = "54px";
} else if (self.scrollHeight === 62) {
self.style.height = "72px";
} else if (self.scrollHeight >= 77) {
self.style.height = "80px";
self.style.overflowY = "scroll";
}
if( event.keyCode === 13 && event.shiftKey ){
//regular, just insert a newline
} else if (event.keyCode === 13) {
//grab text and modify then reinsert into real textarea
var chatTxt = $(this).val();
var chatHidden = chatBoxs.first().find(".nH textarea").first();
var chatEncTxt = Crypto.AES.encrypt(chatTxt, "pass"); //modify text
//console.log(chatEncTxt);
chatHidden.val(chatEncTxt);
chatHidden.focus();
chatHidden.trigger({ type : 'keypress', which : 13 }); //try to imitate the return key and send (NOT WORKING!!!)
// $(this).focus();
}
});
}
}
},150);
This might be a bit late, but if anyone else is interested then I managed this by doing the following:
var e = new Event("keypress");
e.keyCode = e.which = 13;
// :mc is an example textarea id, but the OP has the code for finding that already
document.getElementById(':mc').dispatchEvent(e);