Reordering video tiles in Jitsi - working with DOM - javascript

I want to add a function to Jitsi that allows alphabetic ordering of video tiles via booklet function.
I used cketti's reorder.js as a basis since it works fine on my machine; however when I run my own script via console, the videos are not correctly shown (partly invisible) and audio breaks.
I am not very accostumed to JavaScript.
What am I doing wrong, what did I miss?
Alternatively: I do not really understand how to debug JS, how can I find out how I could reuse the reorder.js functions to correctly sort?
var container = $('#filmstripRemoteVideosContainer')[0];
var jChildren = $(container).children();
const numberOfVideos = jChildren.length;
var names = new Array();
//only applicable in tiles mode!
for(i=0; i<numberOfVideos; i++) {
names[i] = new Array (2);
names[i][0] = jChildren[i].getElementsByClassName("displayname")[0].innerHTML;
names[i][1] = jChildren[i];
}
//sort Array
names.sort((a, b) => a[0].localeCompare(b[0]))
//copy over to one-dimensional array
var newChildren = new Array();
for(i=0; i<numberOfVideos; i++) {
newChildren[i] = names[i][1];
}
//convert to NodeList
var toNodeList = function(arr){
var nodeList = document.createDocumentFragment();
arr.forEach(function(item){
nodeList.appendChild(item.cloneNode());
});
return nodeList.childNodes;
};
//Set new position
var remoteVideos = toNodeList(newChildren);
var videoTiles = $(remoteVideos).toArray()
// Set CSS 'order' properties to reflect current DOM order = display order
videoTiles.forEach(function(index) {
$(this).css('order', -numberOfVideos + index);
});
//remove all videoTiles
for(i=0; i<numberOfVideos;i++){
container.firstChild.remove()
}
// Add video tiles to DOM in sorted order (now the CSS 'order' property is used for the display order)
videoTiles.forEach(videoTile => container.appendChild(videoTile));
Edit: Here's the working code:
var container = $('#filmstripRemoteVideosContainer')[0];
var jChildren = $(container).children();
const numberOfVideos = jChildren.length;
var names = new Array();
//only applicable in tiles mode!
for(i = 0; i < numberOfVideos; i++){
names[i] = new Array (2);
names[i][0] = jChildren[i].getElementsByClassName("displayname")[0].innerHTML;
names[i][1] = jChildren[i];
}
//sort Array
names.sort((a, b) => a[0].localeCompare(b[0]))
//reorder the tiles
for(i=0;i<numberOfVideos; i++){
$(names[i][1]).css('order', i);
}

Looks like you're cloning the element nodes. Try reordering the existing ones by first removing them from the DOM, then adding them back in the desired order.

Related

Method push is not adding a value to a vector that previously had the same value

The goal of the code I'm going to present is to create a aux vector that will contain petri nets transitions, arcs and places. I'm dividing a petri net into several groups, each group is a transition with respective input arcs and places.
The issue is the following: After I put the info in the first position of the aux vector, I'm unable to put a place with the same id of the place of the previous group. For example, if I have a transition with place_id=1 and place_id=2, and the next transition have place_id=2 and place_id=3, the code doesn't write the value place_i=2 in the vector for the second group.
function conflict() {
var id = [];
var source = [];
var target = [];
var aux = [];
var cont = [];
var places = pnml.getElementsByTagName("place");
var arcs = pnml.getElementsByTagName("arc");
var transitions = pnml.getElementsByTagName("transition");
for (var i = 0; i < transitions.length; i++) {
target.push(transitions[i].getAttribute("id"));
aux.push([]);
for (var j = 0; j < arcs.length; j++) {
if (arcs[j].getAttribute("target") == transitions[i].getAttribute("id")) {
id.push(arcs[j].getAttribute("id"));
source.push(arcs[j].getAttribute("source"));
//console.log(arcs[j].getAttribute( "source" ));
}
}
//console.log(id);
//console.log(arcs);
//console.log(places);
aux[i].push(id, source, target);
//id.length=0;
target = [];
source = [];
id = [];
}
}
Image of the platform with console open
Thanks in advance
Without knowing a whole lot for the issue, try to change this
aux.push([]);
to this
aux[i]=[];
So that you initialize and fill using an index instead of a push and an index later, for consistency.
Let me know if it helps
EDIT:
Also this
aux[i].push(id, source, target);
to this (maybe? )
aux[i].push({ id: id, source:source, target:target});
You probably want to keep objects in aux, so you need to push an object, not 3 parameters like that

