javascript id change onclick function - javascript

So I got a 3 x 3 table wich looks like this:
<table align=left width="896px" class="tableCategories">
<tr class="trCategories">
<td class="tdCategories"><input type="button" id="P11" onclick="clickE()" value="E" /></td>
<td class="tdCategories"><input type="button" id="P12" onclick="clickS()" value="S" /></td>
<td class="tdCategories"><input type="button" id="P13" onclick="clickB()" value="B" /></td>
....
I just want that if the user clicks on one of the nine boxes all of the boxes changes their background images and the box which was clicked changes itself to a back button which references to the first 9 images. Like a submenu getting opened if one of the boxes being clicked.
So I tried it in my way but it does not work very well. If I click on one of the boxes it triggers both actions which is connected via id. So my thought was to change the id to, but then I thought maybe there is a smarter way to do that. So I wrote my problem here :D
Edit:
The javascript part is looking like this for every of the functions:
function clickE()
{
document.getElementById("P11").value = "Zurück";
document.getElementById("P11").onclick = clickBack;
document.getElementById("P12").value = "Restaurant";
document.getElementById("P12").onclick =clickCategory("restaurant");
document.getElementById("P13").value = "Imbiss";
document.getElementById("P13").onclick =clickCategory("imbiss");
document.getElementById("P21").value = "Bäckerei";
document.getElementById("P21").onclick =clickCategory("baeckerei");
document.getElementById("P22").value = "Fast Food";
document.getElementById("P22").onclick =clickCategory("fast_food");
document.getElementById("P23").value = "Süßes";
document.getElementById("P23").onclick =clickCategory("suesses");
document.getElementById("P31").value = "Cafe";
document.getElementById("P31").onclick =clickCategory("cafe");
document.getElementById("P32").value = "Bar";
document.getElementById("P32").onclick =clickCategory("bar");
document.getElementById("P33").value = "Kneipe";
document.getElementById("P33").onclick =clickCategory("kneipe");
}
I try it first with the labels because I think it will work with images the same way.

Being unsure of the long term application, I may have a starting point. The initial script provided could get a bit unwieldy if you ever want to extend, so there is now a "defineElements" method that could be used to configure your elements. Please note that argument paramaters have been added to the onclick event in the html as well.
The "defineElements" function returns an associative array object (eg key/value pairs), with each key being named after the html element id. The value of each key is also an associative array that contains the element id (eid), label (lbl) and event (evnt).
Short story long... when you click a button, the label for each button is changed and the appropriate click handler is assigned. If you click the button labeled "Back", the default click handler is reassigned to all.
This would also be an excellent candidate for jQuery if that is available to you.
Hopefully this will get you moving in the right direction:
HTML
<table>
<tr class="trCategories">
<tr class="trCategories">
<td class="tdCategories"><input type="button" id="P11" onclick="clickE(this.id)" value="E" /></td>
<td class="tdCategories"><input type="button" id="P12" onclick="clickS(this.id)" value="S" /></td>
<td class="tdCategories"><input type="button" id="P13" onclick="clickB(this.id)" value="B" /></td>
</tr>
</table>
== And the Javascript
function clickE(id){
var elementDef = defineElements(id);
for(var key in elementDef){
var propObj = elementDef[key];
//console.log(propObj);
document.getElementById(propObj.eid).value = propObj.lbl;
if(id == undefined)
document.getElementById(propObj.eid).onclick = function(){ clickE(this.id);} //--reassign default event
else
document.getElementById(propObj.eid).onclick = propObj.evnt;
}
}
function defineElements(id){
var elementArr = ['P11','P12','P13']; //--add your element id's to this array to extend, and then add a case for each within switch below
var definitionObj = {};
for(var i = 0; i < elementArr.length; i++){
switch(elementArr[i].toUpperCase()){
case 'P11':
definitionObj[elementArr[i].toUpperCase()] = { eid:elementArr[i].toUpperCase(), lbl:'Zuruck', evnt: function(){ clickCategory.call(this, "whatever"); } };
break;
case 'P12':
definitionObj[elementArr[i].toUpperCase()] = { eid:elementArr[i].toUpperCase(), lbl:'Restaurant', evnt: function(){ clickCategory.call(this,"restaurant"); } };
break;
case 'P13':
definitionObj[elementArr[i].toUpperCase()] = { eid:elementArr[i].toUpperCase(), lbl:'Imbiss', evnt: function(){ clickCategory.call(this,"imbiss"); } };
break;
}
}
if(id != undefined){
definitionObj[id]['evnt'] = function(){ clickBack.call(this); } //--assign the clickback function to the selected element based on id paramater
definitionObj[id]['lbl'] = 'Back';
}
return definitionObj;
}
function clickCategory(cat){
alert(cat);
}
function clickBack(){
clickE();
}

