For example, for accessibility reasons I want my onfocus and onmouseover to have identical values. For the sake of maintainability I want to declare this once only.
What I'd like to be able to do is this:
<a onmouseover,onfocus="assist('hello');">linktext</a>
But, of course, that would be too easy, and doesn't work. What's the best way I can achieve this DRYing out of my tags?
The better way is to move all your event handlers out of the HTML and into javascript.
<a id="some_id">link text</a>
(You don't need to use an ID, it's just for ease of demonstration.)
var link = document.getElementById('some_id');
link.onmouseover = link.onfocus = function() {
assist('hello');
};
If you wanted to take it to the next level, you could generalise it across many links. This example uses jQuery.
link text
another link
Then you apply the event handler to all the links in one go (very dry!)
$('a.assist').bind('mouseover focus', function() {
assist(this.href); // you'd need to clean up the href here, but you get the picture
});
Best I can think of is to use a function, set both events to call the function and put the common code in there.
Related
This isnt working, not sure what is wrong. I dont want to use href onclick at all, i usually use an id on ahref links then execure javascript that way but i need to pass parameters from the link to the function, not sure if there are other alternatives?
code using the parameters isnt shown, its basiacly a forum link but its loading the topic into a div
function changetotopicdetails(topicid, topicname) {
$('#loadingAjaxs').show();
$('#flubestext').hide();
#following.Title
I would usually do something like
$('#changeuserstwohour').click(function () {
$('#userswrap').load('#Url.Action("TrendingUsersMenutwohr", "Trending")');
});
but by doing so i cant send parameters to the function during a loop (list of topics)
any suggestions?
Answers pointed out that i need the variables passed to a new {}
$('#changeuserstwohour').click(function () {
$('#userswrap').load('#Url.Action("TrendingUsersMenutwohr", "Trending", new {#theid = id, #thename = name})');
});
You could do your usual click function, eventListener or bind and use data values to indicate you username and trending values.
so your tag would look like
<a href="#" data-id='#following.Id' data-short-name='#following.ShortName'>#following.Title</a>
and then your usual click function which would look like
$('#changeuserstwohour').click(function () {
$('#userswrap').load('#Url.Action($(this).data(id), $(this).data(short-name)');
});
you may need to use .each() if you have multiples or call it after each ajax load to make sure its listening to the new objects. I haven't tested this as I dont really have the functions but this should work! Please let me know how it goes and if you have another question :)
A combination of both techniques provided so far is what you're probably really after.
Your markup for your individual action links would look like:
<a href="#" class="selectorForYourActions" data-id='#following.Id' data-short-name='#following.ShortName'>#following.Title</a>
and then your on-click callback which would look like
$('#idOfContainerYourLoopCreatesItemsWithin').on("click", "a.selectorForYourActions", function () {
$('.userswrap').load('#Url.Action($(this).data(id), $(this).data(short-name)');
});
This will catch any dynamically created items that match that class if they are created within the element selected by the ID selector, but only handle clicks on anchor tags with the marker class, so you can both have many of those anchors with unique (or no) Ids and anchors with normal (or different) functionality.
I have the problem to "stop" href executing any links.
So my question is:
1) Is it possible replace href-elements that generate internal (#) links with any component, maybe <p>, <div> or <span> (or whatever could be working) that keep the same behaviour of <a> element (hovering, underlined etc) but not executing any link?
2) Alternative, a "trick" to avoiding href elements execute links?
1 or 2 without using jquery or any other js library possibly
Thanks Randomize
There are all sorts of tricks that can be employed to do this kind of thing, but what you need to be careful of is modifying the behaviour from that which the users have come to expect from a browser.
For example , it would be possible to swap the meaning of 'OK' & 'Cancel' buttons, but this would just confuse the user. (An extreme example, I know, but you get the idea)
If you could supply some more information about why you are trying to do this, there may be a better way of approaching things.
You can either add an onclick attribute to specific <a> elements:
Or modify the href like this:
To make them look like links, without redirecting the browser.
If instead, you already have a bunch of links with hrefs, and you simply wish to make them all non-redirecting, then the following jQuery will do this to all links on the page:
$(function () {
$('a').click(false);
});
Although nice and short, the above only works with jQuery-1.4.3+. If you are using an older version, then you can use the expanded form:
$(function () {
$('a').click(function () { return false; });
});
Yes. You can prevent links from the default action - the recommended way is to have links work normally (in case JS is disabled or not available - think "mobile browsers"), and then override the default action with JS.
Unfortunately, due to cross-browser incompatibilities, there are three ways to do this ("traditional","W3C" and "IE") and you need all of them: stopPropagation(), cancelBubble and return false. See a complete example at QuirksMode: http://www.quirksmode.org/js/events_order.html#link9
(Incidentally most JS frameworks abstract this away, so in jQuery you'd do this:
$('a').click(function(event){
// do something on click here
event.preventDefault();
});
This does the same thing as the QuirksMode example, but is a easier-to-read example.)
TO disable the link via js add onclick="this.href='javascript:void(0)';" like so:
link text
You can use a similar tactic to make other elements work link links:
<div onclick="this.href='http://www.mysite.com';"></div>
This is working in IE, chrome and firefox:
text link
In the function return void(0):
function functionX() {
...
return void(0);
}
I have the script
<input type="text" name="name" value="Joe Bloggs" onfocus="this.value=''"/>
Just like I am doing with the onfocus="this.value…" can I change the background of the field (+ change other things?)
Also, does anyone have a better idea of how to do the script above, but so that the text reappears when the deselect it?
It's considered best practice to leave styling to CSS and logic to JS.
You can do this in css using the :focus pseudo-class. (http://www.quirksmode.org/css/focus.html) Unfortunately, it doesn't work in IE7 or lower. For those browsers, you can use javascript to add a class to the <input> to do the same thing.
CSS
input:focus, input.focus {background:#ff0}
If you are using jQuery, here is how you would do that.
$('input').focus(function(){
$(this).addClass('focus');
});
$('input').blur(function(){
$(this).removeClass('focus');
});
Something along the lines of
onfocus="this.value=''; this.style.backgroundColor='#f00'" onblur="this.style.backgroundColor='white'"
will get approximately what you want done simply, although it would also be possible for it to interact badly with presentation defined elsewhere and as such is probably rather crude to be considered a best practise.
Alternatively, you could as suggested add / remove a specific class to the element onfocus / onblur. At this point I would also second the jQuery recommendation: although it's hardly necessary just for this, you will find that it makes life with Javascript in general much more pleasant.
If you use jQuery, something like
$('input').focus(function() { $(this).addClass('focus') });
$('input').blur(function() { $(this).removeClass('focus') });
would allow you to cleanly define the appearance of focussed inputs in CSS. Consult jQuery documentation for the surrounding context necessary to make this work.
...id="name" onfocus = "javascript:yourFunction();"...
Then, your js looks something like this:
var inputFld = document.getElementById('name');<br/>
var oldval = inputFld.value;<br/>
var tempval = "";<br/>
function yourFunction(){
inputFld.value = tempval;<br/>
inputFld.className = "test" //(building from the first answer)<br/>
//do other stuff...<br/>
}
Then, you can also add an onblur="javascript:anotherFunction();" where anotherFunction() resets inputFld.value to the original value.
Note, best practices advise you should avoid those global vars and that you attach event listeners for the onblur and onfocus events rather than inlining them. But, at least, initially, you can see if this code as it is written works for you...
On your event, append the class name...
el.className+= 'test'
then set a background on that class in your css.
To be specific, I'm talking about avoiding this type of code:
<input type='text' id='title_33' class='title'
onfocus='updateCharsLeft(33);'
onkeypress='updateCharsLeft(33);' />
Here I would like to put the onfocus and onkeypress event handles separately, i.e in a .js file. Like this:
$(document).ready(function()
{
$(".title").focus(updateCharsLeft);
$(".title").keypress(updateCharsLeft);
);
However here the problem is that the ID of the textbox needs to be passed onto the function updateCharsLeft(). It would suck to have to extract out the id from the ID of the textbox in that function, so it would actually be cleaner to just put in the event handlers within the HTML code.
Thoughts?
Can't you do this:
$(document).ready(function()
{
$(".title").focus(function() {
updateCharsLeft(this.id);
});
$(".title").keypress(function() {
updateCharsLeft(this.id);
});
);
or more neatly:
$(document).ready(function()
{
$(".title .another .someother .andAnother").focus(function() {
updateCharsLeft(this.id);
}).keypress(function() {
updateCharsLeft(this.id);
});
);
I've had to do something similar before and also wasn't happy with parsing the value out the ID attribute. The best thing I can suggest is that you use another attribute for the value you need, like the rel attribute:
<input type='text' id='title_33' class='title' rel='33' />
Or depending on how religious you are about validation, just use a custom attribute:
<input type='text' id='title_33' class='title' myval='33' />
I definitely think you should separate your JavaScript and HTML. It will be easier to find/maintain, and you can edit one place rather than 10. Don't repeat yourself.
I would look into using jQuery's live functionality. If you have 10 text input's, your adding 20 event handlers this way as opposed to 2 (one for EVERY focus handler on the page and one for EVERY keypress handler on the page).
Also re your comment to karim, I don't see why you would be duplicating yourself. It should be trivial to pass the id or transform it with a regular expression if necessary as long as your consistent in your naming convention For example, this.id.replace(/.*(\d+)$/,''). However, it would probably even be better to pass the direct DOM element reference instead, and work with that in your function.
Lastly, you seem to think that some aspect of this will suck. Maybe I'm missing the point, but can you clarify what's so difficult about mainupaliting the id or the DOM reference or whatever else that you need to do? Maybe post a longer code sample of what you're doing next.
If you really don’t want to pass this.Id then you could add a custom attribute to the input tag...
<input type='text' id='title_33' idSuffix='33' class='title'/>
You then set the event handlers like this...
$(document).ready(function()
{
$(".title").focus(function() {
updateCharsLeft(this.idSuffix);
});
$(".title").keypress(function() {
updateCharsLeft(this.idSuffix);
});
);
I personally like custom attributes. They provide a way to give Html tags custom metadata and keep it all in the markup. Html validators don’t like them though :-(
I would try to manage the all events from a single JavaScript block. As long as you are able to reference elements on the page, this should be possible.
You could always use the string functions to parse out the value and pass it along, e.g.
$(".title").focus(function() {
var thisid = this.id;
updateCharsLeft(thisid.substring(thisid.indexOf("_") + 1));
});
I'm not sure what the performance implications would be if you had to do this for a lot of elements though.
$(document).ready(function(){
var update = function(){ updateCharsLeft(this.id.split("_")[1]); };
$("input.title")
.focus(update)
.keypress(update);
});
This is exactly what Unobtrusive Javascript technique focuses on.
I have the following snippet of Javascript, which is just attaching an onclick to a button and then updating the text of an em tag underneath it. I'm slowly trying to educate myself and work with jQuery more as I've found to like the syntax a lot more and for some tasks, it's more of a pleasure to work with.
Some of the best examples I've found have come from Stackoverflow, so I come once again, to see how this could refactored and improved with jQuery; any thoughts?
$$('em.green').each(function(em) {
em.up('button').onclick = function() {
em.update('Saving...')
};
});
Thanks!
Try this, little bit shorter:
$('button').click(function(i, button) {
$(button).closest('em.green').html('Saving...');
});
Saves you from having to loop through every EM and then bind the onclick. Might also help to add a class to the button so you're not binding to every button on the page, just in case there are others.
Here is a line by line translation from your prototype code. Not a lot different:
$('em.green').each(function(i, em) {
$(em).closest('button').click(function() {
$(em).html('Saving...')
})
});
IMO the prototype version looks just as nice if not nicer (without $ sprinkled everywhere).
This is a little shorter and might be easier to understand, but duplicates the "em.green" selector.
$('button:has(em.green)').click(function() {
$(this).find('em.green').html('Saving...');
});
crescentfresh's answer is also good, and doesn't need search for the em element each time. The performance impact shouldn't be noticeable though, since you probably don't have a huge tree of elements under the button.
Matthew Crumley's answer is good but why attach multiple handlers when one will do.
The added advantage is that this will also work if you create any em.green elements later in the lifespan of the document.
$('button:has(em.green)').live('click', function(){
$(this).find('em.green').html('Saving...')
});
(I can't edit, so I'll have to create a new answer but:)
Slightly shorter:
$('button').click(function() {
$(this).closest('em.green').html('Saving...');
});
Saves you from having to loop through every EM and then bind the onclick. Might also help to add a class to the button so you're not binding to every button on the page, just in case there are others.
It's unnecessary to include the function parameters, use the this variable to specify the context you want to find the closest parent of.