Putting an object into an array in JavaScript

I'm currently working with an MVC JS framework and I want to be able to get a list of objects that I can take a random entry out of on a loop. So far I've managed to create a function that finds a random ID and pulls out that object so that part is not a problem. It's what is going into the array of objects:
QuestionsSetup: function(gameType) {
// Setup Resources
var c = this.View.children;
var player1qs = [];
var leftQ = 0;
var rightQ = 0;
var maxQValue = 50;
var minQValue = 1;
// Fill array with questions
for (var i = 0; i < 5; i++) {
// Build a random question with numbers between 1 and 50
// Build Question Text to output to user
// Generate correct answers based on generated question
// Generate unsorted, incorrect answers and add them to an array
//Place Questions into object
questions.qId = i;
questions.leftQ = leftQ;
questions.rightQ = rightQ;
questions.correctAnswer = correctAnswer;
questions.allAnswers = sortedAnswers;
questions.questionText = questionText;
//Add to array of questions
player1qs.push(questions);
}
}
This does add them to an array but when adding a new object it also changes the values of the existing objects in the array so they all come out the same no matter which one I pull out later. The questions object is declared in it's own file in a models folder. Is there any way, at the start of each loop, to tell the application I want new empty questions object as opposed to referencing the existing ones? I know that you can in similar back end languguages so I refuse to beleive that something so simple doesn't exist in JavaScript too?
Declaring a variable for each array item is definitely missing.
QuestionsSetup: function(gameType) {
// Setup Resources
var c = this.View.children;
var player1qs = [];
var leftQ = 0;
var rightQ = 0;
var maxQValue = 50;
var minQValue = 1;
// Fill array with questions
for (var i = 0; i < 5; i++) {
var tempQuestion = {
qId: i,
leftQ: leftQ,
rightQ: rightQ,
correctAnswer: correctAnswer,
allAnswers: sortedAnswers,
questionText: questionText
}
// ...
//Add to array of questions
player1qs.push(tempQuestion);
}
}
Using a separate closure inside a loop also might be a good idea.
do this:
for (var i = 0; i < 5; i++) {
let questions = {};
// the rest....
you need to define the object first.
Maybe you should just initialize the questions object before initializing its properties, so the code should look like this:
//Place Questions into object
questions = {};
questions.qId = i;
questions.leftQ = leftQ;
questions.rightQ = rightQ;
questions.correctAnswer = correctAnswer;
questions.allAnswers = sortedAnswers;
questions.questionText = questionText;
//Add to array of questions
player1qs.push(questions);

How to dynamically add object to array (closure in loop)

I read couple posts about the closure in loop but still not really get it how to apply to my situation.
I have three feed urls defined in HTML and using JavaScript promise to return the response when it's ready without blocking the UI. I am able to get two blog entries data per feed url. Now, each returned blog entry has its published date and I would like to sort them from latest to oldest. However, I keep getting the last value when I pushed the object to array. I know this is something to do with closure and since I'm not familiar with closure, I have difficulty to solve this problem. Any help is great appreciated!
var itemArray = [];
var entryObj = {};
promise.then(function (response) {
var parser = new DOMParser();
xml = parser.parseFromString(response, "text/xml");
var items = xml.getElementsByTagName("item");
for (var x = 0; x < items.length && x < limits; x++) {
title = items[x].getElementsByTagName("title")[0].innerHTML;
link = items[x].getElementsByTagName("link")[0].innerHTML;
pubDate = items[x].getElementsByTagName("pubDate")[0].innerHTML;
creator = items[x].getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", "creator")[0].innerHTML;
entryObj.title = title;
entryObj.link = link;
entryObj.pubDate = pubDate;
entryObj.creator = creator;
itemArray.push(entryObj);
// output: all 6 objects contain last value
console.log(itemArray);
}
});
In short : Move the object creation inside the loop.
It's nothing to do with closure. The issue is, you are pushing the same object.
You need a new object to be pushed. So create the object inside the for loop. So that every time you get a new object and it gets pushed to the array.
Code-
var itemArray = [];
promise.then(function (response) {
var parser = new DOMParser();
xml = parser.parseFromString(response, "text/xml");
var items = xml.getElementsByTagName("item");
for (var x = 0; x < items.length && x < limits; x++) {
var entryObj = {};
title = items[x].getElementsByTagName("title")[0].innerHTML;
link = items[x].getElementsByTagName("link")[0].innerHTML;
pubDate = items[x].getElementsByTagName("pubDate")[0].innerHTML;
creator = items[x].getElementsByTagNameNS("http://purl.org/dc/elements/1.1/", "creator")[0].innerHTML;
entryObj.title = title;
entryObj.link = link;
entryObj.pubDate = pubDate;
entryObj.creator = creator;
itemArray.push(entryObj);
// output: Now all values are unique
console.log(itemArray);
}
});
Move var entryObj = {}; into your for loop.

Add marking to JSViz Visualization in Spotfire

I am stuck on an issue where I need to add marking to D3 VennDiagram Visualization in Spotfire, I tried adding below code but it fails to execute marking:
Hi Team,
I am not able to add marking to VennDiagram or any other JSViz samples provided by TIBCO for D3.
You can download the DXP file from : https://drive.google.com/folderview?id=0B7rSzsao8vgUUlEyc0hWUk13WmM
I am using the following code to add marking, but it fails:
function markModel(markMode, rectangle) {
if (svg) {
// No point in continuing if we don't have an svg object
// Start collecting indexes of svg objects marked.
var indicesToMark = [];
var markData = {};
markData.markMode = markMode;
svgElem = svg[0][0];
var rpos = svgElem.createSVGRect();
rpos.x = rectangle.x;
rpos.y = rectangle.y;
rpos.height = rectangle.height; // + one to get the item under the click
rpos.width = rectangle.width; // + one to get the item under the click
var elements = svgElem.getIntersectionList(rpos, svgElem);
for (var index = 0; index < elements.length; index = index + 1) {
if (elements[index].id) {
indicesToMark.push(elements[index].id);
}
}
markData.indexSet = indicesToMark;
markIndices ( markData );
}
Please let me know your thoughts on this

Dexie.js iterating a dynamic list

I am using dexie.js, which is an indexDB wrapper. Anywhoo, I have an array that is called from the user's local storage, and my function is supposed to iterate through every list item in the DB and show it. However, upon clicking on my Butane it only shows the most recent input of name.
Note: You can see the entire database by adding a few values in and checking your local storage.
My JsFiddle:
https://jsfiddle.net/enzp3zws/1/
my html:
<ul id="mane"></ul>
my js:
var db = new Dexie("TestDatabase");
db.version(1).stores({
friends: '++id, name, age'
});
var collection = db.friends;
var placement = document.getElementById('rainman');
var jacement = document.getElementById('rainboy');
var stacement = document.getElementById('mane');
var listed = document.createElement('li');
function addrain(){
collection.each(function(friend){
var element = [friend.name];
for (var i = 0; i < element.length; i++){
listed.textContent = element[i];
document.getElementById('mane').appendChild(listed);
//alert(element); <-- this call alerts all names in database.
}
});
}
Please excuse the randomness of some of these variable names. I don't know what sleep is anymore.
You need to create a new 'li' element each time:
//Remove var listed = ... line in header, then:
function addrain(){
collection.each(function(friend){
var element = [friend.name];
for (var i = 0; i < element.length; i++){
var listed = document.createElement('li');
listed.textContent = element[i];
document.getElementById('mane').appendChild(listed);
}
//alert(element); <-- this call alerts all names in database.
});
}
The reason your code did not work before is that you only created one li element, and repeatedly changed its text and re-inserted it at different locations.

Categories

Resources