Can't remove all objects from ContentFlow coverflow carousel with remove function - javascript

Before I describe my problem I'd like to outline exactly what I'm attempting
What I'm trying to do here is load different sets of items into a content flow based on buttons a user can press. I've already set up a function triggered by a button that will get the items associated with the name value I pass to it via AJAX (using the jQuery $.get) and put in a div with an ID of itemcontainer. This works great.
function getPictures(Gallery){
$.get( "getimages.php", {name : Gallery}, function( data ) {
for(x in data){
$("#itemcontainer").append(data[x]);
}
addPictures();
}, "json" );
return false;
}
You'll see the function calls another function inside of it ( addPictures() ) that actually adds the pictures to the ContentFlow carousel from the div with an ID of itemcontainer via ContentFlow's addItem method.
function addPictures(){
clearBox();
var it = ajax_cf.items;
// Grabs pictures from 'itemcontainer' and iteratively adds them to 'flow'
var ic = document.getElementById('itemcontainer');
var is = ic.getElementsByTagName('img');
for (var i=0; i< is.length; i++) {
ajax_cf.addItem(is[i],"end");
}
}
You'll notice that the addPictures() function has a function inside it that I previously declare called clearBox(). clearBox() is supposed to loop through the items in my content flow and remove them so I can delete the old gallery of items in the ContentFlow carousel before loading new ones.
It works by looping through the list items (called items) which is a property of the ContentFlow object ajax_cf I create and run a method rmItem on the list element at index 0 for each item. Here's the clearBox function.
var ajax_cf = new ContentFlow('ajax_cf');
function clearBox(){
alert("clear");
var it = ajax_cf.items;
var len = it.length;
for(var i=0; i<len; i++){
ajax_cf.rmItem(0);
}
return false;
}
If you want you can get the source or the docs here.
http://www.jacksasylum.eu/ContentFlow/
Thanks in advance!

I don't know if you've fixed the problem yet, but here's a thought. Since these objects are in the DOM, try making your clearBox() method remove the items in the itemcontainer. So your method could look like:
function clearBox()
{
alert("clear");
var images = $('itemcontainer').children();
for (var i = 0; i < images.length; i++)
{
$('itemcontainer').remove(images[i]);
}
}
This way, you're forcing the ContentFlow object to remove the images and when your addPictures method continues, it will basically reinitialize the ContentFlow carousel.
This is untested but logically seems it would work because all the ContentFlow library's rmItem method would do is remove the object from the DOM, so you are choosing to do that yourself instead.

Related

Referring to the calling object in JavaScript using addEventListener

I'm new to JavaScript/HTML/CSS and I can't spot the mistake I'm doing in this JavaScript function. Our teacher told us to use the addEventListener method cause it has some notable advantages.
This is my entire script with the problematic function
var espandi = function (e) {
var toHide = document.getElementsByClassName("optional");
for (var index = 0; index < toHide.length; index++)
toHide[index].style.display = "none";
var toShow = e.target.getElementsByClassName("optional");
for (index = 0; index < toShow.length; index++)
toShow[index].style.display = "block";
}
var expansibleObjects = document.getElementsByClassName("singleresult");
for (var index = 0; index < expansibleObjects.length; index++)
expansibleObjects[index].AddEventListener("click",espandi);
The fact is the line e.target.getElementsByClassName gets me an error of this type
Uncaught TypeError: Cannot read properties of undefined (reading 'getElementsByClassName').
On the contrary, if I set the function with the property "onclick" directly on the element the function works perfectly. So I think the problem it's about referring to the calling object using e.target
Update 1
First of all, I want to say that this is a project for university and I cannot publish the whole code, it would be risky for my exam.
Then there are more issues apparently. First of all with the method getElementsByClassName() applied on document it seems that he can get the Collection of Elements but then if I try to print the single Element it gives me undefined on the log. Here's the code:
var list = document.getElementsByClassName("prova");
if (list[0]) {
console.log("Assigning using \"list[0]\" as check");
list[0].onclick = espandi();
list[0].addEventListener("click",espandi);
console.log("finished adding listeners");
}
else if(list.item(0)){
console.log("Assigning using \"list.item(0)\" as check");
list.item(0).onclick = espandi();
list.item(0).addEventListener("click",espandi);
console.log("finished adding listeners");
}
else console.log("failed assignment");
console.log("printing list");
console.log(list);
console.log("printing list[0]");
console.log(list[0]);
console.log("printing list.item(0)");
console.log(list.item(0));
and here's the log output:
log output
Apparently the only way I succesfully make my script work is editing the function this way:
function espandi (caller) {
var toHide = document.getElementsByClassName("optional");
for (var index = 0; index < toHide.length; index++)
toHide[index].style.display = "none";
var toShow = caller.getElementsByClassName("optional");
for (index = 0; index < toShow.length; index++)
toShow[index].style.display = "block";
}
and then assigning it to elements directly using the "onclick" HTML attribute, like this:
<table class="prova" onclick="espandi(this)">
so that the parameter "caller" refers to the element who actually triggered the function espandi. The problem is I really want to know 2 things:
how to refer to the caller using an EventHandler function (in the case of method .addEventListener()) and a normal function (in the case of the attribute .onclick of the desired element) in JS.
how to manage the method getElementByClassName() and the collection returned by itself.
In the end, just to sum up, now I have problems with assigning the event listeners and also with referring to the caller without using a parameter like this in the HTML code I showed you.
You are calling espandi instead of assign it to onclick handler.
So you need to remove the () and do expansibleObjects[index].onclick = espandi;
Anyway in your question I don't see any e.target.addEventListener() so when you say The fact is the line e.target.addEventListener() gets me an error I don't understand what you mean, maybe you have to add more code.

