Problems with accessing DOM tree - google-chrome

I'm developing a simple Chrome extension, which should be able to retrieve a DOM nodes and modify them in the specific way. And this is what I'm stuck with.
There are two DOM queries (lets call the A and B) in a javascript file, that i inject in html-page. The first one (A) goes well, but the second one (B) always crushes. Even If I interchange the first (A) query and second one (B), everything will still work in the same way. Query (B) now works as it should in the first place, and A now does nothing.
spans = document.getElementsByTagName('span');
for(j =0 ;j<=divin.length; j++)
{
//Manipulations //Works just fine
}
paragraphs = document.getElementsByTagName('p');
for(j =0 ;j<=paragraphs.length; j++)
{
//Manipulations //Does nothing
}
And what we see here. The same code, but different position.
paragraphs = document.getElementsByTagName('p');
for(j =0 ;j<=paragraphs.length; j++)
{
//Manipulations //Works just fine
}
spans = document.getElementsByTagName('span');
for(j =0 ;j<=divin.length; j++)
{
//Manipulations //Does nothing
}
I tried every way of injecting this code, but result was always the same.

Seems like you're using divin.length instead of spans.length.

Related

Angular: Posting Data to a Table with a loop and giving a problem when posting the i of the loop into the table

Good day,
I am trying to get data into a table, with the tour_id and every single media_id (the station_id i am getting from somewhere else), the ordernumber is what is giving me a headache:
I am trying to get every station one number for every media i am posting.
For example:
station 1 has 2 medias
and station 2 has 3
then the odernumbers should be like this: 0, 0, 1, 1, 1
I am using the following Code at this moment:
for(var i = 0; i < this.currentStations.length; i++){
this.http.get("http://localhost:3000/mediasforstation/" + this.currentStations[i].id).subscribe((res) => {
medias = res;
for (var j = 0; j < medias.length; j++){
this.http.post("http://localhost:3000/posttourstations",
{"tour_id": id, "media_id": medias[j].id, "ordernumber": i}).subscribe(function(res) {
console.log(res);
}.bind(this));
}
});
}
Everything but the ordernumber works, however, the ordernumber always takes the number of stations involved, in our example above it would be 2.
How do I fix this?
Thank you very much for your help.
As I understand, you need to keep the index value. The type of variable i is var which is function scoped. Within outer loop, you are calling an API that returns some response, meanwhile the value of i is updated and for next index/counter, the API call has been sent. When you get response from API calls, you get the value of i where the outer loop has been called of.
In other words, you need to understand the difference between var and let. Your problem can be solved by replacing
for(var i=0;...)
with
for(let i=0;...)
Here's providing you the sample code.
//block scoped - retains value of i
for (let i=0;i<10;i++){
this.http.get('https://jsonplaceholder.typicode.com/users').subscribe(res=>{
for(var j=0;j<5;j++){
console.log(`i=>${i}`)
}
})
}
//function scoped - gets updated value of i
for (var i=0;i<10;i++){
http.get('https://jsonplaceholder.typicode.com/users').subscribe(res=>{
for(var j=0;j<5;j++){
console.log(`i=>${i}`)
}
})
}

one eventListener for different targets

I want to have only one event listener that work with 3 different buttons: btn1, btn2, btn3.
I know that "btn+i" doesn't exist and doesn't work. Theres any way to do this? Sorry, I'm a beginner...
for(var i:uint=1;i<4;i++){
btn+i.addEventListener(MouseEvent.CLICK, btnClicked);
}
You should be able to do this["btn" +i].
But you'd probably be better off stuffing them all into an array and accessing them that way. Then your code isn't so dependent on everything being named a certain way.
Something like this:
var buttons:Array = [btn1, btn2, btn3];
for(var i:int = 0; i < buttons.length; i++){
buttons[i].addEventListener(MouseEvent.CLICK, btnClicked);
}

IE8 select population performance issues - solutions needed

