How to hold "invisible" values and get them using JavaScript - javascript

I run a music blog using WordPress and I have a custom music player for it. Every time a post has a song attached to it, I want to create a way to hold that information and later access custom variables. What I need is something along the lines of...
<div class="playable"
title="Song Title"
mp3="URL"
soundcloudLink="https://soundcloud.com/cashcash/take-me-home-jordy-dazz">
</div>
Then in my $(document).ready() function I would need a function that finds all objects of class "playable" and be able to access the title tag, mp3 tag, soundcloudLink tag, etc.
Any easy suggestions?

It sounds like you're looking for data-* attributes:
3.2.3.9 Embedding custom non-visible data with the data-* attributes
A custom data attribute is an attribute in no namespace whose name starts with the string "data-", has at least one character after the hyphen, is XML-compatible, and contains no uppercase ASCII letters.
All attribute names on HTML elements in HTML documents get ASCII-lowercased automatically, so the restriction on ASCII uppercase letters doesn't affect such documents.
Custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements.
These attributes are not intended for use by software that is independent of the site that uses the attributes.
E.g., they always pass validation, and they're only for your use.
So for instance:
<div class = "playable"
title = "Song Title"
data-mp3 = "URL"
data-soundcloudLink = "https://soundcloud.com/cashcash/take-me-home-jordy-dazz"
></div>
When you need to access that information, you get a jQuery object for the div, and then use attr("data-mp3") or data("mp3") to access it. (Or without jQuery, get the HTMLDivElement and use getAttribute.) Note that I haven't changed title. title is a valid attribute, and accessible via .prop("title") on jQuery instances or via .title on DOM elements.
Note that data is assymetrical: It reads from data-* attributes for initialization, but doesn't write to them.

You can try the data- attribute which can easily be retrieved by .data() method.
HTML:
<div id="thing" data-title="Keine Lust" data-file="keine_lust.mp3"></div>
JQuery
var song_title = $("#thing").data("title");
var song_file = $("#thing").data("file");

You can use the .hasClass() jquery function to display the attributes of the elements with that class. Add an ID to the element like in this case I added test.. here is how to alert them.
$(document).ready(function(){
var className = $('#test').hasClass('playable')
if( className ){
var url = $('#test').attr('soundcloudLink');
var title = $('#test').attr('title');
document.write(title);
document.write(url);
}
});
This one displays the soundcloud link and the title if the element has the class playable. here is a fiddle. http://jsfiddle.net/uprosoft/2Frk3/3/

Related

How to remove/add html tag in ng-repeat

