Best practice to avoid element name conflicts in views - BoilerplateJS - javascript

Imagine you have several components in your application, each having its own view.
While the components are independent, their views may use the same identifiers for DOM elements, e.g. there is a chance that 2 or more components would have views with similar input control like:
<label for="Bid">Bid</label>
<input type="text" id="Bid" name="Bid" value="0"/>
After components are activated, their views are attached to the DOM by Boiler.ViewTemplate, and now there's a name conflict for Bid element, causing side effects, e.g. clicking on the label works only in 1 view, and is disabled in the others.
What is the best practice to avoid such collisions? Should i use "unique" suffix/prefix for all elements in my views, like id="ComponentName_Bid"? Or there is more elegant solution?

This is indeed a very good question. I too struggled with it many times. Sometime back I did an implementation of giving an auto generated unique id for every ViewTemplate instance.
This UID could be used from JS logic (viewmodel.js etc) by passing it from the ViewTemplate instance.
This could be used by view.html as well as by the component specific .css file as a tag {comp.uid} which will be replaced by a special ViewTemplate logic, just as used for 'nls' replacement (see line 105 at view-template.js).
That ofcourse worked, but the complexity was too much for the developers to understand. So in a later version of BoilerplateJS I removed this functionality and let developers to manage the elementIDs manually as you have suggested above.
I still do not know what the best approach for this.. but for the moment I believe managing it manually results in a much cleaner code.

Another option is to simply put input inside label like this:
<label>
Last Name
<input type="text" name="lastname" />
</label>

Related

The best way to target DOM

I'm a front-end developer, and I'm worried about the best way to target my DOM.
Let's imagine a tiny form to create a new zombie :
<h1>Add a new zombie</h1>
<form id="create-zombie">
<input id="zombie" type="text" name="zombie" />
<input id="lvl" type="text" name="lvl" />
<button type="submit">Add</button>
</form>
...and if I want to get the values of zombie and lvl, I will code something like this:
class Zombie_Add extends Controller
# Dom References
el:
'form': '#create-zombie'
'zombie': '#zombie'
'lvl': '#lvl'
run: ->
#on 'submit', #el.form, #validate
validate: (e) =>
e.preventDefault()
zombie = $(#el.zombie).val()
lvl = $(#el.lvl).val()
module.exports = Zombie_Add
That's "ok" and it does the job, but I have some problems with that "structure" :
If somebody touches the DOM and removes an ID, I'm just fucked, it breaks my code (Captain Obvious spotted !)
For more complicated selectors, it's just a mess (I'm thinking about some stuff like that [name^="dummy-"] input:first). I guess it's easy to imagine how shitty the names of el are.
Anyway, what I want to learn today is what's the best way to target the DOM from JS. Is it better to use IDs, class values or, data-* attributes? How we can prettify a selector with plain English, etc...
If somebody touches the DOM and removes an ID, I'm just ****ed, it
breaks my code (Captain Obvious spotted !)
The best way to target a single, unique element in the DOM is with an ID like you are doing with zombie and lvl. It is both fast to execute and simple to code.
It is a given that if someone messes with the id values in your HTML, that will break your Javascript. That's just the way it is. Anyone messing with your HTML has to be smart enough to know that an ID value is there for a reason so if they want to change that or remove it, then it is their responsibility to find someone who can make corresponding changes in the Javascript. That's just the way it is.
For more complicated selectors, it's just a mess (I'm thinking about
some stuff like that [name^="dummy-"] input:first). I guess it's easy
to imagine how ****ty the names of el are.
The same goes for more complicated selectors. Like it or not, a modern web page is a melding of server-side stuff, presentation HTML and Javascript. The three have to work together to deliver the final solution. While you strive to avoid unnecessary dependencies with good design techniques and practices, you cannot avoid all dependencies, nor would even trying to avoid all possible dependencies be an efficient way to develop.
Example
There are coding practices that can make your code less sensitive to edits to the HTML and I consider those to be desirable practices. For example, consider this HTML snippet:
<div class="header">
<div class="headerBorder">
<div class="actions>
Hide
</div>
<div class="contentContainer">
<div class="content">
... content here
</div>
</div>
</div>
</div>
<div class="header">
... more of these repeated
</div>
And you want to have code that, when you click on the Hide link, it will hide the content.
If you code that like this:
$(".header .actions .hide").click(function() {
$(this).parent().next().children().first().hide();
});
Then, you have embedded in your Javascript some extremely detailed knowledge of the HTML structure in the area of your button and content and pretty much any structural change to that HTML (even just adding one more level of div to help with some layout) will break the Javascript. This is bad.
Instead, you could write this:
$(".header .actions .hide").click(function() {
$(this).closest(".header").find(".content").hide();
});
This depends only upon one HTML structural concept - that the .content that corresponds to the .hide button is somewhere in the common .header parent element. The entire structure within that .header parent can be changed and this code will not break. This is robust code that tries to be as independent of the details of the HTML structure as possible.
Anyway, what I want to learn today is what's the best way to target
the DOM from JS. Is it better to use IDs, class values or, data-*
attributes? How we can prettify a selector with plain English, etc...
It's best to use IDs to target elements for which there is only one unique element in the page.
It's best to use class names to target elements for which there can be more than one element in the page and you can combine that with other parts of a selector if you want to target only a specific item with a class name.
data attributes can be used in selectors, but that isn't really their primary purpose. I can't think of any reason why it would be better to use a data attribute instead of a class name. I use data attributes for storing actual data on an object that will be used by scripts. This tends to allow the code to be more generic and let the content describe itself.
When you talk about classes getting removed to change the state of the element, that is a legitimate use of a class, but it would just be a bad design decision to use the same class for selecting an element as for add/removing state. Use different class names for those two purposes. For example, you could have a class name called "selected" that indicates a selection state, but you would only use that in a selector if you wanted just the selected objects. If you wanted all line items in a table, you wouldn't use ".selected", you'd create a more descriptive class name for that object such as "lineitem". Remember, you can have multiple class names on an object so you can use different class names on the same object for different purposes.
You seem to be searching for some magic bullet here that prevents changes in the HTML from affecting Javascript in any way. That simply does not exist. Selecting a DOM element or finding a DOM element relative to something that was clicked will rely on some inherent knowledge of how the HTML is structured or tagged. What is important is that you minimize that dependence to only what is required and that anyone messing with the HTML has an understanding of how to best change things and not break the Javascript or discusses changes with someone who knows the Javascript. If you're using different skills/people on different portions of the project, they have to coordinate their efforts in order to not break things or be aware of what dependencies there are with the other parts of the system. That's just the way it is. There is no magic answer here that removes all dependencies between HTML and Javascript. Smart designs have smaller and more obvious dependencies. Poor designs have large and often hidden depedencies.
Your question about "plain English" isn't particularly clear to me. It seems obvious to use descriptive ID names, class names or attribute names that make it as obvious to the reader what that particular name is being used for. I'm not sure what you were looking for beyond that.

