I have made a list application using JavaScript. I want to be able to put in items and when I click the button grab the items or tasks randomly. I got it to grab the tasks randomly, but want it to end once its gone through the items added. Right now it just keeps randomly cycling through the list endlessly. What am I missing?
Here's the code:
var taskList = [];
var $ = function(id) {
return document.getElementById(id);
}
var listTasks = function() {
textList = "";
for (var i in taskList) {
textList += taskList[i] + "\n";
}
$("task_list").value = textList;
}
var addTask = function() {
taskList[taskList.length] = $("new_task").value;
$("new_task").value = "";
$("new_task").focus();
listTasks();
}
var showNextTask = function() {
if (taskList.length == 0) {
alert("No tasks in the list");
$("next_task").value = "";
} else {
$("next_task").value = taskList[Math.floor(Math.random() * taskList.length)];
taskList.shift(Math.value());
}
if (taskList.length == 0) {
alert("No tasks in the list");
$("next_task").value = "";
}
};
window.onload = function() {
$("add_task").onclick = addTask;
$("show_next_task").onclick = showNextTask;
$("new_task").focus();
}
Related
I am writing a tinymce custom plugin called Mergetable. which will merger two user selected table.
Problem statement:
TinyMce is not allowing to select two table , by using shift and mouse I can select content of the table. So I can't use tinmce.activeeditor.selection.getNode() method instead using tinmce.activeeditor.selection.getContent().
Form getcontent() method I am getting proper html of both table. After do some operation while setting content using tinmce.activeeditor.selection.setContent() both table merged properly but two more table with empty td created one in top and one in bottom . Please see below plugin code.
code:
(function () {
var mergeTable = (function () {
'use strict';
tinymce.PluginManager.add("mergeTable", function (editor, url) {
function Merge(){
var selectedhtml=editor.selection.getContent();
//using getContent() as getnode returning body node
var dv=document.createElement('div');
dv.innerHTML= selectedhtml;
var tableElements = dv.getElementsByTagName('TABLE');
if (tableElements.length == 2) {
var tableOne = tableElements[0];
var tableTwo = tableElements[1];
var tempTable = null;
var offsetLeft = tableOne.offsetLeft;
var offsetTop = tableOne.offsetTop;
var elem = tableElements[0];
if (tableOne.nodeName == "TABLE" && tableTwo.nodeName == "TABLE") {
for (var r = 0; r < tableTwo.rows.length; r++) {
var newTR = tableOne.insertRow(tableOne.rows.length);
for (var i = 0; i < tableTwo.rows[r].cells.length; i++) {
var newTD = newTR.insertCell()
newTD.innerHTML = tableTwo.rows[r].cells[i].innerHTML;
newTD.colSpan = tableTwo.rows[r].cells[i].colSpan;
newTD.rowSpan = tableTwo.rows[r].cells[i].rowSpan;
newTD.style.cssText = tableTwo.rows[r].cells[i].style.cssText;
if (tableOne.style.border != "") {
newTD.style.border = "1px dotted #BFBFBF"
}
}
}
tableTwo.remove();
console.log(dv.innerHTML);
editor.selection.setContent(dv.innerHTML);
editor.nodeChanged();
}
else {
alert("Please select two tables");
}
}
}
editor.ui.registry.addButton('mergeTable', {
text: "Merge Table",
onAction: function(){ Merge();}
});
});
}());
}());
I am able to fix my problem by using some work around . Instead use setContent() method. I have remove selected content and use insertContent().
Please find working code below.
(function () {
var mergeTable = (function () {
'use strict';
tinymce.PluginManager.add("mergeTable", function (editor, url) {
var cmd = function (command) {
return function () {
return editor.execCommand(command);
};
};
function Merge(){
var selectedhtml=editor.selection.getContent();
var dv=document.createElement('div');
dv.innerHTML= selectedhtml;
var tableElements = dv.getElementsByTagName('TABLE');
if (tableElements.length == 2) {
var tableOne = tableElements[0];
var tableTwo = tableElements[1];
var tempTable = null;
var tableOneMaxCell=0
var tabletwoMaxCell=0
var tempCellcount=0
var tableOneRowcount=tableOne.rows.length;
tableOne.querySelectorAll("tr").forEach(function(e){
tempCellcount= e.querySelectorAll("td").length ;
if(tempCellcount>tableOneMaxCell)
{
tableOneMaxCell=tempCellcount;
}
});
tableTwo.querySelectorAll("tr").forEach(function(e){
tempCellcount= e.querySelectorAll("td").length ;
if(tempCellcount>tabletwoMaxCell)
{
tabletwoMaxCell=tempCellcount;
}
});
if (tableOne.nodeName == "TABLE" && tableTwo.nodeName == "TABLE") {
for (var r = 0; r < tableTwo.rows.length; r++) {
var newTR = tableOne.insertRow(tableOne.rows.length);
for (var i = 0; i < tableTwo.rows[r].cells.length; i++) {
var newTD = newTR.insertCell()
newTD.innerHTML = tableTwo.rows[r].cells[i].innerHTML;
newTD.colSpan = tableTwo.rows[r].cells[i].colSpan;
newTD.rowSpan = tableTwo.rows[r].cells[i].rowSpan;
newTD.style.cssText = tableTwo.rows[r].cells[i].style.cssText;
if (tableOne.style.border != "") {
newTD.style.border = "1px dotted #BFBFBF"
}
if(i==tableTwo.rows[r].cells.length-1 && tableOneMaxCell>tabletwoMaxCell){
newTD.colSpan = tableTwo.rows[r].cells[i].colSpan + (tableOneMaxCell-tabletwoMaxCell);
}
}
}
for( var t1=0; t1<tableOneRowcount; t1++ ){
var celllen=tableOne.rows[t1].cells.length;
tableOne.rows[t1].cells[celllen-1].colSpan=tableOne.rows[t1].cells[celllen-1].colSpan+(tabletwoMaxCell-tableOneMaxCell)
}
tableTwo.remove();
// cmd('mceTableDelete');
// var selObj = editor.selection;
// var selstartRange = selObj.getStart();
// var selectendRange= selObj.getEnd();
// var selrng=selObj.getRng();
// console.log(selstartRange);
// console.log(selectendRange);
// editor.execCommand('mceTableDelete');
// selObj.removeAllRanges();
editor.selection.getSelectedBlocks().forEach(function(elm){
elm.remove();
});
// selObj.setRng(selrng,true);
editor.insertContent(dv.innerHTML);
editor.nodeChanged();
}
else {
editor.notificationManager.open({
text: 'Please select two table.',
type: 'error'
});
}
}
else {
editor.notificationManager.open({
text: 'Please select two table.',
type: 'error'
});
}
}
editor.ui.registry.addButton('mergeTable', {
text: "MergeTable",
onAction: function(){ Merge();}
});
});
}());
}());
So for some reason, the JavaScript that I'm using is not working on IE - There are errors which I will point out below. If someone knows anything else that I can try or knows how I can manipulate the code to make it more IE friendly, I'd really appreciate it.
Here are the steps that I've taken:
- Use https://babeljs.io/ to convert the whole page to ES2015.
- Added a polyfill script tag from https://polyfill.io/
Lots of code below (Whole general.js file which I've already converted using Babel (Please let me know if you want me to upload the original general.js file)):
Everything below rtd3Confirmation function is supposed to be:
for (var inputElement of rtd3ChangeClass) {
inputElement.addEventListener('change', rtd3Confirmation);
}
but that was before babel converted it.
"use strict";
// Form wrapper variables
var contactFormID = document.getElementById('contactForm');
var formWrapperSpecific = document.getElementById('form-wrapper-specific');
var formWrapperCertainSelection = document.getElementById('form-wrapper-certain-selection');
var formWrapperCertain = document.getElementById('form-wrapper-certain');
var formWrapperConfirm = document.getElementById('rtd3Confirm'); // Alert variables
var stateAlertID = document.getElementById('stateWarning');
var stateQuery = document.querySelector('#stateWarning b#stateName');
var resident = document.getElementById('resident');
var is_submitted = document.getElementsByClassName('is-submitted'); // Right to Know variables
var rtk5_selection = document.getElementById('rtk5');
var rtk5declaration = document.getElementById('rtk5Declaration'); // Right to Delete variables
var rtdChange = document.getElementById('rtd3');
var rtd3ChangeClass = document.querySelectorAll(".rtd3_change"); // Array for states
var states = []; // Once the DOM has loaded, call functions
document.addEventListener('DOMContentLoaded', function () {
formHandler();
residentAlert();
rtdCheckboxSelection();
rtd3Confirmation();
rtk5Declaration();
get_states();
}); // Show/hide form depending if state is included in array on dropdown selection
function formHandler() {
contactFormID.style.display = 'block';
if (resident == null) return;
if (!states.includes(resident.value)) contactFormID.style.display = 'none';
resident.addEventListener('change', formHandler);
} // Show/hide state alert for non-residents
function residentAlert() {
if (resident !== null) {
resident.addEventListener('change', function () {
// If value in states array is true, show the form
if (!states.includes(resident.value)) {
stateAlertID.style.display = 'block';
stateQuery.textContent = resident.options[resident.selectedIndex].text;
} else {
stateAlertID.style.display = 'none';
}
});
}
} // Show states dropdown depending on PHP variables
function get_states() {
var data_states = contactFormID.getAttribute('data-states').match(/\w{1,}/g);
data_states.forEach(function (state, i) {
return states[i] = state;
});
} // If RTK5 is selected, show declaration field and set required tag
function rtk5Declaration() {
if (!rtk5_selection.checked) {
formWrapperSpecific.style.display = 'none';
rtk5declaration.removeAttribute('required');
} else {
formWrapperSpecific.style.display = '';
rtk5declaration.setAttribute('required', 'required');
}
}
rtk5_selection.addEventListener('change', rtk5Declaration); // If RTD3 is selected, show/hide more checkboxes
function rtdCheckboxSelection() {
formWrapperCertain.style.display = rtdChange.checked ? '' : 'none';
document.querySelectorAll('[name="rtd[checked]"]').forEach(function (r) {
return r.addEventListener('change', rtdCheckboxSelection);
});
} // If at least one checkbox inside rtd3 is checked, show confirmation and make required
function rtd3Confirmation() {
if (document.querySelectorAll('.rtd3_change:checked').length) {
formWrapperCertainSelection.style.display = '';
formWrapperConfirm.required = true;
} else {
formWrapperCertainSelection.style.display = 'none';
formWrapperConfirm.required = false;
}
}
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = rtd3ChangeClass[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var inputElement = _step.value;
inputElement.addEventListener('change', rtd3Confirmation);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
I have a todo list where I want to show all todos, todos flagged false (on click) and todos flagged true (on click). Each item has (for now here) only a title and a button, which (when clicked) flaggs the item (true).
I couldnt really find anything online that helped me. Any help much appreciated!
I have created a codepen so you can (hopefully) easier see the problem.
https://codepen.io/helloocoding/pen/XEXJJN?editors=1010
How can I do the following:
1:
For all flagged items: When I click on the 'showFlagged' button I am being shown flagged items which is what I want. However, it should also show the newly added item too (without a page refresh). Here what I did was, calling the showNotFlagged function inside the function where I set flag to true. However, like this, when you click on the flag button (next to the added item), the whole list of showNotFlagged items is being shown.
How can I call the showFlagged function only if its already 'open', so add it to dom but not show it yet?
2:
For not flagged items:
when I add new item, its flagged automatically false. How can I add the newly added item 'show Not Flagged list' without adding it to the dom yet? I cant call the function where I append all not flagged items because I just want to add new items, but not to the DOM yet.
HTML:
<div>
<input id="title" />
<button type="submit" id="add">Add me</button>
</div>
<ul id="todoList"></ul>
<button type="submit" id="showFlagged">Show Flagged</button>
<button type="submit" id="showNotFlagged">Show not Flagged</button>
<ul id="flaggedTodos"></ul>
JS:
function Todo(title) {
this.title = title;
this.flag = false;
}
window.onload = init;
function init() {
//showAll();
var addButton = document.querySelector("#add");
addButton.onclick = addItem;
var flagedButton = document.querySelector("#showFlagged");
flagedButton.onclick = showFlaggedTodos;
var notFlagedButton = document.querySelector("#showNotFlagged");
notFlagedButton.onclick = showNotFlaggedTodos;
}
function showAll() {
var ul = document.getElementById("todoList");
var listFragment = document.createDocumentFragment();
var todos = JSON.parse(localStorage.getItem("todos")) || [];
todos.map(function(item) {
var li = create(item);
listFragment.appendChild(li);
})
ul.appendChild(listFragment);
}
function addItem() {
var title = document.querySelector("#title").value;
var todoItem = new Todo(title);
var ul = document.getElementById("todoList");
var li = create(todoItem);
ul.appendChild(li);
saveItem(todoItem)
}
function create(todoItem) {
var li = document.createElement("li");
var titleElem = document.createElement("li");
var title = document.createTextNode(todoItem.title);
titleElem.appendChild(title);
var button = document.createElement("button");
var buttonFlag = document.createTextNode("flag me");
button.appendChild(buttonFlag);
button.addEventListener("click", function(ev) {
isFlagged(todoItem, ev);
})
li.appendChild(titleElem);
li.appendChild(button);
return li;
}
function saveItem(todoItem) {
var todos = JSON.parse(localStorage.getItem("todos")) || [];
todos.push(todoItem);
localStorage.setItem("todos", JSON.stringify(todos));
}
function updateItem(todoItem) {
console.log("3", todoItem)
var todos = JSON.parse(localStorage.getItem("todos")) || [];
var updatedItem = todoItem;
todos.map(function(item, i) {
if (todoItem.title == item.title) {
todos.splice(i, 1);
todos.push(updatedItem);
}
})
localStorage.setItem("todos", JSON.stringify(todos));
}
function isFlagged(todoItem, ev) {
todoItem.flag = !todoItem.flag;
updateItem(todoItem);
showFlaggedTodos();
}
function showFlaggedTodos() {
console.log("called")
var ul = document.getElementById("flaggedTodos");
var listFragment = document.createDocumentFragment();
var todos = JSON.parse(localStorage.getItem("todos")) || [];
todos.map(function(item) {
if (todos.length > 0) {
if (item.flag) {
var li = create(item);
listFragment.appendChild(li);
} else {
console.log("no flagged items")
}
} else {
console.log("no items")
}
})
ul.appendChild(listFragment);
var flagedButton = document.querySelector("#showFlagged");
flagedButton.onclick = "";
}
function showNotFlaggedTodos() {
var ul = document.getElementById("flaggedTodos");
var listFragment = document.createDocumentFragment();
var todos = JSON.parse(localStorage.getItem("todos")) || [];
todos.map(function(item) {
if (todos.length > 0) {
if (!item.flag) {
var li = create(item);
listFragment.appendChild(li);
} else {
console.log("no not flagged items")
}
} else {
console.log("no items")
}
})
ul.appendChild(listFragment);
var notFlagedButton = document.querySelector("#showNotFlagged");
notFlagedButton.onclick = "";
}
Here is the page where I'm trying to display content. It's showing up blank. My application is a single page application, so most of the code is in the index.html file
verbPractice.html
<div>
<h1>Practice verbs here</h1>
<div class="row" ng-repeat="sentence in listOfSentences">
<div class="col-xs-12">
<p>{{sentence.first}} {{sentence.second}} {{sentence.third}}</p>
</div>
</div>
</div>
This page is linked to from another page called verbSelect.html. Here is the relevant code from that page
<div class="btn btn-primary" ui-sref="app.verbPractice" ng-click="storeInfo(); generateSentences()">Submit</div>
Both the above pages are under the same controller called verbController:
(function() {
'use strict';
angular.module('arabicApp')
.controller('verbController', ['$scope', 'verbFactory', 'pronounFactory', 'attachedFactory', function($scope, verbFactory, pronounFactory, attachedFactory){
//Gets verbs from server
$scope.verbArray = verbFactory.getVerbs().query(
function(response) {
$scope.verbArray = response;
}
);
//Gets pronouns from server
$scope.pronouns = pronounFactory.getPronouns().query(
function(response) {
$scope.pronouns = response;
}
);
$scope.attached = attachedFactory.getAttached().query(
function(response) {
$scope.attached = response;
}
);
//Stores the array of selected verbs
$scope.selectedVerbs = [];
$scope.numSelectedVerbs = 0;
//Searches theArray for name and returns its index. If not found, returns -1
$scope.searchArray = function(theArray, name) {
for (var i = 0; i < theArray.length; i++) {
if (theArray[i].name === name) {
return i;
}
}
return -1;
};
//Adds verbs to selected list
$scope.addToSelected = function(theVerb) {
var num = $scope.searchArray($scope.selectedVerbs, theVerb.name);
var divToChange = document.getElementById("verbSelect_"+theVerb.name);
if (num > -1) { //Found. Remeove it from selectedVerbs
$scope.selectedVerbs.splice(num, 1);
divToChange.className = divToChange.className.replace( /(?:^|\s)listItemActive(?!\S)/g , '' );
$scope.numSelectedVerbs = $scope.numSelectedVerbs - 1;
} else { //Not found. Add it in
$scope.selectedVerbs.push(theVerb);
divToChange.className += " listItemActive";
$scope.numSelectedVerbs = $scope.numSelectedVerbs + 1;
}
};
//Stores how many practice questions the user wants
$scope.howMany = 0;
//Stores what tense of verbs the user wants
$scope.verbTense = "Both";
//Stores what form the user wants
$scope.verbVoice = "Both";
//Include commands?
$scope.includeCommands = false;
//Sentense that will be generated
$scope.listOfSentences = [];
$scope.generateSentence = function(isCommand, theTense, theVoice) {
var sent = {"first": "", "second": "", "third": ""};
var attachedPicker = Math.floor(Math.random()*14);
var attachedToUse = $scope.attached[attachedPicker].attached;
var pronounPicker = Math.floor(Math.random()*14);
var pronounToUse = $scope.pronouns[pronounPicker].pronoun;
sent.first = pronounToUse;
var verbPicker = Math.floor(Math.random()*$scope.numSelectedVerbs);
var verbToUse = $scope.selectedVerbs[verbPicker][theTense][pronounToUse];
if (isCommand === true) {
sent.second = verbToUse;
} else {
if (theVoice === "Passive") {
if (theTense === "Past") { sent.second = "were"; }
else { sent.second = "are"; }
sent.third = verbToUse;
} else {
sent.second = verbToUse;
sent.third = attachedToUse;
}
}
return sent;
};
$scope.storeInfo = function() {
localStorage.setItem("howMany", $scope.howMany);
localStorage.setItem("verbTense", $scope.verbTense);
localStorage.setItem("verbVoice", $scope.verbVoice);
localStorage.setItem("includeCommands", $scope.includeCommands);
};
$scope.getStoredInfo = function() {
$scope.howMany = localStorage.getItem("howMany");
$scope.verbTense = localStorage.getItem("verbTense");
$scope.verbVoice = localStorage.getItem("verbVoice");
$scope.includeCommands = localStorage.getItem("includeCommands");
};
//Generates sentences using the variables from verbSelect
$scope.generateSentences = function() {
$scope.getStoredInfo();
var tensePicker;
var voicePicker;
var doCommand;
var rand;
for (var i = 0; i < $scope.howMany; i++) {
//Picks the verb tense
if ($scope.verbTense === "Both") {
rand = Math.floor(Math.random());
if (rand === 0) { tensePicker = "Past"; }
else { tensePicker = "Present"; }
} else {
tensePicker = $scope.verbTense;
}
//Picks the verb voice
if ($scope.verbVoice === "Both") {
rand = Math.floor(Math.random());
if (rand === 0) { voicePicker = "Active"; }
else { voicePicker = "Passive"; }
} else {
voicePicker = $scope.verbVoice;
}
//If the voice is passive, use past tense
if ($scope.verbVoice === "Passive") { tensePicker = "Past"; }
//Determines if the sentence will be a command sentence or not
if ($scope.includeCommands === true) {
rand = Math.floor(Math.random() * 6);
if (rand === 0) { doCommand = true; }
else { doCommand = false; }
} else {
doCommand = false;
}
var sentence = $scope.generateSentence(doCommand, tensePicker, voicePicker);
$scope.listOfSentences.push(sentence);
}
console.log($scope.listOfSentences);
};
}])
;
})();
The variables: howMany, verbTense, verbVoice, isCommand, are set on this verbSelect.html page using ng-model. Both the verbSelect.html page and verbPractice.html page are under the same controller.
Everything seems to be working fine. At the end of my generateSentences() function, I output $scope.listOfSentences to the log, and it shows up without any problems, the array is being populated just fine. However, in my verbPractice.html page, nothing is showing up except the <h1> heading. For some reason, even though the $scope.listOfSentences array is populated, ng-repeat doesn't seem to be looping. Does anyone have any idea why?
Sorry for the long post
Thanks for taking the time to read and answer this question!
what is wrong with this code I get an undefined error. my checkbox is not an array on front end it uses different names and I want user to select only one checkbox:
function select_item(index){
var choice_options = [];
choice_options['S'] = 'item_cb_S';
choice_options['T'] = 'item_cb_T';
choice_options['Z'] = 'item_cb_Z';
choice_options['D'] = 'item_cb_D';
choice_options['N'] = 'item_cb_N';
for (i in choice_options) {
var vl = choice_options[i];
if(vl.substring(8) == index) {
document.wizardform.choice_options[index].checked = true;
//alert("true");
}
else {
document.wizardform.vl.checked = false;
}
}
return true;
}
It's not so pretty but you could use eval......
function select_item(index){
var choice_options = [];
choice_options['S'] = 'item_cb_S';
choice_options['T'] = 'item_cb_T';
choice_options['Z'] = 'item_cb_Z';
choice_options['D'] = 'item_cb_D';
choice_options['N'] = 'item_cb_N';
for (i in choice_options) {
var vl = choice_options[i];
if(vl.substring(8) == index) {
eval("document.wizardform." + choice_options[index] + ".checked = true;");
//alert("true");
}
else {
document.wizardform.vl.checked = false;
}
}
return true;
}