How to access hidden buttons and click them - javascript

I am trying to make a web page easier to use. At the moment, there is a drop down menu with a 'Delete' button. When I inspect, it looks like this:
<a title="" class="ajax-command" command="deletePost" href="#">Delete</a>
Is there any way I can execute this somehow? I am trying to create a new button that executes this command without the need of the dropdown. It is part of a set of buttons under this dropdown menu:
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li class="item">
I have tried just replicating the click of the drop down selection, but I can't get it to work. Any help would be great!

jquery solution
$(".ajax-command[command='deletePost']").click()

Simulate the click event on the link, it doesn't matter that it's hidden. I'll demonstrate this here by writing script that clicks meta link in hidden stackoverflow dropdown to the left:
// Straight from MDN
var evt = new MouseEvent("click", {
bubbles: true,
cancelable: true,
view: window
});
var cb = document.querySelectorAll("div.js-help-dialog li:nth-child(3) a.js-gps-track");
var canceled = !cb[0].dispatchEvent(evt);
This is what you should do. If you try to run their AJAX request you will find yourself re-inventing half of the whole application frontend.

Related

X-Editable AJAX call not working after disabling / enabling

I recently stumbled across a problem with enabling / disabling X-Editable forms which I have (after days of trying) not been able to solve yet. Any help would be greatly appreciated.
I've created a fiddle containing the core of my problem:
http://jsfiddle.net/xBB5x/11749/
I have multiple labels which are editable;
The input should be submitted to a server using ajax;
Up to here everything works perfect. But then there is also a button who is basically just disabling and enabling (right after disabling) the x-editable functionality.
If you click this button before you edit the labels - the AJAX call isn't made.
Things you might find suspicious:
The selector: In my (simplified) example, the selector isn't actually needed. It's there because parts of our application are dynamically (re)loaded.
Why am i trying to do this? I have multiple labels which should all be editable - but only one at I time. So if the focus changes, I disable all of them and enable the one who just got the focus. Well, at least I try to do that...
Thanks for any help!
Here's the HTML:
<button type="button" id='thebutton'>Don't click Me!</button>
<div style="margin: 150px" id='navi'>
<h4>
<a href="#" class='title'>awesome 1</a>
</h4>
<h4>
<a href="#" class='title'>awesome 2</a>
</h4>
<h4>
<a href="#" class='title'>awesome 3</a>
</h4>
</div>
<div id='output'>
...
</div>
And here's the JS:
$('#navi').editable({
selector:'.title',
url: function(params) {
$.ajax({
url: '/echo/js/?js=SUBMITTED!',
complete: function(response) {
$('#output').html(response.responseText);
},
error: function() {
$('#output').html('Bummer: there was an error!');
},
});
},
send: 'always'
});
jQuery('body').on('click', '#thebutton', function () {
$('.title').editable('toggleDisabled');
$('.title').editable('toggleDisabled');
})
Edited - Some additional information:
We have a navigation (which is basically a "folder structure") which is created by the user. This means the user should be able to add additional navigation items and rename them if he wants. The user is only allowed to rename the active item. The content of each item gets dynamically loaded in the main panel.
The Navigation
So when the user selects an item, the following script is run (which disables x-editable functionality on all links and reactivites it on the new active one:
if (!$(this).hasClass("active")) {
// Load content to the main panel
DisplayOpRiskLeaf($(this).attr('id'));
// Change active navigation element
$('.oprisk-link').removeClass("active");
$(this).addClass("active");
$('.oprisk-leaves-panel').removeClass("active");
$(this).parents('.oprisk-leaves-panel').addClass("active");
// Change x-editable...
// disable all ($(this) is also getting disabled here)
$('.portfolio-title').editable('option', 'disabled', true);
// enable the active elemnt
$(this).editable('option', 'disabled', false);
}

External link with Bootstrap 3 Tabs using JQuery

I'm using tabs with Twitter Bootstrap 3 and want one of them to function as an external link that opens a new window. I removed the data-toggle="tab" and added some JQuery to accomplish this. The code below doesn't work and gives me the following error message, however if I add class="active" to the li element, it works perfectly (other than that tab having incorrect styling). Why is this the case? How can I alter my code so I don't need class="active" on the parent li?:
HTML:
<li>
<a href="https://www.google.com/" class="external-link" target="_blank">
<span class="nav-text-wrapper">Example Tab Name</span>
</a>
</li>
Javascript:
$('.external-link').click(function(){
window.open($(this).attr('href'));
});
EDIT:
I found the solution. I had the following JQuery code to allow for nested tabs, but apparently this conflicted with me using external links on tabs
var $mainTabs = $('.tab-menu a');
$mainTabs.click(function (e) {
e.preventDefault();
$(this).tab('show');
});
How about this?
$('a.external-link').on('show.bs.tab', function (e) {
e.preventDefault(); // prevents the default tab selection behavior
window.open($(this).attr('href'));
});
show.bs.tab is an event that gets raised for a tab right before it is shown. By cancelling it with e.preventDefault(), you're interrupting the tab's show() function early on and inserting your own behavior. If you don't stop the show() function early like this, it will try to select the tab panel referenced in your href in order to show it. The error you were getting was because the tab plugin was trying to find a DOM element with a selector like this: $('https://www.google.com').

Using a bookmarklet to click Gmail's "Show original" button

When I have an email open in Gmail, I'm trying to click the "Show original" dropdown menu item programmatically. The IDs of all the elements change dynamically with each email, so that's not a reliable way to find the menu item I'm trying to click. To start, I'm just trying to make a piece of JavaScript that clicks it in Chrome's console. After loading jQuery, I've tried this:
jQuery('div[role=menuitem]:contains(Show original)').click();
While it seems to select the proper div and click it, it's not the expected behaviour and the click doesn't really do anything. Here's a piece of a fully loaded email's menu containing the menu item I'd like to click with JavaScript:
<div class="J-N" role="menuitem" aria-hidden="false" id="so" style="-webkit-user-select: none;"><div class="J-N-Jz"><div><div id=":173" class="cj" act="32"><img class="dS J-N-JX" src="images/cleardot.gif" alt="">Show original</div></div></div></div>
My intention is to use a bookmarklet, but I'm having trouble loading jQuery in a bookmarklet because of a security warning, but that's another question/issue. Also, should I try to open the dropdown before clicking the "Show original" button or is it likely that I am able to click this button without opening the menu first?
You must open menu at least once, so Gmail loads required menu elements.
To click on elements use dispatchEvent() straight on DOM elements (not jQuery collections)
Basic example might look like this:
// Create events
var mouseDownEvent = new MouseEvent('mousedown', { 'bubbles': true });
var mouseUpEvent = new MouseEvent('mouseup', { 'bubbles': true });
// Get DOM elements
var menu = jQuery("div[role='button'][aria-label='More']").get(0);
var button = jQuery("div[role='menuitem']:contains('Show original')").get(0);
// Open and close menu, to ensure button existence
menu.dispatchEvent(mouseDownEvent);
menu.dispatchEvent(mouseDownEvent);
// Click menu item
button.dispatchEvent(mouseDownEvent);
button.dispatchEvent(mouseUpEvent);
That will work only in Chrome, Firefox and Opera.

addClass in JQuery

I am pretty new in JQuery and I have a question about addClass(). I spent some time to try to get this working, but seems like I did something wrong. I created a top menu with HTML and bootstrap. I assume visitors will land on my index.php first, so I created the class="active" for my index.php. Then if they click on any other link on the top menu (ex. About Us), then the class="active" will add to the and remove the class="active" from the "li" tab for index.php.
Below is my HTML code:
<div class="nav-collapse collapse">
<ul class="nav pull-right">
<li id="home" class="active"> Home</li>
<li id="about"> About Us</li>
<li id="browse"> Browse</li>
<li id="contact"> Contact</li>
</ul>
</div>
And below is the JQuery code that I use and try to get this done.
$(function (){
var sidebar = $('.nav');
sidebar.delegate("li", "click", function(){
if($(this).hasClass('active')){
//If click on the tab that is currently active, it will do nothing.
}else{
sidebar.find('.active').addClass('inactive');
sidebar.find('.active').removeClass('active');
$(this).removeClass('inactive');
$(this).addClass('active');
}
});
});
I tested it out on my local server. I could see the tab in my top menu turned to grey after I clicked it, but it didn't stay. So I am sure I did something wrong, but not sure where. I am really new in JQuery, so I hope I can learn from you guys. thank you!
When the link is clicked on, it takes the browser to a whole new page which starts a whole new javascript environment and nothing you've done to the current page carries over to the newly loaded page.
Thus the active class may be changed on the current page, but then a whole new page loads which inherits nothing from the first page (e.g. it's starts over from scratch). Your code from the first page is no longer in play once the new page is loaded.
You need to either just code the active class into each separate page (since each page knows what page it is) or have one common set of JS that sets the active class when the page loads based on the URL so it is intialized properly when the page loads.
Also, you probably don't need an inactive class. The default CSS state can represent the inactive look and the active class can apply a CSS override to show the active state.
This is not working, because when someone clicks on another link, they are redirected to a different page. However, your header doesn't really know which link was clicked on nor which page it is on. You need to let your header know which page you are. Does this make sense?
The other answers are correct, when you click on the tag you are opening a new page and therefore losing your javascript environment.
If you want to have a single page app, you can use preventDefault to stop the browser from following the link.
sidebar.delegate("li", "click", function(e){
e.preventDefault();
if($(this).hasClass('active')){
//If click on the tab that is currently active, it will do nothing.
}else{
sidebar.find('.active').addClass('inactive');
sidebar.find('.active').removeClass('active');
$(this).removeClass('inactive');
$(this).addClass('active');
}
});

jQuery toggle not working when back button is hit

I have the following jQuery code:
$(function() {
var linkSet = $('#link1').add('#link2');
linkSet.click(function() {
linkSet.toggle();
if ($(this).attr('id')=='link1'){
$('#frame').attr('src', 'www.google.com');
} else if ($(this).attr('id')=='link2'){
$('#frame').attr('src', 'www.yahoo.com');
}
});
});
On pageload, the link with id link1 is shown while link2 is hidden. When the user click the link1, it will the link1 then show the link2 then vice versa. While toggle takes place, it also changes the source of an iframe which is named frame.
My problem here is when I hit back button, the content of the frame will go back to its previous content BUT the link are not changing. What did I missed here? Thanks in advance!
Note: The links are on a webpage, then inside that webpage is an iframe.
EDIT:
<div id="header">
<ul>
<li><a id="link1" href=#">Link1</a>
<li><a id="link2" href=#">Link2</a>
</ul>
</div>
<div id="iframe">
<iframe id="frame" src="www.google.com"></iframe>
</div>
You mean when pressing the browser's back button right.
If so:
The issue is you need to have an event to trigger when the history changes, as that is the only easy way to respond to changes in history (such as when clicking the back button). Since the iframe url is indeed changing, it is therefore also affected by the back button naturally.
To get other non history based logic to work when pressing the back button and such...
There are two ways to do this. The new one is by using the history API, while the other more supported, and simpler way is by adding a hash to the url.
WHAT DOES THIS MEAN?
When you click the button you change the url with a hash. Like the url can become
'http://domain.com/blah/#myHash'
Then instead of doing your logic in the click, you do it when the hash changes. So this way as the user clicks back and/or forward the logic always runs fully.
I wrote an entire article about this technique a few months ago at http://andresgallo.com/2012/06/08/ajaxifying-the-web-the-easy-way/

Categories