rollmorad hinzugefügt
This commit is contained in:
@@ -0,0 +1,568 @@
|
||||
RllmrdLevelEditr = function(_editor) {
|
||||
|
||||
var that = this;
|
||||
|
||||
that.data = '../../data/';
|
||||
that.currentTile = 0;
|
||||
that.tilePainting = false;
|
||||
that.erasing = false;
|
||||
that.tiles = {};
|
||||
that.layers = {};
|
||||
that.currentLayer = 0;
|
||||
that.nextLayer = 1;
|
||||
that.level = {}
|
||||
|
||||
that.tileSize = 64;
|
||||
that.tileSetSize = 1024;
|
||||
that.zoom = 0.5;
|
||||
|
||||
that.width = 0;
|
||||
that.height = 0;
|
||||
|
||||
that.defaultImageLayer = {
|
||||
id: 0,
|
||||
type: 'imagelayer',
|
||||
z: 0.0,
|
||||
imageFilename: '',
|
||||
imageOffset: '',
|
||||
tiling: '',
|
||||
movement: '',
|
||||
color: '',
|
||||
};
|
||||
|
||||
that.defaultTilemapLayer = {
|
||||
id: 0,
|
||||
tileSetFilename: '',
|
||||
visible: 1,
|
||||
enablePhysics: 1,
|
||||
type: 'tilemaplayer',
|
||||
z: 0
|
||||
};
|
||||
|
||||
that.defaultLevel = {
|
||||
name: '',
|
||||
size: '(40, 15)',
|
||||
backgroundColor: '(1.0, 1.0, 1.0, 1.0)',
|
||||
gravity: '(0.0, 9.81)',
|
||||
musicFilename: '',
|
||||
supportedGameModes: 'GM_STORY',
|
||||
};
|
||||
|
||||
that.editor = _editor;
|
||||
|
||||
that.addImageLayer = function() {
|
||||
var layerID = that.nextLayer++;
|
||||
that.layers[layerID] = {};
|
||||
for (var z in that.defaultImageLayer) {
|
||||
that.layers[layerID][z] = that.defaultImageLayer[z];
|
||||
}
|
||||
that.layers[layerID].id = layerID;
|
||||
that.updateLayerList();
|
||||
return false;
|
||||
}
|
||||
|
||||
that.addTilemapLayer = function(layerID) {
|
||||
if (typeof layerID == 'undefined') {
|
||||
layerID = that.nextLayer++;
|
||||
var grid = [];
|
||||
for (var y = 0; y < that.height; ++y) {
|
||||
grid[y] = [];
|
||||
for (var x = 0; x < that.width; ++x) {
|
||||
grid[y][x] = 0;
|
||||
}
|
||||
}
|
||||
that.layers[layerID] = {};
|
||||
for (var z in that.defaultTilemapLayer) {
|
||||
that.layers[layerID][z] = that.defaultTilemapLayer[z];
|
||||
}
|
||||
that.layers[layerID].id = layerID;
|
||||
that.layers[layerID].grid = grid;
|
||||
}
|
||||
that.updateLayerList();
|
||||
that.selectLayer(layerID);
|
||||
var div = document.getElementById('layer_' + layerID);
|
||||
if (div) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
var html = '<div class="layer" id="layer_' + layerID + '"><table border="0" cellspacing="0" cellpadding="0">';
|
||||
for (var y = 0; y < that.height; ++y) {
|
||||
html += '<tr>';
|
||||
for (var x = 0; x < that.width; ++x) {
|
||||
html += '<td><div id="box_' + layerID + '_' + y + '_' + x + '" onclick="return RLE.applyTile(event)" onmouseover="return RLE.hoverBox(event)" onmousemove="return RLE.hoverBox(event)" onmousedown="return RLE.applyTile(event)" style="width: ' + parseInt(that.tileSize * that.zoom) + 'px; height: ' + parseInt(that.tileSize * that.zoom) + 'px;">'
|
||||
var tile = that.tiles[parseInt(that.layers[layerID].grid[y][x])];
|
||||
if (tile) {
|
||||
html += '<img src="' + that.data + "tilesets/" + tile.filename + '" style="' + 'top: -' + parseInt(tile.posY * that.zoom) + 'px; left: -' + parseInt(tile.posX * that.zoom) + 'px; width: ' + parseInt(that.tileSetSize * that.zoom) + 'px; height: ' + parseInt(that.tileSetSize * that.zoom) + 'px;" onmousedown="return false;" />';
|
||||
}
|
||||
html += '</div></td>';
|
||||
}
|
||||
html += '</tr>';
|
||||
}
|
||||
html += '</table></div>';
|
||||
that.editor.innerHTML += html;
|
||||
return false;
|
||||
}
|
||||
|
||||
that.deleteLayer = function(id) {
|
||||
if (!confirm("Wirklich?")) return;
|
||||
delete that.layers[id];
|
||||
var elem = document.getElementById('layer_' + id);
|
||||
if (elem) {
|
||||
elem.parentNode.removeChild(elem);
|
||||
}
|
||||
that.updateLayerList();
|
||||
return false;
|
||||
}
|
||||
|
||||
that.layerComparator = function(a, b) {
|
||||
return that.layers[a].z - that.layers[b].z;
|
||||
}
|
||||
|
||||
that.getLayerOrder = function() {
|
||||
var ids = [];
|
||||
for (var i in that.layers) {
|
||||
ids.push(i);
|
||||
}
|
||||
ids.sort(that.layerComparator);
|
||||
return ids;
|
||||
}
|
||||
|
||||
that.updateLayerList = function() {
|
||||
var layerlist = document.getElementById('layers').getElementsByTagName('div')[0];
|
||||
var html = '';
|
||||
var layerOrder = that.getLayerOrder();
|
||||
for (var j = 0; j < layerOrder.length; ++j) {
|
||||
var i = layerOrder[j];
|
||||
html += '<div id="layerselector_' + i + '"';
|
||||
if (i == that.currentLayer) {
|
||||
html += ' style="background-color: #ffc;"';
|
||||
}
|
||||
html += '>';
|
||||
var refLayer;
|
||||
switch (that.layers[i].type) {
|
||||
case 'imagelayer':
|
||||
html += i + ': image';
|
||||
refLayer = that.defaultImageLayer;
|
||||
break;
|
||||
case 'tilemaplayer':
|
||||
html += '<a href="#" onclick="return RLE.selectLayer(' + i + ')">' + i + ': tilemap</a>';
|
||||
refLayer = that.defaultTilemapLayer;
|
||||
break;
|
||||
}
|
||||
html += ' [<a href="#" onclick="return RLE.toggle(\'editlayer_' + i + '\');">edit</a>] ';
|
||||
html += ' [<a href="#" onclick="return RLE.deleteLayer(' + i + ');">entf.</a>]';
|
||||
html += '<div id="editlayer_' + i + '" style="display: none;">';
|
||||
html += '<form action="#" onsubmit="return RLE.updateLayer(this);">';
|
||||
html += '<input type="hidden" name="__layerid" value="' + i + '" >';
|
||||
for (var z in refLayer) {
|
||||
if (z == 'grid' || z == 'objects' || z == 'type') {
|
||||
continue;
|
||||
}
|
||||
html += '<label for="editlayer_' + i + '_' + z + '">' + z + ': </label>';
|
||||
html += '<input type="text" id="editlayer_' + i + '_' + z + '" name="' + z + '" value="' + (that.layers[i][z] || refLayer[z]) + '"/><br />';
|
||||
}
|
||||
html += '<input type="submit" value="Speichern" />';
|
||||
html += '</form>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
}
|
||||
layerlist.innerHTML = html;
|
||||
}
|
||||
|
||||
that.updateLayer = function(form) {
|
||||
var layerInfo = {};
|
||||
for (var i = 0; i < form.elements.length; ++i) {
|
||||
var e = form.elements[i];
|
||||
if (e.id) {
|
||||
layerInfo[e.name] = e.value;
|
||||
}
|
||||
}
|
||||
if (!layerInfo.id || !that.layers[layerInfo.id]) {
|
||||
return false;
|
||||
}
|
||||
for (var i in layerInfo) {
|
||||
that.layers[layerInfo.id][i] = layerInfo[i];
|
||||
}
|
||||
that.updateLayerList();
|
||||
that.selectLayer(layerInfo.id);
|
||||
return false;
|
||||
}
|
||||
|
||||
that.selectLayer = function(id) {
|
||||
if (that.layers[id].type != 'tilemaplayer') {
|
||||
return false;
|
||||
}
|
||||
var elem = document.getElementById('layerselector_' + that.currentLayer);
|
||||
if (elem) {
|
||||
that.toggle2('layer_' + that.currentLayer);
|
||||
elem.style.backgroundColor = '';
|
||||
}
|
||||
that.currentLayer = id;
|
||||
that.toggle2('layer_' + that.currentLayer);
|
||||
that.loadTileset(that.data + "tilesets/" + that.layers[that.currentLayer].tileSetFilename, true);
|
||||
document.getElementById('layerselector_' + that.currentLayer).style.backgroundColor = '#ffc';
|
||||
return false;
|
||||
}
|
||||
|
||||
that.hoverBox = function(event) {
|
||||
var ret = that.applyTile(event);
|
||||
var box = event.currentTarget;
|
||||
var info = /box_(\d+)_(\d+)_(\d+)/.exec(box.getAttribute('id'));
|
||||
if (!info) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
var layerID = info[1];
|
||||
var y = parseInt(info[2]);
|
||||
var x = parseInt(info[3]);
|
||||
|
||||
var html = '<strong>Tile</strong> ' + that.layers[layerID].grid[y][x] + ' @ X: ' + x + ' Y: ' + y + ' ';
|
||||
|
||||
var levelX = x + parseFloat(event.layerX / that.zoom / that.tileSize);
|
||||
var levelY = y + parseFloat(event.layerY / that.zoom / that.tileSize);
|
||||
html += '<strong>Level</strong> X: ' + levelX + ' Y: ' + levelY + ' ';
|
||||
|
||||
document.getElementById('statusbar').innerHTML = html;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
that.setSize = function(width, height) {
|
||||
if (width == that.width && height == that.height) {
|
||||
// nothing changed
|
||||
return;
|
||||
}
|
||||
|
||||
that.width = width;
|
||||
that.height = height;
|
||||
|
||||
for (var layerID in that.layers) {
|
||||
var layer = that.layers[layerID];
|
||||
if (layer.type != 'tilemaplayer') {
|
||||
continue;
|
||||
}
|
||||
var grid = []
|
||||
for (var y = 0; y < height; ++y) {
|
||||
grid[y] = [];
|
||||
for (var x = 0; x < width; ++x) {
|
||||
if (layer.grid[y] && layer.grid[y][x]) {
|
||||
grid[y][x] = layer.grid[y][x];
|
||||
} else {
|
||||
grid[y][x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
that.layers[layerID].grid = grid;
|
||||
that.addTilemapLayer(layerID);
|
||||
}
|
||||
|
||||
if (that.currentLayer) {
|
||||
that.selectLayer(that.currentLayer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
that.createLevelForm = function() {
|
||||
var html = '<form action="#" id="level_info" onsubmit="return RLE.processLevelForm(this);">';
|
||||
for (var z in that.defaultLevel) {
|
||||
html += ' <label for="level_' + z + '">' + z + '</label>';
|
||||
html += ' <input type="text" name="level_' + z + '" id="level_' + z + '" value="' + that.defaultLevel[z] + '" />';
|
||||
html += ' <br />\n';
|
||||
}
|
||||
html += ' <input type="submit" value="Speichern" />';
|
||||
html += '</form>';
|
||||
document.getElementById('levelform').innerHTML = html;
|
||||
}
|
||||
|
||||
that.processLevelForm = function(form) {
|
||||
var info = {};
|
||||
for (var z in that.defaultLevel) {
|
||||
if (!form['level_' + z]) continue;
|
||||
info[z] = form['level_' + z].value;
|
||||
}
|
||||
that.setLevelInfo(info);
|
||||
return false;
|
||||
}
|
||||
|
||||
that.setLevelInfo = function(info) {
|
||||
that.level = info;
|
||||
var size = /\((\d+), (\d+)\)/.exec(that.level.size);
|
||||
if (size) {
|
||||
that.setSize(size[1], size[2]);
|
||||
}
|
||||
var form = document.getElementById('level_info');
|
||||
for (var z in info) {
|
||||
form['level_' + z].value = that.level[z] || that.defaultLevel[z];
|
||||
}
|
||||
}
|
||||
|
||||
that.applyTile = function(event) {
|
||||
if ((event.type == 'mouseover' || event.type == 'mousemove') && !that.tilePainting && !that.erasing) {
|
||||
return false;
|
||||
}
|
||||
var element = event.currentTarget;
|
||||
var box = /box_(\d+)_(\d+)_(\d+)/.exec(element.id);
|
||||
if (!box || !box[1] || !box[2] || !box[3]) {
|
||||
return false;
|
||||
}
|
||||
var layer = box[1];
|
||||
var y = box[2];
|
||||
var x = box[3];
|
||||
|
||||
if (event.button == 2 || that.erasing || that.currentTile == 'eraser') {
|
||||
that.layers[layer].grid[y][x] = 0;
|
||||
element.innerHTML = '';
|
||||
return false;
|
||||
}
|
||||
that.layers[layer].grid[y][x] = that.currentTile;
|
||||
var tile = that.tiles[that.currentTile];
|
||||
element.innerHTML = '<img src="' + that.data + "tilesets/" + tile.filename + '" style="' + 'top: -' + parseInt(tile.posY * that.zoom) + 'px; left: -' + parseInt(tile.posX * that.zoom) + 'px; width: ' + parseInt(that.tileSetSize * that.zoom) + 'px; height: ' + parseInt(that.tileSetSize * that.zoom) + 'px;" onmousedown="return false;" />';
|
||||
return false;
|
||||
}
|
||||
|
||||
that.loadTileset = function(filename, silent) {
|
||||
var ajax = new af_AJAX();
|
||||
try {
|
||||
var resp = ajax.getSync(filename);
|
||||
} catch(e) {
|
||||
alert(
|
||||
'Tileset konnte nicht geladen werden!\n'
|
||||
+ 'Um den Editor lokal zu benutzen, muss in die Adresszeile "about:config" eingegeben werden und dann\n'
|
||||
+ '"security.fileuri.strict_origin_policy" auf false gesetzt werden.\n\n'
|
||||
+ e
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!resp.responseXML) {
|
||||
if (!silent) {
|
||||
alert('Tileset konnte nicht geladen werden!');
|
||||
}
|
||||
return;
|
||||
}
|
||||
var tileset = resp.responseXML;
|
||||
var root = tileset.getElementsByTagName('TileSet')[0];
|
||||
if (!root) return
|
||||
var img = root.getAttribute('imageFilename');
|
||||
var tileDefs = tileset.getElementsByTagName('Tile');
|
||||
|
||||
var tileSelector = document.getElementById('tiles');
|
||||
var html = '<div id="tile_eraser" onclick="return RLE.selectTile(\'eraser\');"></div>';
|
||||
for (var i = 0; i < tileDefs.length; ++i) {
|
||||
var pos = /(\d+), ?(\d+)/.exec(tileDefs[i].getAttribute('position'));
|
||||
var id = parseInt(tileDefs[i].getAttribute('id'));
|
||||
that.tiles[id] = { filename: img, posX: pos[1], posY: pos[2] };
|
||||
html += '<div style="background: url(\'' + that.data + "tilesets/" + img + '\'); float: left; ';
|
||||
html += 'background-position: -' + pos[1] + 'px -' + pos[2] + 'px;" ';
|
||||
html += 'onclick="return RLE.selectTile(' + id + ');" id="tile_' + id + '"></div>';
|
||||
}
|
||||
tileSelector.innerHTML = html;
|
||||
that.selectTile('eraser');
|
||||
}
|
||||
|
||||
that.selectTile = function(id) {
|
||||
var elem = document.getElementById('tile_' + that.currentTile)
|
||||
if (elem) {
|
||||
elem.style.borderColor = '';
|
||||
}
|
||||
that.currentTile = id;
|
||||
document.getElementById('tile_' + that.currentTile).style.borderColor = '#f00';
|
||||
return false;
|
||||
}
|
||||
|
||||
that.loadLevel = function(filename) {
|
||||
that.unloadLevel();
|
||||
var file = that.data + "levels/" + filename;
|
||||
var ajax = new af_AJAX;
|
||||
try {
|
||||
var resp = ajax.getSync(file);
|
||||
} catch (e) {
|
||||
alert(
|
||||
'Level konnte nicht geladen werden!\n'
|
||||
+ 'Um den Editor lokal zu benutzen, muss in die Adresszeile "about:config" eingegeben werden und dann\n'
|
||||
+ '"security.fileuri.strict_origin_policy" auf false gesetzt werden.\n\n'
|
||||
+ e
|
||||
);
|
||||
return;
|
||||
}
|
||||
var xml = resp.responseXML;
|
||||
if (!xml) {
|
||||
alert('Level konnte nicht geladen werden!');
|
||||
return false;
|
||||
}
|
||||
document.getElementById('level_filename').value = filename;
|
||||
var root = xml.getElementsByTagName('Level')[0];
|
||||
|
||||
that.setLevelInfo(that.getObjectFromAttributes(root.attributes));
|
||||
|
||||
var layers = xml.getElementsByTagName('Layers')[0].childNodes;
|
||||
for (var n = 0; n < layers.length; ++n) {
|
||||
var layer = layers[n];
|
||||
switch (layer.tagName) {
|
||||
case 'ImageLayer':
|
||||
var layerAttributes = that.getObjectFromAttributes(layer.attributes);
|
||||
layerAttributes.type = 'imagelayer';
|
||||
that.layers[layerAttributes.id] = layerAttributes;
|
||||
that.nextLayer = Math.max(that.nextLayer, parseInt(layerAttributes.id) + 1);
|
||||
break;
|
||||
case 'TileMapLayer':
|
||||
var objects = layer.getElementsByTagName('Objects')[0];
|
||||
var layerObjects = [];
|
||||
if (objects) {
|
||||
for (var i = 0; i < objects.childNodes.length; ++i) {
|
||||
var object = objects.childNodes[i];
|
||||
if (object.nodeType != 1) {
|
||||
continue;
|
||||
}
|
||||
var obj = that.getObjectFromAttributes(objects.childNodes[i].attributes);
|
||||
obj.__type = object.nodeName;
|
||||
layerObjects.push(obj);
|
||||
}
|
||||
}
|
||||
var rows = layer.getElementsByTagName('Row');
|
||||
var i = 0;
|
||||
var grid = [];
|
||||
for (var y = 0; y < that.height; ++y) {
|
||||
grid[y] = [];
|
||||
var row = rows[i++].textContent.split(', ');
|
||||
var j = 0;
|
||||
for (var x = 0; x < that.width; ++x) {
|
||||
grid[y][x] = (row[j++] - 0) || 0;
|
||||
}
|
||||
}
|
||||
var layerAttributes = that.getObjectFromAttributes(layer.attributes);
|
||||
layerAttributes.type = 'tilemaplayer';
|
||||
layerAttributes.objects = layerObjects;
|
||||
layerAttributes.grid = grid;
|
||||
that.layers[layerAttributes.id] = layerAttributes;
|
||||
that.nextLayer = Math.max(that.nextLayer, parseInt(layerAttributes.id) + 1);
|
||||
that.addTilemapLayer(layerAttributes.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
that.updateLayerList();
|
||||
return false;
|
||||
}
|
||||
|
||||
that.unloadLevel = function() {
|
||||
that.currentTile = 0;
|
||||
that.tilePainting = false;
|
||||
that.erasing = false;
|
||||
that.tiles = {};
|
||||
that.layers = {};
|
||||
that.currentLayer = 0;
|
||||
that.nextLayer = 1;
|
||||
|
||||
that.setLevelInfo(that.defaultLevel);
|
||||
|
||||
document.getElementById('tiles').innerHTML = '';
|
||||
that.editor.innerHTML = '';
|
||||
that.updateLayerList();
|
||||
|
||||
document.getElementById('level_filename').value = '';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
that.saveLevel = function() {
|
||||
var xml = '';
|
||||
xml += '<?xml version="1.0" ?>\n';
|
||||
xml += '<Level' + that.getAttributesFromObject(that.level) + '> \n';
|
||||
xml += ' <Layers>\n';
|
||||
for (var i in that.layers) {
|
||||
var layer = that.layers[i];
|
||||
switch (layer.type) {
|
||||
case 'imagelayer':
|
||||
xml += ' <ImageLayer' + that.getAttributesFromObject(layer, ['type']) + ' />\n';
|
||||
break;
|
||||
case 'tilemaplayer':
|
||||
xml += ' <TileMapLayer' + that.getAttributesFromObject(layer, ['grid', 'objects', 'type']) + '>\n';
|
||||
xml += ' <Objects>\n';
|
||||
for (var i in layer.objects) {
|
||||
var obj = layer.objects[i];
|
||||
xml += ' <' + obj.__type + that.getAttributesFromObject(obj, ['__type']) + ' />\n';
|
||||
}
|
||||
xml += ' </Objects>\n';
|
||||
for (var y = 0; y < that.height; y++) {
|
||||
xml += ' <Row>' + layer.grid[y].join(', ') + '</Row>\n';
|
||||
}
|
||||
xml += ' </TileMapLayer>\n';
|
||||
break;
|
||||
}
|
||||
}
|
||||
xml += ' </Layers>\n';
|
||||
xml += '</Level>\n';
|
||||
|
||||
var win = window.open('about:blank', 'rollmorad level editor output', '');
|
||||
win.document.open('text/xml');
|
||||
win.document.write(xml);
|
||||
win.document.close();
|
||||
}
|
||||
|
||||
that.getObjectFromAttributes = function(attributes) {
|
||||
var obj = {};
|
||||
for (var i = 0; i < attributes.length; ++i) {
|
||||
obj[attributes[i].nodeName] = attributes[i].value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
that.getAttributesFromObject = function(object, exclude) {
|
||||
var exc = {}
|
||||
exclude = exclude || [];
|
||||
for (var i = 0; i < exclude.length; ++i) {
|
||||
exc[exclude[i]] = true;
|
||||
}
|
||||
var attributes = '';
|
||||
for (var z in object) {
|
||||
if (exc[z] || object[z] === '' || typeof object[z] == undefined) {
|
||||
continue;
|
||||
}
|
||||
attributes += ' ' + z + '="' + object[z] + '"';
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
that.toggle2 = function(id) {
|
||||
// return that.toggle(id)
|
||||
var elem = document.getElementById(id)
|
||||
if (!elem) return
|
||||
if (elem.style.MozOpacity != 0.5) elem.style.MozOpacity = 0.5
|
||||
else elem.style.MozOpacity = 1.0
|
||||
if (elem.style.zIndex != 10) elem.style.zIndex = 10
|
||||
else elem.style.zIndex = 100
|
||||
return false
|
||||
}
|
||||
|
||||
that.toggle = function(id) {
|
||||
var elem = document.getElementById(id);
|
||||
if (!elem) {
|
||||
return;
|
||||
}
|
||||
if (elem.style.display != 'none') {
|
||||
elem.style.display = 'none';
|
||||
} else {
|
||||
elem.style.display = '';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
that.startTilePainting = function(event) {
|
||||
if (event.button == 2) {
|
||||
that.erasing = true;
|
||||
} else {
|
||||
that.tilePainting = true;
|
||||
}
|
||||
}
|
||||
|
||||
that.stopTilePainting = function(event) {
|
||||
that.tilePainting = false;
|
||||
that.erasing = false;
|
||||
af_Events.stopEvent(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
af_Events.addEventListener(window, 'mousedown', that.startTilePainting);
|
||||
af_Events.addEventListener(window, 'mouseup', that.stopTilePainting);
|
||||
that.createLevelForm();
|
||||
that.setLevelInfo(that.defaultLevel);
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
af_DragNDrop = function() {
|
||||
|
||||
var that = this;
|
||||
|
||||
// offset inside clicked element
|
||||
that.mouseOffset = {};
|
||||
// all drop targets
|
||||
that.dropTargets = {};
|
||||
|
||||
// container which is actually being moved around
|
||||
that.dragContainer = null;
|
||||
// element that is currently being dragged
|
||||
that.currentlyDragging = null;
|
||||
// drag-Id
|
||||
that.currentId = '';
|
||||
// dragging already initialized?
|
||||
that.draggingInitialized = false;
|
||||
// position, where we started dragging
|
||||
that.startPosition = {};
|
||||
|
||||
that.dragRegex = /\bdrag_(.*?)\b/;
|
||||
that.dropRegex = /\bdrop_(.*?)\b/;
|
||||
// @TODO: maybe this can be replaced by manually setting the regex.global flag?
|
||||
that.dropRegexG = /\bdrop_(.*?)\b/g;
|
||||
|
||||
that.load = function() {
|
||||
|
||||
// create drag container
|
||||
that.dragContainer = document.createElement('div');
|
||||
that.dragContainer.className = 'dragcontainer';
|
||||
// better solution for this?
|
||||
document.getElementsByTagName('body')[0].appendChild(that.dragContainer);
|
||||
|
||||
// find draggable elements
|
||||
var elements = af_CSS.getElementsByClass(that.dragRegex);
|
||||
for (var i = 0; i < elements.length; ++i) {
|
||||
af_Events.addEventListener(elements[i], 'mousedown', that.startDrag);
|
||||
af_Events.addEventListener(elements[i], 'click', that.interceptClick);
|
||||
// af_Events.addEventListener(elements[i], 'click', function(event) {alert('Clicked!'); });
|
||||
}
|
||||
|
||||
// find drop targets
|
||||
var elements = af_CSS.getElementsByClass(that.dropRegex);
|
||||
var match;
|
||||
for (var i = 0; i < elements.length; ++i) {
|
||||
// an elment can serve as a drop target for differend IDs
|
||||
while (match = that.dropRegexG.exec(elements[i].className)) {
|
||||
var id = match[1];
|
||||
that.dropTargets[id] = that.dropTargets[id] || new Array();
|
||||
that.dropTargets[id].push(elements[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
that.startDrag = function(event) {
|
||||
event = event || window.event;
|
||||
|
||||
var mpos = af_Events.getMousePosition(event);
|
||||
var epos = af_CSS.getPosition(this);
|
||||
|
||||
// record mouse offset
|
||||
that.mouseOffset = {
|
||||
x: mpos.x - epos.x,
|
||||
y: mpos.y - epos.y
|
||||
}
|
||||
|
||||
that.startPosition = mpos;
|
||||
that.currentlyDragging = this;
|
||||
that.draggingInitialized = false;
|
||||
|
||||
af_Events.stopEvent(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
that.initDrag = function(event) {
|
||||
|
||||
// find drag id
|
||||
var match = that.dragRegex.exec(that.currentlyDragging.className);
|
||||
if (!match || !match[1]) {
|
||||
return false;
|
||||
}
|
||||
that.currentId = match[1];
|
||||
|
||||
// are there any drop targets?
|
||||
if (!that.dropTargets[that.currentId]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// highlight drop targets
|
||||
for (var i = 0; i < that.dropTargets[that.currentId].length; ++i) {
|
||||
af_CSS.addClass(that.dropTargets[that.currentId][i], 'active_' + that.currentId);
|
||||
}
|
||||
|
||||
var mpos = af_Events.getMousePosition(event);
|
||||
|
||||
// prepare drag container
|
||||
that.dragContainer.innerHTML = '';
|
||||
that.dragContainer.style.top = mpos.y - that.mouseOffset.y + 'px';
|
||||
that.dragContainer.style.left = mpos.x - that.mouseOffset.x + 'px';
|
||||
// copy element into drag container
|
||||
var clone = that.currentlyDragging.cloneNode(true)
|
||||
var dims = af_CSS.getDimensions(that.currentlyDragging);
|
||||
clone.style.width = dims.width + 'px';
|
||||
clone.style.height = dims.height + 'px';
|
||||
that.dragContainer.appendChild(clone);
|
||||
that.dragContainer.style.display = 'block';
|
||||
// mark element as being dragged
|
||||
af_CSS.addClass(that.currentlyDragging, 'dragging');
|
||||
that.draggingInitialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
that.runDrag = function(event) {
|
||||
if (!that.currentlyDragging) {
|
||||
return;
|
||||
}
|
||||
event = event || window.event;
|
||||
|
||||
if (!that.draggingInitialized) {
|
||||
// first mouse move, set up dragging
|
||||
if (!that.initDrag(event)) {
|
||||
af_Events.stopEvent(event);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var mpos = af_Events.getMousePosition(event);
|
||||
|
||||
// move drag container
|
||||
that.dragContainer.style.left = (mpos.x - that.mouseOffset.x) + 'px';
|
||||
that.dragContainer.style.top = (mpos.y - that.mouseOffset.y) + 'px';
|
||||
|
||||
var dropTarget = null;
|
||||
for (var i = 0; i < that.dropTargets[that.currentId].length; ++i) {
|
||||
if (
|
||||
that.dropTargets[that.currentId][i] != that.currentlyDragging &&
|
||||
that.testBoundingBox(that.getBoundingBox(that.dropTargets[that.currentId][i]), mpos)
|
||||
) {
|
||||
af_CSS.addClass(that.dropTargets[that.currentId][i], 'hover_' + that.currentId);
|
||||
} else {
|
||||
af_CSS.removeClass(that.dropTargets[that.currentId][i], 'hover_' + that.currentId);
|
||||
}
|
||||
}
|
||||
|
||||
// required for Internet Explorer:
|
||||
return false;
|
||||
}
|
||||
|
||||
that.endDrag = function(event) {
|
||||
if (!that.draggingInitialized) {
|
||||
that.currentlyDragging = null;
|
||||
}
|
||||
if (!that.currentlyDragging) {
|
||||
return;
|
||||
}
|
||||
event = event || window.event;
|
||||
|
||||
// find drop target
|
||||
if (!that.dropTargets[that.currentId]) {
|
||||
return;
|
||||
}
|
||||
var dropTarget = null;
|
||||
var mpos = af_Events.getMousePosition(event);
|
||||
for (var i = 0; i < that.dropTargets[that.currentId].length; ++i) {
|
||||
if (that.testBoundingBox(that.getBoundingBox(that.dropTargets[that.currentId][i]), mpos)) {
|
||||
dropTarget = that.dropTargets[that.currentId][i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reset highlighted drop targets
|
||||
for (var i = 0; i < that.dropTargets[that.currentId].length; ++i) {
|
||||
af_CSS.removeClass(that.dropTargets[that.currentId][i], 'active_' + that.currentId);
|
||||
af_CSS.removeClass(that.dropTargets[that.currentId][i], 'hover_' + that.currentId);
|
||||
}
|
||||
|
||||
// backup element
|
||||
var element = that.currentlyDragging;
|
||||
|
||||
// stop dragging
|
||||
af_CSS.removeClass(that.currentlyDragging, 'dragging');
|
||||
that.currentlyDragging = null;
|
||||
that.dragContainer.style.display = 'none';
|
||||
that.dragContainer.style.top = 0;
|
||||
that.dragContainer.style.left = 0;
|
||||
that.dragContainer.innerHTML = '';
|
||||
|
||||
af_Events.stopEvent(event);
|
||||
|
||||
if (dropTarget && that['drop' + that.currentId]) {
|
||||
return that['drop' + that.currentId](element, dropTarget);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// intercepts clicks if mouse has moved
|
||||
that.interceptClick = function(event) {
|
||||
event = event || window.event;
|
||||
var mpos = af_Events.getMousePosition(event);
|
||||
if (mpos.x != that.startPosition.x || mpos.y != that.startPosition.y) {
|
||||
// mouse was moved => dragging took place => intercept click
|
||||
af_Events.stopEvent(event);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
that.getBoundingBox = function(element) {
|
||||
var coords = af_CSS.getPosition(element);
|
||||
var dimensions = af_CSS.getDimensions(element);
|
||||
return {
|
||||
xMin: coords.x,
|
||||
yMin: coords.y,
|
||||
xMax: coords.x + dimensions.width,
|
||||
yMax: coords.y + dimensions.height
|
||||
}
|
||||
}
|
||||
|
||||
that.testBoundingBox = function(bbox, mpos) {
|
||||
return (
|
||||
mpos.x > bbox.xMin &&
|
||||
mpos.x < bbox.xMax &&
|
||||
mpos.y > bbox.yMin &&
|
||||
mpos.y < bbox.yMax
|
||||
);
|
||||
}
|
||||
|
||||
af_Events.addOnEvent(window, 'load', that.load);
|
||||
af_Events.addEventListener(document, 'mousemove', that.runDrag);
|
||||
af_Events.addEventListener(document, 'mouseup', that.endDrag);
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
function af_var_dump(obj) {
|
||||
var str = typeof(obj) + '\n';
|
||||
for (x in obj) {
|
||||
str += x + ' = ' + obj[x] + '\n';
|
||||
}
|
||||
return str;
|
||||
}
|
||||
af_CSS = {
|
||||
addClass: function(element, className) {
|
||||
element.className += ' ' + className;
|
||||
},
|
||||
|
||||
removeClass: function(element, className) {
|
||||
if (!element || !element.className) {
|
||||
return;
|
||||
}
|
||||
var classes = element.className.split(' ');
|
||||
var newclasses = new Array();
|
||||
for (var i = 0; i < classes.length; ++i) {
|
||||
if (classes[i] != className) {
|
||||
newclasses.push(classes[i]);
|
||||
}
|
||||
}
|
||||
element.className = newclasses.join(' ');
|
||||
},
|
||||
|
||||
getElementsByClass: function(pattern, node, tag) {
|
||||
node = node || document;
|
||||
tag = tag || '*';
|
||||
|
||||
var nodes = new Array();
|
||||
var elements = node.getElementsByTagName(tag);
|
||||
for (var i = 0; i < elements.length; ++i) {
|
||||
if (pattern.test(elements[i].className)) {
|
||||
nodes.push(elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
},
|
||||
|
||||
getPosition: function(element) {
|
||||
var coords = {x:0, y:0};
|
||||
var e = element;
|
||||
do {
|
||||
coords.x += e.offsetLeft;
|
||||
coords.y += e.offsetTop;
|
||||
e = e.offsetParent;
|
||||
} while (e && e.offsetParent)
|
||||
|
||||
return coords;
|
||||
},
|
||||
|
||||
getDimensions: function(element, includeBorder) {
|
||||
if (includeBorder) {
|
||||
return {width:element.offsetWidth, height:element.offsetHeight};
|
||||
} else {
|
||||
// @TODO: check IE compatibility
|
||||
return {width:element.clientWidth, height:element.clientHeight};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
af_Events = {
|
||||
|
||||
addEventListener: function(element, event, handler, capture) {
|
||||
if (element.addEventListener) {
|
||||
element.addEventListener(event, handler, false);
|
||||
return;
|
||||
}
|
||||
if (element.attachEvent) {
|
||||
// @TODO: find a cleaner solution
|
||||
var mname = '_____on'+event;
|
||||
element[mname] = handler;
|
||||
element.attachEvent('on' + event, function(event) { return element[mname](event); });
|
||||
}
|
||||
},
|
||||
|
||||
removeEventListener: function(element, event, handler) {
|
||||
if (element.removeEventListener) {
|
||||
element.removeEventListener(event, handler, false);
|
||||
return;
|
||||
}
|
||||
if (element.detachEvent) {
|
||||
// @TODO: remove handler from element
|
||||
element.detachEvent('on' + event, handler);
|
||||
}
|
||||
},
|
||||
|
||||
addOnEvent: function(element, event, handler) {
|
||||
event = 'on' + event;
|
||||
var tmp = element[event];
|
||||
if (typeof tmp != 'function') {
|
||||
element[event] = handler;
|
||||
} else {
|
||||
element[event] = function(e) {
|
||||
if (tmp) {
|
||||
tmp(e);
|
||||
}
|
||||
handler(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
stopEvent: function(event) {
|
||||
if (typeof window.event != 'undefined') {
|
||||
window.event.cancelBubble = true;
|
||||
window.event.returnValue = false;
|
||||
} else {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
getMousePosition: function(event) {
|
||||
if (event.pageX || event.pageY) {
|
||||
return {x: event.pageX, y:event.pageY};
|
||||
}
|
||||
return {
|
||||
x: event.clientX + document.body.scrollLeft - document.body.clientLeft,
|
||||
y: event.clientY + document.body.scrollTop - document.body.clientTop
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function af_AJAX() {
|
||||
|
||||
var that = this;
|
||||
|
||||
that.enabled = true;
|
||||
|
||||
if (typeof XMLHttpRequest == 'undefined') {
|
||||
try {
|
||||
XMLHttpRequest = function() {
|
||||
return new ActiveXObject('Microsoft.XMLHTTP');
|
||||
}
|
||||
} catch (msex) {}
|
||||
}
|
||||
|
||||
if (typeof XMLHttpRequest == 'undefined') {
|
||||
that.enabled = false;
|
||||
}
|
||||
|
||||
that.getSync = function(url) {
|
||||
req = new XMLHttpRequest();
|
||||
req.open('GET', url, false);
|
||||
req.send(null);
|
||||
return req;
|
||||
}
|
||||
|
||||
that.getAsync = function(url, callback) {
|
||||
req = new XMLHttpRequest();
|
||||
req.open('GET', url);
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState == 4) {
|
||||
callback(req);
|
||||
}
|
||||
}
|
||||
req.send(null);
|
||||
}
|
||||
|
||||
that.postSync = function(url, data) {
|
||||
req = new XMLHttpRequest();
|
||||
req.open('POST', url, false);
|
||||
var encodedData = that.urlencode(data);
|
||||
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
req.setRequestHeader("Content-length", encodedData.length);
|
||||
req.setRequestHeader("Connection", "close");
|
||||
req.send(encodedData);
|
||||
return req;
|
||||
}
|
||||
|
||||
that.postAsync = function(url, data, callback) {
|
||||
req = new XMLHttpRequest();
|
||||
req.open('POST', url);
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState == 4) {
|
||||
callback(req);
|
||||
}
|
||||
}
|
||||
req.send(that.urlencode(data));
|
||||
}
|
||||
|
||||
that.urlencode = function(data) {
|
||||
encodedData = new Array();
|
||||
for (i in data) {
|
||||
encodedData.push(i + '=' + encodeURIComponent(data[i]));
|
||||
}
|
||||
return encodedData.join('&');
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user