JSFiddle - React, Tailwind, and code Playground
by eprouver
HTML
<script src="http://interactjs.io/js/interact.js"></script>
<div ng-app="genknow">
<div ng-controller="boardCtrl as board">
<h3>Drag Red Boxes into the Blue Categories</h3>
<div>Total Score: {{board.totalscore}}</div>
<p>Powered by Wikipedia</p>
<hr/>
<h4>Categories</h4>
<div class="spliter">
<div ng-repeat="c in board.categories" class="droppable" ng-cloak ng-controller="dropClue">{{c.title}}
<ol>
<li ng-repeat="a in c.accepted">{{a.text}} <a class="linker" target="_BLANK" ng-href="{{a.link}}">link</a>
</li>
</ol>
</div>
</div>
<h4>Pages Remaining: {{board.remaining}}</h4>
<div ng-repeat="s in board.subcats" class="draggable" data-id="{{s.pageid}}" ng-controller="dragClue">{{s.title}}</div>
</div>
</div>
CSS
* {
font-family:Arial;
text-align:center;
}
h4 {
text-align:left;
}
body {
background:#eee;
}
.spliter {
display:-webkit-box;
-webkit-box-pack: horizontal;
}
.droppable {
-webkit-box-flex: 1;
padding: 15px;
margin: 10px;
border: 2px solid blue;
background: rgb(249, 249, 255);
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.draggable {
padding: 15px;
margin: 10px;
border: 2px solid red;
background: rgb(255, 247, 247);
cursor:pointer;
display: inline-block;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.linker {
display:none;
}
.finished .linker {
display:inline;
}
JavaScript
app = angular.module('genknow', []);
app.controller('dropClue', function($scope, $element) {
interact($element[0]).dropzone({
drop: function (ui) {
console.log('enter', $element);
var s = angular.element(ui.relatedTarget).scope().s;
var i = $element.scope().c.subs.indexOf(s);
if (i > -1) {
$element.scope().c.accepted.push({
text: ui.relatedTarget.textContent.trim(),
link: 'http://en.wikipedia.org/wiki?curid=' + ui.relatedTarget.dataset['id']
});
$scope.$emit('correctAnswer', s);
} else {
ui.relatedTarget.style.webkitTransform = ui.relatedTarget.style.transform =
'translate(' + 0 + 'px, ' + 0 + 'px)';
ui.relatedTarget.setAttribute('data-x', 0);
ui.relatedTarget.setAttribute('data-y', 0);
}
//if (angular.element(this._element).scope().c.accepted.length >= 5) {
//mark as complete
//}
}
});
});
app.controller('dragClue', function($element) {
interact($element[0]).draggable({
onmove: function (event) {
var target = event.target,
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.webkitTransform = target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
});
});
app.controller('boardCtrl', function($scope, $http) {
var board = this;
this.categories = [], this.subcats = [], this.totalscore = 0, this.remaining = 0;
$scope.$on('correctAnswer', function (s, data) {
board.totalscore += 3;
board.remaining -= 1;
board.subcats.splice(board.subcats.indexOf(data), 1);
...