Capturing the anchor tag - javascript

I've written a JavaScript code which over-ride the native alert() method.
I need to capture the HTML element which comprises the code of alert() execution.
First two cases are examples. I have printed the elements in console.log.
Case 1 - Capturing the <script> tag:
HTML: <script> alert(1); </script>
JS:
window.alert = function()
{
console.log(document.currentScript); // <script> is printed
}
Case 2 - Capturing the <img> tag:
HTML: <img src='1' onerror="alert(1)">
JS:
window.alert = function()
{
console.log(arguments.callee.caller.arguments[0].target);
// arguments.callee --> console.log()
// arguments.callee.caller --> onerror(event) {}
// arguments.callee.caller.arguments[0] --> event
// arguments.callee.caller.arguments[0].target --> <img>
}
Case issue - Capturing the <a> tag:
HTML: Click here for alert
JS:
window.alert = function()
{
console.log( // how to find <a> element)
}
Please don't suggest me to modify the HTML by including IDs for <a> or something similar. Consider that the HTML is purely static, and I can't modify anything. I can just add a JavaScript, and I just wan't to know how this can be done.

You might be able to find such alerts and convert them to click events. Something like this. Note the click event alert call could be made much more sophisticated and potentially use eval(), but i leave that for you to risk.
window.alert = (function(){
var selected = document.querySelectorAll("a[href^='javascript:alert('");
Array.from(selected).forEach(function(item){
var old = item.href
item.addEventListener("click", function(){ alert(old.substring(11)); });
item.href="javascript:void(0);";
});
var _alert = function(msg) {
console.log(msg);
console.log(arguments.callee.caller.arguments[0].target);
};
return _alert;
})();
test

You can use load event at window; click event at selector "a[href='javascript:alert(1);']" to get value of href attribute; call event.preventDefault() within click handler; String.prototype.match() to create array of values withing href attribute; define matches globally; new Function(); Function.prototype.call() to set this to <a> element; call .click() on selector : <a> element with matched parameters returned by .match()
window.alert = function() {
console.log(arguments, this)
}
window.addEventListener("load", function() {
a = document.querySelector("a[href='javascript:alert(1);']");
a.addEventListener("click", function(event) {
event.preventDefault();
var data = this.href.replace(/javascript/, "");
matches = data.match(/\w+(?=\()|(\(.*\))/g);
matches[1] = matches[1].replace(/\(|\)/g, "");
var fn = new Function(matches[0] + ".call(a, matches[1])");
fn();
});
a.click();
});

Don't use the href attribute to call JavaScript. It should be avoided. It is not recommended usage. Use the onclick event instead. See here: https://stackoverflow.com/a/10242595/5969411
<script>
window.alert = function(msg, element) {
console.log('Msg:', msg);
console.log('Element:', element);
};
</script>
Test 1
Test 2
Test 3
I've returned false from the onclick event above in order to repress the anchor from going to '#' URL directive, but you could easily return true instead here, if you wish.

Related

jQuery nested functions

I am still new to JavaScript and jQuery, so I am confused as to why the following code is not working as I anticipated. All I am trying to do is save input on a button click (id=recordInput) and display it with another button click (id=displayInput). What I observe is that tempInput is stored, (the code works until that point) but assignment of displayInputs onclick attribute is not executed. My question is, can you not nest a $().click() call inside of another &().click() call?
<script>
$(document).ready(function () {
$('#recordInput').click(function(event) {
var tempInput = $('#testInput').val();
&('#displayInput').click(function(event) {
console.log(tempInput);
});
});
});
</script>
My thinking is this in pseudocode:
assign recordInput onclick attribute to the following function:
store tempInput
set displayInput onclick to alert the tempInput value
what is wrong with my thinking?
NOTE: I did not include any html tags but all of the ids are referenced correctly
It's not working because you have put & instead of $ here
$('#displayInput').click(function(event) {
Fixing this may work, but you shouldn't set event handlers this way. Because every time your first handler function is called it will set an event handler for the second one. You can try with your console.log and you will see that the number of console.log is increasing by every click on #recordInput. So you should better set it like this :
var tempInput;
$('#recordInput').click(function(event) {
tempInput = $('#testInput').val();
});
$('#displayInput').click(function(event) {
console.log(tempInput);
});
I would change
$(document).ready(function () {
$('#recordInput').click(function(event) {
var tempInput = $('#testInput').val();
&('#displayInput').click(function(event) {
console.log(tempInput);
});
});
});
to
$(function(){
var testInput = '';
$('#recordInput').click(function(){
testInput = $('#testInput').val();
});
$('#displayInput').click(function(){
if(testInput !== ''){
console.log(testInput);
}
});
});
You are using & instead of $. Of course, you don't have to format the code exactly like I did.

Modify target url in onclick handler

Is it possible to modify the target URL in the onclick handler? How?
I don't want to use things like window.location = ... because it changes the browsers' behaviour (click vs ctrl-click, opening in new tab, opening in particular window/frame etc...). I want a clean solution - just change the url and the rest should be done itself as it would normally be.
$(...).click(function () {
if (check_some_condition)
// modify target url here...
// do not want to do window.location= - this is not clean
// as it changes the browsers' behaviour (ctrl-click, opening in particular window/frame etc.)
return true;
});
Try
​$(function(){
$("#theLink").click(function(){
$(this).attr("href","http://tnbelt.com");
});
});​​​​
Edit: Updated code because the event handler script is executed first and then the default action takes place.
Added below version to show you that you can use .click as you didn't notice the quirks mode link I shared with you. DEMO
$(document).ready (function () {
$('#changeMe'). click (function (e) {
var goLucky = Math.floor(Math.random()*12);
if (goLucky % 2 == 0) {
this.href = "http://www.google.com";
} else {
this.href = "http://www.hotmail.com";
}
});
});
Commented e.preventDefault(); & $(this).click() as it is not required..
DEMO
$(document).ready (function () {
$('#changeMe').one ('click', function (e) {
//e.preventDefault();
this.href = "http://www.google.com";
//$(this).click();
});
});
Let us consider a hidden anchor tag
<a id="linkId" href="myPageToGo.html" class="thickbox" title="" style="visibility:hidden;">Link</a>
Then you can simulate the anchor click in your code...
$(...).click(function () {
if (check_some_condition)
$('#linkId').click();
return true;
});
EDIT - Alternative way
Wrap the element clicked inside a anchor tag...
$(...).click(function () {
if (check_some_condition)
$(this).wrap('<a id="new1" />');
$('#new1').click();
return true;
});
Yup.
$(this).attr('href', 'http://example.com/');
A lot of the answers including the top comment have missed out on an important point. If a user simply right clicks the URL to perhaps open in a new tab/window, this method won't work because you're directly requesting at the location specified by the 'href' URL instead of going through the onclick event.
You could try the same at this demo fiddle mentioned on Gourneau's post.
http://jsfiddle.net/skram/PtNfD/7/
$(document).ready (function () {
$('#changeMe').one ('click', function (e) {
this.href = "http://www.google.com";
});
});

How can I attach event to a tag which is in string form?

I'm creating html on runtime like this:
var myVar = "<div id='abc'>some clickable text</div>"
Now, I want to attach some event, say onclick, to this div. How can I do that on next line? I'll add this to DOM later.
PS: I've to accomplish this without using JQuery.
Instead of building your div as a string, you'll want to use document.createElement('div'). This way you will have a real dom object, and can get and set it's propeties, including onClick
Will this help? Since you dynamically generate it, you know the control id of the DIV.
document.getElementbyId('abc').onClick = foo;
function foo()
{
alert("All your impl to go here");
}
Try building the div as a DOM element first.
var myVar = document.createElement("div"),
parentDiv = document.getElementById("parent_div");
parentDiv.appendChild(myVar);
myVar.innerHTML = "some clickable text";
if(myVar.addEventListener){
myVar.addEventListener("click", clickFn, false);
}
else if(myVar.attachEvent){
myVar.attachEvent("onclick", clickFn);
}
else{
myVar.onclick = clickFn;
}
The addEventListener method is standard, but not every browser plays nice with the standard.
EDIT: As mentioned, an element must be added to the DOM first.
Or you can use this technique: attach event to the document.body. Then if the event target is not the needed div than just do nothing. It is the same techinque jquery uses for its live function:
// crossbrowser event attachment function
function listen(evnt, elem, func) {
if (elem.addEventListener) {
elem.addEventListener(evnt, func, false);
}
else if (elem.attachEvent) {
var r = elem.attachEvent("on" + evnt, func);
return r;
}
else window.alert('I\'m sorry Dave, I\'m afraid I can\'t do that.');
}
// this is an analog of the jquery.live
var assignLiveEvent = function(id, evnt, callback) {
var handler = function(e) {
e = e || window.event;
e.target = e.target || e.srcElement;
if (e.target.id == id) {
//your code here
callback(e);
}
};
listen(evnt, document.body, handler);
};
var myVar = "<div id='abc'>some clickable text</div>";
assignLiveEvent("abc", "click", function(e) {
//your code here
});
// now you can add your div to DOM even after event handler assignation
Here is demo.
Brian Glaz is totally right but, if for some reason, you really need to do it this way, you have two options:
you can only add events to something that is already in the DOM, using pure javascript, so you would have to include it in the html like:
document.body.innerHTML += myVar;
and then, attach the event with
document.getElementById('abc').addEventListener('click', function(e){
//your code
}, 1);
With jQuery, you could use .live() to attach events to elements that are not yet present in the DOM:
$('#abc').live('click', function(e){
//your code here
});
so you could add the div later...

Javascript: embedding a result of a function into a HREF

I have a javascript function that reformats a link. When a HREF link is clicked, I need to execute this method to finish creating the HREF.
Example JS method:
function fixURL (dest, val){
return dest + val;
}
I have an regular HREF and would like to combine the result of the above method to create:
<a href="http://www.site.com/" + fixURL('poo','no')>Click me!</a>
Is this possible and is it ideal to do so?
You can use an onclick handler. Note, you're generally better off not using inline event handlers like onclick="something...", so this is just for demonstration purposes.
Also, this will try to open a new window/tab with the search result.
<a target="_blank"
href="https://www.google.com/search?q=chris+rock"
rel="chris+rock|dave+chappelle"
onclick="fixURL(this)">Test</a>
function fixURL(el){
var vals = el.rel.split('|');
el.href = el.href.replace(vals[0],vals[1]);
}
http://jsfiddle.net/sxtuz/1/
The same effect, only using DOM event handlers. Note the id="fixme" attribute.
<a id="fixme"
target="_blank"
href="https://www.google.com/search?q=chris+rock"
rel="chris+rock|dave+chappelle">Test</a>
function fixURL(el){
var vals = el.rel.split('|');
el.href = el.href.replace(vals[0],vals[1]);
}
window.onload = function(){
document.getElementById('fixme').onclick = function(){
fixURL(this);
};
}
http://jsfiddle.net/sxtuz/
You can embed the result of a function into a href, yes, but the function call cannot be inlined within the HTML. Try this:
A link
<script type="text/javascript">
!function(links) {
links[links.length-1].href+=fixURL('arg1', 'arg2');
}(document.getElementsByTagName('a'));
</script>
If you keep it as:
Click Me!
You can then use jQuery to do:
$("a[href='http://www.site.com/']").attr("href", "http://www.site.com/" + fixURL('poo','no'))
Explanation:
The $("a[href='http://www.site.com/']") matches a element with an existing href equal to http://www.site.com/, then changes its href attribute to the second parameter that you pass in. In this case "http://www.site.com/" + fixURL('poo','no')

edit in place with jQuery selecting newly inserted elements

I am trying to write my own edit-in-place using jQuery. My code is something like this;
$(".comment-edit").bind({
click: function(){
commentId = $(this).parent().parent().attr("id");
commentEditable = $("#"+commentId+" .comment-text");
if (commentEditable.hasClass('active-inline')) {
alert("already editable aq");
return false;
}
contents = $.trim($("#"+commentId+" .comment-text").text());
commentEditable.addClass("active-inline").empty();
var editBox = '<textarea id="newComment"cols="50" rows="6"></textarea><button class="newCommentSave">Save</button><button class="newCommentCancel">Cansel</button>';
$(editBox+" textarea").val(contents).appendTo(commentEditable).focus();
$.(".newCommentSave").live({
click: function(){
alert("Save");
return false;
}
});
$.(".newCommentCancel").click(function(){
alert("Cancel");
return false;
});
return false;
}
});
As you can see I tried both "live()" and "click()" for interacting with the newly created buttons. However this doesn't work.
I am getting XML filter is applied to non-XML value (function (a, b) {return new (c.fn.init)(a, b);})
Any ideas? What seems to be going wrong?
Edit:
Html looks something like this:
<div class="comment" id="comment-48">
<div class="comment-author">
defiant
<span class="date">2010-11-09 01:51:09</span>
</div>
<div class="comment-text">Comment Text....</div>
</div>
The problem is here:
var editBox = '<textarea id="newComment"cols="50" rows="6"></textarea><button class="newCommentSave">Save</button><button class="newCommentCancel">Cancel</button>';
$(editBox+" textarea").val(contents).appendTo(commentEditable).focus();
editBox is a string, so you're getting this as a result:
$("<textarea/><button /> textarea")
...which isn't XML or a valid selector, throwing an error. Instead you want this:
$(editBox).filter("textarea").val(contents)
.end().appendTo(commentEditable).focus();
This gets the <textarea> from that object you just created via .filter() (since it's a root level element), sets the contents, then uses .end() to hop back in the chain to $(editBox) which contains both elements to append. This would focus the button though, so you may want this instead:
$(editBox).appendTo(commentEditable).filter("textarea").val(contents).focus();
As it turns out, the reason for XML error was a "."
$.(".newCommentSave").live({
// stuff
})
The dot after the dollar sign is what causing this error. At least the code was working fine without it.
I tend to do something like this to attach a click event (to a span in my example)
var span = $("<span>some text</span>");
span.click( function() { alert('yay'); });
I'd break down your editBox variable into three different variables and see what happens then.
The .live() syntax is .live('event', function), I don't think it accepts a map of event:function pairs.
So would something like this work?
$.(".newCommentSave").live('click', function(){
alert("Save");
return false;
});
I'm not sure why your .click() handler didn't work though.

Categories

Resources