I have an application that is having issue when populating selects with over 100 items. This problem only occurs in IE8. I am using angularjs to do the population, but my research shows that this is a general problem with IE8. What solutions have others used to deal with this problem. We have over 40,000 users tied to IE8 for the foreseeable future (Fortune 200 company) so moving to another browser is not an option.
Some thoughts I had.
Create a series of option tags as a one long string in memory and replace the innerHTML of the . But running some people samples this does not appear to solve the issue.
Originally populating the select with a few and then adding the rest as the user scrolls down. I am not sure if this is possible, or how to implement this
I am sure others have run into this issue. Does anyone have some ideas?
Thanks,
Jerry
Another solution that preserves the original <select> is to set the <option> values after adding the options to the <select>.
Theory
Add the <option> elements to a document fragment.
Add the document fragment to the <select>.
Set the value for each <option>.
Practice
In practice we end up with a couple issues we have to work around to get this to work:
IE11 is very slow when setting the value for each individual <option>.
IE8 has selection bugs because it isn't properly doing a re-flow/layout on the <select>.
Result
To handle these what we really do is something like the following:
Add the <option> tags to a document fragment. Make sure to set the values so that step 3 is a no-op in IE11.
Add the document fragment to the <select>.
Set the value for each <option>. In IE8 this will set the values, in IE11 this is a no-op.
In a setTimeout add and remove a dummy <option>. This forces a re-flow.
Code
function setSelectOptions(select, options)
{
select.innerHTML = ''; // Blank the list.
// 1. Add the options to a document fragment.
var docFrag = document.createDocumentFragement();
for (var i = 0; i < options.length; i++)
{
var opt = document.createElement('option');
opt.text = options[i];
docFrag.appendChild(opt);
}
// 2. Add the document fragment to the select.
select.appendChild(docFrag);
// 3. Set the option values for IE8. This is a no-op in IE11.
for (i = 0; i < options.length; i++)
select.options[i].text = options[i];
// 4. Force a re-flow/layout to fix IE8 selection bugs.
window.setTimeout(function()
{
select.add(document.createElement('option'));
select.remove(select.options.length - 1);
}, 0);
}
The best solution seems to be to create the Select and it's options as a text string and add that string as the innerHTML of the containing tag such as a DIV. Below is some code.
<div id="selectHome" ></div>
In JS (from angular controller)
function insertSelect(divForSelect) {
var str = "<select id='myselect'>";
for (var i = 0; i < data.length; i++) {
str += '<option>' + data[i] + '</data>';
}
str += '</select>';
divForSelect.innnerHTML = str;
}
Note that inserting options into a existing Select is very slow (8,000 msecs for 2000 items). But, if the select and the options are inserted as a single string it is very fast (12 msec for 2000 items).

referring to textfields in for loop

I've looked up how I can do this and nothing seems to work.
Trying to use the i in the loop to refer to all my textfields and set them.
Suppose my textfields are named textField0, textField1, textfield2, etc.
Something like:
for(var i:int = 0; i < numberOfFields; i++)
{
parent.child.getChildByName("textField" + i).text = stringArray[i];
}
Any help would be much appreciated
Thanks
Let's assume your hierarchy looks like this
0: root:MainTimeline ¬
0: Background:Shape
1: textField1:TextField
2: textField2:TextField
3: myClip:MovieClip
4: textField3:TextField
We've got some "noise" in the list, so a straight-up iteration over all those might not be the best way. We could, and place an if statement that tests the name of the object, or its object type, or we could create a manual list of pointers to each of these TextFields. In that scenario, each textfield could hypothetically exist in any nested container. It depends on what you have set up.
In the example you gave above, you're referencing an object literally called "child", which would mean your hierarchy might look like this...
0: root:MainTimeline ¬
0: child:MovieClip ¬
0: textField1:TextField
1: textField2:TextField
2: textField3:TextField
1: myClip:MovieClip // <- assuming that this is the class your code is coming from
So, the logic you have is that we go up a level with an implicit this reference (this.parent == parent), and then down to our container named child, and iterate over its children (note: I suspect this is not the case, and part of the reason its failing).
Assuming the same hierarchy, I might rewrite it this way:
for (var i:int = 0; i < parent.child.numChildren; i++) {
var txt:TextField = parent.child.getChildAt(i);
txt.text = stringArray[i];
}

GWT wrap a table and manipulate contents programmatically

I have a well formatted HTML table (the HTML text is generated by a reporting tool) and I want to turn it into a "programmable" table in GWT.
I need to show that content as it is provided, but I also need to inspect the DOM, get the tables, and add ClickHandler's to the rows and cells.
I am able to do something similar with images:
Html html = new HTML(htmlText);
ImageElement domElement = getChildImageByTagAndId(html.getElement(), "img", "blah");
Image image = Image.wrap(domElement);
image.addClickHandler(...);
My question is: What is the correct way to do this with tables?
I could not find a wrap() method for <table>, <tr>, and <td> elements.
Note: this question was asked (and not answered) in the comments in the accepted answer here.
I am unaware of an easy way to wrap an existing Table with the sub tr and td elements.
Given the constraint that you are relying on a third party tool, I recommend trying to build a custom table parser which will parse the existing table, build a FlexTable, and then replace the existing table with the new FlexTable.
As ugly as this is, I am not sure there is a better way...
It may depend on how exactly the table is setup, but you may try playing around with something like the below example to go through the existing table and use the getNodeValue() to build the content of the FlexTable....
Element table = DOM.getElementById("someTableId");
int numTopNodes = table.getChildNodes().getLength();
for(int topNode = 0; topNode < numTopNodes; topNode++){
Node top = table.getChildNodes().getItem(topNode);
System.out.println("Top Node: "+top);
for(int subNode = 0; subNode < top.getChildCount(); subNode ++){
Node sub = top.getChildNodes().getItem(subNode);
System.out.println("Sub Node: "+sub);
for(int rows = 0; rows < sub.getChildCount(); rows ++){
Node row = sub.getChildNodes().getItem(rows);
System.out.println("Row: "+row);
for(int cells = 0; cells < row.getChildCount(); cells++ ){
Node cell = row.getChildNodes().getItem(cells);
System.out.println("CELL: "+cell.getNodeValue()); // use value to build to build a new FlexTable
}
}
}
}