Переглянути джерело

added more functionality

tags/v0.2.0^2
big bad waffle 6 роки тому
джерело
коміт
09c21da160
19 змінених файлів з 3501 додано та 124 видалено
  1. +3
    -7
      helpers/passives/index.html
  2. +5
    -2
      helpers/passives/js/app.js
  3. +3
    -1
      helpers/passives/js/constants.js
  4. +84
    -30
      helpers/passives/js/generator.js
  5. +113
    -0
      helpers/passives/js/helpers.js
  6. +21
    -10
      helpers/passives/js/input.js
  7. +65
    -15
      helpers/passives/js/main.js
  8. +91
    -27
      helpers/passives/js/renderer.js
  9. +174
    -0
      helpers/passives/plugins/css.js
  10. +123
    -0
      helpers/passives/plugins/html.js
  11. +4
    -0
      helpers/passives/plugins/jquery.min.js
  12. +72
    -0
      helpers/passives/plugins/json.js
  13. +2106
    -0
      helpers/passives/plugins/require.js
  14. +391
    -0
      helpers/passives/plugins/text.js
  15. +3
    -32
      helpers/passives/styles.css
  16. +69
    -0
      helpers/passives/ui/factory.js
  17. +13
    -0
      helpers/passives/ui/templates/nodeInfo/nodeInfo.js
  18. +8
    -0
      helpers/passives/ui/templates/nodeInfo/template.html
  19. +153
    -0
      helpers/passives/ui/uiBase.js

+ 3
- 7
helpers/passives/index.html Переглянути файл

@@ -3,14 +3,10 @@
<head>
<title>test</title>
<link rel="stylesheet" href="styles.css">
<script src="../../src/client/plugins/require.js" data-main="js/app"></script>
<script src="plugins/require.js" data-main="js/app"></script>
</head>
<body>
<div class="left">
<canvas class="canvas"></canvas>
</div>
<div class="right">
</div>
<canvas class="canvas"></canvas>
<div class="ui-container"></div>
</body>
</html>

+ 5
- 2
helpers/passives/js/app.js Переглянути файл

