Using jQuery data() vs native javascript getAttribute vs input hidden - javascript

I need to access general information from my site using javascript. So far, I have the following options:
Using an html element :<input type="hidden" value="MyValue"/>
Using a custom attribute in an existing html element : <div id="HtmlElement" myattr="MyValue"></div> and then access it using document.getElementById("HtmlElement").getAttribute("myattr")
Using a data attribute in an existing html element: <div id="HtmlElement" data-myattr="MyValue"></div> and then access it using jQuery("#HtmlElement").data("myattr")
I was wondering what are the benefits of using either option.
I'm not a fan of using hidden inputs because I don't like the idea of having a loose html element that contains information. But since I need it to display general information, not information related to an existing html element in the page, it doesn't seem so bad.
On the other side, I'm not a fan of abusing the use of an external library but in my case I'm allready loading jQuery in my site, so it's not as if i was loading an entire library just for this.
And finally, even dough performance is allways an issue, in my case it's not gonna make much difference if it's the fastest solution.

I would go with data attributes because that's what they are for and modern browsers have a native api for accessing them, while still allowing non-modern browsers to access them as custom attributes.
given this html:
<div data-foo="bar"></div>
// modern browser:
foo = document.getElementByID("myelementid").dataset.foo;
// older browser:
foo = document.getElementByID("myelementid").getAttribute("data-foo");
// jQuery (all browsers)
foo = $("#myelementid").data("foo");
Note if your data attribute is data-foo-bar, the key in dataset and .data will be fooBar
As sdespont mentions, the data should be relevant to the element you are storing it on.
Update:
It's also important to note that you can also get the value of a data attribute using the .attr method, however there is a pretty important difference between the two. Getting a data attribute's value with .data will attempt to parse the value of the attribute into the correct javascript type, for example, if it can be converted to an int, it will be converted to an int. If it can be converted into an object or an array, it will be converted to an object or an array. If you instead used .attr(), you can be sure that you will always have a string.
Probably also worth mentioning that using .attr() should be prefered over .data() unless you specifically need the features given by .data() due to the fact that by using .data(), a data cache will be created for that element and it's data, which isn't needed unless you actually intend to use .data() multiple times or need the extra features provided by .data()

Related

How to execute elixir code in a js file?

