I have a page where you can invite teams. Clicking "Invite teams" makes a popup box appear showing a search input. The search-function is AJAX based. When a team is found through your search word(s), you'll have to click on the team whereupon the team will be showed in a "Invited-teams"-box.
It works in a way that when you "add" the team, a hidden input field is generated containing the team's ID as a value. The problem is that with my current code, it is possible to add the same team as many times as you wish. I should be possible to check, if the team can be found in the hidden-input-data. If it already exists, it should not be possible to add the sane team.
My current javascript-code can be found beneath here. Please notice that I have tried to make the code that checks the team, but it doesn't work.
function addTeam(tid) {
// Grab the input value
var teamName = document.getElementById(tid).innerHTML;
var teamID = document.getElementById(tid).id;
// If empty value
if(!teamName || !teamID) {
alert('An error occured.');
} else {
//Tried to do the "team-adlready-added"-test, but it doesn't work
var stored_teams = $t('#store-teams').getElementsByTagName('input');
for (var i = 0; i < stored_teams.length; i++) {
var stored_team = stored_teams[i];
if(stored_team.value == teamID) {
break;
var team_already_added = 1;
}
alert(team_already_added);
}
if((team_already_added) || team_already_added != 1) {
// Store the team's ID in hidden inputs
var store_team = document.createElement('input');
store_team.type = 'hidden';
store_team.value = teamID;
// Append it and attach the event (via onclick)
$t('#store-teams').appendChild(store_team);
// Create the teams with the value as innerHTML
var div = document.createElement('div');
div.className = 'team-to-invite';
div.innerHTML = teamName;
// Append it and attach the event (via onclick)
$t('#teams').appendChild(div);
}
div.onclick = removeTeam;
}
return false;
}
Thanks in advance.
I just want to give you a hint for a possible solution without html elements.
You can create a new functional object for team:
var Team = function (id, name) {
this.name = name;
this.id = id;
}
Create an array which will contain teams:
var TeamList = [];
Add you Teams:
TeamList.push(new Team(1, "Team 1"));
TeamList.push(new Team(2, "Team 2"));
TeamList.push(new Team(3, "Team 3"));
TeamList.push(new Team(4, "Team 4"));
Write a function which loops trough the list of teams and checks with the id if a team already exists:
function containsTeam(id) {
for (var i = 0; i < TeamList.length; i++) {
if (TeamList[i].id == id) {
return true;
}
}
return false;
}
Just check it:
containsTeam(1); //returns true
containsTeam(5); //returns false
Have a look at the jsFiddle DEMO and open the console to see the output.
EDIT: In addition, to remove an element you can write a function which looks pretty much the same as the containsTeam function. Just use array.splice instead of returning true:
function removeTeam(id) {
for (var i = 0; i < TeamList.length; i++) {
if (TeamList[i].id == id) {
TeamList.splice(i, 1);
}
}
}
And remove a team:
removeTeam(3);
Your variable scope is off.
You declare team already added in the wrong spot.
Declare it with team name and team id and it will get you in the right direction
Related
I've been dealing with this for some time. I've a list of sections in which the user checks some checkboxes and that is sent to the server via AJAX. However, since the user can return to previous sections, I'm using some objects of mine to store some things the user has done (if he/she already finished working in that section, which checkboxes checked, etc). I'm doing this to not overload the database and only send new requests to store information if the user effectively changes a previous checkbox, not if he just starts clicking "Save" randomly. I'm using objects to see the sections of the page, and storing the previous state of the checkboxes in a Map. Here's my "supervisor":
function Supervisor(id) {
this.id = id;
this.verif = null;
this.selections = new Map();
var children = $("#ContentPlaceHolder1_checkboxes_div_" + id).children().length;
for (var i = 0; i < children; i++) {
if (i % 2 == 0) {
var checkbox = $("#ContentPlaceHolder1_checkboxes_div_" + id).children()[i];
var idCheck = checkbox.id.split("_")[2];
this.selections.set(idCheck, false);
}
}
console.log("Length " + this.selections.size);
this.change = false;
}
The console.log gives me the expected output, so I assume my Map is created and initialized correctly. Since the session of the user can expire before he finishes his work, or he can close his browser by accident, I'm storing this object using local storage, so I can change the page accordingly to what he has done should anything happen. Here are my functions:
function setObj(id, supervisor) {
localStorage.setItem(id, JSON.stringify(supervisor));
}
function getObj(key) {
var supervisor = JSON.parse(localStorage.getItem(key));
return supervisor;
}
So, I'm trying to add to the record whenever an user clicks in a checkbox. And this is where the problem happens. Here's the function:
function checkboxClicked(idCbx) {
var idSection = $("#ContentPlaceHolder1_hdnActualField").val();
var supervisor = getObj(idSection);
console.log(typeof (supervisor)); //Returns object, everythings fine
console.log(typeof (supervisor.change)); //Returns boolean
supervisor.change = true;
var idCheck = idCbx.split("_")[2]; //I just want a part of the name
console.log(typeof(supervisor.selections)); //Prints object
console.log("Length " + supervisor.selections.size); //Undefined!
supervisor.selections.set(idCheck, true); //Error! Note: The true is just for testing purposes
setObj(idSection, supervisor);
}
What am I doing wrong? Thanks!
Please look at this example, I removed the jquery id discovery for clarity. You'll need to adapt this to meet your needs but it should get you mostly there.
const mapToJSON = (map) => [...map];
const mapFromJSON = (json) => new Map(json);
function Supervisor(id) {
this.id = id;
this.verif = null;
this.selections = new Map();
this.change = false;
this.selections.set('blah', 'hello');
}
Supervisor.from = function (data) {
const id = data.id;
const supervisor = new Supervisor(id);
supervisor.verif = data.verif;
supervisor.selections = new Map(data.selections);
return supervisor;
};
Supervisor.prototype.toJSON = function() {
return {
id: this.id,
verif: this.verif,
selections: mapToJSON(this.selections)
}
}
const expected = new Supervisor(1);
console.log(expected);
const json = JSON.stringify(expected);
const actual = Supervisor.from(JSON.parse(json));
console.log(actual);
If you cant use the spread operation in 'mapToJSON' you could loop and push.
const mapToJSON = (map) => {
const result = [];
for (let entry of map.entries()) {
result.push(entry);
}
return result;
}
Really the only thing id change is have the constructor do less, just accept values, assign with minimal fiddling, and have a factory query the dom and populate the constructor with values. Maybe something like fromDOM() or something. This will make Supervisor more flexible and easier to test.
function Supervisor(options) {
this.id = options.id;
this.verif = null;
this.selections = options.selections || new Map();
this.change = false;
}
Supervisor.fromDOM = function(id) {
const selections = new Map();
const children = $("#ContentPlaceHolder1_checkboxes_div_" + id).children();
for (var i = 0; i < children.length; i++) {
if (i % 2 == 0) {
var checkbox = children[i];
var idCheck = checkbox.id.split("_")[2];
selections.set(idCheck, false);
}
}
return new Supervisor({ id: id, selections: selections });
};
console.log(Supervisor.fromDOM(2));
You can keep going and have another method that tries to parse a Supervisor from localStorageand default to the dom based factory if the localStorage one returns null.
I have variables which:
display the result (result), and
reference the current node (thisNode).
What do I need to change in my code so that it would display the HTML class?
var thisNode = document.body.firstChild;
var result = document.getElementById("resultOfButton");
result.InnerHTML = thisNode.;
/* Here, in JS are there any ways like displaying the class name,
like nodeClass */
Please give recommendations for my code. There may be some errors. Thank you.
var thisNode = document.body.firstChild;
var result = document.getElementById("resultOfButton");
var block = false;
function buttonDown()
{
if(block == true)
{
thisNode = thisNode.parentElement.firstChild;
block = false;
}
thisNode = thisNode.nextSibling;
result.innerHTML = thisNode.nodeName;
if(thisNode == thisNode.parentNode.lastChild)
{
block = true
}
}
function buttonUp()
{
// not done now...
}
function buttonEnter()
{
thisNode = thisNode.firstChild;
result.innerHTML = thisNode.c;
}
function buttonBack()
{
// not done now...
}
I think you're asking for the className attribute. I copied your first sample and added some code so you can run it on this page. You'll get the second emoji replaced by the class name of the inserted element.
var thisNode = document.getElementById("thisNode"); // document.body.firstChild;
var result = document.getElementById("resultOfButton");
result.innerHTML = thisNode.className; /*Here, in JS are there any ways like displaying the class name, like nodeClass*/
<div id="thisNode" class="sample-class">🙂</div>
<div id="resultOfButton">🙃</div>
Quoting MDN:
"The className property of the Element interface gets and sets the value of the class attribute of the specified element."
I'm trying to turn an option from a select list into text to then use the text in a function that returns a message topic for Firebase. I have had to use a function to get the text out of the list correctly but I don't know how to then output the text from the function in the second function to be used for the messaging. I can console.log the text, but I don't know what to use to just output the text itself inside the message function. I may be confusing myself a little. Please note: There are const being declared that are being used later on so any comment of "Why are you declaring those consts" won't be helpful. I need to know what to put in the TWO ### WHAT GOES HERE ### blocks to make this work?
I have tried just using jquery's text() to simply output the data I want but that just brings back undefined every time. The only way I've been able to actually get the option text is to place it in a function, but I have to actually DO something with it and I'm not sure what function will give me my desired results.
Here is the code
const select = $("#schoolSelect");
selectedOption = function() {
### WHAT GOES HERE? ###($("#schoolSelect option:selected").text())
}
const stage2 = $("#stage2Div");
const stage3 = $("#stage3Div");
const popupClose = $("#popupClose");
const popup = $("#popup");
const selectedValues = getSelectValues(select);
// Alert Buttons Functions
// Stage 2 Button
// Sends Soft Lockdown to all devices subscribed
stage2.click(function() {
var select = $("#schoolSelect"),
selectedValues = getSelectValues(select);
if (selectedValues.length == 0) {
popup.addClass("show");
}
else if (selectedValues.length > 0) {
for (var i = 0; i < selectedValues.length; i++) {
var message = createSLMessage(
"/topics/" + ### WHAT GOES HERE? ###
)
sendMessage(message);
}
}
});
For reference, here is the jQuery that is creating the list
populateList = function() {
$.getJSON("/assets/JSON/schools.JSON", function(result) {
$.each(result, function(i){
var schools = result.schools;
var output = "";
for (var i = 0; i < schools.length; i++) {
output += "<option>" + schools[i].topic + "</option>";
}
$("#schoolSelect").html(output);
});
})
};
Here is the html of the table (though less important) for reference
<select
size="100"
multiple
id="schoolSelect"
class="school_select"
></select>
I would like the function selectedOption to actually output the text. If I place console.log where the ### WHAT GOES HERE ### tag is in the function selectedOption itself and then call the selectedOption() later, the console indeed logs the correct value from the select list. I am losing my mind a little because I know there has to be some simple way to do this I just can't seem to figure it out.
I'm new to reactjs and I am trying to not overwrite files that is already existed on reactjs. But I really don't know hot to declare if the files already existed.
I've already searched the data by using get props document/search.
This is where I add it on the api
creater(form) {
debugger
var name = form.something.length;
for (var i = 0; i < name; i++) {
form.State = 1;
if (form.Name already exist){
form.Name=(form.something[i] + "(1)");
this.props.poster('document/post', form);
}
}
}
Where are you storing the names? You need to store the already existing names somewhere and check if they exist before using the new ones.
Let's say you have an array storing all names. You could do something like this:
creater(form) {
const names = ['Peter', 'Ben', 'Alice', 'Robert'];
for (let i = 0; i < form.names.length; i++) { // Check each name in form and change if necessary
if (names.indexOf(form.names[i]) > -1) { // Already exists
form.names[i] = form.names[i]+'1';
}
}
this.props.poster('document/post', form);
}
basic JS question, please go easy on me I'm a newb :)
I pass 2 variables to the findRelatedRecords function which queries other related tables and assembles an Array of Objects, called data. Since findRelatedRecords has so many inner functions, I'm having a hard time getting the data Array out of the function.
As it currently is, I call showWin inside findRelatedRecords, but I'd like to change it so that I can get data Array directly out of findRelatedRecords, and not jump to showWin
function findRelatedRecords(features,evtObj){
//first relationship query to find related branches
var selFeat = features
var featObjId = selFeat[0].attributes.OBJECTID_1
var relatedBranch = new esri.tasks.RelationshipQuery();
relatedBranch.outFields = ["*"];
relatedBranch.relationshipId = 1; //fac -to- Branch
relatedBranch.objectIds = [featObjId];
facSel.queryRelatedFeatures(relatedBranch, function(relatedBranches) {
var branchFound = false;
if(relatedBranches.hasOwnProperty(featObjId) == true){
branchFound = true;
var branchSet = relatedBranches[featObjId]
var cmdBranch = dojo.map(branchSet.features, function(feature){
return feature.attributes;
})
}
//regardless of whether a branch is found or not, we have to run the cmdMain relationship query
//the parent is still fac, no advantage of the parent being branch since cmcMain query has to be run regardless
//fac - branch - cmdMain - cmdSub <--sometimes
//fac - cmdMain - cmdSub <-- sometimes
//second relationship query to find related cmdMains
var relatedQuery = new esri.tasks.RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0; //fac -to- cmdMain
relatedQuery.objectIds = [featObjId];
//rather then listen for "OnSelectionComplete" we are using the queryRelatedFeatures callback function
facSel.queryRelatedFeatures(relatedQuery, function(relatedRecords) {
var data = []
//if any cmdMain records were found, relatedRecords object will have a property = to the OBJECTID of the clicked feature
//i.e. if cmdMain records are found, true will be returned; and continue with finding cmdSub records
if(relatedRecords.hasOwnProperty(featObjId) == true){
var fset = relatedRecords[featObjId]
var cmdMain = dojo.map(fset.features, function(feature) {
return feature.attributes;
})
//we need to fill an array with the objectids of the returned cmdMain records
//the length of this list == total number of mainCmd records returned for the clicked facility
objs = []
for (var k in cmdMain){
var o = cmdMain[k];
objs.push(o.OBJECTID)
}
//third relationship query to find records related to cmdMain (cmdSub)
var subQuery = new esri.tasks.RelationshipQuery();
subQuery.outFields = ["*"];
subQuery.relationshipId = 2;
subQuery.objectIds = [objs]
subTbl.queryRelatedFeatures(subQuery, function (subRecords){
//subRecords is an object where each property is the objectid of a cmdMain record
//if a cmdRecord objectid is present in subRecords property, cmdMain has sub records
//we no longer need these objectids, so we'll remove them and put the array into cmdsub
var cmdSub = []
for (id in subRecords){
dojo.forEach(subRecords[id].features, function(rec){
cmdSub.push(rec.attributes)
})
}
var j = cmdSub.length;
var p;
var sub_key;
var obj;
if (branchFound == true){
var p1 = "branch";
obj1 = {};
obj1[p1] = [cmdBranch[0].Branches]
data.push(obj1)
}
for (var i=0, iLen = cmdMain.length; i<iLen; i++) {
p = cmdMain[i].ASGMT_Name
obj = {};
obj[p] = [];
sub_key = cmdMain[i].sub_key;
for (var j=0, jLen=cmdSub.length; j<jLen; j++) {
if (cmdSub[j].sub_key == sub_key) {
obj[p].push(cmdSub[j].Long_Name);
}
}
data.push(obj);
}
showWin(data,evtObj) <---this would go away
})
}
//no returned cmdRecords; cmdData not available
else{
p = "No Data Available"
obj = {}
obj[p] = []
data.push(obj)
}
showWin(data,evtObj) <--this would go away
})
})
}
I'd like to have access to data array simply by calling
function findRelatedRecords(feature,evt){
//code pasted above
}
function newfunct(){
var newData = findRelatedRecords(feature,evt)
console.log(newData)
}
is this possible?
thanks!
Edit
Little more explanation.....
I'm connecting an Object event Listener to a Function like so:
function b (input){
dojo.connect(obj, "onQueryRelatedFeaturesComplete", getData);
obj.queryRelatedFeatures(input);
console.log(arr) //<----this doesn't work
}
function getData(relatedFeatData){
var arr = [];
//populate arr
return arr;
}
So when obj.QueryRelatedFeatures() is complete, getData fires; this part works fine, but how to I access arr from function b ?
Post Edit Update:
Due to the way that this event is being hooked up you can't simple return data from it. Returning will just let Dojo call to the next method that is hooked up to onSelectionComplete.
When init runs it is long before findRelatedRecords will ever be executed/fired by the onSelectionComplete event of the well, which is why you were seeing undefined/null values. The only way to work with this sort of system is to either 1) call off to a method like you're already doing or 2) fire off a custom event/message (technically it's still just calling off to a method).
If you want to make this method easier to work with you should refactor/extract snippets of it to make it a smaller function but contained in many functions. Also, changing it to have only one exit point at the end of the findRelatedRecords method will help. The function defined inside of subTbl.queryRelatedFeatures() would be a great place to start.
Sorry, you're kind of limited by what Dojo gives you in this case.
Pre Edit Answer:
Just return your data out of it. Everywhere where there is a showWin call just use this return.
return {
data: data,
evtObj: evtObj
}
Then your newfunct would look like this.
function newfunct(){
var newData = findRelatedRecords(feature,evt);
console.log(newData);
console.log(newData.data);
console.log(newData.evtObj);
}
If you only need that "data" object, then change your return to just return data;.
Also, start using semicolons to terminate statements.