// global // var ikrpg var ikrpg = ikrpg || {}; (function() { var db2 = new PouchDB('maps.ikrpg'); listMaps(); fillLibrary(); makeRemover($('#img-library')); $('#img-library .lib-img.tile').each(function(index, el) { var $el = $(el); makeDraggableCreator(8, '#map-area .tile', 90, 250)($el); }); $('#img-library .lib-img.token, #img-library .lib-img.base').each(function(index, el) { var $el = $(el); makeDraggableCreator(1, '#map-area .token, #map-area .base', 22.5, 125)($el); }); makeMapSaver($('#save-as')); function fillLibrary() { appendHWTiles(); appendCTTiles(); appendGMTiles(); append10x3tokens(); append1x1Stokens(); append4x3tokens(); append1x1Ltokens(); appendSmallBases(); appendMediumBases(); function appendHWTiles() { $.each(['01', '02', '03', '04', '05', '06', '07', '08', '09'], function(i, id) { $.each(['A', 'B'], function(j, key) { $('#hw-boards').append('\
  • \

    HW Board '+key+id+'

    \ \
  • \ '); }); }); } function appendCTTiles() { $.each(['01', '02', '03', '04', '05', '06', '07', '08', '09'], function(i, id) { $.each(['A', 'B'], function(j, key) { $('#ct-boards').append('\
  • \

    CT Board '+key+id+'

    \ \
  • \ '); }); }); } function appendGMTiles() { $.each(['01', '02', '03', '04'], function(i, id) { $.each(['A', 'B'], function(j, key) { $('#gm-boards').append('\
  • \

    GM Board '+key+id+'

    \ \
  • \ '); }); }); } function append10x3tokens() { $.each(['03', '10', '17', '24'], function(i, id) { $.each(['A', 'B'], function(j, key) { $('#tokens10x3').append('\
  • \

    HW '+key+id+'

    \ \
  • \ '); }); }); } function append1x1Stokens() { $.each(['04', '05', '06', '07', '11', '12', '13', '14', '18', '19', '20', '21', '25', '26', '27', '28'], function(i, id) { $.each(['A', 'B'], function(j, key) { $('#tokens1x1s').append('\
  • \

    HW '+key+id+'

    \ \
  • \ '); }); }); } function append4x3tokens() { $.each(['02', '09', '16', '23'], function(i, id) { $.each(['A', 'B'], function(j, key) { $('#tokens4x3').append('\
  • \

    HW Board '+key+id+'

    \ \
  • \ '); }); }); } function append1x1Ltokens() { $.each(['01', '08', '15', '22'], function(i, id) { $.each(['A', 'B'], function(j, key) { $('#tokens1x1l').append('\
  • \

    HW '+key+id+'

    \ \
  • \ '); }); }); } function appendSmallBases() { $.each(['Farrow-Brigand', 'Gullin', 'Knor', 'Lurk', 'Razor-Boar', 'Slaughterhouser', 'Warlord-Morrg', 'Zocha'], function(i, name) { $('#bases-small').append('\
  • \ \
  • \ '); }); } function appendMediumBases() { $.each(['Longchops'], function(i, name) { $('#bases-medium').append('\
  • \ \
  • \ '); }); } } function makeRemover($el) { $el.droppable({ accept: 'img', drop: function(event, ui) { $(ui.draggable).remove(); } }) } function makeDraggableCreator(step, stackSelector, angle, duration) { return function($el) { $el.click(function(event) { var $img = createImg($el.attr('class'), $el.attr('src')); $img.offset({ top: event.pageY - $img.height() / 2, left: event.pageX - $img.width() / 2 }); makeDraggable(step, stackSelector)($img); makeRotateable(angle, duration)($img); disableContextMenu($img); }); }; } function makeMapSaver($el) { $el.click(function(event) { event.preventDefault(); var map = currentMapData(); var _id = $('#map-name').val(); var json = { '_id': _id, 'data': map }; db2.get(_id, function(error, doc) { if(error) { // map not in db yet doc = json; doc["_id"] = _id; db2.put(doc); } else { // map already in db json["_id"] = doc["_id"]; json["_rev"] = doc["_rev"]; db2.put(json); } listMaps(); $('#map-area img').remove(); setTimeout(function() { fill(false, json); }, 300); }); }); } function listMaps() { $("#load-maps > tbody").remove(); $("#load-maps").append(""); db2.allDocs({include_docs: true}, function(error, results) { if(!error) { var rows = results.rows; $.each(rows, function(index, row) { var map = row.doc; function appendTr() { $("#load-maps > tbody").append(""); } function appendTd() { $("#load-maps > tbody > tr:last-of-type").append(""); } function lastTd() { return $("#load-maps > tbody > tr:last-of-type > td:last-of-type"); } appendTr(); appendTd(); lastTd().text(map["_id"]); appendTd(); lastTd().html("Load"); lastTd().find('a').click(showMap(map['_id'])); appendTd(); lastTd().html("Delete"); lastTd().find('a').click(deleteMap(map['_id'], map['_rev'])); }); } }); } function showMap(_id) { return function(event) { event.preventDefault(); $('#map-name').val(_id); db2.get(_id, fill); }; }; function fill(error, json) { if(!error) { var map = json.data; $('#map-area img').remove(); var mapAreaOffset = $('#map-area').offset(); $.each(map, function(index, img) { var top = img.top; var left = img.left; var angle = img.angle; var src = img.src; var classes = img.classes; var $img = createImg(classes, src); console.log('up', mapAreaOffset.top, mapAreaOffset.left) // TODO: SUUUPER dirty! Refactor this! if(classes.indexOf('tile') > 0) { makeDraggable(8, '#map-area .tile')($img); makeRotateable(90, 250)($img); } else if(classes.indexOf('token') > 0 || classes.indexOf('base') > 0) { makeDraggable(1, '#map-area .token, #map-area .base')($img); makeRotateable(22.5, 125)($img); } $img.offset({ top: top + $('#map-area').offset().top, left: left + $('#map-area').offset().left }); $img.css({ transform: "rotate(" + angle + "deg)" }); $img.data('angle', angle); disableContextMenu($img); }); } } function deleteMap(_id, _rev) { return function(event) { event.preventDefault(); if(confirm("This will delete your map. Do you want to proceed?")) { db2.remove(_id, _rev, function(error, code) { var map = currentMapData(); listMaps(); $('#map-area img').remove(); var json = { 'data': map }; setTimeout(function() { fill(false, json); }, 300); }); } }; }; function createImg(classes, src) { var $img = $(''); $img.addClass(classes); $img.attr('src', src); $('#map-area').append($img); return $img; } function makeDraggable(step, stackSelector) { return function($el) { $el.draggable({ cursor: 'crosshair', cursorAt: { left: $el.width() / 2, top: $el.height() / 2 }, opacity: 0.5, drag: grid(), stack: stackSelector }); function grid() { var $parent = $el.parent(); var parentOffset = $parent.offset(); var compensation = { top: parentOffset.top % step, left: parentOffset.left % step }; return function(event, ui) { var remainder = { top: ui.position.top % step, left: ui.position.left % step }; ui.position = { top: ui.position.top - remainder.top + compensation.top, left: ui.position.left - remainder.left + compensation.left }; }; }; }; }; function makeRotateable(degree, duration) { return function($el) { // Idea: If $el is clicked but not moved, it is rotated $el.data('angle', 0); $el.mousedown(function(event) { var offset = $el.offset(); $el.data('moved', false); }); $el.mousemove(function(event) { $el.data('moved', true); }); $el.mouseup(function(event) { var offset = $el.offset(); if(!$el.data('moved')) { // Rotate element clockwise if it did not move. On right click, rotate counterclockwise. rotateElement($el, event.button === 2 ? -degree : degree, duration); } $el.removeData('moved'); }); return $el; }; function rotateElement($el, degree, duration) { var w = $el.css('width'); var h = $el.css('height'); var currentAngle = getCurrentRotationAngle($el); var angle = currentAngle + degree; $({deg: currentAngle}).animate({deg: angle}, { duration: duration, step: function(now){ $el.css({ transform: "rotate(" + now + "deg)" }); } }); $el.data('angle', angle); } function getCurrentRotationAngle($el) { var st = window.getComputedStyle($el[0], null); var tr = st.getPropertyValue("-webkit-transform") || st.getPropertyValue("-moz-transform") || st.getPropertyValue("-ms-transform") || st.getPropertyValue("-o-transform") || st.getPropertyValue("transform") || 'none'; if(tr === 'none') { tr = 'matrix(0.0, 0.0, 0.0, 0.0, 0px, 0px)'; } var values = tr.split('(')[1].split(')')[0].split(','); var a = values[0]; var b = values[1]; var scale = Math.sqrt(a*a + b*b); var sin = b/scale; var angle = Math.round(Math.atan2(b, a) * (180/Math.PI)); return angle; } }; function disableContextMenu($el) { $el[0].oncontextmenu = function() { return false; } } function currentMapData($mapArea) { var data = []; var $mapArea = $('#map-area'); var areaOffset = $mapArea.offset(); $mapArea.find('img').each(function(i, img) { var $img = $(img); $img.css('width', 0); $img.css('height', 0); $img.css({ transform: 'rotate(0deg)' }); var imgOffset = $img.offset(); console.log('down', areaOffset.top, areaOffset.left) var entry = { top: imgOffset.top - areaOffset.top, left: imgOffset.left - areaOffset.left, angle: $img.data('angle'), src: $img.attr('src'), classes: $img.attr('class') }; data.push(entry); }); return data; } })();