I have a js "my_js_file.js" file which I include only into a single page. In that js file I need to get an url by calling a phoenix helper:
# my_js_file.js
function func1(userLogin) {
var createUserUlr = "<%= user_home_path(#conn, :create, userLogin) %>";
//...........
But it doesn't work.
When I rename it to "my_js_file.js.eex", it still doesn't work -- the value between "<%= %>" isn't getting evaluated. Why not? And what are the options?
Note that I'm passing a variable to the url.
I don't think this is possible, because the assets in the static/ directory are not processed by Elixir, but by your asset pipeline (Brunch by default). They are pre-compiled so even if it worked, you would not have access to the #conn variable, since this is not available at the time when static assets are compiled.
Keep in mind this is a good thing! The server does not need to re-render your Javascript on every page request.
You have several options to get the desired result:
Hard coding
Might seem hacky, but works well enough for simple cases. I recommend hard coding just a path, using // at the start to preserve the current protocol (http/https). If you need to resolve this to a full URL, you can use this trick.
Data attributes
For one-off usage, you can add a data attribute to a related portion of your markup, for example for a login form:
<div id="create-user" data-url="<%= user_home_path(#conn, :create, userLogin) %>">
<!-- ... -->
</div>
Then in your JavaScript, you can access the data attribute. Note that depending on your use case, there might be a better way to retrieve the DOM node containing the data attribute than using document.querySelector, this is just an example:
let createUserUrl = document.querySelector("#create-user").getAttribute("data-url");
If you only need to target IE11+ or willing to use a polyfill, you can also use dataset
let createUserUrl = document.querySelector("#create-user").dataset.url;
Or if you're using jQuery:
let createUserUrl = $("#create-user").data("url");
Maybe you'll be able to extract the URL from a different attribute such as the url of a form, should you be overriding the onclick handler of the submit button, for example.
Add property on window object
For truly global values, such as authentication tokens etc. you can set a property on the window object, for example in web/templates/layout/app.html.eex
<script>window.userToken = "<%= assigns[:user_token] %>";</script>
then in your JavaScript, you can simply access
window.userToken
Other solutions
There are also more advanced solutions available for this problem, including:
Add a separate JSON endpoint that returns the required data as JSON which can then be requested from your JavaScript
If you use a JavaScript framework such as React.js, Vue.js, etc. you might be able to leverage routing logic from the framework or auxiliary JavaScript packages.
I'm sure there's even more options I didn't think of right now.

how does data-render attribute works in javascript

Can anyone explain the functionality of data-render="true" attribute works in javascript and how to use it in javascript?
I believe what that would be is a data attribute. I am not sure if this is the main use, but I know it makes sending data from html to javascript very easy. Data Attributes
I used it in a project when ids for a table were created at runtime, and depending on the row clicked on, grabbed the data attribute.
To go to your question, I believe that is what is happening with the data-render. It is just a "variable" to store a boolean in a sense.
In HTML5 specification, you are allowed to create attributes into your tags.
The specification recommends that you use some naming guidelines to create your own tags, thus as using something like "data-[some namespace to define your project]-[attribute_name]"
You can access those attributes in js, and load them with data when your server returns the page to the client. These type of attributes allow you to communicate data between server and client codes in a quite simple and clean way.

Why can't you stringify a jQuery object?

The line JSON.stringify( $("p") ); causes an error:
InvalidStateError: Failed to read the 'selectionDirection' property from 'HTMLInputElement': The input element's type ('button') does not support selection.
(I'm using Google Chrome 34)
Why?
How else should I make $("p") more portable so I can store it or pass it in a message?
There's a ton of state (attributes, event handlers, the code related to those, internal state, ...) involved in an HTML element. It just doesn't make sense to serialize all of that into JSON.
If you want to get some kind of representation of the element in JSON, you could for instance use .html() to get a HTML string representing the element. Or come up with a format that encodes, for instance, tag names, attributes and text only. You could have to implement that by hand though (or find a library - "html to json" could be a good keyword)

jQuery variable name appended with a large number

I often see in my code I am loading from my company's media central that jQuery is not available in the console normally. (No $ and jQuery)
But sometimes, to those elements to which jQuery is attached, it has a long number with it.
jQuery18306575689211022109_1378907534666
What is the purpose of doing this? Security?
Also, jQuery is sometimes available directly in the console, but only with the above numbers.
I am therefore unable to debug my apps in console, where I need to query using jQuery.
However, in the JavaScript code, jQuery is perfectly being used as $ and jQuery. So I apply a break-point and export as window.jQuery = jQuery.
Is this a proper way to debug the app, when jQuery is obfuscated?
UPDATE:
For eg., check this URL the app is calling. It seems that the URL knows what is the number appended to jQuery. How do I come to know of the same number while debugging? Any lights on what is going on?
It's a callback id automatically generated by jQuery. See the documentation for jsonpCallback.
It is preferable to let jQuery generate a unique name as it'll make it easier to manage the requests and provide callbacks and error handling.
It seems that you are confusing two different variables. You can make a quick test on this website : http://www.jquery4u.com/function-demos/jsonp/#demo. Click "run demo", open Chrome's console, type "jQuery" in order to retrieve the callback's name, then perform this simple comparison :
jQuery16409391013463027775_1379048051365 === jQuery // false
That said, the fact that the variables named "$" and "jQuery" are not available in your case may be due to a specific implementation. One possibility could be the use of jQuery.noConflict() which allows either to customize the name used as a reference to jQuery, or to completely remove all references to jQuery from the global scope (window), so there is no way to access it in the console.

Template method for dojo

When I look in the dojo documentation for template all I get is for dijit and examples only show you been able to use them in a widgit. I'm looking for the equivalent of the below methods in js prototype
var tmpl = new Template(url)
tmpl.evaluate(templateObj)
Does dojo have a template method that you can use in a dojo.declare( class ){} like you can do in js prototype. If not how could I go about similar functionality
Thanks
You may be interested in dojo.string.substitute (you'll need to dojo.require("dojo.string")).
http://dojotoolkit.org/api/dojo/string/substitute
[Edit] Also, if you're interested in acquiring a template for use in substitution from a URL on the same server, you may also want to look into dojo.cache (which is also what is often used to fetch widget templates):
http://dojotoolkit.org/reference-guide/dojo/cache.html
To clarify missingno's response, I don't think dojo.parser is what you're interested in right now; its job is to scan the DOM and transform DOM nodes into widgets and other Dojo components. dijit._Templated only uses dojo.parser when child widgets are involved (i.e. widgetsInTemplate is true); on the other hand, it uses dojo.string.substitute in all cases, to initially parse ${...} strings (e.g. ${id}) in the template.
I don't know Prototype, but this sounds like dojo.parser stuff. It is what is used by dijit._Templated behind the scenes (you can chack that in the source code if you want...)
Just note that you probably wouldn't need to cal this yourself - there is parseOnLoad=true for automatically parsing your initial HTML.

Categories

Resources