Close #36 and #25 - zoom while resizing and minimap disappearing when back from fullscreen
/* Declaring the Renkan Namespace Rkns and Default values */
(function(root) {
"use strict";
if (typeof root.Rkns !== "object") {
root.Rkns = {};
}
var Rkns = root.Rkns;
var $ = Rkns.$ = root.jQuery;
var _ = Rkns._ = root._;
Rkns.pickerColors = ["#8f1919", "#a80000", "#d82626", "#ff0000", "#e87c7c", "#ff6565", "#f7d3d3", "#fecccc",
"#8f5419", "#a85400", "#d87f26", "#ff7f00", "#e8b27c", "#ffb265", "#f7e5d3", "#fee5cc",
"#8f8f19", "#a8a800", "#d8d826", "#feff00", "#e8e87c", "#feff65", "#f7f7d3", "#fefecc",
"#198f19", "#00a800", "#26d826", "#00ff00", "#7ce87c", "#65ff65", "#d3f7d3", "#ccfecc",
"#198f8f", "#00a8a8", "#26d8d8", "#00feff", "#7ce8e8", "#65feff", "#d3f7f7", "#ccfefe",
"#19198f", "#0000a8", "#2626d8", "#0000ff", "#7c7ce8", "#6565ff", "#d3d3f7", "#ccccfe",
"#8f198f", "#a800a8", "#d826d8", "#ff00fe", "#e87ce8", "#ff65fe", "#f7d3f7", "#feccfe",
"#000000", "#242424", "#484848", "#6d6d6d", "#919191", "#b6b6b6", "#dadada", "#ffffff"];
Rkns.__renkans = [];
var _BaseBin = Rkns._BaseBin = function(_renkan, _opts) {
if (typeof _renkan !== "undefined") {
this.renkan = _renkan;
this.renkan.$.find(".Rk-Bin-Main").hide();
this.$ = Rkns.$('<li>')
.addClass("Rk-Bin")
.appendTo(_renkan.$.find(".Rk-Bin-List"));
this.title_icon_$ = Rkns.$('<span>')
.addClass("Rk-Bin-Title-Icon")
.appendTo(this.$);
var _this = this;
Rkns.$('<a>')
.attr({
href: "#",
title: _renkan.translate("Close bin")
})
.addClass("Rk-Bin-Close")
.html('×')
.appendTo(this.$)
.click(function() {
_this.destroy();
if (!_renkan.$.find(".Rk-Bin-Main:visible").length) {
_renkan.$.find(".Rk-Bin-Main:last").slideDown();
}
_renkan.resizeBins();
return false;
});
Rkns.$('<a>')
.attr({
href: "#",
title: _renkan.translate("Refresh bin")
})
.addClass("Rk-Bin-Refresh")
.appendTo(this.$)
.click(function() {
_this.refresh();
return false;
});
this.count_$ = Rkns.$('<div>')
.addClass("Rk-Bin-Count")
.appendTo(this.$);
this.title_$ = Rkns.$('<h2>')
.addClass("Rk-Bin-Title")
.appendTo(this.$);
this.main_$ = Rkns.$('<div>')
.addClass("Rk-Bin-Main")
.appendTo(this.$)
.html('<h4 class="Rk-Bin-Loading">' + _renkan.translate("Loading, please wait") + '</h4>');
this.title_$.html(_opts.title || '(new bin)');
this.renkan.resizeBins();
if (_opts.auto_refresh) {
window.setInterval(function() {
_this.refresh();
},_opts.auto_refresh);
}
}
};
_BaseBin.prototype.destroy = function() {
this.$.detach();
this.renkan.resizeBins();
};
/* Point of entry */
var Renkan = Rkns.Renkan = function(_opts) {
var _this = this;
Rkns.__renkans.push(this);
this.options = _.defaults(_opts, Rkns.defaults);
_(this.options.property_files).each(function(f) {
Rkns.$.getJSON(f, function(data) {
_this.options.properties = _this.options.properties.concat(data);
});
});
this.read_only = this.options.read_only || !this.options.editor_mode;
this.project = new Rkns.Models.Project();
if (typeof this.options.user_id !== "undefined") {
this.current_user = this.options.user_id;
}
this.$ = Rkns.$("#" + this.options.container);
this.$
.addClass("Rk-Main")
.html(this.template(this));
this.tabs = [];
this.search_engines = [];
this.current_user_list = new Rkns.Models.UsersList();
this.current_user_list.on("add remove", function() {
if (this.renderer) {
this.renderer.redrawUsers();
}
});
this.colorPicker = (function() {
var _tmpl = _.template('<li data-color="<%=c%>" style="background: <%=c%>"></li>');
return '<ul class="Rk-Edit-ColorPicker">' + Rkns.pickerColors.map(function(c) { return _tmpl({c:c});}).join("") + '</ul>';
})();
if (this.options.show_editor) {
this.renderer = new Rkns.Renderer.Scene(this);
}
if (!this.options.search.length) {
this.$.find(".Rk-Web-Search-Form").detach();
} else {
var _tmpl = _.template('<li class="<%= className %>" data-key="<%= key %>"><%= title %></li>'),
_select = this.$.find(".Rk-Search-List"),
_input = this.$.find(".Rk-Web-Search-Input"),
_form = this.$.find(".Rk-Web-Search-Form");
_(this.options.search).each(function(_search, _key) {
if (Rkns[_search.type] && Rkns[_search.type].Search) {
_this.search_engines.push(new Rkns[_search.type].Search(_this, _search));
}
});
_select.html(
_(this.search_engines).map(function(_search, _key) {
return _tmpl({
key: _key,
title: _search.getSearchTitle(),
className: _search.getBgClass()
});
}).join("")
);
_select.find("li").click(function() {
var _el = Rkns.$(this);
_this.setSearchEngine(_el.attr("data-key"));
_form.submit();
});
_form.submit(function() {
if (_input.val()) {
var _search = _this.search_engine;
_search.search(_input.val());
}
return false;
});
this.$.find(".Rk-Search-Current").mouseenter(
function() { _select.slideDown(); }
);
this.$.find(".Rk-Search-Select").mouseleave(
function() { _select.hide(); }
);
this.setSearchEngine(0);
}
_(this.options.bins).each(function(_bin) {
if (Rkns[_bin.type] && Rkns[_bin.type].Bin) {
_this.tabs.push(new Rkns[_bin.type].Bin(_this, _bin));
}
});
var elementDropped = false;
this.$.find(".Rk-Bins")
.on("click",".Rk-Bin-Title,.Rk-Bin-Title-Icon", function() {
var _mainDiv = Rkns.$(this).siblings(".Rk-Bin-Main");
if (_mainDiv.is(":hidden")) {
_this.$.find(".Rk-Bin-Main").slideUp();
_mainDiv.slideDown();
}
});
if (this.options.show_editor) {
this.$.find(".Rk-Bins").on("mouseover", ".Rk-Bin-Item", function(_e) {
var _t = Rkns.$(this);
if (_t && $(_t).attr("data-uri")) {
var _models = _this.project.get("nodes").where({
uri: $(_t).attr("data-uri")
});
_(_models).each(function(_model) {
_this.renderer.highlightModel(_model);
});
}
}).mouseout(function() {
_this.renderer.unhighlightAll();
}).on("mousemove", ".Rk-Bin-Item", function(e) {
try {
this.dragDrop();
}
catch(err) {}
}).on("touchstart", ".Rk-Bin-Item", function(e) {
elementDropped = false;
}).on("touchmove", ".Rk-Bin-Item", function(e) {
e.preventDefault();
var touch = e.originalEvent.changedTouches[0],
off = _this.renderer.canvas_$.offset(),
w = _this.renderer.canvas_$.width(),
h = _this.renderer.canvas_$.height();
if (touch.pageX >= off.left && touch.pageX < (off.left + w) && touch.pageY >= off.top && touch.pageY < (off.top + h)) {
if (elementDropped) {
_this.renderer.onMouseMove(touch, true);
} else {
elementDropped = true;
var div = document.createElement('div');
div.appendChild(this.cloneNode(true));
_this.renderer.dropData({"text/html": div.innerHTML}, touch);
_this.renderer.onMouseDown(touch, true);
}
}
}).on("touchend", ".Rk-Bin-Item", function(e) {
if (elementDropped) {
_this.renderer.onMouseUp(e.originalEvent.changedTouches[0], true);
}
elementDropped = false;
}).on("dragstart", ".Rk-Bin-Item", function(e) {
var div = document.createElement('div');
div.appendChild(this.cloneNode(true));
try {
e.originalEvent.dataTransfer.setData("text/html",div.innerHTML);
}
catch(err) {
e.originalEvent.dataTransfer.setData("text",div.innerHTML);
}
});
}
Rkns.$(window).resize(function() {
_this.resizeBins();
});
var lastsearch = false, lastval = '';
this.$.find(".Rk-Bins-Search-Input").on("change keyup paste input", function() {
var val = Rkns.$(this).val();
if (val === lastval) {
return;
}
var search = Rkns.Utils.regexpFromTextOrArray(val.length > 1 ? val: null);
if (search.source === lastsearch) {
return;
}
lastsearch = search.source;
_(_this.tabs).each(function(tab) {
tab.render(search);
});
});
this.$.find(".Rk-Bins-Search-Form").submit(function() {
return false;
});
};
Renkan.prototype.template = _.template(
'<% if (options.show_bins) { %><div class="Rk-Bins"><div class="Rk-Bins-Head"><h2 class="Rk-Bins-Title"><%- translate("Select contents:")%></h2>' +
'<form class="Rk-Web-Search-Form Rk-Search-Form"><input class="Rk-Web-Search-Input Rk-Search-Input" type="search" placeholder="<%- translate("Search the Web") %>" />' +
'<div class="Rk-Search-Select"><div class="Rk-Search-Current"></div><ul class="Rk-Search-List"></ul></div>' +
'<input type="submit" value="" class="Rk-Web-Search-Submit Rk-Search-Submit" title="<%- translate("Search the Web") %>" /></form>' +
'<form class="Rk-Bins-Search-Form Rk-Search-Form"><input class="Rk-Bins-Search-Input Rk-Search-Input" type="search" placeholder="<%- translate("Search in Bins") %>" />' +
'<input type="submit" value="" class="Rk-Bins-Search-Submit Rk-Search-Submit" title="<%- translate("Search in Bins") %>" /></form></div>' +
'<ul class="Rk-Bin-List"></ul></div><% } %>' +
'<% if (options.show_editor) { %><div class="Rk-Render Rk-Render-<% if (options.show_bins) { %>Panel<% } else { %>Full<% } %>"></div><% } %>'
);
Renkan.prototype.translate = function(_text) {
if (Rkns.i18n[this.options.language] && Rkns.i18n[this.options.language][_text]) {
return Rkns.i18n[this.options.language][_text];
}
if (this.options.language.length > 2 && Rkns.i18n[this.options.language.substr(0,2)] && Rkns.i18n[this.options.language.substr(0,2)][_text]) {
return Rkns.i18n[this.options.language.substr(0,2)][_text];
}
return _text;
};
Renkan.prototype.onStatusChange = function() {
this.renderer.onStatusChange();
};
Renkan.prototype.setSearchEngine = function(_key) {
this.search_engine = this.search_engines[_key];
this.$.find(".Rk-Search-Current").attr("class","Rk-Search-Current " + this.search_engine.getBgClass());
var listClasses = this.search_engine.getBgClass().split(" ");
var classes = "";
for (var i= 0; i < listClasses.length; i++) {
classes += "." + listClasses[i];
}
this.$.find(".Rk-Web-Search-Input.Rk-Search-Input").attr("placeholder", this.translate("Search in ") + this.$.find(".Rk-Search-List "+ classes).html());
};
Renkan.prototype.resizeBins = function() {
var _d = + this.$.find(".Rk-Bins-Head").outerHeight();
this.$.find(".Rk-Bin-Title:visible").each(function() {
_d += Rkns.$(this).outerHeight();
});
this.$.find(".Rk-Bin-Main").css({
height: this.$.find(".Rk-Bins").height() - _d
});
};
/* Utility functions */
var getUUID4 = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
};
Rkns.Utils = {
getUUID4 : getUUID4,
getUID : (function() {
function pad(n){
return n<10 ? '0'+n : n;
}
var _d = new Date(),
ID_AUTO_INCREMENT = 0,
ID_BASE = _d.getUTCFullYear() + '-' +
pad(_d.getUTCMonth()+1) + '-' +
pad(_d.getUTCDate()) + '-' +
getUUID4();
return function(_base) {
var _n = (++ID_AUTO_INCREMENT).toString(16),
_uidbase = (typeof _base === "undefined" ? "" : _base + "-" );
while (_n.length < 4) { _n = '0' + _n; }
return _uidbase + ID_BASE + '-' + _n;
};
})(),
getFullURL : function(url) {
if(typeof(url) === 'undefined' || url == null ) {
return "";
}
if(/https?:\/\//.test(url)) {
return url;
}
var img = new Image();
img.src = url;
var res = img.src;
img.src = null;
return res;
},
inherit : function(_baseClass, _callbefore) {
var _class = function(_arg) {
if (typeof _callbefore === "function") {
_callbefore.apply(this, Array.prototype.slice.call(arguments, 0));
}
_baseClass.apply(this, Array.prototype.slice.call(arguments, 0));
if (typeof this._init === "function" && !this._initialized) {
this._init.apply(this, Array.prototype.slice.call(arguments, 0));
this._initialized = true;
}
};
_(_class.prototype).extend(_baseClass.prototype);
return _class;
},
regexpFromTextOrArray: (function() {
var charsub = [
'[aáàâä]',
'[cç]',
'[eéèêë]',
'[iíìîï]',
'[oóòôö]',
'[uùûü]'
],
removeChars = [
String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807),
"{", "}", "(", ")", "[", "]", "【", "】", "、", "・", "‥", "。", "「", "」", "『", "』", "〜", ":", "!", "?", " ",
",", " ", ";", "(", ")", ".", "*", "+", "\\", "?", "|", "{", "}", "[", "]", "^", "#", "/"
],
remsrc = "[\\" + removeChars.join("\\") + "]",
remrx = new RegExp(remsrc, "gm"),
charsrx = _(charsub).map(function(c) {
return new RegExp(c);
});
function replaceText(_text) {
var txt = _text.toLowerCase().replace(remrx,""), src = "";
function makeReplaceFunc(l) {
return function(k,v) {
l = l.replace(charsrx[k], v);
};
}
for (var j = 0; j < txt.length; j++) {
if (j) {
src += remsrc + "*";
}
var l = txt[j];
_(charsub).each(makeReplaceFunc(l));
src += l;
}
return src;
}
function getSource(inp) {
switch (typeof inp) {
case "string":
return replaceText(inp);
case "object":
var src = '';
_(inp).each(function(v) {
var res = getSource(v);
if (res) {
if (src) {
src += '|';
}
src += res;
}
});
return src;
}
return '';
}
return function(_textOrArray) {
var source = getSource(_textOrArray);
if (source) {
var testrx = new RegExp( source, "im"),
replacerx = new RegExp( '(' + source + ')', "igm");
return {
isempty: false,
source: source,
test: function(_t) { return testrx.test(_t); },
replace: function(_text, _replace) { return _text.replace(replacerx, _replace); }
};
} else {
return {
isempty: true,
source: '',
test: function() { return true; },
replace: function(_text) { return text; }
};
}
};
})(),
/* The minimum distance (in pixels) the mouse has to move to consider an element was dragged */
_MIN_DRAG_DISTANCE: 2,
/* Distance between the inner and outer radius of buttons that appear when hovering on a node */
_NODE_BUTTON_WIDTH: 40,
_EDGE_BUTTON_INNER: 2,
_EDGE_BUTTON_OUTER: 40,
/* Constants used to know if a specific action is to be performed when clicking on the canvas */
_CLICKMODE_ADDNODE: 1,
_CLICKMODE_STARTEDGE: 2,
_CLICKMODE_ENDEDGE: 3,
/* Node size step: Used to calculate the size change when clicking the +/- buttons */
_NODE_SIZE_STEP: Math.LN2/4,
_MIN_SCALE: 1/20,
_MAX_SCALE: 20,
_MOUSEMOVE_RATE: 80,
_DOUBLETAP_DELAY: 800,
/* Maximum distance in pixels (squared, to reduce calculations)
* between two taps when double-tapping on a touch terminal */
_DOUBLETAP_DISTANCE: 20*20,
/* A placeholder so a default colour is displayed when a node has a null value for its user property */
_USER_PLACEHOLDER: function(_renkan) {
return {
color: _renkan.options.default_user_color,
title: _renkan.translate("(unknown user)"),
get: function(attr) {
return this[attr] || false;
}
};
},
/* The code for the "Drag and Add Bookmarklet", slightly minified and with whitespaces removed, though
* it doesn't seem that it's still a requirement in newer browsers (i.e. the ones compatibles with canvas drawing)
*/
_BOOKMARKLET_CODE: function(_renkan) {
return "(function(a,b,c,d,e,f,h,i,j,k,l,m,n,o,p,q,r){a=document;b=a.body;c=a.location.href;j='draggable';m='text/x-iri-';d=a.createElement('div');d.innerHTML='<p_style=\"position:fixed;top:0;right:0;font:bold_18px_sans-serif;color:#fff;background:#909;padding:10px;z-index:100000;\">" +
_renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_") +
"</p>'.replace(/_/g,String.fromCharCode(32));b.appendChild(d);e=[{r:/https?:\\/\\/[^\\/]*twitter\\.com\\//,s:'.tweet',n:'twitter'},{r:/https?:\\/\\/[^\\/]*google\\.[^\\/]+\\//,s:'.g',n:'google'},{r:/https?:\\/\\/[^\\/]*lemonde\\.fr\\//,s:'[data-vr-contentbox]',n:'lemonde'}];f=false;e.forEach(function(g){if(g.r.test(c)){f=g;}});if(f){h=function(){Array.prototype.forEach.call(a.querySelectorAll(f.s),function(i){i[j]=true;k=i.style;k.borderWidth='2px';k.borderColor='#909';k.borderStyle='solid';k.backgroundColor='rgba(200,0,180,.1)';})};window.setInterval(h,500);h();};a.addEventListener('dragstart',function(k){l=k.dataTransfer;l.setData(m+'source-uri',c);l.setData(m+'source-title',a.title);n=k.target;if(f){o=n;while(!o.attributes[j]){o=o.parentNode;if(o==b){break;}}}if(f&&o.attributes[j]){p=o.cloneNode(true);l.setData(m+'specific-site',f.n)}else{q=a.getSelection();if(q.type==='Range'||!q.type){p=q.getRangeAt(0).cloneContents();}else{p=n.cloneNode();}}r=a.createElement('div');r.appendChild(p);l.setData('text/x-iri-selected-text',r.textContent.trim());l.setData('text/x-iri-selected-html',r.innerHTML);},false);})();";
},
/* Shortens text to the required length then adds ellipsis */
shortenText: function(_text, _maxlength) {
return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text);
},
/* Drawing an edit box with an arrow and positioning the edit box according to the position of the node/edge being edited
* Called by Rkns.Renderer.NodeEditor and Rkns.Renderer.EdgeEditor */
drawEditBox: function(_options, _coords, _path, _xmargin, _selector) {
_selector.css({
width: ( _options.tooltip_width - 2* _options.tooltip_padding )
});
var _height = _selector.outerHeight() + 2* _options.tooltip_padding,
_isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
_left = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length ),
_right = _coords.x + _isLeft * ( _xmargin + _options.tooltip_arrow_length + _options.tooltip_width ),
_top = _coords.y - _height / 2;
if (_top + _height > (paper.view.size.height - _options.tooltip_margin)) {
_top = Math.max( paper.view.size.height - _options.tooltip_margin, _coords.y + _options.tooltip_arrow_width / 2 ) - _height;
}
if (_top < _options.tooltip_margin) {
_top = Math.min( _options.tooltip_margin, _coords.y - _options.tooltip_arrow_width / 2 );
}
var _bottom = _top + _height;
/* jshint laxbreak:true */
_path.segments[0].point
= _path.segments[7].point
= _coords.add([_isLeft * _xmargin, 0]);
_path.segments[1].point.x
= _path.segments[2].point.x
= _path.segments[5].point.x
= _path.segments[6].point.x
= _left;
_path.segments[3].point.x
= _path.segments[4].point.x
= _right;
_path.segments[2].point.y
= _path.segments[3].point.y
= _top;
_path.segments[4].point.y
= _path.segments[5].point.y
= _bottom;
_path.segments[1].point.y = _coords.y - _options.tooltip_arrow_width / 2;
_path.segments[6].point.y = _coords.y + _options.tooltip_arrow_width / 2;
_path.closed = true;
_path.fillColor = new paper.GradientColor(new paper.Gradient([_options.tooltip_top_color, _options.tooltip_bottom_color]), [0,_top], [0, _bottom]);
_selector.css({
left: (_options.tooltip_padding + Math.min(_left, _right)),
top: (_options.tooltip_padding + _top)
});
return _path;
}
};
})(window);
/* END main.js */