Related

Modify HtmlHelper value when using JS clone.node

I have a table where a user inputs info for the DB. The 2 fields here are
"type" and "name". Type must be either "L" or "S", but it is depicted to user as "Large" or "Small".
Say the user needs a new row for more data. I have 2 buttons, "Large" and "Small", that
fire the same JS function to create a new row. I want the value from the button to be
input into the new row in the type column. How would I accomplish this?
I'd like to do this using the clone.node function somehow, but the HtmlHelpers are throwing me off as well.
<tr id=rowToClone>
<td style="width:30px">
#Html.DropDownList("manifests.Type",
new SelectList(new List<Object>
{
new { value = "L", text = "Large"},
new { value = "S", text = "Small"},
},
"value",
"text"
)
)
</td>
<td>
#Html.TextBox("manifests.Name")
</td>
</tr>
<input type="button" value="Add Large" id="btAddL" style="display: none; float:left" onclick="addRow('L')"/>
<input type="button" value="Add Small" id="btAddS" style="display: none; float: left" onclick="addRow('S')"/>
<script>
function addRow(type) {
document.getElementById("btAddL").style.display = "none";
document.getElementById("btAddS").style.display = "none";
var row = document.getElementById("rowToClone");
var table = document.getElementById("tableToClone");
var clone = row.cloneNode(true);
clone.style.display = "table-row";
/*clone.node.td.type = type;*/
table.appendChild(clone);
}
</script>
This answer is purely from the perspective of the JS, I'm not sure about those ASP.NET helpers at the top...
I think that what you want within the clone you're trying to reach for the <td> cell? is that right?
I imagine this is what you are thinking because you've commented out clone.node.td
Probably you need to find the <td> element itself
var td_element = clone.querySelectorAll('td:first-child')
td_element.type = type; // this line makes no sense as <td> elements do not have types so maybe the line above should select for a kind of an HTML element that has a type
If the thing you want to clone is pretty small it could be easy (and a good exercise) just to create new elements instead of the cloning.
https://javascript.info/searching-elements-dom#querySelectorAll
https://www.w3schools.com/tags/att_type.asp

Add event to change input value

I´m trying to create a function to change input value in the HTML script. HTML looks like this:
<tr>
<td>6500</td>
<td>
<input type="text" size="3" value="3"/>
</td>
</tr>
<tr>
<td>6500</td>
<td>
<input type="text" size="3" value="3"/>
</td>
</tr>
I want to create an event where the value updates depending on the userinput and change the value so that when I click the button it performs the calculation which Ive already written functions for. I am getting stuck, only thing I have is the cells where userinput is an option. I need to do simle plain js and not jquery.
function input() {
var table = document.getElementById("list");
var x = table.getElementsByTagName("input");
console.log(x);
}
Thanks in advance.
Not sure why I never replied with an answer after your follow up comment, and I know this is terribly late, but if this no longer helps you, it may still help others.
Using JavaScript:
var inputs = document.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener('input', function() {
this.setAttribute('value', this.value);
});
}
Using jQuery:
$(document).on('input', 'input', function() {this.setAttribute('value', this.value);});

What is a FORM's equivalent to DOM's getNextSibling?

