I'll be impressed if anyone can answer this, but I am generally a Javascript dummy, so maybe this is an easy question.
I am working with the Script.aculo.us javascript library to create an event calendar where events can be dragged from one day to another. Creating draggables is easy, but it might get a little overwhelming. Here is what I have so far for the javascript portion:
Code: javascript
Sortable.create('november26',{dropOnEmpty:true,tag:'td',containment:['november26','november27','november28'],ghosting:true,constraint:false});
Sortable.create('november27',{dropOnEmpty:true,containment:['november26','november27','november28'],ghosting:true,constraint:false});
Sortable.create('november28',{dropOnEmpty:true,containment:['november26','november27','november28'],ghosting:true,constraint:false});
Here's the problem, this code is going to get overwhelming very quickly if I do an entire month of 30 days. Not only do I have to create sortables for every ID, but I have to define them in the containment: array.
Is there any way I can do this in a more efficient manner? Maybe a getElementById? I'm a little lost...
Today's article: A Unique Look at Adwords Advertising
Well, I'm not so much looking to install a pre-made system as to make a system custom to what I am looking for (this is going to be a part of a much bigger program).
I have gotten somewhere...I am using this code right now:
Code: javascript
<script type="text/javascript" language="javascript">
var sortables = document.getElementsByClassName('sortables');
for(var i=0; i < sortables.length; i++){
Sortable.create(sortables[i], {tree:true,dropOnEmpty:true,containment:sortables});
}
</script>
This almost works. The problem I am having right now is using the ID's in creating the sortable, and also allowing the lists themselves to be sortable. I don't know if that makes any sense at all...
Today's article: A Unique Look at Adwords Advertising
Okay -- so, have you tried something like this?
Code:
addEvent(window, "load", sortables_init);
var SORT_COLUMN_INDEX;
function sortables_init() {
// Find all tables with class sortable and make them sortable
if (!document.getElementsByTagName) return;
tbls = document.getElementsByTagName("table");
for (ti=0;ti<tbls.length;ti++) {
thisTbl = tbls[ti];
if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
//initTable(thisTbl.id);
ts_makeSortable(thisTbl);
}
}
}
function ts_makeSortable(table) {
if (table.rows && table.rows.length > 0) {
var firstRow = table.rows[0];
}
if (!firstRow) return;
// We have a first row: assume it's the header, and make its contents clickable links
for (var i=0;i<firstRow.cells.length;i++) {
var cell = firstRow.cells[i];
var txt = ts_getInnerText(cell);
cell.innerHTML = '<a href="#" class="sortheader" '+
'onclick="ts_resortTable(this, '+i+');return false;">' +
txt+'<span class="sortarrow"> </span></a>';
}
}
function ts_getInnerText(el) {
if (typeof el == "string") return el;
if (typeof el == "undefined") { return el };
if (el.innerText) return el.innerText; //Not needed but it is faster
var str = "";
var cs = el.childNodes;
var l = cs.length;
for (var i = 0; i < l; i++) {
switch (cs[i].nodeType) {
case 1: //ELEMENT_NODE
str += ts_getInnerText(cs[i]);
break;
case 3: //TEXT_NODE
str += cs[i].nodeValue;
break;
}
}
return str;
}
function ts_resortTable(lnk,clid) {
// get the span
var span;
for (var ci=0;ci<lnk.childNodes.length;ci++) {
if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
}
var spantext = ts_getInnerText(span);
var td = lnk.parentNode;
var column = clid || td.cellIndex;
var table = getParent(td,'TABLE');
// Work out a type for the column
if (table.rows.length <= 1) return;
var itm = ts_getInnerText(table.rows[1].cells[column]);
sortfn = ts_sort_caseinsensitive;
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
if (itm.match(/^[£$]/)) sortfn = ts_sort_currency;
if (itm.match(/^[\d\.]+$/)) sortfn = ts_sort_numeric;
SORT_COLUMN_INDEX = column;
var firstRow = new Array();
var newRows = new Array();
for (i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }
for (j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }
newRows.sort(sortfn);
if (span.getAttribute("sortdir") == 'down') {
ARROW = ' ↑';
newRows.reverse();
span.setAttribute('sortdir','up');
} else {
ARROW = ' ↓';
span.setAttribute('sortdir','down');
}
// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
// don't do sortbottom rows
for (i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}
// do sortbottom rows only
for (i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}
// Delete any other arrows there may be showing
var allspans = document.getElementsByTagName("span");
for (var ci=0;ci<allspans.length;ci++) {
if (allspans[ci].className == 'sortarrow') {
if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
allspans[ci].innerHTML = ' ';
}
}
}
span.innerHTML = ARROW;
}
function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
return el;
else
return getParent(el.parentNode, pTagName);
}
function ts_sort_date(a,b) {
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
if (aa.length == 10) {
dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
} else {
yr = aa.substr(6,2);
if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
}
if (bb.length == 10) {
dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
} else {
yr = bb.substr(6,2);
if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
}
if (dt1==dt2) return 0;
if (dt1<dt2) return -1;
return 1;
}
function ts_sort_currency(a,b) {
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
return parseFloat(aa) - parseFloat(bb);
}
function ts_sort_numeric(a,b) {
aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
if (isNaN(aa)) aa = 0;
bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
if (isNaN(bb)) bb = 0;
return aa-bb;
}
function ts_sort_caseinsensitive(a,b) {
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
if (aa==bb) return 0;
if (aa<bb) return -1;
return 1;
}
function ts_sort_default(a,b) {
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
if (aa==bb) return 0;
if (aa<bb) return -1;
return 1;
}
function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+, NS6 and Mozilla
// By Scott Andrew
{
if (elm.addEventListener){
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent){
var r = elm.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be removed");
}
}
Once again, I was able to get it to work - its not pretty, but its working. For those who are curious, here's a row from the calendar:
Code: html
<tr>
<td id="november_19" class="CalendarDay"><p>19</p></td>
<td id="november_20" class="CalendarDay"><p>20</p></td>
<td id="november_21" class="CalendarDay"><p>21</p></td>
<td id="november_22" class="CalendarDay"><p>22</p></td>
<td id="november_23" class="CalendarDay"><p>23</p>
<ul id="list1" class="sortables">
<li id="article_1"><a href="#">My First Homebrew</a></li>
<li id="article_2"><a href="#">Build Your Own Keggerator</a></li>
</ul>
</td>
<td id="november_24" class="CalendarDay"><p>24</p>
<ul id="list2" class="sortables">
<li id="article_5" class="sortable"><a href="#">Yet Another Article</a></li>
</ul>
</td>
<td id="november_25" class="CalendarDay"><p>25</p></td>
</tr>
And the javascript to make everything sortable:
Code: javascript
var dropzone = document.getElementsByClassName('CalendarDay');
var sortables = document.getElementsByClassName('sortables');
for(var i=0; i < dropzone.length; i++){
sortables.push(dropzone[i]);
}
for(var i=0; i < sortables.length; i++){
Sortable.create(sortables[i], {tree:true,dropOnEmpty:true,containment:sortables,constraint:false});
}
If anyone has a more elegant solution, I'd be happy to look at it.
TA, thanks for the script, but I'm not sorting tables like that - although that code is definitely useful for an upcoming project. 
Today's article: A Unique Look at Adwords Advertising
Glad you got it to work, SR -- good to hear that the last code I posted will be of help to you later. 
Well, one thing works, another thing breaks. Now I'm having trouble getting it to serialize...
Crap.
If there are any scriptaculous gurus here, let me know.
Today's article: A Unique Look at Adwords Advertising
Heh heh -- frustrating, isn't it?
Okay; let's see if this helps you any...
Code:
<style>
#content #testlist {
list-style-type:none;
margin:0;
padding:0;
}
#content #testlist li {
width:200px;
font:13px Verdana;
margin:0;
margin-left:20px;
padding-left:20px;
padding:4px;
cursor:move;
}
div.image {
height:6px;
width:200px;
background: url(/images/image name.jpg) left top;
margin-top:-3px;
margin-left:-5px;
z-index:1000;
overflow: hidden;
}
</style>
<ul id="testlist">
<li id="image_1"whatever"</li>
<li id="image_2"whatever"</li>
<li id="image_3"whatever"</li>
<li id="image_4"whatever"</li>
<li id="image_5"whatever"</li>
<li id="image_7"whatever"</li>
<li id="image_6"whatever"</li>
<li id="image_8"whatever"</li></ul>
<script type="text/javascript" language="javascript">
Sortable.create('testlist',{ghosting:true,constraint:false})
alert(Sortable.serialize('testlist'));
</script>
In this example, the output of the serialization will only give the numbers after the underscore in the list item IDs.
| Never |


