jQuery .click() does not work in Safari - javascript

I have seen several similar posts with solutions that seemed to have worked for those people, but I CANNOT get this to work.
I am using http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/ in my project. It works PERFECTLY, in all browsers, except in Safari the "BROWSE" button does not open a file dialog. The following code exists in script.js (which is included for the plugin to work):
$('#drop a').click(function(){
// Simulate a click on the file input button
// to show the file browser dialog
$(this).parent().find('input').click();
});
The .click() does not fire in Safari. I have tried the solution as per jQuery .click() works on every browser but Safari and implemented
$('#drop a').click(function(){
var a = $(this).parent().find('input');
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);
a.dispatchEvent(evObj);
});
But then I get the error that dispatchEvent is not a function. I then did some research on this, and tried the jQuery.noConflict() route, but this did not resolve the error. Also, I use a LOT of jQuery in my main file and I cannot have the noConflict() mode activated for the entire page. There is also no reason that the jQuery should be conflicting with anything as I am only using jQuery and normal javascript and I am not using anything like prototype or angular. Does anybody know of another way to simulate a click in Safari?
UPDATE: Just FYI, I have added an alert('test') in the mentioned function (which triggers when "BROWSE" is clicked), and I do get the alert in Safari, but it is not simulating the click of the file input element, i.e: it is not openening the file dialog.

The second section of code in my original question turned out to work, except for 2 things.
1) The method does not like jQuery, so instead of
var a = $(this).parent().find('input')[0];
I assigned an ID to my file input and instead called
var a = document.getElementById('upload_select');
2) Safari blatantly ignores this if the input is hidden (display:none;), which is was, so instead I made the input font-size = 1px; and opacity = 0.
Implementing these two changes got the code working.

You need to read that answer more closely. :-)
dispatchEvent is a function on the DOM element, not the jQuery object. You're trying to call it on the jQuery object. So:
$('#drop a').click(function(){
var a = $(this).parent().find('input')[0];
// Change here -----------------------^^^
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);
a.dispatchEvent(evObj);
});
Using the [0] on the jQuery object gives you the first DOM object in the jQuery object, or undefined if the jQuery object is empty.

Related

Suppressing an onclick link event without stopping the actual page re-direct

Is there a way to disable the onclick function but still use the href to re-direct the user to the requested link. Example a header menu there are many links that looks like below :
Phones
I am unable to remove the "DA_A('id', ':per:shop', this.href); return false;" from the HTML page. However using a tag manager how would one go about injecting a snippet of JavaScript code function which will de-activate/mute the "DA_A" function but still make the link work as normal? Is it possible? It seems the function "DA_A" is a function that calls another ".push" function and pass some data.
What are my options? as I am unable to edit the menus in questions?
You can probably remove the onclick from the element if you can run some javascript after the DOM renders:
var anchor = document.getElementById("someId"); // or tagname, querySelector, etc
anchor.onclick = "";
You could also disable the function it calls altogether, depending on whether it is needed elsewhere:
window.DA_A = function() { /* do nothing */ };
The first snippet would need to be run after the DOM was rendered (for example, if you are using jquery then enclose it in a $(function() {})), and the second snippet would need to run after the DA_A function is defined in the first place.
Either of these by themselves should disable the onclick, but still allow the anchor to navigate.
this code snippet will do the trick:
window.onload = function()
{
document.querySelctor("a").removeAttribute("onclick"); // make selector more specific
};

How to remove an event out of content script scope?