DOM does not update when element changes (VUE)

for a vue/mvc project i am making a page divided into html sections.
If the user clicks on a button a javascript function is called that changes the display properties of the sections so that only the clicked section is shown.
When the dom is created, it calls the function and correctly shows one section.
However when the button is clicked, the function is called again, but the dom does not change.
Here is the code for the created function:
created: function () {
var self = this;
var sectionElements = document.getElementsByTagName("section");
for (var i = 0; i < sectionElements.length; i++) {
self.sections.push({ isSelected: false, object: sectionElements[i] });
}
for (var i = 0; i < self.sections.length; i++) {
self.sections[i].isSelected = false;
}
this.showSelectedSection(0);
},
Here is the code of the javascript function.
showSelectedSection(index) {
for (var i = 0; i < this.sections.length; i++) {
if (i == index) {
this.sections[i].isSelected = true;
this.sections[i].object.style.display = "block";
}
else {
this.sections[i].isSelected = false;
this.sections[i].object.style.display = "none";
}
}
Does anyone know why this is happening and how i can fix it?
Any tips or help is greatly appreciated.
First of all, I don't totally get why you're using self = this in this example, seems like it's not necessary. Nevertheless that is not your problem. You're modifying an object inside an array, and you're doing this by accessing the index. Normally that would be ok, but vue is not aware of this change. Try either passing the direct reference to the object inside the array or add a deep watch to your array so vue can hear this changes and make the proper modifications to your DOM.

Calling a javascript function that contains dynamic parameters

I am trying to call a javascript function that contains dynamic variable as a parameter. I think i am failing in the syntax to get this particular function executed. I have tried a few combinations and none of them seem to work. Please can someone advise..
for( i=0; i<succeedList.length; i++){
var file_uniq_id = succeedList[i].filename_uniq;
//Creating dynamic button
var subm_btn = document.createElement("INPUT");
subm_btn.setAttribute("onclick", "UploadMyScript.submitTitle(this.id,'+file_uniq_id+')");
p_titleBtn.appendChild(subm_btn);
}
UploadMyScript.submitTitle = function(id, uniqID){
// Does something ....
}
My problem is I cannot appear to pass on the 'file_uniq_id' value to UploadMyScript.submitTitle().
Why not use an event listener ?
subm_btn.addEventListener('click', function () {
UploadMyScript.submitTitle(subm_btn.id, file_uniq_id); },
false);

for loop in multiselect not called first time javascript/jquery

I have a multiselect dependency where I display cities and their areas respectively.
The problem is that, both for loops in the function getArea only get called upon the second select of the cities option element.
Note: In debugger it works fine. I think its a scope problem and I tried using the foreach function but to no avail.
I have indicated below the line where the issue occurs.
//Global Variables
var allAreas = new Array();
$(document).ready(function() {
getCities();
$("#sel-city").bind("change", getAreas);
});
//get Cities on reload
function getCities() {
$.getJSON("cities.json", function(json) {
var citySelect = $("#sel-city");
for (var i in json) {
$("#sel-city")
.append($('<option>', {value: json[i].id})
.text(json[i].name));
}
});
}
function getAreas() {
var parentID = $(this).val();
console.log(parentID);
if (allAreas.length == 0) {
$.getJSON("areas.json", function(json) {
for (var i in json) {
allAreas.push(json[i]);
}
});
}
$('option', $("#sel-area")).remove();
var areasByParentID = new Array();
//Loop here
for (var i in allAreas) {
if (allAreas[i].city_id == parentID) {
areasByParentID.push(allAreas[i]);
}
}
console.log(areasByParentID);
//Loop here
for (var k in areasByParentID) {
$("#sel-area")
.append($('<option>', {value: areasByParentID[k].id})
.text(areasByParentID[k].name));
}
}
With the information you gave us and without sample data everything looks fine. But you have some minor mistakes which could lead to bad results. I decided to have a look on it, make some corrections and get it workin correctly with some sample data.
What you should take care of?
use for loops instead of for-in for arrays
you should avoid the new Array() operation
you should cache jquery variables to reduce siteload
for the areas to be set correctly on siteload you should just define init functions
What here could cause an error?
var a = [];
a[5] = 5;
for (var x in a) {
// Shows only the explicitly set index of "5", and ignores 0-4
}
The use of the for-in statement is to enumerate over object properties and will even inherited properties. Depending on your data it could give wrong results as shown in my example.
here is a jsfiddle with sample data.

Why doesn't this javascript bind the correct parameters with the event?

In this code I am supposed to bind a rollover effect to each <area> tag in a <map> element.
function initLinks(webrt) {
var areas = document.querySelectorAll("map#streetmap > area");
var links = new Array(areas.length);
for (var i=0; i<links.length; i++) {
links[i] = new Image(786,272);
links[i].src = webrt+"templates/default/sketches/links"+(i+1)+".png";
areas[i].onmouseover=function(){switchLinkImg(webrt+"templates/default/sketches/links"+(i+1)+".png");};
areas[i].onmouseout=function(){switchLinkImg(webrt+"templates/default/sketches/links.png");};
}
}
Strangely, each <area> onmouseover event tries to load the non-existing image: /templates/default/sketches/links6.png. Why does it keep this variable i which has incremented to 6 as a global variable rather than take the string I am passing to the function?
How do I fix this?
Note: No jQuery!
i often find it cleaner to use array methods when using the index because you don't need extra wrappers and everything reads a little cleaner (imho):
function initLinks(webrt) {
[].forEach.call(document.querySelectorAll("map#streetmap > area"),
function(elm, index){
var img = new Image(786,272);
img.src = webrt+"templates/default/sketches/links"+(index+1)+".png";
elm.onmouseover=function(){switchLinkImg(webrt+"templates/default/sketches/links"+(index+1)+".png");};
elm.onmouseout=function(){switchLinkImg(webrt+"templates/default/sketches/links.png");};
});
}
the variable count is way down, and we avoid extra ram-hogging closures by not creating a extra new function in each iteration of the "loop".
to be sure, both ways work, but the newer array methods can also allow the procedure to be recycled by ripping it out of the forEach() call, and giving it a name.
Try using the following code:
function initLinks(webrt) {
var areas = document.querySelectorAll("map#streetmap > area");
var links = new Array(areas.length);
for (var i=0; i<links.length; i++) {
(function(index) {
links[index] = new Image(786,272);
links[index].src = webrt+"templates/default/sketches/links"+(index+1)+".png";
areas[index].onmouseover=function(){switchLinkImg(webrt+"templates/default/sketches/links"+(index+1)+".png");};
areas[index].onmouseout=function(){switchLinkImg(webrt+"templates/default/sketches/links.png");};
})(i);
}
}
You should wrap the i variable into a closure. Otherwise it gets incremented.

Categories

Resources