Have jquery filter inside live event - javascript

Hi I have this following code with jquery , so it will alternate colors on each row of a table:
$("tr").filter(':nth-child(2n+1)').addClass('odd').next().addClass('even');
but unfortunately it doesnt work when the table comes from an ajax call .. is there a way to put this into a $("tr").live... and make it work like that? .. I have tried different aproaches like this: ( I know the syntax may not be correct ).
$("tr").live({
$("this").filter(':nth-child(2n+1)').addClass('odd').next().addClass('even')
});
But doestn seem to work

live isn't a catch-all solution for problems that come from dynamic content. It only works with events. Normally, you listen for events with bind; when your content is dynamic, live is a way to capture events reliably. So you need another solution for styles...
The simplest solution is to define your CSS using nth-child:
tr:nth-child(2n+1) {
// whatever the odd styles are
}
tr:nth-child(2n) {
// whatever the even styles are
}
This won't work in all browsers, since it's CSS3. (In particular, it won't work in Firefox 3 or Internet Explorer before version 9.)
The other solution is to update all the tr elements on the page after every AJAX call using ajaxComplete:
$(document).ajaxComplete(function() {
$('tr:nth-child(2n+1)').addClass('odd').next().addClass('even');
});
This won't have great performance, but it probably won't be a particular drain as it will always happen asynchronously. This will, obviously, work cross-browser.

Its possible to use the :odd and :even tags for example
JSfiddle example

Related

css3pie messes up DOM, results in jQuery selector errors

In order to get CSS3 effects (border-radius, box-shadow...) on IE 6/7/8, I'm using css3pie.
However, css3pie generates some css3-container (v1) / css3pie (v2) tags in DOM, which disorders the expected architecture. Here is an example:
CSS
pre {
border: 1px solid #aaa;
border-radius: 5px;
behavior: url(pie.htc);
}
HTML
<div class="foo">bar</div>
<p class="getme">paragraph</p>
<pre>preformatted</pre>
jQuery
// undefined expected: getme
alert($("pre").prev().attr("class"));
// css3-container expected: p
alert($("pre").prev()[0].tagName);
// getme expected: foo
alert($("pre").prev().prev().attr("class"));
// 4 expected: 3
alert($("body").children().size());
// will not set expected: Impact
$("p+pre").css({fontFamily: "Impact"});
// it almost affects all such jQuery selctors
The actual generated source is like this:
<DIV class="foo">bar</DIV>
<P class="paragraph">paragraph</P>
<css3-container...>
<border...>
<shape...><stroke></stroke><stroke></stroke></shape>
</border>
</css3-container>
<PRE>preformatted</PRE>
Has anyone encountered this kind of problems? Any workaround? Is there an alternative to css3pie to get CSS3 working on IE 6/7/8?
I tried using CSS3PIE too, and faced similar problems (mostly with jquery and mediaqueries). I found no easy/practical solution for all the problems it causes, indeed.
My advice would be to use Modernizr's load to progressively enhance older IE's user experience. It requires an harder/longer process, as you've to setup a single polyfill for each and every CSS3 feature. As mario.tco already told you, there's a list of cross-browser polyfills on Modernizr's repo. And here's a list of feature detection snippets.
Also have a look at html5please and caniuse.
In regard to IE6 and 7, unless your site statistics indicate something different, usage rates are below 1% on average (with some exceptions, check ie6countdown), so you can almost ignore them. However, with conditional comments you can target each IE<10 version with specific fallbacks.
Keep in mind that you don't really need to have box-shadows and other visual decorations (unless they are needed for usability) on IE<9. Indeed, any fallback will probably cause a huge performance problem (think about what hardware an IE7 user could have). Websites don't need to look exactly the same in any browser.
CSS3PIE is a very useful and powerful way to simulate CSS3 rounded corners - and in my company it is the one that we chose, but there are many other ways to do it.
The way CSS3PIE creates the rounded corners it will create the <css3-container> tag as the previous sibling to the element that has the behavior attribute, so it will change DOM structure and break your prev() calls. The css-container is important because it is a VML drawing of the rounded corner background behind your <pre> tag.
One way you could do this would be to wrap your <pre> tag in something else like a <div> and then use that <div> to navigate the DOM using the prev() function.
Another way you could do this would be to create a jQuery plugin like this
/* This adds a plugin prevPie and nextPie - it is the same as the
existing prev and next, but it will ignore css3-containers. */
(function($){
function addPlugin(name) {
$.fn[name + 'Pie'] = function() {
var result = [];
this[name]().each(function(i,el){
if (el.tagName == 'css3-container') {
var val = $(el)[name]()[0];
val && result.push(val);
} else {
result.push(el);
}
});
return $(result);
}
}
addPlugin('prev');
addPlugin('next');
})(jQuery);
Now the following should work like you wanted it to in all browsers.
// undefined expected: getme
alert($("pre").prevPie().attr("class"));
// css3-container expected: p
alert($("pre").prevPie()[0].tagName);
// getme expected: foo
alert($("pre").prevPie().prevPie().attr("class"));
// P expected: div
alert($("pre").prevPie().prevPie()[0].tagName));
Have you tried this:
http://blog.reybango.com/2010/10/11/how-polyfills-fill-in-the-gaps-to-make-html5-and-css3-usable-today/
Here is a list of polyfills you can use for other features:
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills
This is probably not the answer you're looking for, but instead of trying to get jQuery to ignore PIE's injected elements, I recommend (re)writing your jQuery to use classes / IDs more and be less dependent on page structure. This has the benefit of making your code more resilient against other page structure changes, as well as making your code a bit more portable and reusable.
When you must traverse the DOM, most (if not all) of jQuery's traversal methods include a filter selector argument that you can use to exclude PIE's elements, for example:
$("pre").prevUntil('*', 'not(css3-container)')
$("body").children('not(css3-container)')
Instead of just using the raw prev() add a CSS selector to it to narrow down the search
$("pre").prevUntil('p').attr("class");
// OR
$("pre").prevUntil('.paragraph').attr("class");
If you are going to use a CSS3 "hack" to make IE 6/7/8 behave correctly don't try and rely on expected DOM structure when walking the DOM try to be more specific.
EDIT
changed the prev() function call to prevUntil()

