Same ID's in jQuery Tabs - javascript

I am using the jQuery Tabs library in a small application. The page has 5 tabs and the content for each page is loaded using Ajax. The problem is, once I load a tab, it remains in the browsers memory (and so do its HTML elements). So if I use lets say a DIV element with the same ID as a previously loaded tab, all JS function related to that ID try to interact with the old tab.
IN other words, lets say I have a page with 2 tabs, "Traffic Data1", "Traffic Data2". Now first, I click on the Traffic Data1 tab which makes the ajax call and loads the page just fine. This page, has 2 date input fields, id for the first field is "dateFrom" and the other field is "dateTo". Next to that is a "Go" button. Upon clicking the button, a JS function shows an alert box with the values in each of the input fields.
Now, I click on the "Traffic Data2" tab. The contents of the page are very different, but it has the identical input fields, 2 for dates (with same IDs) and Go Button. When I press the Go button on this page, I see the alert box with values form the previous tab.
So my question is, Is there a way to unload the previous tab? Or is the only alternative to use elements with unique divs (even though the pages are complete separate).
Thanks

You cannot have multiple element with the same ID. When you find an element by ID the first one found is always returned because it is expected that IDs will be unique.
Leave the name attributes for the input elements the same but change their IDs to be unique.
You can select an element by its name attribute like this: $('[name="foobar"]')
Update
In the docs for jQuery UI Tabs there is an option called cache that when set to false should remove the old tabs from the DOM after you navigate away from them:
Whether or not to cache remote tabs content, e.g. load only once or
with every click. Cached content is being lazy loaded, e.g once and
only once for the first click. Note that to prevent the actual Ajax
requests from being cached by the browser you need to provide an extra
cache: false flag to ajaxOptions.
Source: http://jqueryui.com/demos/tabs/

You are looking for jQuery Live.
Description: Attach an event handler for all elements which match the current selector, now and in the future.
If you use it jQuery will magically auto-update to match your new elements as they appear/disapear.
// code sample
$("a.offsite").live("click", function(){ alert("Goodbye!"); });

Since the tabs click event reloads your form and assuming you're using divs to contain the ajax-loaded content, add .click(function () { $(this).children('div').children.remove(); }) to your tabs() declaration.
That should remove the div content and any event handlers that are bound to it.

If you can pass a context to the jquery functions, you could make your calls relative to currently selected tab...
$("#someDuplicatedId", activeTab).doStuff();
Or if caching the content is not important, go with Jasper's answer.

Related

Content added to DevExtreme dxPopup not working unless Popup has been shown already

I am using a DevExtreme Popup that will show whenever a user selects an option from a SelectBox. The Popup will identify placeholder values inside the selected value and present the user options to replace them with.
When the SelectBox value changes, I look for placeholders and append a dxSelectBox for each placeholder to a div valuesList inside the popup.
var matches = selectedValue.match(templateRegex);
if (matches.length > 0) {
matches.forEach(function (m) {
var newDiv = $("<div/>");
newDiv.dxSelectBox();
newDiv.appendTo("#valuesList");
});
$("#myPopup").dxPopup("instance").show();
}
The problem is the first time this runs, it doesn't append anything to the Popup content. Using the debugger I confirm that the code does run, but nothing gets added. The popup shows with no content. However, if I select the value again in the SelectBox, it runs and the popup gets new content appended to it as it should, as well as all subsequent changes. It's only the first time that doesn't work.
I confirmed this by adding this to the JavaScript:
$(document).ready(function () {
$("#myValuePopup").dxPopup("instance").show();
$("#myValuePopup").dxPopup("instance").hide();
});
With that added, content is correctly appending the first time I select a new value from the SelectBox, confirming that it only works if the Popup has already been shown. This seems to be a sloppy solution though, and it requires adding a bunch of checks to the onHidden event handler for the Popup since some variables it uses aren't initialized yet, so I'd rather not have to resort to it.
Is there another way to pre-initialize the dxPopup? I couldn't find anything going through the documentation. And the Popup's _initialized property is true even before being shown the first time.
Update:
The dxPopup is created using Razor inside my View:
#(Html.DevExtreme().Popup()
.ID("myPopup")
.OnHidden("myPopupClosed")
.ContentTemplate(
#<text>
<div id="valuesList">
</div>
</text>
)
)

Chrome Extension, Append Element & Re-Append Across Page Changes

I have a Chrome Extension that, when its button is clicked, appends an element to the current page. However, I want to keep that element across pages; i.e., if the user clicks on a link, the new page loads, and then the element is appended.
I tried using window.onhashchange to detect page changes, check if the element was appended, and if not, append it, but that didn't seem to have any affect at all. Any tips on how to do this, or if it's possible? (preferably in javascript, no jquery)
some general description how would I do it, would be:
-when user clicks the button, append element and send msg to background to store that tab (ID)
-add listeners chrome.tabs.onCreated.addListener & onUpdated (in bg script)
-test newly created and updated tabs against your stored
-if newly created/updated tab is child of your stored tab (tabs), inject script for element appending or send msg to content script to append element
sample for BG script to start with:
chrome.tabs.onCreated.addListener(function(tab) {
console.log('tab id is'+tab.id);
console.log('opener is'+tab.openerTabId);
});
cople of things to be careful:
-openerTabId is undefined if link is dragged (extension for dragging links)
-those events are fired multiple times, so if you are sending msg to content script to append your element (or injecting), check it first
something like
if (yourElement) return;
else //append element
maybe there are better/simpler ways to achieve what you want... can't think of it right now
EDIT:
you actually don't need initial messaging when button is clicked, because listener for that button is already in bg script, and the whole process is very simple.

