How to replace onclick event with GreaseMonkey? - javascript

This website has a gallery of images. Each time I click on a thumbnail image it opens the URL in a new tab (not because I set firefox to open links in new tabs). I want to just open the URL in the same window. An example of what the thumbnail images looks like is this.
<span class="thumb" id="789">
<a href="/post/image/12345" onclick="return PostMenu.click(12345)">
<img class="preview" src="http://abc.com/image.jpg" title="title" alt="">
</a>
</span>
I believe that onclick="return PostMenu.click(12345)" is doing this. How can I replace the PostMenu.click() function with my own empty function in GreaseMonkey? Is there a way to make a GreaseMonkey script intercept all onclick events?
My only other option is to go through all the span classes and remove the onclick="return PostMenu.click(12345)" from the link tags. But since there can be over a hundred of these on a single page, I'd rather not do that.

Actually, deleting the onclicks is not at all an onerous task.
With jQuery, the code would merely be:
$("span.thumb a").prop ("onclick", null);
Or, for older versions of jQuery:
$("span.thumb a").removeAttr ("onclick");
A complete script:
// ==UserScript==
// #name _Kill select onClicks
// #include http://YOUR_SERVER/YOUR_PATH/*
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
// ==/UserScript==
$("span.thumb a").prop ("onclick", null);
The advantage of this approach is that:
(1) You preserve PostMenu.click() in case you want it, or it's needed, elsewhere,
(2) You are removing crud from the page, which makes it just a little bit less unwieldy.
(3) I suspect that you might also need to unwrap or modify that link -- in which case, the targeted rewrite approach using jQuery is the way to go.
If you really just want to replace the PostMenu.click() function with your own empty function, the code for that is just:
unsafeWindow.PostMenu.click = function () {};
As for having Greasemonkey intercept all onclick events... That is not easy to do reliably. Forget that approach unless there is an overwhelming need for some reason (which there doesn't seem to be, in this case).

Related

JQM 1.4.5 : disabling button breaks page rendering

Going through a steep learning curve, i am currently experimenting various UX 'toys' that i will require to implement an app. One of these is to disable a button and enable it on the fly. Following the instructions of the good book , I wrote a little snippet of code to test it out. Clicking on "Soap" runs a series of chained promises, and toggles the "Soap1" button disabled prop.
My HTML/JS
<div data-role="content">
<a href="#" id="btn_soap1" class="ui-input-btn ui-btn ui-mini ui-btn-inline ui-icon-back "
onclick="getInitialNotifications();">Soap1</a>
<button id="btn_soap" class="ui-btn ui-btn-inline ui-mini ui-icon-bullets "
onclick="getInitialNotifications();">
Soap
</button>
<script>
$("#btn_soap1").button({ // required initialization
disabled:false
});
$("#btn_soap").on("click", function () {
// bubbled from the onClick thingie in the markup
var isDis = $("#btn_soap1").button("option","disabled");
$("#btn_soap1").button("option","disabled",!isDis);
// var but = $("#btn_soap1");
// var className = "ui-state-disabled";
// if(but.hasClass(className)) {
// but.removeClass(className);
// } else {
// but.addClass(className);
// }
});
</script>
</div>
Intended rendering
Broken rendering (all browsers and device sims and devices)
Question : can you see any noob error in the JS that would cause this side-effect. I added (in comments) my work-around, which works as specified, but is seems counter-intuitive.
EDIT: (from Mr. Duc Nguyen's answer). What breaks the rendering is adding the initialization. If it is not there, i get an exception whining that i am calling a function prior to initialization when changing the disabled state.
EDIT AGAIN : discovered JSfiddle, ... a fiddle that reproduces this
Edited: new answer basing on jsFiddle
You have gotten yourself in a very interesting situation, some points below:
jQM has an auto-initaliasation merchanism, if you want to leverage that, you have to follow the rules, or totally disable it and do the initialisation yourself. jQM global config
You have 2 "buttons", but they are actually 1 <a> and 1 <button>, disabling the <a> was never an easy one, have a look here disabling html link
jQM might confuse you that the <a> tag is a button widget, but it is not! It just has the same styling as a button, not a button widget. Button widget is only applying to <button> and appropriate <input> type (it was clearly mentioned in the documents back in 1.2.0's days, I couldn't find it in the 1.4.5 docs)
So, here is how I would do to leverage the jQM auto-initialisation:
Soap1
<button id="btn_soap" data-inline="true">Soap</button>
Notice on the <a>:
The attribute data-role="button" was to tell jQM to mark it up as a button
This classclass="ui-disabled" was to disable it initially.
And how to disable the link <a> on-the-fly. Notice that by just adding a class, it won't work on some specific infamous browsers, referring to the above stackoverflow answer for more information.
var isDis = $("#btn_soap1").hasClass("ui-disabled");
if (!isDis) {
$("#btn_soap1").addClass("ui-disabled");
} else {
$("#btn_soap1").removeClass("ui-disabled");
}
Again, you can only call .button([method]) on a real button!
Have a look on this updated jsFiddle, I have cleaned things up a bit.

how to call a onclick function in <a> tag?

I want to open a new window on click of 1
$leadID = "<a href='javascript:onclick=window.open(lead_data.php?leadid=1, myWin, scrollbars=yes, width=400, height=650);'>1</a>";
It is not showing me error. Is there any other way to open new window?
Here is the fiddle
http://jsfiddle.net/ankurdhanuka/uwypv/
Try onclick function separately it can give you access to execute your function which can be used to open up a new window, for this purpose you first need to create a javascript function there you can define it and in your anchor tag you just need to call your function.
Example:
function newwin() {
myWindow=window.open('lead_data.php?leadid=1','myWin','width=400,height=650')
}
See how to call it from your anchor tag
<a onclick='newwin()'>Anchor</a>
Update
Visit this jsbin
http://jsbin.com/icUTUjI/1/edit
May be this will help you a lot to understand your problem.
Fun! There are a few things to tease out here:
$leadID seems to be a php string. Make sure it gets printed in the right place. Also be aware of all the risks involved in passing your own strings around, like cross-site scripting and SQL injection vulnerabilities. There’s really no excuse for having Internet-facing production code not running on a solid framework.
Strings in Javascript (like in PHP and usually HTML) need to be enclosed in " or ' characters. Since you’re already inside both " and ', you’ll want to escape whichever you choose. \' to escape the PHP quotes, or &apos; to escape the HTML quotes.
<a /> elements are commonly used for “hyper”links, and almost always with a href attribute to indicate their destination, like this: Google homepage.
You’re trying to double up on watching when the user clicks. Why? Because a standard click both activates the link (causing the browser to navigate to whatever URL, even that executes Javascript), and “triggers” the onclick event. Tip: Add a return false; to a Javascript event to suppress default behavior.
Within Javascript, onclick doesn’t mean anything on its own. That’s because onclick is a property, and not a variable. There has to be a reference to some object, so it knows whose onclick we’re talking about! One such object is window. You could write Activate me to reload when anything is clicked.
Within HTML, onclick can mean something on its own, as long as its part of an HTML tag: <a href="#" onclick="location.reload(); return false;">. I bet you had this in mind.
Big difference between those two kinds of = assignments. The Javascript = expects something that hasn’t been run yet. You can wrap things in a function block to signal code that should be run later, if you want to specify some arguments now (like I didn’t above with reload): <a href="javascript:window.onclick = function () { window.open( ... ) };"> ....
Did you know you don’t even need to use Javascript to signal the browser to open a link in a new window? There’s a special target attribute for that: Google homepage.
Hope those are useful.
You should read up on the onclick html attribute and the window.open() documentation. Below is what you want.
<a href='#' onclick='window.open("http://www.google.com", "myWin", "scrollbars=yes,width=400,height=650"); return false;'>1</a>
JSFiddle: http://jsfiddle.net/TBcVN/
Use the onclick as an attribute of your a, not part of the href
<a onclick='window.open("lead_data.php?leadid=1", myWin, scrollbars=yes, width=400, height=650);'>1</a>
Fiddle: http://jsfiddle.net/Wt5La/

Prefixing a URL in an window.open function jQuery

I have this HTML:
Track Your Package »
Somebody on this site was able to provide me with a script to prefix the URL with the domain http://www.example.com/ Here's the script:
$(document).ready(function(){
$('a[onclick^="window.open(\'TrackPackage.asp"]').attr('onClick', $('a[onclick^="window.open(\'TrackPackage.asp"]').attr('onClick').replace("window.open('", "window.open('http://www.example.com/"));
});
However, I am having a little trouble with this:
The first issue is where there is multiple instances of the element. Here's a fiddle: http://jsfiddle.net/VMmZx/
Instead of one anchor being signed with ID=4 and the other with ID=5 as intended, they're both being signed with ID=4.
The idea is, each window.open function should be prefixed with http://www.example.com however, the remainder of the URL should remain intact...
The second problem I'm encountering is when the element does not exist on a page, the remainder of the jQuery fails...
Here's another fiddle: http://jsfiddle.net/VPf32/
The <a> should get the class foo, but since the element does not exist on the page, the jQuery does not execute.
Since the JavaScript is being included in the HTML template of the ASP.NET server, this can create many problems.
I hope I've been clear and you can help me. Thanks.
You can use .each() to iterate over each matching element and change them individually:
$('a[onclick^="window.open(\'TrackPackage.asp"]').each(function(index, element) {
element = $(element);
element.attr('onclick', element.attr('onclick').replace(/open\('/, 'open(\'http://www.example.com/'));
});​
However, I don't think using links with a href of # and an onclick opening a window is as semantic as it could be. If possible, try changing the markup to this:
Track Your Package »
Now if someone is curious where it will lead them, the browser can show something useful in the status bar when you hover over it.
If you need to adjust the behavior further, add a class and bind for the click event. When they click, prevent the default action and open the window yourself, as you did before.
Why are you doing the click even inline like that? I would just output the links like:
Link Text
And then:
$('a[target=_blank]').click(function(){
var prefix = 'http://domain.com';
window.open(prefix + $(this).attr('href'));
});

Invoking Link in Javascript or jQuery

I have an href taged object (graphic) on a page that I want to programatically click on. However,I can't figure out how to reference the object. Here is the tag:
<div id="getthebutton">
<div>
<a onmouseout="MM_swapImage('btn123','','http://www.comp.com/img/btn_img.png',1)" onmousedown="MM_swapImage('btn123','','http://www.comp.com/img/buttons/btn_inv.png',1)" onmouseover="MM_swapImage('btn123','','http://www.comp.com/img/buttons/btn_inv.png',1)" href="javascript:do_activity("param1", 1);">
<img id="btn123" width="180" height="60" alt="" src="http://www.comp.com/img/buttons/other_btn.png"/>
</a>
</div>
</div>
How do I click on this thing? If I read this right "btn123" is just an image file.
To programmatically click on that you would have to do something like this
$("a").click();
Of course it helps to have an event handler assigned first, but it is really that simple :)
Using parentNode will give you access to the <a> tag, but I don't know if that helps you, cause I'm not sure what exactly you are doing.
document.getElementById("btn123").parentNode
I believe in jQuery, it is parent():
$('#btn123').parent()
So you could probably do:
$('#btn123').parent().click()
First off, you should really listen to the comments (javascript: links == dark side). That being said ...
$("div#getthebutton div a").click();
In this case, the anchor has a javascript href-value. Understanding that you have no control over the source, your only other option would be to evaluate the value of the HREF:
// run the href-javascript from the parent anchor
eval($("#btn123").parent().attr("href"));
Invoking a click from the code will not invoke the javascript code. As such, you must evaluate it instead.
If you want to get the result of clicking on the image, from the code I would say your JavaScript should simply be:
do_activity("param1", 1);
That's what ultimately happens when the image is clicked by a human. This bypasses the 'click' events, so you might miss out on some side-effects, but it's what I'd try first.

Unobtrusive Javascript: Removing links if Javascript is enabled

I'm using PopBox for magnifying thumbnails on my page.
But I want my website to work even for users which turned javascript off.
I tried to use the following HTML code:
<a href="image.jpg">
<img src="thumbnail.jpg" pbsrc="image.jpg" onclick="Pop(...);"/>
</a>
Now i need to disable the a-Tag using javascript, otherwise my PopBox won't work.
How do I do that?
Just put the onclick on the a-tag:
<img ...>
Make sure to return false either at the end of the function (here Pop) or inline like in the above example. This prevents the user from being redirected to the link by the <a>'s default behaviour.
Put the onclick event onto the link itself, and return false from the handler if you don't want the default behavior to be executed (the link to be followed)
You could give all your fallback anchor tags a particular classname, like "simple"
Using prototype, you can get an array of all tags using that class using a CSS selector, e.g.
var anchors=$$('a.simple')
Now you can iterate over that array and clear the href attributes, or install an onclick handler to override the normal behaviour, etc...
(Edited to add that the other methods listed above are much simpler, this just came from a background of doing lots of unobtrusive javascript, where your JS kicks in and goes and augments a functioning HTML page with extra stuff!)
May I suggest, in my opinion, the best solution? This is using jQuery 1.4+.
Here you have a container with all your photos. Notice the added classes.
<div id="photo-container">
<a href="image1.jpg">
<img class="popup-image" src="thumbnail1.jpg" pbsrc="image1.jpg" />
</a>
<a href="image2.jpg">
<img class="popup-image" src="thumbnail2.jpg" pbsrc="image2.jpg" />
</a>
<a href="image3.jpg">
<img class="popup-image" src="thumbnail3.jpg" pbsrc="image3.jpg"/>
</a>
</div>
An then you make a single event handler this way:
<script type="text/javascript">
$(document).ready(function(){
var container = $('#photo-container');
// let's bind our event handler
container.bind('click', function(event){
// thus we find (if any) the image the user has clicked on
var target = $(event.target).closest('img.popup-image');
// If the user has not hit any image, we do not handle the click
if (!target.length) return;
event.preventDefault(); // instead of return false;
// And here you can do what you want to your image
// which you can get from target
Pop(target.get(0));
});
});
</script>
The href attribute is not required for anchors (<a> tags), so get rid of it...
<a id="apic001" href="pic001.png"><img src="tn_pic001.png"></a>
<script type="text/javascript">
document.getElementById("apic001").removeAttribute("href");
</script>
This method will avoid library contention for onclick.
Tested in IE6/FF3/Chrome. Side benefit: You can link directly to the portion of the page containing that thumbnail, using the id as a URI fragment: http://whatever/gallery.html#apic001.
For maximum browser compatibility, add a name="apic001" attribute to the anchor tag in your markup ('name' and 'id' values must be identical).
Using jQuery, dojo, Prototype, etc. you should be able to do the removeAttribute on multiple, similar anchors without needing the id.
You should be able to mix and match the return false from Chris's idea with your own code:
<a href="image.jpg" onclick="return false;">
<img src="thumbnail.jpg" pbsrc="image.jpg" onclick="Pop(...);">
</a>
If someone has Javascript disabled, then their browser ignores the onclick statement in both elements and follows the link; if they have Javascript enabled, then their browser follows both OnClick statements -- the first one tells them not to follow the <a> link. ^_^

Categories

Resources