is it possible to remove/add the html tag dynamically with condition in the javascript?
https://jsfiddle.net/kimsoon/Ldy9xhjt/3/
Example i need to remove the number 2 th column when button is clicked, insert back again when button is clicked. I have using this but does not work.
angular.element(document).find('.dataTable tfoot').remove($scope.items);///to remove
angular.element(document).find('.dataTable thead').prepend($scope.items);//to add
According to the Angular documentation on angular.element().find():
Note: Keep in mind that this function will not find elements by tag
name / CSS selector. For lookups by tag name, try instead
angular.element(document).find(...) or $document.find(), or use the
standard DOM APIs, e.g. document.querySelectorAll().
So, angular.element(document).find(...) can only be used lookup by tag name not class name.
Therefore, your code is not working because your .find() is not returning the element(s) you expect it to (in fact it's not returning any).
Use the DOM method getElementsByClassName to select using class name:
const dataTable = angular.element(document.getElementsByClassName("dataTable"));
Then you can perform your prepends or removals on the wrapped angular dataTable element:
dataTable.remove($scope.items); //to remove
dataTable.prepend($scope.items); //to add

HTML image attribute returns undefined

I have a set of 5 images each with a unique filter attribute in a list of filters and the main image in a separate div.
The main image does not have a filter applied to it.
I would like to have users click on any of the images on the sidebar and then apply the selected filter to the main image.
I tried using an event listener for that but I don't really understand what's happening.
Here's my code:
<img src='http://res.cloudinary.com/demo/image/upload/c_fill,e_art:audrey,h_80,w_120/sample' filter='audrey' className='filter' />
and an event listener that gets called when a user selects an image.
onFilterSelect = event => {
console.log(evenet.target) // returnsimg element
console.log(event.target.src) // returns src of img element
console.log(event.target.filter) // returns undefined
}
I would like to use the filter='filter' prop to dispatch an action that sets the state to the newly selected filter but I keep on getting undefined as a result.
HTMLImageElement.prototype does not have a filter property (which you are trying to access).
Your image has a filter-attribute (which makes your HTML invalid because it is not a valid attribute on img elements).
If you need to stick with that invalid attribute name, you can access it using
console.log(event.target.getAttribute('filter'))
The better solution would be to change that attribute to a data-filter attribute, which you can access like this:
console.log(event.target.dataset.filter)
Please note that there is a special naming convention in the .dataset object:
data-filter="Audrey"
can be accessed using
img.dataset.filter
but
data-image-filter="Audrey"
would be accessed using
img.dataset.imageFilter
Notice the automatic conversion of kebab-case to camel-case!
console.log(event.target.getAttribute('filter'))
Not all HTML attributes are in element's properties. Also using data is better for custom attributes, as suggested by others.

Simple DOM attribute matching in Google Tag Manager

Using Google Tag Manager, I'm able to use pre-defined variables like Click Classes, Click ID to match the class and id attributes of DOM element But what about something like this below,
<div data-user_tag="interested-in-service"></div>
Which GTM feature am i supposed to use to match custom attributes like data-user_tag above?
I've tried using Custom Javascript but i'm unable to get the parameters right to access these attributes.
couldn't find a particular example to help me in GTM documentation
Any Ideas?
Go to variables, click "new", select "DOM Selector Element. Set to method "CSS selector", enter the selector (tricky part, see below) and set attribute name to "data-user_tag":
The problem is of course that the selector in this case does not (necessarily) address a unique element. If you have multiple divs this variable will return only the first div with the data-user_tag (actually since attribute name is set it will return the value of the data-user_tag, not the element itself).

Is it bad form to use html class attribute as a variable

I am wondering if the html class attribute should only be used for styling. Is there any drawback to using the class attribute as a variable. The W3 spec http://www.w3.org/TR/html5/dom.html#classes does not specify one way or another but, all examples and training point in the direction of styling only for multiple objects.
In my case I want to use the class attribute as variable that matches the key value in a object array. For example in my Javascript code I have an object that has a number of key/value pairs. On my web app I have a number of save buttons. When a save button is clicked I grab the parents class attribute value and use it as the key for the object to know which value to change. The class attribute on the parent has not other value than to let me know which key value pair to change in my object
While I'm sure it's possible to use classes that way, it's certainly not their intended purpose. html has data attributes that provide the functionality you want, for example
<button data-key="some value" name="" id="">click me</button>
You can then get that value (onClick if you like) and use it as a key for your object/data structure. Theres a good overview here
While it is not bad, it neither is best practice.
You can, instead of using the class attribute, define explicit data attributes. Using the class attribute would mean that you could not use several classes (because that would be a weird key to search for in an object, right?).
For instance:
<div class="any classes you like" data-mykey="searchforthiskey">
<button></button>
</div>
In jQuery:
$('button').click(function() {
var key = $(this).closest('div').attr('data-mykey');
});
From a functional perspective, there's no reason to NOT use the class attribute to store information about that element. You can access a class attribute as easily as you can a data attribute.
From a standards perspective, it is probably better to use a data attribute. Why? Well, if you are the only person working on your front-end, no big deal. If you are one of many on a team of front-end developers, who works specifically on the javascript side of things, you may run into a conflict with another front-end developer who works on the HTML/CSS side of things. They may remove a class from the element, not realizing that its also being used as your javascript hook into that element. In that case, you're better off creating your own data attribute, which then makes it clear that this attribute is probably data related and won't be molested by someone just trying to fix the styling of that element.

pure javascript dom dynamic insert, update and delete

I want to know the most effctive way to dynamically update, insert or remove elements from an html page.
The outcome of this is that, I can change an input element into a div element and vice versa based on a user action.
eg
<form><input type="text" value="Value to save"/></form>
and based on some event, i will change that to
<form><div>Value to Save</div></form>
Tx
I think you could do this task this way (pure JS, without using external frameworks):
//retrieve the <form>
var form = document.getElementsByTagName('form')[0];
//retrieve the <input> inside the form
var input = form.getElementsByTagName('input')[0];
//create a new <div> DOM element
var newElement = document.createElement('div');
//The containing div text is equal to the input value (your case)
newElement.innerHTML = input.value;
//simple empty the form by set innerHTML = ""
form.innerHTML = "";
//append the <div> inside the form
form.appendChild(newElement);
By the way, I sugges you, if you want to manipulate DOM and do stuff like these in an easier way, learn how to do it by using frameworks like jQuery or mootools ;)
This is a general description:
Creating: You can create elements with document.createElement and then use one the various insertion methods to the insert the element at a certain position (e.g. Node.appendChild). You need to get references to related nodes first.
Most browser also support the innerHTML attribute for elements. You can set that attribute to an HTML(or text) string and the content of the element will be updated accordingly.
Updating: It depends on which data you want to update. E.g. an input element has an attribute value. In order to change the value of a text input you need to get a reference to that element first, then you can do element.value = 'new value'. For content, you can use the already mentioned innerHTML attribute.
Have a look at an HTML element reference to see what attributes they have.
Deleting: You want Node.removeChild.
I suggest to also have a look at DOM traversal methods and be aware of browser differences.
Using:
element.removeChild
element.appendChild
By using these methods, you can retain references to the elements in case you want to swap them back over again. Any event handlers in place will remain attached to the elements, too.
This depends on your definition of most effective.
If you mean the simplest way, then you can use a library like jQuery and do it like this:
$('form').html('<dynamic markup>');
If you mean the most performant way you can do the following:
document.getElementByTagName('form').innerHTML = '<dynamic markup>';

Categories