I have a form, as follows:
<FORM name="form1">
<TABLE onkeypress="focusNextFormElement(event)">
<TR>
<TD><INPUT name="SomeObscureName"></TD><TD>Some data</TD>
</TR>
<TR>
<TD><INPUT name="ThisName"><span>Here's some obscure text.</span></TD><TD>Some data</TD>
</TR>
<TR>
<TD><INPUT name="someNameIdontKnow"></TD><TD>Some data</TD>
</TR>
</TABLE>
</FORM>
Is there a better, more efficient way to write this function? (Of course, this is a simplified example)
function focusNextFormElement(ev){
var el = ev.target;
var f = el.form;
var xx = f.elements.length - 1;
for(var x = 0; x < xx; x++){
if(f.elements[x] === el){
f.elements[x+1].focus();
}
}
}
There may be thousands of elements on this form, and I don't see it as particularly efficient to loop through them all each time the function runs.
Also, I could arbitrarily select an input with my mouse, so a tracking array may not be of much use.
I have no control of the generation of the page, as it's a greasemonkey script to help with automation of another page.
EDIT
Thanks to #Trincot and, from a broader point of view, #Oriol, the answer is found.
function nextFormSibling(el){
var elems = el.form.elements;
var idx = [].indexOf.call(elems, el);
return elems[idx+1] || el;
}
function previousFormSibling(el){
var elems = el.form.elements;
var idx = [].indexOf.call(elems, el);
return elems[idx-1] || el;
}
You could get the element's index calling indexOf() on the form's elements collection. Although this collection is not a native JavaScript array, you can use indexOf.call like this:
function nextFormElement(el) {
var f = el.form;
if (f) return f.elements[1+[].indexOf.call(f.elements, el)];
}
Here is a demo snippet using this function to move focus to the next element when a form element is clicked. This is obviously quite useless, but it shows that it works:
function nextFormElement(el) {
var f = el.form;
if (f) return f.elements[1+[].indexOf.call(f.elements, el)];
}
function focusNextFormElement(ev){
var el = nextFormElement(ev.target);
if (el) el.focus();
}
document.querySelector('form').onclick = focusNextFormElement;
<FORM name="form1">
<TABLE onkeypress="focusNextFormElement(event)">
<TR>
<TD><INPUT name="SomeObscureName"></TD><TD>Some data</TD>
</TR>
<TR>
<TD><INPUT name="ThisName"><span>Here's some obscure text.</span></TD><TD>Some data</TD>
</TR>
<TR>
<TD><INPUT name="someNameIdontKnow"></TD><TD>Some data</TD>
</TR>
</TABLE>
</FORM>
Basically, no, without knowing the strusture of the DOM a priory, you need the index of the element in the elements collection in order to access the next one. And iterating it seems the only way, but consider using indexOf instead of doing it manually.
However, if you want to access the next element multiple times, you can do it only once and cache the result:
var nextFormElement = (function() {
var cache = new WeakMap();
return function(el) {
if(!cache.has(el)) {
var els = el.form.elements,
idx = [].indexOf.call(els, el);
cache.set(el, els[idx+1] || null);
}
return cache.get(el);
};
})();
If ES6 is not supported you can use a plain object instead of a weakmap, where the values are the next elements, and the keys are some identifiers which you can store in the elements as data-* attributes.
Then, use it like
var next = nextFormElement(event.target);
if(next) next.focus();
var nextFormElement = (function() {
var cache = new WeakMap();
return function(el) {
if(!cache.has(el)) {
var els = el.form.elements,
idx = [].indexOf.call(els, el);
cache.set(el, els[idx+1] || null);
}
return cache.get(el);
};
})();
document.forms.form1.addEventListener('keypress', function(event) {
var next = nextFormElement(event.target);
if(next) next.focus();
});
<form name="form1">
<div>
<input name="SomeObscureName" />
<span>Some data</span>
</div>
<div>
<input name="ThisName" />
<span>Here's some obscure text.</span>
<span>Some data</span>
</div>
<div>
<input name="someNameIdontKnow" />
<span>Some data</span>
</div>
</form>
That said, this code is completely obtrusive, and I don't recommend it. If the user wants to focus the next text focusable field, he can use the tab key. If he doesn't want to change focus and you do it for him, it will be so annoying.
Assuming that the HTML strictily adeheres to your example you can try :
function focusNextFormElement (ev) {
// First find the tr element of this input...
var tr = ev.target.parentNode.parentNode; // find the tr node
// Advance to the next table row ...
tr = tr.nextElementSibling
// Then focus the input element in that row...
tr.querySelector ('input').focus ();
}
Could you elaborate as what are you planning to achieve? Do you want to keep shifting your Input Focus to Input Elements? If so, it's better you should use the 'tabindex' attribute.
Rer: http://www.wufoo.com/html5/attributes/27-tabindex.html
If not, then would like to know more about the problem.
Note: Your 'onkeypress' on 'TABLE' element has more problem because, for every key pressed in the input field, it immediately switches to next input field.

Trying to pass in an object as a parameter for an innerHTML function

