I'm trying to create 5 different audio players from the following code to call them out individually wherever I need it in the HTML document: https://codepen.io/katzkode/pen/ZbxYYG
The issue is that this 2 loops use a single div element to call the function:
For audio:
/* createAudioElements
* create audio elements for each file in files */
function createAudioElements() {
for (f in files) {
var audioString = "<audio id=\"audio-" + f + "\" class=\"audio\" preload=\"true\"><source src=\"http://www.alexkatz.me/codepen/music/" + files[f] + "\"></audio>";
$("#audio-players").append(audioString);
}
}
For div element:
/* createAudioPlayers
* create audio players for each file in files */
function createAudioPlayers() {
for (f in files) {
var playerString = "<div id=\"audioplayer-" + f + "\" class=\"audioplayer\"><button id=\"playbutton-" + f + "\" class=\"play playbutton\"></button><div id=\"timeline-" + f + "\" class=\"timeline\"><div id=\"playhead-" + f + "\" class=\"playhead\"></div></div></div>";
$("#audio-players").append(playerString);
}
}
But what I'm trying to do is to create 5 different elements to tickle them all individually and call them wherever I need it in the website with div id="audio-players1", div id="audio-players2", etc.
I've tried to do this for both loops:
Instead of
$("#audio-players")
Add this:
$("#audio-players" + f)
But then the buttons won't work.
Here's the code to pull the files from:
var files = ["interlude.mp3", // 0
"chooseyourweapon.mp3", // 1
"interlude.mp3", // 2
"scriptures.mp3",
"scriptures.mp3"// 3
];
And I'm unsure how to proceed, I'm still learning. Thank you.
Here's a CODEPEN of what you're looking for.
Changes compared to your code:
Re-ordered div and audio creation:
createAudioPlayers();
createAudioElements();
As you need something like #audio-players2, just tweaked this code a bit:
for (f in files) {
var playerString = "<div id=\"audio-players-" + f + "\" class=\"audioplayer\"><button id=\"playbutton-" + f + "\" class=\"play playbutton\"></button><div id=\"timeline-" + f + "\" class=\"timeline\"><div id=\"playhead-" + f + "\" class=\"playhead\"></div></div></div>";
$("body").append(playerString);
}
In the function createAudioElements(), append audio based on the audio-player (DIV) ID:
$("#audio-players-"+f).append(audioString);
Edit:
New CODEPEN. I think I figured out the issue here. So when you try to add the players separately, the buttons wouldn't work BUT when they were added on the go while creation, all worked fine, right?
So here's the thing: bindAudioPlayer wasn't finding the correct element on adding a player separately to the DOM as well as the timeline and other elements.
In the new codepen, I've added a button with a select option, which when selected adds a particular player (based on the value) to the DOM. Check the onClick code:
$('a.add_player').click(function() {
var val = $(this).parent().find('select.player_num').val();
if(!$('body div#audio-players'+val).length) {
var playerString = "<div id=\"audio-players" + val + "\" class=\"audioplayer\"><button id=\"playbutton-" + val + "\" class=\"play playbutton\"></button><div id=\"timeline-" + val + "\" class=\"timeline\"><div id=\"playhead-" + val + "\" class=\"playhead\"></div></div><audio id=\"audio-" + val + "\" class=\"audio\" preload=\"true\"><source src=\"http://www.alexkatz.me/codepen/music/" + files[val-1] + "\"></audio></div>";
$("body").append(playerString);
// Populate Audio List
populateAudioList(val);
populateComponentDictionary(val);
}
});
If you can also check the populateAudioList function, in which the loop is gotten rid of and the passed value is used to select the DOM element and accordingly events are bound to the selector.
Let me know if this is the desired output. Hope this helps. :)
Edit 2
CODEPEN
I've added a function named createAudioPlayersSeparately() which, I think, fulfils the requirement.
If you notice, I've swapped files for player 3 and player 4 i.e. used file 4 for player 3 and file 3 for player 4. Now, that means, it should be easy enough to call any player with any audio "wherever" you'd like on the page. Just make sure you call populateAudioList() and populateComponentDictionary() accordingly.
Hope this helps. :)
Related
I'm working on a .NET Core project for my company where work orders are loaded from our SQL database using Entity Framework, filtered and then displayed as markers on a map through Google Maps API for our installers.
We have two types of filters: one that gets included in an Ajax POST, and one that filters locally to decrease load times and performance issues. What I'm trying to do is load the local filter items (lists that are included in the response when calling the initial Ajax POST). If the list of filter items exceeds 5 items, I want them to collapse to only 5 items and insert an anchor which expands (utilizes jQuery's toggle()) showing the rest of the items in that list.
This is the excerpt from the JavaScript function which takes care of that:
filterItems
.forEach((filterItem, i) => {
var localItem = '<label class="' + selectorContainerClass
+ ' selectorContainer" id="' + selectorContainerIdPrefix + filterItem.key
+ '"><input id="' + convertValToEng(filterItem.value)
+ '" type = "checkbox" class="filled-in navy" name="' + inputName
+ '" value="' + filterItem.key
+ '" onchange="localFilter(this, this.value)" /><span class="selector-value">'
+ filterItem.value
+ '</span> <span id="' + paramName + 'Cnt__' + filterItem.key
+ '" class="selector-count"></span></label ><br />';
document.querySelector("#" + colId).insertAdjacentHTML('beforeend', localItem);
if (i >= 5) {
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).addClass("collapse");
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).toggle(100);
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key + " + br").toggle(100);
}
});
if (filterItems.length > 5) {
//TODO: Fix the bug here; the .filter-collapse element is not being inserted under local installers.
var newEl = '<a class="filter-collapse" onclick="toggleFilterExpand(false, this)";><i class="material-icons">expand_more</i></a>';
document.getElementById(colId).insertAdjacentHTML('beforeend', newEl);
}
I should be getting a newEl inserted under the "Installer" column (8 installers, 3 of them not being displayed), but I'm not. I've tried jQuery's after() and insertAfter() methods, but neither of those worked. newEl is being generated for the "Area" column, as it should, but for the "Installer" column it's not.
I've also tried inserting the element manually through the console window with the exact same code and it works.
Would appreciate some help with this as I feel lost regarding this issue.
Thanks.
It turned out to be a stupid mistake on my end where I was removing the element newEl from the all the other filter lists before inserting a new one to the currently iterated one.
I'm writing my first code in an interactive/follow-along program through Cengage (MindTap). The program is instructing me to "write the HTML code for the inline element showing the sky image to use in the webpage." I am supposed to create a variable named imgStr that stores this text string:
<img src='sd_skyMap.png' />
Where Map is the value of the mapNum variable (there are 23 files titled sd_sky0, sd_sky1, sd_sky3 and so fourth). It says to use the + operator to combine text strings together and to include single-quote characters within the text strings.
I cannot get the sky images to appear on the webpage to save my life.
I've attempted going through a tutor provided through my university but have still have no luck getting the image to display.
var imgStr = "<img src='sd_sky0 + sd_sky1 + sd_sky2 + sd_sky3 +
sd_sky4 + sd_sky5 + sd_sky6 + sd_sky7 + sd_sky8 + sd_sky9 +
sd_sky10 + sd_sky11 + sd_sky12 + sd_sky13 + sd_sky14 + sd_sky15
+ sd_sky16 + sd_sky17 + sd_sky18 + sd_sky19 + sd_sky20 +
sd_sky21 + sd_sky22 + sd_sky23' + mapNum + '.png' />";
document.getElementById("planisphere").insertAdjacentHTML() = imgStr;
Having inserted the code into jshint.com, it stated one warning and one unused variable.
(Bad assignment.)
document.getElementById("planisphere").insertAdjacentHTML() = imgStr;
and mapNum is an unused variable.
InsertAdjacentHTML takes two strings as parameters.
The first parameter is the position which takes one of four static values.
The second parameter is your HTML string to be inserted.
An example for what you want could be:
document.getElementById("planisphere").insertAdjacentHTML('afterbegin', imgStr);
You were nearly there, just append beforeend using the document.insertAdjacentHTML()
const imgStr = `<img src='sd_sky0 + sd_sky1 + sd_sky2 + sd_sky3 +
sd_sky4 + sd_sky5 + sd_sky6 + sd_sky7 + sd_sky8 + sd_sky9 +
sd_sky10 + sd_sky11 + sd_sky12 + sd_sky13 + sd_sky14 + sd_sky15
+ sd_sky16 + sd_sky17 + sd_sky18 + sd_sky19 + sd_sky20 +
sd_sky21 + sd_sky22 + sd_sky23' + mapNum + '.png' />`;
document.getElementById("planisphere").insertAdjacentHTML('beforeend', imgStr);
<div id = "planisphere">
</div>
There are two problems on your code, the first is you need to run trough the different image files and add each one separately. On the code you provided, all image's names are being combined as one.
The second problem is your use of the insertAdjacentHTML() function. The function expects as arguments the position of the new tag and the tag itself, none is being passed. Check here for a better explanation.
Assuming you have n images that you want to add as n tags, you can try something like this:
// variable to hold the total number of images used
var numberOfImages = 23;
// we loop trough all images, where i will count from 0 to numberOfImages
for (var i = 0; i < numberOfImages; i++) {
// on each step of the loop we add a new img tag with sd_skyi as source
document.getElementById("planisphere")
.insertAdjacentHTML('afterend', "<img src='sd_sky" + i + ".png' />")
}
If you use this exerpt as is, it will add 23 img tags to an element with id planisphere.
My question is this, if I have an Text html element that looks like...
<a id='1' onmouseover="changeImage('setname/setnumber')">Cardname</a>
Can I retrieve the id (in this case 1) on a mouseover event so that I may use it in javascript to do something else with it.
Not sure if I can do this, but I'm hoping I can. What I have is a bit of javascript code that is taking data from an xml document. I have a list of 500+ cards that I have parsed through and stored by categories that are used often. Here are the relevant functions as they apply to my question.
var Card = function Card(cardName, subTitle, set, number, rarity, promo, node)
{
this.cardName = cardName;
this.subTitle = subTitle;
this.set = set;
this.number = number;
this.rarity = rarity;
this.promo = promo;
this.node = node;
}
Where node is the position within the list of cards, and due to the formatting of the document which I started with contains each card alphabetically by name, rather than numbered logically within sets.
Card.prototype.toLink = function()
{
var txt = "";
this.number;
if (this.promo == 'false')
{
var image = this.set.replace(/ /g, "_") + '/' + this.number;
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + "')>";
txt += this.toString() + "</" + "a>";
}
else
{
var image = this.set.replace(/ /g, "_") + '/' + this.rarity + this.number;
var txt = "";
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ')>";
txt += this.toString() + "</a>";
}
return txt;
}
Here is what I am using to populate a list of cards, with names that upon hovering over will display a card image.
function populateList () {
for (i = 0; i<cards.length; i++)
document.getElementById('myList').innerHTML += '<li>'+cards[i].toLink()+</li>;
}
What I am trying to do is retrieve the id of the element with the onmouseover event so that I can retrieve everything that is not being saved to a value.
I realized I can pass the id as part of the changeImage function as a temporary workaround, though it involves rewriting my toLink function and my changeImage function to include a second argument. As a married man, I've enough arguments already and could do with one less per card.
In summary, and I suppose all I needed to ask was this, but is there a way using only javascript and html to retrieve the id of an element, onmouseover, so that I may use it in a function. If you've gotten through my wall of text and code I thank you in advance and would appreciate any insights into my problem.
if I have an Text html element that looks like...
<a id='1' onmouseover="changeImage('setname/setnumber')">Cardname</a>
Can I retrieve the id (in this case 1) on a mouseover event so that I may use it in javascript to do something else with it.
Yes, if you can change the link (and it looks like you can):
<a id='1' onmouseover="changeImage('setname/setnumber', this)">Cardname</a>
Note the new argument this. Within changeImage, you'd get the id like this:
function changeImage(foo, element) {
var id = element.id;
// ...
}
Looking at your code, you'd update this line of toLink:
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ', this)>";
Of course, you could also just put the id in directly:
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ', " + this.node + ")>";
And then changeImage would be:
function changeImage(foo, id) {
// ...
}
I didn't use quotes around it, as these IDs look like numbers. But if it's not reliably a number, use quotes:
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ', '" + this.node + "')>";
I'm trying to make a generator for a mod menu in Call of Duty. I want people to be able to add a menu or delete one. I'm trying to id the menus sequentially so that I can use the text field values correctly. I made it so that if they delete a menu it changes the ids of all the other menus to one lower and same for the button id, but I don't know how to change the onlick event to remove the right element.
Better yet, if there's a better way to do this, I would love to know it.
<script type="text/javascript">
y = 1
function test2()
{
document.getElementById("test2").innerHTML += "<div id=\"child" + y + "\"><input type=\"text\" value=\"menu name\" \><input id=\"button" + y + "\" type=\"button\" value=\"remove?\" onclick=\"test3(" + y + ")\" /></div>";
y++;
alert(y);
}
function test3(x)
{
document.getElementById("test2").removeChild(document.getElementById("child" + x));
for(var t = x+1;t < y;t++)
{
alert("t is " + t + ". And y is " + y);
document.getElementById("button" + t).setAttribute("onclick" , "test3(t-1)");
document.getElementById("button" + t).id = "button" + (t-1);
document.getElementById("child" + t).id = "child" + (t-1);
}
y--;
}
</script>
<input value="testing" type="button" onclick="test2()" />
<div id="test2" class="cfgcode"></div>
I wouldn't worry about re-indexing all of the elements after you add or remove one, that seems a waste. It would be better to simply write a more generic function, rather than one with the element id hard coded into it.
For example, your first function could be written as so:
function genericFunction(el)
{
var html = ''; // create any new html here
el.innerHTML = html;
}
You can then add onclick handlers such as:
myDiv.onclick = function() { genericFunction(this) };
I would also agree with all the commenters above, use jQuery, it makes any code which interacts with the DOM much much simpler.
I'm working my way through a JQuery Solution and for the most part it works but I"m stumped on seemingly a small detail I know I'm overlooking. Heck, maybe my implementation/approach needs to be reconsidered.
Here's the flow of what works.
1. Click an anchor that adds to a table.
2. Add CSS Class.
3. Disable (Unbind) click on after preappend().
4. From the table of dynamically added record remove table based on ID.
5. delete class that was added in step 2.
6. Bind 'click'
However, although I can bind the click and alert on it. The expected functionality does not allow me to step through the above process again.
The code in question:
HTML SAMPLE:
link that starts the process:
table that holds new records after click of link
<table id="carrier-table"><tbody></tbody></table>
JQUERY and Custom Javascript Function
<script type="text/javascript" id="removeCarrier">
function removeCarrierFromList(obj) {
var i = obj.parentNode.parentNode.rowIndex;
document.getElementById('carrier-table').deleteRow(i);
$('a#' + obj.id).removeClass('delete-carrier-company');
//alert(obj.id); //.hasClass('add-carrier-company').tostring() ); //
$('a#' + obj.id).bind('click', function() {
//alert('User clicked on ' + obj.id);
});
}
</script>
<script type="text/javascript" id="carrierListJS">
$(function() {
// Link
// This adds a carrier to a list
$('.add-carrier-company').click(
function() {
var target = $(this).attr("id");
alert(target);
$("#carrier-table").prepend("<tr id='carrierRow_" + target + "'>" +
"<td><a href='#' id='" + target + "' class='delete' onclick='removeCarrierFromList(this)'> </a></td>" +
"<td class='carrier-list-text'>" + target + " " + $("#name_" + target).val() + "</td>" +
"</tr>");
return false;
});
$('.add-carrier-company').click(
function() { $(this).addClass('delete-carrier-company').unbind('click'); }
);
});
</script>
There were a few issues I noticed with the code. For one thing, as #RussellUresti mentioned, you create two tags with the same ID. For another thing, if you're using ID's in a selector in jQuery, don't include the tag name, just use the id (ie. use $('#id') not $('a#id')) it will be faster (it won't break your code though).
I have created a jsfiddle to answer your question (though I rewrote most of it). :) I think it's what you're looking for.
Here's the code:
Test HTML
aa
bb
cc
10002
10003
<table id="carrier-table" style="border:1px solid #000"><tbody></tbody></table>
JavaScript
function addCarrier() {
var target = $(this).attr("id");
$("#carrier-table").prepend("<tr id='carrierRow_" + target + "'>" + "<td><a href='#' id='a" + target + "' class='delete'> </a></td>" + "<td class='carrier-list-text'>" + target + " " + $("#name_" + target).val() + "</td>" + "</tr>");
$('#a' + target).click(removeCarrierFromList);
$(this).addClass('delete-carrier-company').unbind('click');
return false;
}
function removeCarrierFromList() {
var $this = $(this);
var id = $this.attr('id').replace("a","");
$this.closest('tr').remove();
$('#' + id).removeClass('delete-carrier-company').click(addCarrier);
}
$(function() {
// Link
// This adds a carrier to a list
$('.add-carrier-company').click(addCarrier);
});