Text is not being rendered after new pages loaded - JQuery Mobile

I have a program that given an SQL statement (browser database using HTML5-SQL), it populates a set of field in my jquery mobile page. The SQL statement is changed based on an ID passed through the url. So when a button/link is clicked, the same page is called with a different parameter value: index.html?id=545.
Although the first page load seamless, when I click the link to the next page, the objects (page, buttons, link, div) show, but the text inside these objects doesn't show up.
I am using the $('div').live('pageshow',function(event, ui){ event in order to trigger the events of doing the following:
$("#title").text(Title);
$("#date").text(mdate);
When I print the value of Title and mdate in the console of Chrome debugger, it shows the right value. I don't know why the same text doesn't show in the buttons and labels.
Can anybody help me with this.
Thanks
When using jQM you need to refresh the controls. Here are the docs:
http://jquerymobile.com/demos/1.0/docs/forms/docs-forms.html
Refreshing form elements In jQuery Mobile, some enhanced form controls are simply styled (inputs), but others are custom
controls (selects, sliders) built from, and kept in sync with, the
native control. To programmatically update a form control with
JavaScript, first manipulate the native control, then use the refresh
method to tell the enhanced control to update itself to match the new
state. Here are some examples of how to update common form controls,
then call the refresh method:
Checkboxes:
$("input[type='checkbox']").prop("checked",true).checkboxradio("refresh");
Radios:
$("input[type='radio']").prop("checked",true).checkboxradio("refresh");
Selects:
var myselect = $("#selectfoo");
myselect[0].selectedIndex = 3;
myselect.selectmenu("refresh");
Sliders:
$("input[type='range']").val(60).slider("refresh");
Flip switches (they use slider):
var myswitch = $("#selectbar");
myswitch[0].selectedIndex = 1;
myswitch.slider("refresh");
if it's the page you need, try this:
http://jquerymobile.com/demos/1.0/docs/pages/page-scripting.html
Enhancing new markup The page plugin dispatches a pagecreate event, which most widgets use to auto-initialize themselves. As long
as a widget plugin script is referenced, it will automatically enhance
any instances of the widgets it finds on the page.
However, if you generate new markup client-side or load in content via
Ajax and inject it into a page, you can trigger the create event to
handle the auto-initialization for all the plugins contained within
the new markup. This can be triggered on any element (even the page
div itself), saving you the task of manually initializing each plugin
(listview button, select, etc.).
For example, if a block of HTML markup (say a login form) was loaded
in through Ajax, trigger the create event to automatically transform
all the widgets it contains (inputs and buttons in this case) into the
enhanced versions. The code for this scenario would be:
$( ...new markup that contains widgets... ).appendTo( ".ui-page" ).trigger( "create" );

How to handle Android's Back Button click in a single HTML page webapp using PhoneGap?

I read from the documentation that we can handle the back button click using the following code:
document.addEventListener("backbutton", backKeyDown, true);
function backKeyDown() {
// Call my back key code here.
alert('go back!');
}
My concern is that I have a single HTML5 web page in which I have multiple div tags which I animate using jQuery as per the navigation option selected by the user from the menu options.
How can I, in this single page webapp, handle the back button click using PhoneGap and show the user the previously animated div. Clicking on the back button again would again take him to the previous div of the current previous div :-)
Thanks.
I solved the problem by creating a global array variable as
var myStack = new Array();
Then whenever I clicked on the div tag, I inserted the function prototype along with the arguments inside the myStack variable. For eg:
myStack.push(\"myfunction(args1, args2);\");
Then, using the code which I posted in my question, inside the BackButton handler, I wrote the following code:
var divToShow = myStack.pop();
eval(divToShow);
Hope this helps others.
I did an implementation in a similarly structured phonegap app. My situation was a bit more complex because I was loading in html as well as external data via ajax (rather than just unhiding divs). I created a global array called history which I used to keep track of current position as well as previous positions (position here being the most recent ajax function called, so the array was actually storing function names as text). The right sequence and combination of .pop and .push array methods got me a fully functioning js back button that scaled nicely and handled any kind of back and forth navigation I could think of.
I will just post my overall idea of handling this situation. Hope you can improvise and change it to suit your needs.
Have a global variable to remember the current div id that is
visible. For example, when a menu item x is clicked, set this global
variable to the div id that is currently visible (before showing the next div corresponding to menu item x).
When the back button is pressed, use the global variable's value to identify the previous div. Hide the current div and show the previous one.

Can I cache an empty form template as a second page in browser?

can I cache an empty form template as a second page in browser cache
so that when you click "create event" button on first page it immediately
opens empty form template without having a need to download the template
from the server as it's cached.
Just like CREATE EVENT button in Google calendar; which let's you to switch between calendar and new event form template.
Well, you can either use Javascript for building the new page from scratch when the respective action is invoked (probably quite tedious) or you can use an invisible section (e.g., a separate <div>) of the HTML page (style = display: none) and make it visible by changing its class to a visible style and making the original page invisible (change its style to display: none).
One way to accomplish this would be to load your second view into a hidden container. You can hide it with a simple CSS display property toggle, like this:
<div id="mySecondView" style="display: none;">
<!-- content of second view here -->
</div>
And on button click you can do this to unhide it:
With jQuery:
$('#mySecondView').show();
or
$('#mySecondView').fadeIn();
Without jQuery:
document.getElementById('mySecondView').style.display = '';
Of course you'll have to position the second view via CSS as you want it, otherwise it'll just pop up in some weird place that won't make sense.

Categories