I'm trying to fill out multiple table cell innerHTML with information based on a choice of several different objects. I currently have multiple functions, one for each choice:
<input onClick="firstChoice();" type="radio" id="first-choice">
<input onClick="secondChoice();" type="radio" id="second-choice">
<tr>
<td>A</td>
<td id="aCell">xx</td>
</tr>
<tr>
<td>B</td>
<td id="bCell">xx</td>
</tr>
<script>
function Foo(a, b) {
this.a = a;
this.b = b;
}
first = new Foo(42, 8);
second = new Foo(100, 4);
var aCell = document.getElementById("first-choice");
var bCell = document.getElementById("second-choice");
function firstChoice() {
aCell.innerHTML = first.a;
bCell.innerHTML = first.b;
}
function secondChoice() {
aCell.innerHTML = second.a;
bCell.innerHTML = second.b;
}
</script>
This is currently working, but I'm sure there must be a way of using a single function and passing in an object as a parameter instead of having a function for each object but I'm pretty inexperienced with javascript and can't seem to find an answer anywhere and trial and error has taken me hours. I'm looking for something maybe along the lines of:
function choice(choicePicked) {
aCell.innerHTML = choicePicked.a;
bCell.innerHTML = choicePicked.b;
}
Or maybe there's a completely different way of accomplishing the task - any help at all would be appreciated!
You're on the right track with:
function choice(choicePicked) {
aCell.innerHTML = choicePicked.a;
bCell.innerHTML = choicePicked.b;
}
You'll just need to change your event handlers like this:
<input onClick="choice(first);" type="radio" id="first-choice">
<input onClick="choice(second);" type="radio" id="second-choice">
This way, you're passing the desired objects to the choice function.

Get elements from Parent Row of checked checkboxes

I have the following row in a table.
<tr class="data_rows" ng-repeat='d in t2'>
<td class="tds"> <input class='checkBoxInput' type='checkbox' onchange='keepCount(this)'></td>
<td class="tds"><a href='perf?id={{d.ID}}'>{{d.ID}}</a></td>
<td class="tds">{{d.HostOS}}</td>
<td class="tds">{{d.BuildID}}</td>
<td class="tds">{{d.Description}}</td>
<td class="tds">{{d.User}}</td>
<td class="tds">{{d.StartTime}}</td>
<td class="tds">{{d.UniqueMeasure}}</td>
<td class="tds">{{d.TotalMeasure}}</td>
</tr>
Here's the HTML for button that will invoke the function to collect the ids from checked check boxes and store them.
<div id='compButtonDiv' align='center' style="display: none;">
<input id='cButton' type='button' value='compare selections' onclick='submitSelection()' style= "margin :0 auto" disabled>
</div>
The data is in t2 which consists of an array of length 15-20.
What i want to do is get the value of ID i.e, {{d.ID}} of the 2 checked check boxes so that i can store them in a variable and pass them as query parameters to URL using `location.href = url?param1&param2'
Here's the javascript:
function keepCount(obj){
debugger;
//var count=0;
if(obj.checked){
obj.classList.add("checked");
}else{
obj.classList.remove("checked");
}
var count = document.getElementsByClassName("checked").length;
var cBtn = document.getElementById('cButton');
//alert(count);
if(count == 2){
cBtn.disabled = false;
}
else if(count < 2){
cBtn.disabled= true;
}
else{
cBtn.disabled= true;
alert("Please Select two sets for comparison. You have selected: " + count);
}
}
function submitSelection(){
// what should be the code here??
location.href= "existingURL?a&b";
}
Now can someone please tell me how to get the id's?? I need to extract ID from the checkboxes that are checked(on the click of button whose code i've mentioned above'.
Thanks.
-Ely
Firstly when we use angularjs we tend to depend less and less on DOM manipulation.
For this reason, what you can do is to attach ngModel to the checkbox.
Like:
<input class='checkBoxInput' ng-model='d.isChecked' type='checkbox' onchange='keepCount(this)'>
What this does is, it attaches the variable (in your case the property of item in the list) to the check box. If it is checked it is true, if unchecked, initially it will be undefined, later on checking and then unchecking it will be false.
Now, when you submit, just loop over the original list in the function and check the values of d.isChecked (true/falsy values). Then you can add the necessary items in a separate list for submission.
The only concern is when checking the list on submission , check if(d.isChecked), so that it ignores the falsy values(false/undefined).

Categories