Polymer: Can i replace native HTML element with polymer's

F.e. i have elements on website like this:
<input type="text">
Can i replace them with paper-input, f.e.? The problem is, i using Drupal, there is many forms generated by Form API and other elements. Replace them all to paper - is pain or not can be done, so i looking for method to replace default html elements with polymer's.
I think this is something you would need to do through Drupal or their templating system. You can't really overwrite the native HTML elements that it's outputting to the DOM. You would need to either have the Forms API output paper-inputs instead, or you would have to replace them all with JavaScript created elements, which wouldn't be very efficient.
Polymer permits the extension of native elements
Additionally, you can wrap the existing input in paper-input-container to achieve the same result as using paper-input (this is how paper-input works)
<paper-input-container>
<label>Your name</label>
<input is="iron-input">
</paper-input-container>
There's not going to be any easy way besides editing your Drupal form templates.

Should all the view logic go in templates?

For example, I need to disable every input when the view's model isn't new (has an id).
I can do :
if(!view.model.isNew()) {
view.$('input, select, textarea').prop('disabled', true);
}
or I can go do an "if" on every input I have in my template:
<input type="text" {{# if model.id }}disabled{{/ if }}/>
If we follow the MVC (or MVP) pattern, I guess the second approach would be best, since the view logic is in the view. However, if I go with this approach and decide to change the condition that disables the inputs, I need to change it for every input in EVERY template. If I leave in the JS code, there is only one place to change.
This is just one example, but I am having similar dilemmas with alot of things. Hopefully you got an answer for that.
Cheers!
Based on your question, I'd say that you're probably running into this general problem for two related reasons -
You're using backbone exclusively, rather than a framework like Marionette or Chaplin.
Your views are "too big" and trying to incorporate too much material into a single view.
I almost never include logic into templates and that's because I almost never need to. That's because I write a lot of very small views, and piece them together to make large views. Marionette's view classes make this very easy to do, by subclassing the backbone view into different view types, adding additional utilities and drastically cutting down on boilerplate. Marionette is also very good at handling nested views, which really allow you to drill down and create the exact view tool you need for a specific use case.
It's not at all uncommon to be able to define a useful view using Marionette in 1-2 lines of code, which gives you a lot of flexibility to make very small, efficient views. The disadvantage to making lots of small views is that it's a lot of code to write, and could become difficult to maintain, but Marionette makes that disadvantage relatively insignificant. Marionette only took me a couple of days to get the hang of, and I highly recommend integrating it into your Backbone apps for exactly this problem.
When your views are big, and try to do too much, you wind up with the problem you're describing - you have to modify them too much to fit your specific needs and your code gets ugly and hard to read. When you have a lot of small views, they're very responsive and need little if any customization.
The example from your question is, I think, a border line case. My gut instinct would be to create two entirely separate views and run them under the following pseudo code:
editableView = { //definition }}
disabledView = { //definition }}
if (newModel)
editableView.render()
else
disabledView.render()
This is my gut instinct because my bet is that there are other differences between the views than whether the inputs are editable. Even if there aren't now, you may find in a few months that your needs have changed and that you'd like to incorporate some changes. The approach I suggest allows you to put those changes right into the appropriate View and not have to worry about logicking them out in a single view and deciding whether that logic belongs in the template or the view.
If you were absolutely certain that the only difference between the two views was going to be whether the inputs were editable, and that your needs are not going to change in the future, then maybe you would want to think about rendering them with the same view. If that is the case, I'd recommend that you put the logic in the javascript, rather than in the template, for the reasons you identified. But as I said, your example really is a borderline case, and in most instances I think you'll find that shrinking your view scope will really help you to see where your "template logic" belongs.
NOTE: I've talked a lot about Marionette in this answer, but I also mentioned Chaplin as another option above. I don't have much experience with Chaplin, but you may want to consider it at it as a Marionette alternative.
I prefer to do implement view logic in templates:
It is easier to change and read
Any dependency to id, element and etc can be implemented in template
List item
complex logic can be implemented in templateHelper of marionette or serializeData of Backbone without any dependencies to content of template or view
you can also implement complex logic using Handlebar Helper
Disadvantages of view logic in code are:
in case of changes to selectors (id, classes and so), all views have to be changed or reviewed
logic has to be applied again if view is re-rendered
Perhaps what you might be looking for presenter (aka decorator).
Instead of sending the template the model directly, consider sending it though a presenter, this way you can construct the attributes for the input field. Something like this:
present = function(model) {
return {
inputAttributes: model.isNew() ? 'disabled' : '',
id: model.id,
name: 'Foobar'
}
}
template(present(model));
then in your template:
<input type="text" {{inputAttributes}}>

Best practice for generating html ids with grails

I have a template that could be rendered multiple times within the same view.
The template contains a form and I have some jquery event listeners attached to the form elements using the html id.
For now I'm using 'g:set' to create an elementId variable at the top of the template using the current time in milliseconds and appending it to each element on the form. This way each form element will have a unique id within the page no matter how many times the same template is rendered.
My approach works but it seems to me that there must be a better way to achieve what I want to do?
Heres an example of my approach :
<g:set var="elementId" value="${'elementId-' + new Date().getTime()}" />
<form>
<g:textField id="${elementId}name" name="name"/>
<g:textField id="${elementId}address" name="address"/>
</form>
<script>
$("#${elementId}name").on("click", myFunction())
$("#${elementId}address").on("click", myFunction())
</script>
While it may feel a bit 'odd' or 'strange' to do this, your approach will accomplish what you are after. Adding in a random number or UUID that you generate at the GSP level too would help avoid collisions (though that may be overkill).
Grails doesn't offer any assistance in this manner per say. Since this is a concern of how elements are addressed in the browsers DOM and Grails typically addresses server-side concerns.
The alternative is to refactor your code to not rely upon element ids but rather something more generic and based on classification instead. Using class names would be a good approach. Depending on your requirements this may or may not work well.

What is the difference between id and js-.. for js apeel in css?

This question relates to the article http://davidwalsh.name/css-do .
What are the differences and advantages these approaches?
<div class="do-launch-login">...</div>
<a class="do-close-modal">...</a>
<input class="do-autocomplete" />
and
<div id ="login" class="launch-login">...</div>
<a id="close" class="close-modal">...</a>
<input id="autocomplete" class="clautocomplete" />
The author calls them do- prefixes, i call them (and use them as) js- or jQ- prefixes.
Javascript has a whole scale of possible applications in DOM manipulation... than just a do-
Those prefixes are to indicate classes used exclusively by JS, means you cannot find them in i.e: style.css but rather as part of some Javascript logic in script.js.
Also you cannot use ID multiple times cause ID should be unique-per-page, so, classes in any case, spiced with a prefix to distinguish it's application.
(hm...do-... still seems pretty funny.)
Personally for me, I generate a lot of dynamic HTML on the fly for my web applications. Because of this, I try to never use IDs as I make multiple instances of the same HTML objects.
It is considered terrible practice to ever have a duplicate of an ID, so I always use class names as selectors.
But that's just me.
Id should only be used for a single thing. However a class can be given to many different things.
You could easily google this for more in depth answer
Some consider use of id in css a bad practice, because of:
The element is not re-usable on that page.
This is the beginning downward sprial into specificity.
Usually, IDs refer to something specific, and abstracting would be tough.
Any performance gains picked up by using id, is negated by adding any other selector to the left for that id
quoted from http://screwlewse.com/

Categories