I'm trying to unbind an event from a specific element and upon research, I found this. Which is useful. In itself. I didn't know you could do that. But:
Is there a way to make it work in a browser/Chrome extension? I'm talking about content scripts.
The reason why this doesn't work the way it's described there is that the website which has attached the event in question with its own script is using a different jQuery object than the one in my extension's includes/ folder. And I can try to search the event via jQuery._data(el, 'click'); but that is my jQuery object, not the one of the website where the events are apparently stored. I'm glad I figured that out after hours of fiddling around.
Or maybe it is possible to access the website's jQuery object itself?
EDIT:
What I'm ultimately trying to achieve works in theory but … it's complicated. The original script uses a plugin event and keeps reinstalling it with .on('mouseleave',….
Anyway, this is what I got thanks to you, pdoherty926:
var $el = $('div.slideshow');
$('h2', $el).click(function(){ console.log('ouch!'); }); // test event
var $slides = $('.slides', $el).detach();
$copy = $el.clone(false);
$slides.prependTo($copy);
$el.replaceWith($copy);
The test event doesn't get triggered but the event I'm actually trying to remove still fires. I can imagine figuring it out, though, now that I got closer to my goal.
Okay, the aforementioned re-installation on mouseleave really messed up this otherwise satisfying suggestion. (The site is using the jQuery Timer plug-in by Cyntaxtech). So here's how I solved it instead: I simply changed the class name (-.-' )
Now the re-installation code cannot find the element anymore.
This is how my finished script looks like:
function stop_happening() {
var $el = $('div.fullwall div.slideshow');
$el
// first, stop the current automation.
.timer('stop') // Timer plug-in
// next, change class name in order to prevent the timer
// from being started again.
.removeClass('slideshow').addClass('slideshow-disabled-automation');
//--- copied some extra code from the website itself for the onclick
// events which are supposed to keep working. I wish I could do *that*
// programmatically but I'm glad I got as far as I got. ---//
// […]
}

Programmatically activating a custom TinyMCE button

I've got a lot of custom buttons on my TinyMCE toolbar, most of which open a dialog box with some further options in when you click them. This all works fine.
Here is an example of something in my tinyMCE_setup() function:
ed.addButton('link2', {
title: '{!link!}',
image: '../style/common/images/link_20x20.png',
onclick: function() {
replyBoxDialog('link', ed);
}
});
However, I want to be able to call these programatically, and faking a .click() on the button with jQuery won't cut it.
I've tried calling the function directly
replyBoxDialog('link',tinyMCE);
But no matter what I try as the second argument, I can't get the right object (so it fails when it's time to insert something into the editor, as it doesn't know what the editor is).
I've also had a try with various execCommand() calls, but I've no idea what to put in there.
Any clues?
All you have to do is to use a real editor object as paramter
var editor_instance = tinymce.activeEditor; // in case you just use one editor
var editor_instance = tinymce.get('my_special_editor_id'); // in case you have more than one editor
replyBoxDialog('link', editor_instance);
I've managed to make it work by creating a variable 'globalEd' at the top of the script and adding globalEd = ed; to tinyMCE_setup(), then I can call replyBoxDialog('dragndrop', globalEd);. This seems like a properly hacky way of doing things though, so I'd welcome any further advice.

mootools and jQuery conflict

