Showing posts with label jquery. Show all posts
Showing posts with label jquery. Show all posts

Disqus: Detect when comment count has loaded

With Django deprecating their contrib comments module, they suggested that we switched to Disqus as an alternative. It's pretty good, but I found that it was a little tricky to configure stuff on the Javascript side of things.

Sometimes we get a nice callback option to know when values have been filled in. That way we can tweak the output to suit our site if needed.

Not in the case with Disqus' count.js script. It populates any elements with a URL ending with "#disqus-thread" or the attribute "data-disqus-identifier" with the count values fetched from the Disqus server.

The only problem is we don't know when that's done, and it also fills in "0 comments" for us when we may not want it to.

The tl;dr solution

Here's the default unmodified script they tell you to paste in:

<script type="text/javascript">
var disqus_shortname = 'YOUR_SITENAME';
(function () { var s = document.createElement('script');
s.async = true;
s.type = 'text/javascript';
s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>

And this is what I'm telling you to paste in:

Explanation

If you haven't noticed already, the modified version uses jQuery in two places. If you don't want to use jQuery, then you should be able to port this code to any other Javascript library fairly easily.

The first place is via $.getScript(). This loads the count.js script file, executes it and then calls the callback function disqus_counts_loaded().

When the script is done with whatever it needs to do, it inserts another script called count-data.js into your page to fetch the data.

When count-data.js is loaded, DISQUSWIDGETS.displayCount() is automatically called to fill the elements full of the new luscious data.

Because we overridden displayCount() with our own function, it now fires an event afterwards to any elements wishing to know when the "disqus-counts-loaded" occurs.

Example usage

<script type="text/javascript">
$('.comments').bind('disqus-counts-loaded', function() {
var obj = $(this);

if (obj.text() == "0 Comments") {
obj.text("");
}
else if (obj.hasClass("user-review")) {
obj.text(obj.text().replace("Comments", "User reviews"));
}
});
</script>

This snippet hides anything that says "0 Comments". Why? Because it's distracting. It also changes "Comments" with "User reviews" on certain elements.

Spot the difference between the before/after screenshots.

imageimage

The layout on the right is much cleaner with  the "0 comments" clutter hidden away.

Sources

Dell: Replace all driver "download" buttons with direct links (Australian)

I'm not sure if this works on the US site, but this worked a treat for me on the Australian site.

The main issue was I was getting annoyed with the Javascript download question asking me to use the download manager.

I just wanted to queue up files into my own download manager and batch download the files during my off-peak period.

When you're on the driver download page, open up Firebug and paste this into the console.

var rex = /javascript:DownloadFile\('\d+','\d+','.+','(.+)','\w+','HTTP'\);/;

var x = $('a[href*="javascript:DownloadFile"]').each(function(index, item) {
var obj = $(item);
var href = obj.attr('href');
var match = rex.exec(href);

if (match != null) {
var url = unescape(match[1])
obj.attr('href', url);
}
});

This will change all the "download file" buttons so they point to the direct file download link.

I'm sure someone can easily convert this into a GreaseMonkey script.

BOXOd

Now, back to the horrors of formatting!

Twitter Bootstrap: How to change the tooltip text label

Oh my God, twitter bootstrap is a pretty damn good styling and widget framework. Check it out!

My first issue with it however is that I couldn't find a way to change the tooltip label after it's been created.

It's easily solved, but with a rather convoluted and hidden method.

$('#target').attr('data-original-title', item.value + ' selected.').tooltip('fixTitle');

What this one line wonder does is change the title attribute, then tell it to update using the "fixTitle" call.

Flying-kick-headshot 
BOOM! HEADSHOT!

Source

jQuery: Detect enter keypress

A neat little snippet which detects when a user has pressed "Enter" on the keyboard.

$('#id_query').keypress(function(e) {
var key = (e.keyCode || e.which);

if (key == 13) {
e.preventDefault();
alert("hi!");
}
});

Sources

jQuery: Slide left and right like slideUp/slideDown but horizontally

So easy that I wish I found this information sooner!

To show:

$('#selector').animate({ width: 'show' });

To hide:

$('#selector').animate({ width: 'hide' });

Alternatively, you can also give a fixed width when showing it.

Other than that, OMG you're done!

OMG

Source

Django: Ajax POST and CSRF giving "403 Forbidden" responses

If you want to protect your site from cross site request forgery, you'll have to enable the CSRF protection middleware.

You can do that by adding "django.middleware.csrf.CsrfViewMiddleware" to your MIDDLEWARE_CLASSES setting.

Once that's done, you have one of two ways to protect yourself.

When rendering forms, you can either:

  • use {{ form }} to print the form automatically
  • or if rendering manually, use the {% csrf_token %} tag somewhere in the form

When it comes to AJAX however, you'll have to either:

  • rewrite the request in a Form (troublesome in most cases)
  • add the output of {{ csrf_token }} (this one is not a tag) into an element and manually append it on every Ajax POST request
  • use a little jQuery snippet to automatically add in an "X-CSRFToken" header to each POST request

The third method is by far the easiest, and this snippet comes straight from the Django docs!

$(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;

if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');

for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);

// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}

return cookieValue;
}

function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host;
// host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;

// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}

function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});