@@ -2,7 +2,10 @@ require.config({
baseUrl: '',
waitSeconds: 120,
paths: {
'jquery': '../../src/client/plugins/jquery.min',
'jquery': 'plugins/jquery.min',
'text': 'plugins/text',
'html': 'plugins/html',
'css': 'plugins/css'
},
shim: {
'jquery': {
@@ -12,7 +15,7 @@ require.config({
});

require([
'../../src/client/js/misc/helpers',
'js/helpers',
'jquery',
'js/main'
], function (


+ 3
- 1
helpers/passives/js/constants.js Переглянути файл

@@ -10,6 +10,8 @@ define([
defaultDistanceInc: 60,
defaultAngle: Math.PI / 2,
defaultAngleInc: Math.PI / 8,
gridSize: 30
gridSize: 30,

scrollSpeed: 0.5
};
});

+ 84
- 30
helpers/passives/js/generator.js Переглянути файл

@@ -1,18 +1,20 @@
define([
'js/tplNode'
'js/tplNode',
'js/events'
], function (
tplNode
tplNode,
events
) {
return {
links: [],
nodes: [],

selected: null,

init: function () {
events.on('onAreaSelect', this.events.onAreaSelect.bind(this));

this.actions.addNode.call(this, {
x: 23,
y: 14
x: 100,
y: 100
});
},

@@ -22,21 +24,34 @@ define([

callAction: function (action, options = {}) {
var node = options.node || this.findNode(options.x, options.y);
if ((action == 'addNode') && (options.shiftDown))
action = 'moveNode';

options.node = node;
this.actions[action].call(this, options);
return !this.actions[action].call(this, options);
},

getSelected: function (single) {
var selected = this.nodes.filter(n => n.selected);
if ((single) && (selected.length != 1))
return null;

if (single)
return selected[0];
else
return selected;
},

actions: {
selectNode: function (options) {
if (this.selected)
this.selected.selected = false;
if (
(!options.node) ||
(!this.nodes.some(n => ((n.selected) && (n == options.node))))
)
this.nodes.forEach(n => (n.selected = false));

if (options.node)
options.node.selected = true;
this.selected = options.node;

return !options.node;
},

addNode: function (options) {
@@ -50,9 +65,11 @@ define([
connectNode: function (options) {
var node = options.node;
if (!node)
return;
return true;

if (this.selected) {
var singleSelected = this.getSelected(true);

if (singleSelected) {
if (options.shiftDown) {
this.links.spliceWhere(l => (
(
@@ -60,45 +77,82 @@ define([
(l.to == node)
) &&
(
(l.from == this.selected) ||
(l.to == this.selected)
(l.from == singleSelected) ||
(l.to == singleSelected)
) &&
(node != this.selected)
(node != singleSelected)
));
} else {
this.links.push({
from: this.selected,
from: singleSelected,
to: node
});
}
this.callAction('selectNode');
return this.callAction('selectNode');
} else {
this.callAction('selectNode', {
return this.callAction('selectNode', {
node: node
})
}
},

moveNode: function (options) {
if (!this.selected)
return;
var selected = this.getSelected();
if (!selected.length) {
selected = this.findNode(options.x, options.y);
if (!selected)
return true;

this.callAction('selectNode', {
node: selected
});
}

this.selected.pos.x = options.x;
this.selected.pos.y = options.y;
selected.forEach(function (s) {
s.pos.x = options.x;
s.pos.y = options.y;
});
},

deleteNode: function (options) {
var selected = this.getSelected(true);
this.nodes.spliceWhere(n => (n == selected));
this.links.spliceWhere(n => ((n.from == selected) || (n.to == selected)));

selected.selected = false;
},

recolorNode: function () {
if (!this.selected)
return;
var selected = this.getSelected(true);
if (!selected)
return true;

this.selected.color = (this.selected.color + 1) % 4;
selected.color = (selected.color + 1) % 4;
},

resizeNode: function () {
if (!this.selected)
return;
var selected = this.getSelected(true);
if (!selected)
return true;

selected.size = (selected.size + 1) % 3;
}
},

events: {
onAreaSelect: function (from, to) {
this.nodes.forEach(n => (n.selected = false));

for (var i = from.x; i <= to.x; i++) {
for (var j = from.y; j <= to.y; j++) {
var node = this.findNode(i, j);
if (!node)
continue;
node.selected = true;
}
}

this.selected.size = (this.selected.size + 1) % 3;
console.log(this.getSelected());
}
}
};


+ 113
- 0
helpers/passives/js/helpers.js Переглянути файл

@@ -0,0 +1,113 @@
Array.prototype.firstIndex = function (callback, thisArg) {
var T = thisArg;
var O = Object(this);
var len = O.length >>> 0;

var k = 0;

while (k < len) {
var kValue;

if (k in O) {
kValue = O[k];

if (callback.call(T, kValue, k, O))
return k;
}
k++;
}

return -1;
};

Array.prototype.spliceWhere = function (callback, thisArg) {
var T = thisArg;
var O = Object(this);
var len = O.length >>> 0;

var k = 0;

while (k < len) {
var kValue;

if (k in O) {
kValue = O[k];

if (callback.call(T, kValue, k, O)) {
O.splice(k, 1);
k--;
}
}
k++;
}
};

Array.prototype.spliceFirstWhere = function (callback, thisArg) {
var T = thisArg;
var O = Object(this);
var len = O.length >>> 0;

var k = 0;

while (k < len) {
var kValue;

if (k in O) {
kValue = O[k];

if (callback.call(T, kValue, k, O)) {
O.splice(k, 1);
return kValue;
}
}
k++;
}
};

window._ = {
create: function () {
var result = {};

[].slice.call(arguments).forEach(function (a) {
$.extend(true, result, a);
});

return result;
},
get2dArray: function (w, h, def) {
def = def || 0;

var result = [];
for (var i = 0; i < w; i++) {
var inner = [];
for (var j = 0; j < h; j++) {
if (def == 'array')
inner.push([]);
else
inner.push(def);
}

result.push(inner);
}

return result;
},
randWeighted: function (weights) {
var sample = [];
weights.forEach(function (w, i) {
for (var j = 0; j < w; j++) {
sample.push(i);
}
});

return sample[~~(Math.random() * sample.length)];
}
};

define([

], function (

) {
return window._;
});

+ 21
- 10
helpers/passives/js/input.js Переглянути файл

@@ -25,9 +25,9 @@ define([
mouse: {
button: null,
x: 0,
y: 0
y: 0,
raw: null
},
mouseRaw: null,

keys: {},

@@ -38,7 +38,8 @@ define([
$('canvas')
.on('mousedown', this.events.mouse.onMouseDown.bind(this))
.on('mouseup', this.events.mouse.onMouseUp.bind(this))
.on('mousemove', this.events.mouse.onMouseMove.bind(this));
.on('mousemove', this.events.mouse.onMouseMove.bind(this))
.on('mousewheel', this.events.mouse.onMouseWheel.bind(this));
},

resetKeys: function () {
@@ -60,10 +61,10 @@ define([

},

isKeyDown: function (key, noConsume) {
isKeyDown: function (key, consume) {
var down = this.keys[key];
if (down != null) {
if (noConsume)
if (!consume)
return true;
else {
this.keys[key] = 2;
@@ -126,17 +127,18 @@ define([
return;

var button = e.button;
this.mouse.button = null;
this.mouse.down = false;

events.emit('onMouseUp', this.mouse);

this.mouse.button = null;
},

onMouseMove: function (e) {
if (e)
this.mouseRaw = e;
this.mouse.raw = e;
else
e = this.mouseRaw;
e = this.mouse.raw;

if (!e)
return;
@@ -145,10 +147,19 @@ define([
if ((!el.hasClass('canvas')) || (el.hasClass('blocking')))
return;

this.mouse.x = ~~((e.offsetX + renderer.pos.x + 40) / constants.gridSize)
this.mouse.y = ~~((e.offsetY + renderer.pos.y + 40) / constants.gridSize)
var x = ~~((e.offsetX + renderer.pos.x) / constants.gridSize);
var y = ~~((e.offsetY + renderer.pos.y) / constants.gridSize);

this.mouse.x = x;
this.mouse.y = y;

events.emit('onMouseMove', this.mouse);
},

onMouseWheel: function (e) {
events.emit('onMouseWheel', {
delta: (e.originalEvent.deltaY > 0) ? 1 : -1
});
}
}
}


+ 65
- 15
helpers/passives/js/main.js Переглянути файл

@@ -2,12 +2,14 @@ define([
'js/events',
'js/generator',
'js/renderer',
'js/input'
'js/input',
'ui/factory.js'
], function (
events,
generator,
renderer,
input
input,
uiFactory
) {
return {
init: function () {
@@ -15,9 +17,15 @@ define([
renderer.init();
input.init();

events.on('onMouseDown', this.events.onMouseDown.bind(this));
events.on('onMouseDown', this.events.onMouseDown.bind(this, true));
events.on('onMouseUp', this.events.onMouseDown.bind(this, false));
events.on('onMouseMove', this.events.onMouseMove.bind(this));
events.on('onMouseWheel', this.events.onMouseWheel.bind(this));
events.on('onKeyDown', this.events.onKeyDown.bind(this));

uiFactory.build('nodeInfo');

renderer.center(generator.nodes[0]);
this.render();
},

@@ -29,27 +37,69 @@ define([
},

events: {
onMouseDown: function (e) {
onMouseDown: function (isDown, e) {
var success = false;

if ((input.isKeyDown('shift')) && (e.button == 2)) {
success = true;

if (e.down)
events.emit('onStartAreaSelect', e);
else
events.emit('onEndAreaSelect', e);
} else if (isDown) {
var action = ([
'addNode',
'connectNode',
'selectNode'
])[e.button];

success = generator.callAction(action, {
x: e.x,
y: e.y,
shiftDown: input.isKeyDown('shift')
});
} else if ((!isDown) && (e.button != 1))
generator.callAction('selectNode', {});

if ((!isDown) || (!success))
renderer.pan(e.raw, isDown ? 'down' : 'up');

renderer.makeDirty();
},

onMouseMove: function (e) {
if ((!e.down) || (e.button != 2) || (input.isKeyDown('shift')))
return;

if (generator.callAction('moveNode', {
x: e.x,
y: e.y
}))
return;

renderer.pan(e.raw, 'move');
},

onMouseWheel: function (e) {
var action = ([
'addNode',
'selectNode',
'connectNode'
])[e.button];
'resizeNode',
'recolorNode'
])[(e.delta > 0) ? 1 : 0];
if (!action)
return;

generator.callAction(action, {
x: e.x,
y: e.y,
shiftDown: input.isKeyDown('shift')
});
generator.callAction(action, {});

renderer.makeDirty();
},

onKeyDown: function (key) {
var action = ({
s: 'resizeNode',
c: 'recolorNode'
d: 'deleteNode'
})[key];
if (!action)
return;

generator.callAction(action, {});



+ 91
- 27
helpers/passives/js/renderer.js Переглянути файл

@@ -9,6 +9,8 @@ define([
canvas: null,
ctx: null,

panOrigin: null,

screen: {
w: 0,
h: 0
@@ -19,6 +21,8 @@ define([
y: 0
},

oldPos: null,

mouse: {
x: 0,
y: 0
@@ -27,9 +31,9 @@ define([
dirty: true,

init: function () {
this.canvas = $('canvas')[0];
this.screen.w = this.canvas.width = $('.left').width();
this.screen.h = this.canvas.height = $('.left').height();
this.canvas = $('.canvas')[0];
this.screen.w = this.canvas.width = $('body').width();
this.screen.h = this.canvas.height = $('body').height();
this.ctx = this.canvas.getContext('2d');

this.ctx.lineWidth = constants.lineWidth;
@@ -40,16 +44,27 @@ define([
});

events.on('onMouseMove', this.events.onMouseMove.bind(this));
events.on('onStartAreaSelect', this.events.onStartAreaSelect.bind(this));
events.on('onEndAreaSelect', this.events.onEndAreaSelect.bind(this));
},

center: function (node) {
this.pos.x = ~~(node.pos.x * constants.gridSize) + (constants.blockSize / 2) - (this.screen.w / 2);
this.pos.y = ~~(node.pos.y * constants.gridSize) + (constants.blockSize / 2) - (this.screen.h / 2);

this.ctx.translate(-this.pos.x, -this.pos.y);
this.makeDirty();
},

pan: function (e, event) {
var action = ({
down: 'onPanStart',
up: 'onPanEnd',
move: 'onPan'
})[event];

this.events[action].call(this, e);
},

makeDirty: function () {
this.dirty = true;
},
@@ -75,7 +90,11 @@ define([

renderers: {
clear: function () {
this.ctx.clearRect(this.pos.x, this.pos.y, this.screen.w, this.screen.h);
var pos = this.oldPos || this.pos;

this.ctx.clearRect(0, 0, this.screen.w, this.screen.h);

delete this.oldPos;
},

grid: function () {
@@ -83,20 +102,28 @@ define([
var ctx = this.ctx;
var mouse = this.mouse;

var w = this.screen.w / gridSize;
var h = this.screen.h / gridSize;
var gapSize = (constants.blockSize - 4) / 2;

var x = ~~(this.pos.x / gridSize) - (this.pos.x / gridSize);
var y = ~~(this.pos.y / gridSize) - (this.pos.y / gridSize);

w = ~~(this.screen.w / gridSize);
h = ~~(this.screen.h / gridSize);

ctx.fillStyle = '#3c3f4c';
for (var i = 0; i < w; i++) {
for (var j = 0; j < h; j++) {
if ((mouse.x == i) && (mouse.y == j)) {
ctx.fillStyle = '#ff6942';
ctx.fillRect((i * gridSize) - 25, (j * gridSize) - 25, 9, 9);
ctx.fillStyle = '#3c3f4c';
} else
ctx.fillRect((i * gridSize) - 23, (j * gridSize) - 23, 5, 5);
for (var i = x; i < w; i++) {
for (var j = y; j < h; j++) {
ctx.fillRect((i * gridSize) + gapSize, (j * gridSize) + gapSize, 4, 4);
}
}

ctx.fillStyle = '#ff0000';
ctx.fillRect(
(this.mouse.x * constants.gridSize) - this.pos.x + (gapSize / 1),
(this.mouse.y * constants.gridSize) - this.pos.y + (gapSize / 1),
8,
8
);
},

node: function (node) {
@@ -111,8 +138,8 @@ define([
constants.blockSize * 2,
constants.blockSize * 3
])[node.size];
var x = (node.pos.x * constants.gridSize) - ((size - constants.blockSize) / 2);
var y = (node.pos.y * constants.gridSize) - ((size - constants.blockSize) / 2);
var x = (node.pos.x * constants.gridSize) - ((size - constants.blockSize) / 2) - this.pos.x;
var y = (node.pos.y * constants.gridSize) - ((size - constants.blockSize) / 2) - this.pos.y;

this.ctx.fillRect(x, y, size, size);

@@ -126,11 +153,11 @@ define([
var ctx = this.ctx;
var halfSize = constants.blockSize / 2;

var fromX = (fromNode.pos.x * constants.gridSize) + halfSize;
var fromY = (fromNode.pos.y * constants.gridSize) + halfSize;
var fromX = (fromNode.pos.x * constants.gridSize) + halfSize - this.pos.x;
var fromY = (fromNode.pos.y * constants.gridSize) + halfSize - this.pos.y;

var toX = (toNode.pos.x * constants.gridSize) + halfSize;
var toY = (toNode.pos.y * constants.gridSize) + halfSize;
var toX = (toNode.pos.x * constants.gridSize) + halfSize - this.pos.x;
var toY = (toNode.pos.y * constants.gridSize) + halfSize - this.pos.y;

ctx.strokeStyle = '#69696e';
ctx.beginPath();
@@ -142,12 +169,6 @@ define([
},

events: {
onClick: function (e) {
generator.onClick(e.button, ~~((e.clientX + this.pos.x + 40) / constants.gridSize) - 1, ~~((e.clientY + this.pos.y + 40) / constants.gridSize) - 1);
e.preventDefault();
return false;
},

onMouseMove: function (pos) {
if ((this.mouse.x == pos.x) && (this.mouse.y == pos.y))
return;
@@ -157,6 +178,49 @@ define([
y: pos.y
};
this.makeDirty();
},

onPanStart: function (e) {
this.panOrigin = {
x: e.clientX,
y: e.clientY
};
},

onPan: function (e) {
if (!this.panOrigin)
return;

if (!this.oldPos) {
this.oldPos = {
x: this.pos.x,
y: this.pos.y
};
}

this.pos.x += (this.panOrigin.x - e.clientX) * constants.scrollSpeed;
this.pos.y += (this.panOrigin.y - e.clientY) * constants.scrollSpeed;

this.panOrigin = {
x: e.clientX,
y: e.clientY
};
},

onPanEnd: function (e) {
this.panOrigin = null;
},

onStartAreaSelect: function (e) {
this.areaSelectOrigin = {
x: e.x,
y: e.y
};
},

onEndAreaSelect: function (e) {
events.emit('onAreaSelect', this.areaSelectOrigin, e);
this.areaSelectOrigin = null;
}
}
};


+ 174
- 0
helpers/passives/plugins/css.js Переглянути файл

@@ -0,0 +1,174 @@
/*
* Require-CSS RequireJS css! loader plugin
* 0.1.8
* Guy Bedford 2014
* MIT
*/

/*
*
* Usage:
* require(['css!./mycssFile']);
*
* Tested and working in (up to latest versions as of March 2013):
* Android
* iOS 6
* IE 6 - 10
* Chome 3 - 26
* Firefox 3.5 - 19
* Opera 10 - 12
*
* browserling.com used for virtual testing environment
*
* Credit to B Cavalier & J Hann for the IE 6 - 9 method,
* refined with help from Martin Cermak
*
* Sources that helped along the way:
* - https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent
* - http://www.phpied.com/when-is-a-stylesheet-really-loaded/
* - https://github.com/cujojs/curl/blob/master/src/curl/plugin/css.js
*
*/

define(function() {
//>>excludeStart('excludeRequireCss', pragmas.excludeRequireCss)
if (typeof window == 'undefined')
return {
load: function(n, r, load) {
load()
}
};

var head = document.getElementsByTagName('head')[0];

var engine = window.navigator.userAgent.match(/Trident\/([^ ;]*)|AppleWebKit\/([^ ;]*)|Opera\/([^ ;]*)|rv\:([^ ;]*)(.*?)Gecko\/([^ ;]*)|MSIE\s([^ ;]*)|AndroidWebKit\/([^ ;]*)/) || 0;

// use <style> @import load method (IE < 9, Firefox < 18)
var useImportLoad = false;

// set to false for explicit <link> load checking when onload doesn't work perfectly (webkit)
var useOnload = true;

// trident / msie
if (engine[1] || engine[7])
useImportLoad = parseInt(engine[1]) < 6 || parseInt(engine[7]) <= 9;
// webkit
else if (engine[2] || engine[8])
useOnload = false;
// gecko
else if (engine[4])
useImportLoad = parseInt(engine[4]) < 18;

//>>excludeEnd('excludeRequireCss')
//main api object
var cssAPI = {};

//>>excludeStart('excludeRequireCss', pragmas.excludeRequireCss)
cssAPI.pluginBuilder = './css-builder';

// <style> @import load method
var curStyle, curSheet;
var createStyle = function() {
curStyle = document.createElement('style');
head.appendChild(curStyle);
curSheet = curStyle.styleSheet || curStyle.sheet;
}
var ieCnt = 0;
var ieLoads = [];
var ieCurCallback;

var createIeLoad = function(url) {
curSheet.addImport(url);
curStyle.onload = function() {
processIeLoad()
};

ieCnt++;
if (ieCnt == 31) {
createStyle();
ieCnt = 0;
}
}
var processIeLoad = function() {
ieCurCallback();

var nextLoad = ieLoads.shift();

if (!nextLoad) {
ieCurCallback = null;
return;
}

ieCurCallback = nextLoad[1];
createIeLoad(nextLoad[0]);
}
var importLoad = function(url, callback) {
if (!curSheet || !curSheet.addImport)
createStyle();

if (curSheet && curSheet.addImport) {
// old IE
if (ieCurCallback) {
ieLoads.push([url, callback]);
} else {
createIeLoad(url);
ieCurCallback = callback;
}
} else {
// old Firefox
curStyle.textContent = '@import "' + url + '";';

var loadInterval = setInterval(function() {
try {
curStyle.sheet.cssRules;
clearInterval(loadInterval);
callback();
} catch (e) {}
}, 10);
}
}

// <link> load method
var linkLoad = function(url, callback) {
var link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
if (useOnload) {
link.onload = function() {
link.onload = function() {};
// for style dimensions queries, a short delay can still be necessary
setTimeout(callback, 7);
}
} else {
var loadInterval = setInterval(function() {
for (var i = 0; i < document.styleSheets.length; i++) {
var sheet = document.styleSheets[i];
if (sheet.href == link.href) {
clearInterval(loadInterval);
return callback();
}
}
}, 10);
}
link.href = url;
head.appendChild(link);
}

//>>excludeEnd('excludeRequireCss')
cssAPI.normalize = function(name, normalize) {
if (name.substr(name.length - 4, 4) == '.css')
name = name.substr(0, name.length - 4);

return normalize(name);
}

//>>excludeStart('excludeRequireCss', pragmas.excludeRequireCss)
cssAPI.load = function(cssId, req, load, config) {

(useImportLoad ? importLoad : linkLoad)(req.toUrl(cssId + '.css'), load);

}

//>>excludeEnd('excludeRequireCss')
return cssAPI;
});

+ 123
- 0
helpers/passives/plugins/html.js Переглянути файл

@@ -0,0 +1,123 @@
define(['text'], function(textPlugin) {

var buildText = {};

return {

load: function(name, req, onLoad, config) {
var self = this,
file = name,
segments = file.split('/');

// If the module name does not have an extension, append the default one
if (segments[segments.length - 1].lastIndexOf('.') == -1) {
file += '.html';
}

textPlugin.get(req.toUrl(file), function(html) {

for (var option in config.config.html) {
if (option in self.transform) {
html = self.transform[option](config.config.html[option], html);
}
}

if (config.isBuild) {
buildText[name] = textPlugin.jsEscape(html);
}

onLoad(html);

}, onLoad.error);
},


write: function(pluginName, moduleName, write) {
if (buildText.hasOwnProperty(moduleName)) {
var name = "'" + pluginName + "!" + moduleName + "'",
text = "function () {return '" + buildText[moduleName] + "';}";

write("define(" + name + ", " + text + ");\n");
}
},


transform: {

comments: function(action, html) {
if (action === 'strip') {
return html.replace(/<!--(.|[\n\r])*?-->/gm, '');
} else {
return html;
}
},


whitespaceBetweenTags: function(action, html) {
var pattern = />[\n\r\s]+</gm;

if (action === 'strip') {
return html.replace(pattern, '><');
} else if (action === 'collapse') {
return html.replace(pattern, '> <');
} else {
return html;
}
},


whitespaceBetweenTagsAndText: function(action, html) {
var afterTagPattern = />[\n\r\s]+/gm,
beforeTagPattern = /[\n\r\s]+</gm;

if (action === 'strip') {
return html.replace(afterTagPattern, '>').replace(beforeTagPattern, '<');
} else if (action === 'collapse') {
return html.replace(afterTagPattern, '> ').replace(beforeTagPattern, ' <');
} else {
return html;
}
},


whitespaceWithinTags: function(action, html) {
if (action === 'collapse') {
var tagPattern = /<([^>"']*?|"[^"]*?"|'[^']*?')+>/g,
attrPattern = /([^\0\n\r\s"'>\/=]+)(?:\s*(=)\s*([^\n\r\s"'=><`]+|"[^"]*"|'[^']*'))?/gi,
lastIndex = 0,
result = '',
match,
tag;

while ((match = tagPattern.exec(html)) !== null) {

// Copy text between the beginning of this match and the end of the last one
result += html.substring(lastIndex, match.index);
tag = match[0];

if (/^<[^\/]/.test(tag)) { // It's a start tag
var attrs = tag.match(attrPattern),
start = attrs.shift(),
end = /\/>$/.test(tag) ? '/>' : '>';

result += start + attrs.map(function(attr) {
return attr.replace(attrPattern, ' $1$2$3');
}).join('') + end;
} else { // It's an end tag
result += tag.replace(/[\n\r\s]+/g, '');
}

lastIndex = tagPattern.lastIndex;
}

return result + html.substring(lastIndex);
} else {
return html;
}
}

}

};

});

+ 4
- 0
helpers/passives/plugins/jquery.min.js
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 72
- 0
helpers/passives/plugins/json.js Переглянути файл

@@ -0,0 +1,72 @@
/** @license
* RequireJS plugin for loading JSON files
* - depends on Text plugin and it was HEAVILY "inspired" by it as well.
* Author: Miller Medeiros
* Version: 0.4.0 (2014/04/10)
* Released under the MIT license
*/
define(['text'], function(text){

var CACHE_BUST_QUERY_PARAM = 'bust',
CACHE_BUST_FLAG = '!bust',
jsonParse = (typeof JSON !== 'undefined' && typeof JSON.parse === 'function')? JSON.parse : function(val){
return eval('('+ val +')'); //quick and dirty
},
buildMap = {};

function cacheBust(url){
url = url.replace(CACHE_BUST_FLAG, '');
url += (url.indexOf('?') < 0)? '?' : '&';
return url + CACHE_BUST_QUERY_PARAM +'='+ Math.round(2147483647 * Math.random());
}

//API
return {

load : function(name, req, onLoad, config) {
if (( config.isBuild && (config.inlineJSON === false || name.indexOf(CACHE_BUST_QUERY_PARAM +'=') !== -1)) || (req.toUrl(name).indexOf('empty:') === 0)) {
//avoid inlining cache busted JSON or if inlineJSON:false
//and don't inline files marked as empty!
onLoad(null);
} else {
text.get(req.toUrl(name), function(data){
var parsed;
if (config.isBuild) {
buildMap[name] = data;
onLoad(data);
} else {
try {
parsed = jsonParse(data);
} catch (e) {
onLoad.error(e);
}
onLoad(parsed);
}
},
onLoad.error, {
accept: 'application/json'
}
);
}
},

normalize : function (name, normalize) {
// used normalize to avoid caching references to a "cache busted" request
if (name.indexOf(CACHE_BUST_FLAG) !== -1) {
name = cacheBust(name);
}
// resolve any relative paths
return normalize(name);
},

//write method based on RequireJS official text plugin by James Burke
//https://github.com/jrburke/requirejs/blob/master/text.js
write : function(pluginName, moduleName, write){
if(moduleName in buildMap){
var content = buildMap[moduleName];
write('define("'+ pluginName +'!'+ moduleName +'", function(){ return '+ content +';});\n');
}
}

};
});

+ 2106
- 0
helpers/passives/plugins/require.js
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 391
- 0
helpers/passives/plugins/text.js Переглянути файл

@@ -0,0 +1,391 @@
/**
* @license RequireJS text 2.0.14 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/requirejs/text for details
*/
/*jslint regexp: true */
/*global require, XMLHttpRequest, ActiveXObject,
define, window, process, Packages,
java, location, Components, FileUtils */

define(['module'], function (module) {
'use strict';

var text, fs, Cc, Ci, xpcIsWindows,
progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
hasLocation = typeof location !== 'undefined' && location.href,
defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
defaultHostName = hasLocation && location.hostname,
defaultPort = hasLocation && (location.port || undefined),
buildMap = {},
masterConfig = (module.config && module.config()) || {};

text = {
version: '2.0.14',

strip: function (content) {
//Strips <?xml ...?> declarations so that external SVG and XML
//documents can be added to a document without worry. Also, if the string
//is an HTML document, only the part inside the body tag is returned.
if (content) {
content = content.replace(xmlRegExp, "");
var matches = content.match(bodyRegExp);
if (matches) {
content = matches[1];
}
} else {
content = "";
}
return content;
},

jsEscape: function (content) {
return content.replace(/(['\\])/g, '\\$1')
.replace(/[\f]/g, "\\f")
.replace(/[\b]/g, "\\b")
.replace(/[\n]/g, "\\n")
.replace(/[\t]/g, "\\t")
.replace(/[\r]/g, "\\r")
.replace(/[\u2028]/g, "\\u2028")
.replace(/[\u2029]/g, "\\u2029");
},

createXhr: masterConfig.createXhr || function () {
//Would love to dump the ActiveX crap in here. Need IE 6 to die first.
var xhr, i, progId;
if (typeof XMLHttpRequest !== "undefined") {
return new XMLHttpRequest();
} else if (typeof ActiveXObject !== "undefined") {
for (i = 0; i < 3; i += 1) {
progId = progIds[i];
try {
xhr = new ActiveXObject(progId);
} catch (e) {}

if (xhr) {
progIds = [progId]; // so faster next time
break;
}
}
}

return xhr;
},

/**
* Parses a resource name into its component parts. Resource names
* look like: module/name.ext!strip, where the !strip part is
* optional.
* @param {String} name the resource name
* @returns {Object} with properties "moduleName", "ext" and "strip"
* where strip is a boolean.
*/
parseName: function (name) {
var modName, ext, temp,
strip = false,
index = name.lastIndexOf("."),
isRelative = name.indexOf('./') === 0 ||
name.indexOf('../') === 0;

if (index !== -1 && (!isRelative || index > 1)) {
modName = name.substring(0, index);
ext = name.substring(index + 1);
} else {
modName = name;
}

temp = ext || modName;
index = temp.indexOf("!");
if (index !== -1) {
//Pull off the strip arg.
strip = temp.substring(index + 1) === "strip";
temp = temp.substring(0, index);
if (ext) {
ext = temp;
} else {
modName = temp;
}
}

return {
moduleName: modName,
ext: ext,
strip: strip
};
},

xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,

/**
* Is an URL on another domain. Only works for browser use, returns
* false in non-browser environments. Only used to know if an
* optimized .js version of a text resource should be loaded
* instead.
* @param {String} url
* @returns Boolean
*/
useXhr: function (url, protocol, hostname, port) {
var uProtocol, uHostName, uPort,
match = text.xdRegExp.exec(url);
if (!match) {
return true;
}
uProtocol = match[2];
uHostName = match[3];

uHostName = uHostName.split(':');
uPort = uHostName[1];
uHostName = uHostName[0];

return (!uProtocol || uProtocol === protocol) &&
(!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
((!uPort && !uHostName) || uPort === port);
},

finishLoad: function (name, strip, content, onLoad) {
content = strip ? text.strip(content) : content;
if (masterConfig.isBuild) {
buildMap[name] = content;
}
onLoad(content);
},

load: function (name, req, onLoad, config) {
//Name has format: some.module.filext!strip
//The strip part is optional.
//if strip is present, then that means only get the string contents
//inside a body tag in an HTML string. For XML/SVG content it means
//removing the <?xml ...?> declarations so the content can be inserted
//into the current doc without problems.

// Do not bother with the work if a build and text will
// not be inlined.
if (config && config.isBuild && !config.inlineText) {
onLoad();
return;
}

masterConfig.isBuild = config && config.isBuild;

var parsed = text.parseName(name),
nonStripName = parsed.moduleName +
(parsed.ext ? '.' + parsed.ext : ''),
url = req.toUrl(nonStripName),
useXhr = (masterConfig.useXhr) ||
text.useXhr;

// Do not load if it is an empty: url
if (url.indexOf('empty:') === 0) {
onLoad();
return;
}

//Load the text. Use XHR if possible and in a browser.
if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
text.get(url, function (content) {
text.finishLoad(name, parsed.strip, content, onLoad);
}, function (err) {
if (onLoad.error) {
onLoad.error(err);
}
});
} else {
//Need to fetch the resource across domains. Assume
//the resource has been optimized into a JS module. Fetch
//by the module name + extension, but do not include the
//!strip part to avoid file system issues.
req([nonStripName], function (content) {
text.finishLoad(parsed.moduleName + '.' + parsed.ext,
parsed.strip, content, onLoad);
});
}
},

write: function (pluginName, moduleName, write, config) {
if (buildMap.hasOwnProperty(moduleName)) {
var content = text.jsEscape(buildMap[moduleName]);
write.asModule(pluginName + "!" + moduleName,
"define(function () { return '" +
content +
"';});\n");
}
},

writeFile: function (pluginName, moduleName, req, write, config) {
var parsed = text.parseName(moduleName),
extPart = parsed.ext ? '.' + parsed.ext : '',
nonStripName = parsed.moduleName + extPart,
//Use a '.js' file name so that it indicates it is a
//script that can be loaded across domains.
fileName = req.toUrl(parsed.moduleName + extPart) + '.js';

//Leverage own load() method to load plugin value, but only
//write out values that do not have the strip argument,
//to avoid any potential issues with ! in file names.
text.load(nonStripName, req, function (value) {
//Use own write() method to construct full module value.
//But need to create shell that translates writeFile's
//write() to the right interface.
var textWrite = function (contents) {
return write(fileName, contents);
};
textWrite.asModule = function (moduleName, contents) {
return write.asModule(moduleName, fileName, contents);
};

text.write(pluginName, nonStripName, textWrite, config);
}, config);
}
};

if (masterConfig.env === 'node' || (!masterConfig.env &&
typeof process !== "undefined" &&
process.versions &&
!!process.versions.node &&
!process.versions['node-webkit'] &&
!process.versions['atom-shell'])) {
//Using special require.nodeRequire, something added by r.js.
fs = require.nodeRequire('fs');

text.get = function (url, callback, errback) {
try {
var file = fs.readFileSync(url, 'utf8');
//Remove BOM (Byte Mark Order) from utf8 files if it is there.
if (file[0] === '\uFEFF') {
file = file.substring(1);
}
callback(file);
} catch (e) {
if (errback) {
errback(e);
}
}
};
} else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
text.createXhr())) {
text.get = function (url, callback, errback, headers) {
var xhr = text.createXhr(), header;
xhr.open('GET', url, true);

//Allow plugins direct access to xhr headers
if (headers) {
for (header in headers) {
if (headers.hasOwnProperty(header)) {
xhr.setRequestHeader(header.toLowerCase(), headers[header]);
}
}
}

//Allow overrides specified in config
if (masterConfig.onXhr) {
masterConfig.onXhr(xhr, url);
}

xhr.onreadystatechange = function (evt) {
var status, err;
//Do not explicitly handle errors, those should be
//visible via console output in the browser.
if (xhr.readyState === 4) {
status = xhr.status || 0;
if (status > 399 && status < 600) {
//An http 4xx or 5xx error. Signal an error.
err = new Error(url + ' HTTP status: ' + status);
err.xhr = xhr;
if (errback) {
errback(err);
}
} else {
callback(xhr.responseText);
}

if (masterConfig.onXhrComplete) {
masterConfig.onXhrComplete(xhr, url);
}
}
};
xhr.send(null);
};
} else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
//Why Java, why is this so awkward?
text.get = function (url, callback) {
var stringBuffer, line,
encoding = "utf-8",
file = new java.io.File(url),
lineSeparator = java.lang.System.getProperty("line.separator"),
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
content = '';
try {
stringBuffer = new java.lang.StringBuffer();
line = input.readLine();

// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
// http://www.unicode.org/faq/utf_bom.html

// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
if (line && line.length() && line.charAt(0) === 0xfeff) {
// Eat the BOM, since we've already found the encoding on this file,
// and we plan to concatenating this buffer with others; the BOM should
// only appear at the top of a file.
line = line.substring(1);
}

if (line !== null) {
stringBuffer.append(line);
}

while ((line = input.readLine()) !== null) {
stringBuffer.append(lineSeparator);
stringBuffer.append(line);
}
//Make sure we return a JavaScript string and not a Java string.
content = String(stringBuffer.toString()); //String
} finally {
input.close();
}
callback(content);
};
} else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&
typeof Components !== 'undefined' && Components.classes &&
Components.interfaces)) {
//Avert your gaze!
Cc = Components.classes;
Ci = Components.interfaces;
Components.utils['import']('resource://gre/modules/FileUtils.jsm');
xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);

text.get = function (url, callback) {
var inStream, convertStream, fileObj,
readData = {};

if (xpcIsWindows) {
url = url.replace(/\//g, '\\');
}

fileObj = new FileUtils.File(url);

//XPCOM, you so crazy
try {
inStream = Cc['@mozilla.org/network/file-input-stream;1']
.createInstance(Ci.nsIFileInputStream);
inStream.init(fileObj, 1, 0, false);

convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']
.createInstance(Ci.nsIConverterInputStream);
convertStream.init(inStream, "utf-8", inStream.available(),
Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);

convertStream.readString(inStream.available(), readData);
convertStream.close();
inStream.close();
callback(readData.value);
} catch (e) {
throw new Error((fileObj && fileObj.path || '') + ': ' + e);
}
};
}
return text;
});

+ 3
- 32
helpers/passives/styles.css Переглянути файл

@@ -1,4 +1,5 @@
html, body {
width: 100vw;
height: 100vh;
}

@@ -9,36 +10,6 @@ body {
overflow: hidden;
}

.left, .right {
float: left;
height: 100%;
}

.left {
width: 85%;
}

.right {
width: 15%;
background-color: #373041;
}

.right .id {
width: 100%;
text-align: center;
padding: 10px;
color: #fafcfc;
font-size: 36px;
}

.right .command {
width: 100%;
text-align: center;
padding: 10px;
color: #fafcfc;
font-size: 24px;
}

.right .id:before {
content: 'id: ';
.canvas, .ui-container {
position: absolute;
}

+ 69
- 0
helpers/passives/ui/factory.js Переглянути файл

@@ -0,0 +1,69 @@
define([
'ui/uiBase'
], function (
uiBase
) {
return {
uis: [],
root: '',

init: function (root) {
if (root)
this.root = root + '/';
},

build: function (type, options) {
var className = 'ui' + type[0].toUpperCase() + type.substr(1);
var el = $('.' + className);
if (el.length > 0)
return;

this.getTemplate(type, options);
$(window).on('resize', this.onResize.bind(this));
},

getTemplate: function (type, options) {
require([this.root + 'ui/templates/' + type + '/' + type], this.onGetTemplate.bind(this, options));
},

onGetTemplate: function (options, template) {
var ui = _.create(uiBase, template);
ui.setOptions(options);
ui.render();
ui.el.data('ui', ui);

this.uis.push(ui);
},

onResize: function () {
this.uis.forEach(function (ui) {
if (ui.centered)
ui.center();
else if ((ui.centeredX) || (ui.centeredY))
ui.center(ui.centeredX, ui.centeredY);
}, this);
},

onKeyDown: function (key) {
if (key == 'esc') {
this.uis.forEach(function (u) {
if (!u.modal)
return;

u.hide();
});
$('.uiOverlay').hide();
}
},

update: function () {
var uis = this.uis;
var uLen = uis.length;
for (var i = 0; i < uLen; i++) {
var u = uis[i];
if (u.update)
u.update();
}
}
};
});

+ 13
- 0
helpers/passives/ui/templates/nodeInfo/nodeInfo.js Переглянути файл

@@ -0,0 +1,13 @@
define([
'html!./template'
], function (
template
) {
return {
tpl: template,

postRender: function () {

}
}
});

+ 8
- 0
helpers/passives/ui/templates/nodeInfo/template.html Переглянути файл

@@ -0,0 +1,8 @@
<div class="uiInventory">
<div class="heading">
<div class="heading-text">Node Info</div>
</div>
<div class="content">
</div>
</div>

+ 153
- 0
helpers/passives/ui/uiBase.js Переглянути файл

@@ -0,0 +1,153 @@
define([
'js/events'
], function (
events
) {
return {
centeredX: false,
centeredY: false,

el: null,
options: null,
shown: true,

eventCallbacks: {},

render: function () {
var container = '.ui-container';
if (this.container)
container += ' > ' + this.container;

this.el = $(this.tpl)
.appendTo(container)
.data('ui', this);

this.el.on('mouseenter', this.onMouseEnter.bind(this, true));
this.el.on('mouseleave', this.onMouseEnter.bind(this, false));

if (this.modal)
this.el.addClass('modal');

this.postRender && this.postRender();

if (this.centered) {
this.centeredX = true;
this.centeredY = true;
}

if ((this.centeredX) || (this.centeredY))
this.center(this.centeredX, this.centeredY);

this.shown = this.el.is(':visible');
},

onMouseEnter: function (enter) {
events.emit('onUiHover', enter);
},

setOptions: function (options) {
this.options = options;
},

on: function (el, event, callback) {
if (typeof (el) == 'string')
el = this.find(el);
else
el = $(el);

el.on(event, function () {
var args = [].slice.call(arguments, 1);
args.splice(0, 0, event);

callback.apply(null, args);
});
},

find: function (selector) {
return this.el.find(selector);
},

center: function (x, y) {
if (x == null)
x = true;
if (y == null)
y = true;

this.centeredX = x;
this.centeredY = y;

var el = this.el;
var pat = el.parent();

var posX = ~~((pat.width() / 2) - (el.width() / 2)) - 10;
var posY = ~~((pat.height() / 2) - (el.height() / 2)) - 10;

el.css('position', 'absolute');
if (x)
el.css('left', posX);
if (y)
el.css('top', posY);
},

show: function () {
if (this.modal)
$('.modal').hide();

this.shown = true;
this.el.show();
},

hide: function () {
if (this.beforeHide)
this.beforeHide();

this.shown = false;
this.el.hide();
},

destroy: function () {
this.offEvents();

if (this.beforeDestroy)
this.beforeDestroy();

this.el.remove();
},

val: function (selector) {
return this.find(selector).val();
},

setDisabled: function (isDisabled) {
this.el.removeClass('disabled')

if (isDisabled)
this.el.addClass('disabled');
},

onEvent: function (event, callback) {
var list = this.eventCallbacks[event] || (this.eventCallbacks[event] = []);
var eventCallback = events.on(event, callback);
list.push(eventCallback);

return eventCallback;
},

offEvent: function (eventCallback) {
for (var e in this.eventCallbacks) {
this.eventCallbacks[e].forEach(function (c) {
if (c == eventCallback)
events.off(e, c);
}, this);
}
},

offEvents: function () {
for (var e in this.eventCallbacks) {
this.eventCallbacks[e].forEach(function (c) {
events.off(e, c);
}, this);
}
}
};
});

Завантаження…
Відмінити
Зберегти