jQuery Mobile "enhance" dynamically re-generated html

jQuery Mobile 1.2.0
I generate the HTML using JavaScript ($(selector).html(content)), add it to the DOM and then display it ($.mobile.changePage()).
Then I invoke an AJAX call, get some data, and re-generate the html (but the parent element, the same $(selector), stays the same, I just change its html(...)).
At this poing the HTML is not "enhanced" by jQM, no styling applied on it.
Now according to the docs I should simply call the page() function on the parent element, i.e $(selector).page().
Other places in the docs suggest triggering the create event, i.e $(selector).trigger("create").
The problem is that non of the above two methods works - the styling of jQM is not applied.
Looking at the code of jQM, I've tried triggering the pagecreate event on that element and it does work, but, this is not documented anywhere, so I'm uncertain of it, especially concerning future releases of jQM.
At some poing in the docs I've read that I can call page() on a page only once..
Anyway, is there any concise/standard way to tell jQM to "enhance" the whole element and its child-elements? Or should I simply stay with triggering the pagecreate event?
Thank you!
To recreate a whole page use this:
$(selector).trigger("pagecreate");
This was my answer to a simmilar question: https://stackoverflow.com/a/14011070/1848600. There's an example of page recreation. Take a look, this should probably solve your problem.
What is the scope of
$(selector).trigger("create");
You should be able to add any elements on the 'pagecreate' event which comes right before 'pageshow' jqm styling is applied to elements. For example I dynamically add a header/footer like this
$(document).on('pagecreate', "[data-role=page]", function() {
var header = "<div data-role='header'>some header stuff</div>";
var footer= "<div data-role='footer'>some footer stuff</div>";
$(this).prepend(header);
$(this).append(footer);
$("[data-role=header]").fixedtoolbar({tapToggle: false});
$("[data-role=footer]").fixedtoolbar({tapToggle: false});
});
Make sure you're using jquery 1.7 or above I think that's when the on method was introduced;
It sounds like you may be generating the DOM and then changing the page, try it the other way around go to the page first then dynamically edit the dom.
EDIT
set the reload page option to true
$.mobile.changePage($(page), {reloadPage: true});
Edit 2
$(selector).children().each(function(){
$(this).trigger('create');
})

Is it possible to create element on the fly with jQuery Mobile?

I have an app built using jQuery (and using various jQuery-UI tools).
For some reason, i have to port it to smartphones/tablet computer, and decided to use jQuery Mobile for that (in order to minimize the number of changes).
In my vanilla app, I created some elements of the page on the fly, depending of user interactions.
For example a slider could be created like that (p is an object with a bunch of params):
function createSlider(p){
return $("<div/>",{
"id":p.id,
"class":p.divClass,
}).slider({
"orientation": p.align,
"min":p.constraint.min,
"max":p.constraint.max,
"step":p.step,
"value":p.curVal,
"animate":"normal"
/*and some event handling here, but it doesn't matter*/
});
}
And it will produce a nice looking slider. Now it looks like:
function createSlider(p){
return $("<range/>",{
"id":p.id,
"class":p.divClass,
"min":p.constraint.min,
"max":p.constraint.max,
"step":p.step,
"value":p.curVal,
});
}
But as it's created on the fly, all the stuff done by jQuery Mobile on the page load isn't done on it.
Is there a way to force that initialization without writing the slider in the html?
Thanks.
EDIT: I found in the doc that it could be achieved using container.trigger("create");
However this does not work yet.
EDIT2: Ok create was the solution.
According to the documentation (see edit in the question), using trigger("create") on the containing element works.
And to make that work, you also need to remember that range is an input type and not a tag...
Working solution:
function createSlider(){
return $("<input/>",{
"type":"range",
"id":"sl",
"min":0,
"max":15,
"step":1,
"value":1,
});
}
function appendSlider(){
$("#yourdiv").append(createSlider()).trigger("create");
}
As a sidenote, the documentation for jQuery mobile lacks a search option.
Try calling .page() on the container the content is being added to. Alternatively, adding .page() to the content you're returning may also work.

