June 15th, 2011
After writing my previous post about “Keeping track of indexes while dragging in jQuery UI Sortable” I received a question about how this would work for sortable table rows. The code I included in the previous post should actually be enough to make everything work (.. as long as I understood the question correctly). I’ve created a minimal example as a complete implementation of the code from the previous post, and I’ve also included it as a live demo here.
This is based on jQuery 1.5.1 and jQuery UI 1.8.13. I’ve simply used the distribution versions of this example (you probably want to build your own UI bundle using the interface on the jQuery UI website).
Here’s a live demo that you can play with.
Inline javascript and WordPress could possibly be better friends.
The complete source for the minimal (but complete) example is included here:
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-
<title>jQuery UI Example Page</title>
-
<script type="text/javascript" src="js/jquery-1.5.1.min.js"></script>
-
<script type="text/javascript" src="js/jquery-ui-1.8.13.custom.min.js"></script>
-
<script type="text/javascript">
-
$(function(){
-
$("tbody").sortable({
-
start: function(event, ui) {
-
ui.item.data('originIndex', ui.item.index());
-
$("#draggingFrom").text("Index: " + ui.item.index());
-
},
-
change: function (event, ui) {
-
var originIndex = ui.item.data('originIndex');
-
var currentIndex = ui.placeholder.index();
-
-
if (currentIndex > originIndex)
-
{
-
currentIndex -= 1;
-
}
-
-
$("#hoveringOver").text("Current Index: " + currentIndex);
-
},
-
stop: function (event, ui) {
-
$("#draggingFrom, #hoveringOver").text("None");
-
}
-
});
-
});
-
</script>
-
<style type="text/css">
-
td
-
{
-
border: 1px solid #888888;
-
background: #eeeeee;
-
padding: 4px;
-
}
-
</style>
-
</head>
-
<body>
-
<dl>
-
<dt>
-
Dragging from index
-
</dt>
-
<dd id="draggingFrom">
-
None
-
</dd>
-
<dt>
-
Hovering index
-
</dt>
-
<dd id="hoveringOver">
-
None
-
</dd>
-
</dl>
-
-
<table>
-
<thead>
-
<tr>
-
<th>
-
Keys
-
</th>
-
<th>
-
Values
-
</th>
-
</tr>
-
</thead>
-
<tbody>
-
<tr>
-
<td>
-
Key 1
-
</td>
-
<td>
-
Value 1
-
</td>
-
</tr>
-
<tr>
-
<td>
-
Key 2
-
</td>
-
<td>
-
Value 2
-
</td>
-
</tr>
-
<tr>
-
<td>
-
Key 3
-
</td>
-
<td>
-
Value 3
-
</td>
-
</tr>
-
<tr>
-
<td>
-
Key 4
-
</td>
-
<td>
-
Value 4
-
</td>
-
</tr>
-
<tr>
-
<td>
-
Key 5
-
</td>
-
<td>
-
Value 5
-
</td>
-
</tr>
-
<tr>
-
<td>
-
Key 6
-
</td>
-
<td>
-
Value 6
-
</td>
-
</tr>
-
</tbody>
-
</table>
-
</body>
-
</html>
Tags: dragging, html, indexes, javascript, jquery, jquery ui, sortable, sorting
Posted in html, javascript, jquery | No Comments »
June 5th, 2011
While you’re handling a drag operation in the jQuery UI Sortable handler, there’s a few small issues that might almost drive you insane. These two solutions are based on information from various places on the net (such as a few discussions on Stack Overflow).
If you want to keep track of which location the item you’re dragging originated from, you can attach to the ‘start’ event in the Sortable configuration constructor. Use this event to attach the origin index as a data element:
-
start: function(event, ui) {
-
ui.item.data('originIndex', ui.item.index());
-
},
If you want to find out what index the user is currently hovering above (to change the numbering of a list instantly), you can use the same method on the placeholder element (available as ui.placeholder, so to fetch the current index the user is hovering over, call ui.placeholder.index()). There is however a gotcha’ here, as the original element is still present in the list – just allow to float freely around (the dragging action). We handle this by fetching the origin index and subtracting one if we’re after the location we started at.
You can handle these events in the ‘change’ event handler:
-
change: function (event, ui) {
-
var originIndex = ui.item.data('originIndex');
-
var currentIndex = ui.placeholder.index();
-
-
if (currentIndex > originIndex)
-
{
-
currentIndex -= 1;
-
}
-
-
// do magic
-
}
Tags: javascript, jquery, jquery sortable, jquery ui, jqueryui, sortable
Posted in javascript, jquery | 4 Comments »
March 11th, 2010
When we launched Gamer.no over a year ago, we had to come up with a wallpaper advertising solution in a rush (everything were a rush back then as we built and launched a site from scratch (after disagreements between the previous owner and Gamer) in just under four days (or 96 hours)). While this solution has worked .. good enough .. it has always had a few irky bugs that I’ve never really had the right inspiration to uncover the cause of. Usually I’ve spent an hour and decided that the time wasn’t worth it at the moment and then moved onto something else, but today! Today is a glorious day!
The bug has been fixed!
The wallpaper element is placed around the main content div, which sadly also makes the wallpaper element receive any click elements that the main content div receives. This leads to the wallpaper getting clicked and the wallpaper ad window opening regardless of where people click – which will get very, very annoying very quick. So to battle this issue the original solution was to call .stopPropagation() on the evt object in a click handler for the main content div. This solved the issue and everyone rejoiced! However, all was not perfect in paradise.
Some time later we discovered that the .stopPropagation() fix borked ctrl-click a link in Firefox. Other browsers handled it just fine, but Firefox were obviously not happy. Not happy at all. Mad and going on a killing spree it shot down the proposed fixes from both myself and other people who had a brief look at the code. It wasn’t a big issue as we only run the wallpaper code for small intervals of time and people didn’t complain (maybe we were some of the few who had the issue).
Today I decided to have a look at the issue again, and finally I realized that we had been way to focused on our call to .stopPropagation(). Everyone had been planning how we could get .stopPropagation to do what we wanted it to do – after all – the issue was that stopPropagation didn’t behave when we ctrl-clicked in Firefox. But wait.
If you instead think of the original problem; the window.open gets triggered when people click the inner element instead of the outer, there may be alternative solutions to using stopPropagation. And yes, THAT was quite a simple fix. Instead of trying to stop the event from bubling up through the cloud.. let’s just set a status variable that tells the code handling the wallpaper click that THIS CLICK IS NOT FOR YOU BAD HANDLER GO AWAY LET OTHER GROWNUPS HANDLE THIS. So that I did.
-
$(document).ready(function () {
-
innerClick = false;
-
$('#wallpaper').click(function() {
-
if (innerClick)
-
{
-
innerClick = false;
-
return true;
-
}
-
-
window.open("..");
-
});
-
$('#content').click(function(evt) {
-
innerClick = true;
-
});
-
});
As soon as I actually spent some time on what we were trying to solve instead of what seemed like the cause of the issue .. everything went better than expected.
Tags: ctrl click, Firefox, hacking, javascript, stoppropagation
Posted in Hacks, javascript, Programming | 2 Comments »
January 21st, 2010
When creating a simple mash-up with data from external sources, you usually want to read the data in a suitable format – such as JSON. The tool for the job tends to be javascript, running in your favourite browser. The only problem is that requests made with XHR (XMLHttpRequest) has to follow the same origin policy, meaning that the request cannot be made for a resource living on another host than the host serving the original request.
To get around this clients usually use JSONP – or a simple modification of the usual JSON output. The data is still JSON, but the output also includes a simple callback at the end of the request, triggering a javascript in the local browser. This way the creator of the data actually tells the browser (in so many hacky ways) that it’s OK, I’ve actually thought this through. Help yourself.
In jQuery you can trigger the usual handling of events by using “?” as the name of your callback function. jQuery will handle this transparently and then trigger the function you provided to .getJSON in the first place.
Example
-
url = "http://feeds.delicious.com/v2/json/recent?callback=?";
-
-
$.getJSON(url, function(data) { alert(data); });
There’s an article up at IBM’s developerWorks giving quite a few more examples and information about the issue.
Tags: getjson, javascript, jquery, json, jsonp, same-origin
Posted in javascript, Programming | 1 Comment »
December 27th, 2009
The first beta of SWFUpload 2.5.0 was released during christmas, and just a few quick notes for those who are going to attempt an upgrade:
button_cursor: SWFUpload.CURSOR.HAND,
.. seems broken. This will probably be fixed soon, but currently I’ve been unable to get the proper mouse cursor for a button.
If you previously relied on any custom settings being available in the settings object (by providing them when initializing the component), SWFUpload 2.5.0 does not include them in the this.settings object any longer.
If you want to include any custom settings, they’ll now have to be included in a setting for that purpose (together with the other options in the settings object):
swfu = new SWFUpload({
[settings settings]
custom_settings : {
redirect : true,
redirect_delay : 500
},
[more settings]
});
These values will then be availble through this.settings.custom_settings in your callback functions, such as this.settings.custom_settings.redirect etc.
Both issues has been reported on the v2.5.0b1 announcement.
Tags: beta, Flash, flash based uploader, javascript, swfupload, swfupload2.5.0b1
Posted in javascript, Web | No Comments »
August 10th, 2009
Now, that’s quite a headline. And this post will explain just the simple concept posted in the headline. How to avoid (at least) firefox from scrolling to the top when you insert content into a textarea.
It’s simple. Very simple. And it was shown to be so very simple for someone who didn’t remember scrollTop by this thread.
In jQuery (which we use with the caret plugin):
-
currentScrollPosition = $("#textareaId").scrollTop();
-
/* do stuff */
-
$("#textareaId").scrollTop(currentScrollPosition);
Yep. So simple that it actually hurts a bit.
Tags: caret, javascript, jquery, scrolltop, textarea
Posted in javascript, Programming, Web | 2 Comments »
May 29th, 2009
After a while you realize that the best way to serve almost-never-changing content is to give the content an expire date way ahead in the future. The allows your server and your network pipes to do more sensible stuff than delivering the same old versions of files again and again and again and again.
A problem does however surface when you want to update the files and make the visiting user request the new version instead of the old. The trick here is to change the URL for the resource, so that the browser requests the new file. You can do this by appending a version number to the file and either rewriting it behind the scenes to the original file, or by appending a timestamp (or some other item) to the URL as a GET value. The web server ignores this for regular files, but as it identifies a new unique resource, the web browser has to request it again and use the new and improved ™ file.
Using the timestamp of the file is a bit cumbersome and requires you to hit the disk one additional time each time you’re going to show an URL to one of the almost-static resources, but luckily we already have an identifier describing which version the file is in: the SVN revision number (.. if you use subversion, that is). You could use the SVN revision for each file by itself, but we usually decide that the global version number for SVN is good enough. This means that each time you update the live code base through svn up or something like that (remember to block .svn directories and their files if you run your production directory from a SVN branch. This can be discussed over and over, but I’m growing more and more fond of actually doing just that..). To avoid having to call svnversion each time, it’s useful to be able to insert the current revision number into the configuration file for the application (or a header file / bootstrap file).
Here’s an example of how you can insert the current SVN revision into a config file for a PHP application.
- Create a backup of the current configuration file.
- Update the current revision through svn up.
- Retrieve the current revision number from svnversion.
- Insert the revision number using sed into a temporary copy of the configuration file.
- Move the new configuration file into place as the current configuration file.
- Party like it’s 1999!
This assumes that you use an array named $config in your configuration file. I suggest that you name it something else, but for simplicity I’m going with that here. First, create a $config['svn'] entry in your config file. If you have some other naming scheme, you’re going to have to change the relevant parts below.
-
#!/bin/bash
-
cp ./config/config.php ./config/config.backup.php
-
svn up
-
VERSION=`svnversion .`
-
echo $VERSION
-
sed "s/config\['svn'\] = '[0-9M]*';/config\['svn'\] = '$VERSION';/" < ./config/config.php > ./config/config.fixed.php
-
mv ./config/config.fixed.php ./config/config.php
Save this into a file named upgrade.sh, make it executable by doing chmod u+x upgrade.sh and run it by typing ./upgrade.sh.
And this is where you put your hands above your head and wave them about. When you’re done with that, you can refer to your current SVN revision using $config['svn'] in your PHP application (preferrably in your template or where you build the URLs to your static resources). Simply append ?v=$config['svn'] to your current filenames. When you have a new version available, run ./upgrade.sh (or whatever name you gave the script) again and let your users enjoy the new experience.
Tags: configuration, PHP, revision, sed, subversion, svn, version number
Posted in Hacks, javascript, PHP, Programming, Scalability | 1 Comment »
April 6th, 2009
When we released jQDynamicFontSize a couple of weeks ago, we hoped that others would find the plugin useful and keep it around as one of the many tools in your toolbox. We also had a small hope that people would find it useful to extend and maybe submit a patch or two back to us.
And lo’ and behold, during the weekend the first patch arrived in my mailbox. Written by Vegard Andreas Larsen, we now also support scaling against the width of a container. I didn’t even have an idea around this, and suddenly we have working code. The power of open source!
This adds two new options when initializing jqDFS:
- limitWidth: Uses the width of the element to determine the size instead of the height. Defaults to false.
- allowUpscaling: Allows the element to grow instead of shrink to fit the provided area. Only works when limitWidth is active currently. Defaults to false.
The original scale method should probably be rewritten to also use allowUpscaling, so if anyone feels slightly hackish tonight, just send the patch my way!
Tags: font size, javascript, jquery, plugins
Posted in javascript, jquery, Programming | No Comments »
March 27th, 2009
We’ve released the first version of jQDynamicFontSize – a jQuery Plugin for dynamically adjusting the font size of an element to fit a number of lines. The plugin was written to allow us to resize a headline to make the headline fit on one line, sacrificing text size to avoid breaking text into two lines.
To paraphrase from the INSTALL file:
In a production system, use jquery-dynamicfontsize.min.js. For debugging
or developing, use jquery-dynamicfontsize.js.
Usage:
Include a reference to the script after loading jQuery:
<script src="jquery-dynamicfontsize.min.js"></script>
Then call:
$("#idOfElement").dynamicFontSize();
This will attempt to scale the font size of the element down with 10% in
3 iterations, stopping when a value has been found that allows the element
to only use one text line.
$("h1").dynamicFontSize();
This will attempt to scale all h1 elements. Other jQuery selectors will also
work.
Options supported:
* squeezeFactor: A float value that will be used as the squeeze factor
for each step. 0.1 means that we'll attempt to scale the font-size down
10% for each iteration. Defaults to 0.1.
* lines: The number of lines we'll attempt to fit the text to. When the
text fits this (or a smaller) amount of lines, we'll stop scaling.
Defaults to 1.
* tries: The number of iterations we'll try before we give up and go with
the last result. Defaults to 3.
We do currently not care for the line-height of elements, so if you’re feeling slightly hackish tonight, feel free to add the required piece of javascript goodness. Any suitable patches are welcome!
Tags: font size, headlines, jquery, plugin, plugins, Typography
Posted in javascript, jquery, Programming | No Comments »