I've got a simple form in a page that is loading Mootools and JQuery. JQuery is in no conflict mode, which seems like it ought to cause no problems.
There's a form element called "name"--
<input class="required" id="sendname" name="sendname" value="">
And I'm trying to attach a click event to it using Mootools to update something else when the name box is clicked:
$('sendname').addEvent('click', function(e){
// do stuff.
});
The problem is that the click event never gets added.
This error appears on load:
Uncaught TypeError: Cannot call method 'addEvent' of null
When I try to interact with the element in a js console, I get the following error:
> $('sendname').setProperty('value', 'test');
TypeError: Object sendname has no method 'setProperty'</strike>
EDIT: the previous was fixed by loading a newer Mootools. However, the click event still isn't functioning properly, though it throws no errors or warning.
This code works fine in almost any situation I've used it in. I assume there's some issue with jQuery conflicting, but the fact that the $ notation works seems to confirm that noConflict mode is operational. Any ideas?
You are targetting the element wrongly... I think this has nothing to do with a possible conflict.
In this case you need to add the hash for an id or a period for a class, like this:
$('#sendname').addEvent('click', function(e){
// do stuff.
});
Notice the # in #sendname
MooTools has Dollar Safe mode that automatically releases the $ to other libs as long as MooTools is loaded last.
If Dollar Safe mode is active, you need to use:
document.id('SomeElementID').someMethod()
What is happening in the example you are giving, is that you're using jQuery to select the element, and a MooTools method on the result. The thing is, jQuery returns the jQuery object which has no such 'addEvent' method on it. MooTools works on the actual elements so you need to select them with a MooTools query method first: $ == document.id or $$ == document.search
You can cache document.id to a var for convenience if you want:
var $M = document.id;
$M('sendname').addEvent(...)
As described in the comments to the OP, the issue was the load-order of the jQuery/Mootools scripts. The jQuery noConflict was being loaded too late, and causing problems. Please see jsfiddle -- http://jsfiddle.net/uSwzL/1/
Without any problem even loading jquery.js after other $ based library loaded:
<script>$=function(){alert('hell');}</script>
<script src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<script>
$.noConflict();
$();
alert(jQuery.trim(' hello '));
</script>
Even in php framework html template:
<script>
function on_doc_ready()
{jQuery(function($)
{$( "#sortable" ).sortable();
$( "#sortable" ).disableSelection();
}
);
}
function load_jquery_ui()
{var s2=document.createElement('scr'+'ipt');
s2.setAttribute('onload', 'on_doc_ready();');
s2.src='/app/idm/statics/jQuery/js/jquery-ui-1.10.0.custom.min.js';
document.getElementsByTagName('head')[0].appendChild(s2);
}
function load_jquery_after_mootools()
{var s1=document.createElement('scr'+'ipt');
s1.src='/app/idm/statics/jQuery/js/jquery-1.9.0.js';
s1.setAttribute('onload', '$.noConflict();load_jquery_ui();');
document.getElementsByTagName('head')[0].appendChild(s1);
}
load_jquery_after_mootools();
<script>

How can I tell if a page has jumped to the anchor (#) in JavaScript?

I have some JavaScript that can appear on many different pages. Sometimes those pages have been accessed via a URL containing an anchor reference (#comment-100, for instance). In those cases I want the JavaScript to delay executing until after the window has jumped. Right now I'm just using a delay but that's pretty hackish and obviously doesn't work in all cases. I can't seem to find any sort of DOM event that corresponds to the window "jump".
Aside from the simple delay, the only solution I've come up with is to have the JS look for the anchor in the URL and, if it finds one, watch for changes in scrollTop. But that seems buggy, and I'm not 100% sure that my script will always get fired before the scrolling happens so then it would only run if the user manually scrolled the page. Anyhow, I don't really like the solution and would prefer something more event driven. Any suggestions?
Edit to clarify:
I'm not trying to detect a hash change. Take the following example:
Page index.php contains a link to post.php#comment-1
User clicks the link to post.php#comment-1
post.php#comment-1 loads
$(document).ready fires
Not long later the browser scrolls down to #comment-1
I'm trying to reliably detect when step 5 happens.
You can check window.onhashchange in modern browsers. If you want cross compatible, check out http://benalman.com/projects/jquery-hashchange-plugin/
This page has more info on window.onhashchange as well.
EDIT: You basically replace all anchor names with a similar linking convention, and then use .scrollTo to handle the scrolling:
$(document).ready(function () {
// replace # with #_ in all links containing #
$('a[href*=#]').each(function () {
$(this).attr('href', $(this).attr('href').replace('#', '#_'));
});
// scrollTo if #_ found
hashname = window.location.hash.replace('#_', '');
// find element to scroll to (<a name=""> or anything with particular id)
elem = $('a[name="' + hashname + '"],#' + hashname);
if(elem) {
$(document).scrollTo(elem, 800,{onAfter:function(){
//put after scroll code here }});
}
});
See jQuery: Scroll to anchor when calling URL, replace browsers behaviour for more info.
Seems like you could use window.onscroll. I tested this code just now:
<a name="end" />
<script type="text/javascript">
window.onscroll = function (e) {
alert("scrolled");
}
</script>
which seems to work.
Edit: Hm, it doesn't work in IE8. It works in both Firefox and Chrome though.
Edit: jQuery has a .scroll() handler, but it fires before scrolling on IE and doesn't seem to work for Chrome or Firefox.
To detect when the element appears on the screen, use the appear plugin:
$('#comment-1').appear(function() {
$(this).text('scrolled');
});

Categories