Making a span/div/p href-like or stopping href "executing" links

I have the problem to "stop" href executing any links.
So my question is:
1) Is it possible replace href-elements that generate internal (#) links with any component, maybe <p>, <div> or <span> (or whatever could be working) that keep the same behaviour of <a> element (hovering, underlined etc) but not executing any link?
2) Alternative, a "trick" to avoiding href elements execute links?
1 or 2 without using jquery or any other js library possibly
Thanks Randomize
There are all sorts of tricks that can be employed to do this kind of thing, but what you need to be careful of is modifying the behaviour from that which the users have come to expect from a browser.
For example , it would be possible to swap the meaning of 'OK' & 'Cancel' buttons, but this would just confuse the user. (An extreme example, I know, but you get the idea)
If you could supply some more information about why you are trying to do this, there may be a better way of approaching things.
You can either add an onclick attribute to specific <a> elements:
Or modify the href like this:
To make them look like links, without redirecting the browser.
If instead, you already have a bunch of links with hrefs, and you simply wish to make them all non-redirecting, then the following jQuery will do this to all links on the page:
$(function () {
$('a').click(false);
});
Although nice and short, the above only works with jQuery-1.4.3+. If you are using an older version, then you can use the expanded form:
$(function () {
$('a').click(function () { return false; });
});
Yes. You can prevent links from the default action - the recommended way is to have links work normally (in case JS is disabled or not available - think "mobile browsers"), and then override the default action with JS.
Unfortunately, due to cross-browser incompatibilities, there are three ways to do this ("traditional","W3C" and "IE") and you need all of them: stopPropagation(), cancelBubble and return false. See a complete example at QuirksMode: http://www.quirksmode.org/js/events_order.html#link9
(Incidentally most JS frameworks abstract this away, so in jQuery you'd do this:
$('a').click(function(event){
// do something on click here
event.preventDefault();
});
This does the same thing as the QuirksMode example, but is a easier-to-read example.)
TO disable the link via js add onclick="this.href='javascript:void(0)';" like so:
link text
You can use a similar tactic to make other elements work link links:
<div onclick="this.href='http://www.mysite.com';"></div>
This is working in IE, chrome and firefox:
text link
In the function return void(0):
function functionX() {
...
return void(0);
}

Expand and collapse issues

I'm a rookie designer having a few troubles with this page: http://www.resolvegroup.co.nz/javasurvey.php
There are problems with the javascript operation of the expanded questions. For Internet Explorer (Version 7) the first question when expanded gets partly hidden under question 2. This happens to varying degrees with all questions, at times making the next question completely hidden and other problems.
Firefox (Version 3.03) does not have the problem as above, but you cannot get access to the explanations or select next question as in IE7.
Does anyone know what's going on with this, and how to fix it?
I'd recommend looking at using a pre-built Accordion script, like that built into the jQuery UI library: http://docs.jquery.com/UI/Accordion
Also, there's a few things I could suggest. This code of yours:
$(".score-list").slideUp(speed);
$(".score-list").removeClass("open");
$("a.open-answer").removeClass("hidden");
$(this).parent().children(".score-list").slideDown(speed);
$(this).parent().children(".score-list").toggleClass("open");
$(this).toggleClass("hidden");
could be made a lot more efficient by storing the results from a jQuery query, as well as taking advantage of jQuery's chaining abilities: quite a lot of jQuery's functions return the jQuery object itself, which means you can call a number of functions in a row without having to reference the object again and again. Here's what I mean:
$(".score-list") // my own preference is to split the calls onto
.slideUp(speed) // multiple lines to make it easier to read.
.removeClass("open")
;
$("a.open-answer").removeClass("hidden");
var $this = $(this); // store the result from a query in an object so you
// don't have to go through that again.
$this
.parent()
.children(".score-list")
.slideDown(speed);
.toggleClass("open")
;
$this.toggleClass("hidden");
If I'm not mistaken, your CSS has some wonkiness. ".question-container h3" and ".question-container h3 span" have relative and absolute positioning, respectively. Internet Explorer does not handle out-of-flow positioning very well. In result, it gets confused and tries to place these elements in weird places.
Construct the accordion without relative or absolute positioning and it should work fine.

Categories

Resources