Apparently this snippet will not work for jQuery v1.5 so you have to be using something newer.

Source:

Javascript: JSON validator

JSON is fine and dandy when it works well, but damned if it's missing a comma or the bloody keywords are quoted in the wrong characters.

I had a problem with some (assumingly) well formed JSON, but it kept puzzled me for hours when a jQuery AJAX post kept silently failing.

Eventually I stumbled upon jsonlint.com, a nifty site that simply validates your JSON and formats it for easy reading.

My example JSON:

{
    'num_votes': 5,
    'up': 4,
    'down': -1
}

Can you spot what's wrong with it?

No? Neither could I... until I got fed up and changed the single quotes with double quotes for the hell of it.

AND IT BLOODY WORKED!

This is the now valid JSON:

{
    "num_votes": 5,
    "up": 4,
    "down": -1
}

FML.

8891
Oh well, back to it!

jQuery: Check if a checkbox is checked or set the checked state

To test if a checkbox has been ticked is a bit tricky.

Using val() will return the potential value of the checkbox, regardless of its check state.

Instead, use the following line to test its state:

$("#checkbox").attr('checked')

This will return true or false depending on its checked state.

*update 27/07/2011*

Use the new .prop() function:

$(".myCheckbox").prop("checked", true);
$(".myCheckbox").prop("checked", false);

jQuery 1.5 and below

The .prop() function is not available so you need to use .attr().

To tick the checkbox (by setting the value of the checked attribute)

$('.myCheckbox').attr('checked', 'checked')

and un-checking (by removing the attribute entirely)

$('.myCheckbox').removeAttr('checked')

Sources

jQuery: Set the content of an empty IFRAME

I had to do some JS trickery to implement a preview feature by posting via AJAX without having to reload the current page.

The problem I ran into was displaying the output into an iframe.

Assuming the HTML is:

<iframe id='preview-iframe' src="about:blank"></iframe>

We can use this jQuery command to inject the HTML into the iframe.

$('#preview-iframe').contents().find('html').html(data);

Update (18/01/13): Thanks Nikri for the IE about:blank fix!

Sources

jQuery: jQueryUI DatePicker with time component

I was looking around for a way to implement the Django AdminDateWidget/AdminTimeWidget but it seemed to be more trouble than its worth.

Looking around a few sites, the best I've found is "jQueryUI datetime". The demo page can be found here.

Syntax is incredibly simple.

$('#datetime').datetime({ value: '+1min' }); });

And that's it!

The good thing is that this is compatible with Django, as the date/time format is the same as the one which the DateTime field accepts, so you can still use the default validation of the Django fields in a form.

jQuery: Ajax post calls error handler even when proper response given

When using an AJAX post with the dataType JSON, be careful when returning a valid HTTP response (200) with an empty string as the content.

If the JSON fails to validate, it will call the error handler.

This was encountered when using jQuery v1.2.6, so I updated to v1.4.2 and it worked again.

Otherwise, you can add a check in the error handler to validate the error's status (so if its 200 then ignore) or check the response HTML if its an empty string.

jQuery: Stop event bubbling from propagating up the element chain

You may have noticed that sometimes when you click on an element, the click event handler of (one of) the parents are triggered.
Thats because events in Javascript are like bubbles which rise from the lowest element (the one which you clicked) to the top element, the HTML body.
You can prevent the event from rising up the element chain by using jQuery's event.stopPropagation().


$('#some_id').click(function(e) {

do_something();

e.stopPropagation();

});


That's it!


Note: If an element has multiple event handlers, this will only stop the one handler from passing on the event bubble.


[ Source ]

jQuery UI: Slider with mouse scrolling tutorial

If you haven't discovered already, jQueryUI allows you to use jQuery in a way which recreates several very useful user interface elements. It also provides additional animation effects to make life easier.

You'll need:

One of which is the slider, which works quite well when dragging the bar but lacks a bit of support for mouse scrolling over the actual element being scrolled.

image

Now the slider will work as normal. When the slider is dragged, the content will scroll accordingly.

To set up the slider:

$(document).ready(function() {
//scrollpane parts
var scrollPane = $('#scroll-pane');
var scrollContent = $('#scroll-content');

//build slider
var slide_handler = function(e, ui) {

if (scrollContent.height() > scrollPane.height()) {
scrollContent.css('margin-top', Math.round(((100 - ui.value) / 100) * (scrollPane.height() - scrollContent.height())) + 'px');
}
else {
scrollContent.css('margin-top', 0);
}
};

var scrollbar = $("#scroll-bar").slider({
orientation: "vertical",
value: 100, // Sets the value to the top
slide: slide_handler
});
});

This will set up the scrollbar, but when you scroll the mouse over the panel it wont register the events. This is because you'll need to set up the mouse-wheel extension.

Within the document ready event, add:

scrollPane.mousewheel(function(event, delta) {
var value = scrollbar.slider('option', 'value');

if (delta > 0) { value += 10; }
else if (delta < 0) { value -= 10; }

// Ensure that its limited between 0 and 100
value = Math.max(0, Math.min(100, value));
scrollbar.slider('option', 'value', value);
event.preventDefault();
});

This will change the slider value, depending on whether you scrolled up or down.

Infuriatingly, the change in slider value will not update the scrolling panel. This took me a while to figure out, but you'll also have to add another event handler called the "change" event.

You can simply reuse the handler when initialising the slider:

var scrollbar = $("#scroll-bar").slider({
orientation: "vertical",
value: 100,
slide: slide_handler,
change: slide_handler
});

Now when you scroll your mouse over the scroll pane, it'll also change the value of the slider. When the "change" event is triggered, it'll scroll the content.

[ Slider documentation ]

jQuery: Slide/expand to a certain size

The stock animation effects given in jQuery are pretty good for the majority of tasks.

However, if you want to show an element at a given size and then slide it to full expanded view, you'll need to do a little magic.

This was based on a small snippet by Chris Pollock, but I've made it a bit more flexible so it'll work on a wider number of cases.

  • Allows effect to apply on more than 1 element at a time.
  • Size is passed into the setup call to allow for multiple sizes.
  • Original height is saved as $.data() rather than an attribute.
  • Maintain original trigger HTML to allow for easier styling.
  • Trigger element made optional argument. Sizable element is now the trigger if none specified.
  • Able to specify the open/close labels for the trigger element.

Snippet:

You can download the snippet here.

Sample uses:

The single element examples apply to individual elements.

Applying sizeExpand to groups of elements will work best if the element expands itself. If you wish to expand the each element with its own trigger, you'll have to manage that within a loop.

$(document).ready(function() {
// single elements
$('#single-element').sizeExpand('50px');

$('#sized-element').sizeExpand('50px', { 'trigger': '#trigger-element' });

$('#sized-element').sizeExpand('50px', { 'trigger': '#trigger-element', 'open_label': 'Show me the money!', 'close_label': 'I have no money :(' });

// groups of elements
$('div.sized-group').sizeExpand('50px');
});

[ Source ]

jQuery: Fade and slide at the same time

Chaining functions is really handy, but when it comes to animation, its a bit annoying because it'll perform them in order.

To get fade and slide at the same time, use animate().

$('#element').animate({ opacity: 'toggle', height: 'toggle' }, "slow", callback_function);

The speed and callback functions are optional.

[ Source ]

jQuery: Limiting Select to Direct Children

Given the example below...

<ul id="example_menu">
<li>Menu Item 1</li>
<li>Menu Item 2</li>
<li>Menu Item 3
<ul>
<li>Dropdown 1</li>
<li>Dropdown 2</li>
<li>Dropdown 3</li>
</ul>
</li>
<li>Menu Item 4</li>
</ul>

This jQuery selector:

$('#example_menu li');

Will return all LI elements within the menu, including the dropdown ones.

To limit your selection to just the "Menu Item X" items and not the dropdowns, use the following selector to limit it to the direct children of #example_menu.

$('#example_menu > li');

That wonderful little > symbol will fix all your problems, as it limits the selector to direct LI elements of the #example_menu.

jQuery: Animated scroll to element

Alot of sites will just link to an anchor on the page and throw the user straight to it. For a person who is new to browsing, that can be pretty confusing.

TruckWheel
To some users, being thrown directly to an anchor may feel like this...

To smoothly scroll your screen to a specific element, use this one liner to help make your site much nicer to navigate:

$('html,body').animate({ scrollTop: $(element).offset().top }, { duration: 'slow', easing: 'swing'});

Slightly modified from source to allow for different types of easing.

You may want to combine this effect with URL anchors for easier hot-linking.

[ Source, jQuery Docs ]

JQuery: Selecting appropriate content based on anchor in URL when displaying page

If a user is given a link to your page, you can automatically display certain content depending on the anchor provided in the url.

http://www.yoursite.com/article_page.html#show-comments

This makes your page more user friendly when people copy pasta links to a friend, removing the need to provide instructions on how to navigate to the content.

First, create an anchor with a name matching the anchor.

<a href="#show-comments">Show</a>

The last bit of code on the page should execute after everything else has been initialised and set up correctly.

function displayAnchor() {
var url = document.location.toString();

// URL contains an anchor
if (url.match('#')) {
var anchor = '#' + url.split('#')[1];
$('a[href="' + anchor + '"]').trigger('click');
}
}

It checks if the URL given contains an anchor name ("#show-comments" in this instance) and tries to trigger the click event on the corresponding element.

This will only work if your "href" is the target anchor name (href="#anchor") and not something like href="/page/something.html#anchor".

If it is the latter, you'll need a different selector.

You can also use an animation to slide to an anchor.

[ Source ]

 
Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog