web/js/renkan.js
changeset 18 9783029ea81d
parent 14 960eb22c078c
child 24 701af897de95
equal deleted inserted replaced
16:b9bf0f859121 18:9783029ea81d
     1           /* *********************************************************
       
     2                   File generated on Wed May 15 15:42:55 CEST 2013
       
     3           ************************************************************
       
     4                           start of      main.js
       
     5           ********************************************************* */
       
     6 
       
     7 /* 
     1 /* 
     8     _____            _               
     2     _____            _               
     9    |  __ \          | |              
     3    |  __ \          | |              
    10    | |__) |___ _ __ | | ____ _ _ __  
     4    | |__) |___ _ __ | | ____ _ _ __  
    11    |  _  // _ \ '_ \| |/ / _` | '_ \ 
     5    |  _  // _ \ '_ \| |/ / _` | '_ \ 
    26  *  "http://www.cecill.info". 
    20  *  "http://www.cecill.info". 
    27  *  
    21  *  
    28  *  The fact that you are presently reading this means that you have had
    22  *  The fact that you are presently reading this means that you have had
    29  *  knowledge of the CeCILL-C license and that you accept its terms.
    23  *  knowledge of the CeCILL-C license and that you accept its terms.
    30 */
    24 */
    31 
       
    32 /* Declaring the Renkan Namespace Rkns and Default values */
    25 /* Declaring the Renkan Namespace Rkns and Default values */
    33 
    26 
    34 if (typeof Rkns !== "object") {
    27 (function(root) {
    35     Rkns = {};
    28 
       
    29 "use strict";
       
    30 
       
    31 if (typeof root.Rkns !== "object") {
       
    32     root.Rkns = {};
    36 }
    33 }
    37 
    34 
    38 Rkns.$ = jQuery;
    35 var Rkns = root.Rkns;
    39 
    36 var $ = Rkns.$ = root.jQuery;
    40 Rkns._ = _;
    37 var _ = Rkns._ = root._;
    41 
    38 
    42 Rkns.VERSION = '0.2';
    39 Rkns.VERSION = '0.2.1';
    43 
    40 
    44 Rkns.pickerColors = ["#8f1919", "#a80000", "#d82626", "#ff0000", "#e87c7c", "#ff6565", "#f7d3d3", "#fecccc",
    41 Rkns.pickerColors = ["#8f1919", "#a80000", "#d82626", "#ff0000", "#e87c7c", "#ff6565", "#f7d3d3", "#fecccc",
    45     "#8f5419", "#a85400", "#d87f26", "#ff7f00", "#e8b27c", "#ffb265", "#f7e5d3", "#fee5cc",
    42     "#8f5419", "#a85400", "#d87f26", "#ff7f00", "#e8b27c", "#ffb265", "#f7e5d3", "#fee5cc",
    46     "#8f8f19", "#a8a800", "#d8d826", "#feff00", "#e8e87c", "#feff65", "#f7f7d3", "#fefecc",
    43     "#8f8f19", "#a8a800", "#d8d826", "#feff00", "#e8e87c", "#feff65", "#f7f7d3", "#fefecc",
    47     "#198f19", "#00a800", "#26d826", "#00ff00", "#7ce87c", "#65ff65", "#d3f7d3", "#ccfecc",
    44     "#198f19", "#00a800", "#26d826", "#00ff00", "#7ce87c", "#65ff65", "#d3f7d3", "#ccfecc",
    48     "#198f8f", "#00a8a8", "#26d8d8", "#00feff", "#7ce8e8", "#65feff", "#d3f7f7", "#ccfefe",
    45     "#198f8f", "#00a8a8", "#26d8d8", "#00feff", "#7ce8e8", "#65feff", "#d3f7f7", "#ccfefe",
    49     "#19198f", "#0000a8", "#2626d8", "#0000ff", "#7c7ce8", "#6565ff", "#d3d3f7", "#ccccfe",
    46     "#19198f", "#0000a8", "#2626d8", "#0000ff", "#7c7ce8", "#6565ff", "#d3d3f7", "#ccccfe",
    50     "#8f198f", "#a800a8", "#d826d8", "#ff00fe", "#e87ce8", "#ff65fe", "#f7d3f7", "#feccfe",
    47     "#8f198f", "#a800a8", "#d826d8", "#ff00fe", "#e87ce8", "#ff65fe", "#f7d3f7", "#feccfe",
    51     "#000000", "#242424", "#484848", "#6d6d6d", "#919191", "#b6b6b6", "#dadada", "#ffffff"];
    48     "#000000", "#242424", "#484848", "#6d6d6d", "#919191", "#b6b6b6", "#dadada", "#ffffff"];
    52 
    49 
    53 Rkns._BaseBin = function(_renkan, _opts) {
    50 Rkns.__renkans = [];
       
    51 
       
    52 var _BaseBin = Rkns._BaseBin = function(_renkan, _opts) {
    54     if (typeof _renkan !== "undefined") {
    53     if (typeof _renkan !== "undefined") {
    55         this.renkan = _renkan;
    54         this.renkan = _renkan;
    56         this.renkan.$.find(".Rk-Bin-Main").hide();
    55         this.renkan.$.find(".Rk-Bin-Main").hide();
    57         this.$ = Rkns.$('<li>')
    56         this.$ = Rkns.$('<li>')
    58             .addClass("Rk-Bin")
    57             .addClass("Rk-Bin")
   109             },_opts.auto_refresh);
   108             },_opts.auto_refresh);
   110         }
   109         }
   111     }
   110     }
   112 };
   111 };
   113 
   112 
   114 Rkns._BaseBin.prototype.destroy = function() {
   113 _BaseBin.prototype.destroy = function() {
   115     this.$.detach();
   114     this.$.detach();
   116     this.renkan.resizeBins();
   115     this.renkan.resizeBins();
   117 };
   116 };
   118 
   117 
   119 /* Point of entry */
   118 /* Point of entry */
   120 
   119 
   121 Rkns.Renkan = function(_opts) {
   120 var Renkan = Rkns.Renkan = function(_opts) {
   122     var _this = this;
   121     var _this = this;
   123     
   122     
       
   123     Rkns.__renkans.push(this);
       
   124     
   124     this.options = _.defaults(_opts, Rkns.defaults);
   125     this.options = _.defaults(_opts, Rkns.defaults);
   125         
   126         
   126     Rkns._(this.options.property_files).each(function(f) {
   127     _(this.options.property_files).each(function(f) {
   127         Rkns.$.getJSON(f, function(data) {
   128         Rkns.$.getJSON(f, function(data) {
   128             _this.options.properties = _this.options.properties.concat(data);
   129             _this.options.properties = _this.options.properties.concat(data);
   129         });
   130         });
   130     });
   131     });
   131     
   132     
   138     }
   139     }
   139     this.$ = Rkns.$("#" + this.options.container);
   140     this.$ = Rkns.$("#" + this.options.container);
   140     this.$
   141     this.$
   141         .addClass("Rk-Main")
   142         .addClass("Rk-Main")
   142         .html(this.template(this));
   143         .html(this.template(this));
   143     this.renderer = new Rkns.Renderer.Scene(this);
   144     
   144     this.tabs = [];
   145     this.tabs = [];
   145     this.search_engines = [];
   146     this.search_engines = [];
   146 
   147 
   147     this.current_user_list = new Rkns.Models.UsersList();
   148     this.current_user_list = new Rkns.Models.UsersList();
       
   149     
       
   150     this.current_user_list.on("add remove", function() {
       
   151         if (this.renderer) {
       
   152             this.renderer.redrawUsers();
       
   153         }
       
   154     });
       
   155     
       
   156     this.colorPicker = (function() {
       
   157         var _tmpl = _.template('<li data-color="<%=c%>" style="background: <%=c%>"></li>');
       
   158         return '<ul class="Rk-Edit-ColorPicker">' + Rkns.pickerColors.map(function(c) { return _tmpl({c:c})}).join("") + '</ul>'
       
   159     })();
       
   160     
       
   161     if (this.options.show_editor) {
       
   162         this.renderer = new Rkns.Renderer.Scene(this);
       
   163     }
   148     
   164     
   149     if (!this.options.search.length) {
   165     if (!this.options.search.length) {
   150         this.$.find(".Rk-Web-Search-Form").detach();
   166         this.$.find(".Rk-Web-Search-Form").detach();
   151     } else {
   167     } else {
   152         var _tmpl = Rkns._.template('<li class="<%= className %>" data-key="<%= key %>"><%= title %></li>'),
   168         var _tmpl = _.template('<li class="<%= className %>" data-key="<%= key %>"><%= title %></li>'),
   153             _select = this.$.find(".Rk-Search-List"),
   169             _select = this.$.find(".Rk-Search-List"),
   154             _input = this.$.find(".Rk-Web-Search-Input"),
   170             _input = this.$.find(".Rk-Web-Search-Input"),
   155             _form = this.$.find(".Rk-Web-Search-Form");
   171             _form = this.$.find(".Rk-Web-Search-Form");
   156         Rkns._(this.options.search).each(function(_search, _key) {
   172         _(this.options.search).each(function(_search, _key) {
   157             if (Rkns[_search.type] && Rkns[_search.type].Search) {
   173             if (Rkns[_search.type] && Rkns[_search.type].Search) {
   158                 _this.search_engines.push(new Rkns[_search.type].Search(_this, _search));
   174                 _this.search_engines.push(new Rkns[_search.type].Search(_this, _search));
   159             }
   175             }
   160         });
   176         });
   161         _select.html(
   177         _select.html(
   162             Rkns._(this.search_engines).map(function(_search, _key) {
   178             _(this.search_engines).map(function(_search, _key) {
   163                 return _tmpl({
   179                 return _tmpl({
   164                     key: _key,
   180                     key: _key,
   165                     title: _search.getSearchTitle(),
   181                     title: _search.getSearchTitle(),
   166                     className: _search.getBgClass()
   182                     className: _search.getBgClass()
   167                 });
   183                 });
   185         this.$.find(".Rk-Search-Select").mouseleave(
   201         this.$.find(".Rk-Search-Select").mouseleave(
   186             function() { _select.hide(); }
   202             function() { _select.hide(); }
   187         );
   203         );
   188         this.setSearchEngine(0);
   204         this.setSearchEngine(0);
   189     }
   205     }
   190     Rkns._(this.options.bins).each(function(_bin) {
   206     _(this.options.bins).each(function(_bin) {
   191         if (Rkns[_bin.type] && Rkns[_bin.type].Bin) {
   207         if (Rkns[_bin.type] && Rkns[_bin.type].Bin) {
   192             _this.tabs.push(new Rkns[_bin.type].Bin(_this, _bin));
   208             _this.tabs.push(new Rkns[_bin.type].Bin(_this, _bin));
   193         }
   209         }
   194     });
   210     });
   195     
   211     
   200             var _mainDiv = Rkns.$(this).siblings(".Rk-Bin-Main");
   216             var _mainDiv = Rkns.$(this).siblings(".Rk-Bin-Main");
   201             if (_mainDiv.is(":hidden")) {
   217             if (_mainDiv.is(":hidden")) {
   202                 _this.$.find(".Rk-Bin-Main").slideUp();
   218                 _this.$.find(".Rk-Bin-Main").slideUp();
   203                 _mainDiv.slideDown();
   219                 _mainDiv.slideDown();
   204             }
   220             }
   205         }).on("mouseover", ".Rk-Bin-Item", function(_e) {
   221         });
       
   222     
       
   223     if (this.options.show_editor) {
       
   224         
       
   225         this.$.find(".Rk-Bins").on("mouseover", ".Rk-Bin-Item", function(_e) {
   206             var _t = Rkns.$(this);
   226             var _t = Rkns.$(this);
   207             if (_t && $(_t).attr("data-uri")) {
   227             if (_t && $(_t).attr("data-uri")) {
   208                 var _models = _this.project.get("nodes").where({
   228                 var _models = _this.project.get("nodes").where({
   209                     uri: $(_t).attr("data-uri")
   229                     uri: $(_t).attr("data-uri")
   210                 });
   230                 });
   211                 Rkns._(_models).each(function(_model) {
   231                 _(_models).each(function(_model) {
   212                     _this.renderer.highlightModel(_model);
   232                     _this.renderer.highlightModel(_model);
   213                 });
   233                 });
   214             }
   234             }
   215         }).mouseout(function() {
   235         }).mouseout(function() {
   216             _this.renderer.unhighlightAll();
   236             _this.renderer.unhighlightAll();
   251             }
   271             }
   252             catch(err) {
   272             catch(err) {
   253                 e.originalEvent.dataTransfer.setData("text",div.innerHTML);
   273                 e.originalEvent.dataTransfer.setData("text",div.innerHTML);
   254             }
   274             }
   255         });
   275         });
       
   276         
       
   277     }
       
   278     
   256     Rkns.$(window).resize(function() {
   279     Rkns.$(window).resize(function() {
   257         _this.resizeBins();
   280         _this.resizeBins();
   258     });
   281     });
   259     
   282     
       
   283     var lastsearch = false, lastval = '';
       
   284     
   260     this.$.find(".Rk-Bins-Search-Input").on("change keyup paste input", function() {
   285     this.$.find(".Rk-Bins-Search-Input").on("change keyup paste input", function() {
   261        var val = Rkns.$(this).val();
   286         var val = Rkns.$(this).val();
   262        Rkns._(_this.tabs).each(function(tab) {
   287         if (val === lastval) {
   263            tab.render(val);
   288             return;
   264        });
   289         }
       
   290         var search = Rkns.Utils.regexpFromTextOrArray(val.length > 1 ? val: null);
       
   291         if (search.source === lastsearch) {
       
   292             return;
       
   293         }
       
   294         lastsearch = search.source;
       
   295         _(_this.tabs).each(function(tab) {
       
   296             tab.render(search);
       
   297         });
       
   298         
   265     });
   299     });
   266     this.$.find(".Rk-Bins-Search-Form").submit(function() {
   300     this.$.find(".Rk-Bins-Search-Form").submit(function() {
   267         return false;
   301         return false;
   268     });
   302     });
       
   303     
   269 };
   304 };
   270 
   305 
   271 Rkns.Renkan.prototype.template = Rkns._.template(
   306 Renkan.prototype.template = _.template(
   272     '<% if (options.show_bins) { %><div class="Rk-Bins"><div class="Rk-Bins-Head"><h2 class="Rk-Bins-Title"><%- translate("Select contents:")%></h2>'
   307     '<% if (options.show_bins) { %><div class="Rk-Bins"><div class="Rk-Bins-Head"><h2 class="Rk-Bins-Title"><%- translate("Select contents:")%></h2>'
   273     + '<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") %>" />'
   308     + '<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") %>" />'
   274     + '<div class="Rk-Search-Select"><div class="Rk-Search-Current"></div><ul class="Rk-Search-List"></ul></div>'
   309     + '<div class="Rk-Search-Select"><div class="Rk-Search-Current"></div><ul class="Rk-Search-List"></ul></div>'
   275     + '<input type="submit" value="" class="Rk-Web-Search-Submit Rk-Search-Submit" title="<%- translate("Search the Web") %>" /></form>'
   310     + '<input type="submit" value="" class="Rk-Web-Search-Submit Rk-Search-Submit" title="<%- translate("Search the Web") %>" /></form>'
   276     + '<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") %>" />'
   311     + '<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") %>" />'
   277     + '<input type="submit" value="" class="Rk-Bins-Search-Submit Rk-Search-Submit" title="<%- translate("Search in Bins") %>" /></form></div>'
   312     + '<input type="submit" value="" class="Rk-Bins-Search-Submit Rk-Search-Submit" title="<%- translate("Search in Bins") %>" /></form></div>'
   278     + '<ul class="Rk-Bin-List"></ul></div><% } %><div class="Rk-Render Rk-Render-<% if (options.show_bins) { %>Panel<% } else { %>Full<% } %>"></div>'
   313     + '<ul class="Rk-Bin-List"></ul></div><% } %>'
       
   314     + '<% if (options.show_editor) { %><div class="Rk-Render Rk-Render-<% if (options.show_bins) { %>Panel<% } else { %>Full<% } %>"></div><% } %>'
   279 );
   315 );
   280 
   316 
   281 Rkns.Renkan.prototype.translate = function(_text) {
   317 Renkan.prototype.translate = function(_text) {
   282     if (Rkns.i18n[this.options.language] && Rkns.i18n[this.options.language][_text]) {
   318     if (Rkns.i18n[this.options.language] && Rkns.i18n[this.options.language][_text]) {
   283         return Rkns.i18n[this.options.language][_text];
   319         return Rkns.i18n[this.options.language][_text];
   284     }
   320     }
   285     if (this.options.language.length > 2 && Rkns.i18n[this.options.language.substr(0,2)] && Rkns.i18n[this.options.language.substr(0,2)][_text]) {
   321     if (this.options.language.length > 2 && Rkns.i18n[this.options.language.substr(0,2)] && Rkns.i18n[this.options.language.substr(0,2)][_text]) {
   286         return Rkns.i18n[this.options.language.substr(0,2)][_text];
   322         return Rkns.i18n[this.options.language.substr(0,2)][_text];
   287     }
   323     }
   288     return _text;
   324     return _text;
   289 };
   325 };
   290 
   326 
   291 Rkns.Renkan.prototype.onStatusChange = function() {
   327 Renkan.prototype.onStatusChange = function() {
   292     this.renderer.onStatusChange();
   328     this.renderer.onStatusChange();
   293 };
   329 };
   294 
   330 
   295 Rkns.Renkan.prototype.setSearchEngine = function(_key) {
   331 Renkan.prototype.setSearchEngine = function(_key) {
   296     this.search_engine = this.search_engines[_key];
   332     this.search_engine = this.search_engines[_key];
   297     this.$.find(".Rk-Search-Current").attr("class","Rk-Search-Current " + this.search_engine.getBgClass());
   333     this.$.find(".Rk-Search-Current").attr("class","Rk-Search-Current " + this.search_engine.getBgClass());
   298 };
   334 };
   299 
   335 
   300 Rkns.Renkan.prototype.resizeBins = function() {
   336 Renkan.prototype.resizeBins = function() {
   301     var _d = + this.$.find(".Rk-Bins-Head").outerHeight();
   337     var _d = + this.$.find(".Rk-Bins-Head").outerHeight();
   302     this.$.find(".Rk-Bin-Title:visible").each(function() {
   338     this.$.find(".Rk-Bin-Title:visible").each(function() {
   303         _d += Rkns.$(this).outerHeight();
   339         _d += Rkns.$(this).outerHeight();
   304     });
   340     });
   305     this.$.find(".Rk-Bin-Main").css({
   341     this.$.find(".Rk-Bin-Main").css({
   308 };
   344 };
   309 
   345 
   310 /* Utility functions */
   346 /* Utility functions */
   311 
   347 
   312 Rkns.Utils = {
   348 Rkns.Utils = {
   313     _ID_AUTO_INCREMENT : 0,
   349     getUID : (function() {
   314     _ID_BASE : (function(_d) {
   350         function pad(n){
   315         
   351             return n<10 ? '0'+n : n;
   316         function pad(n){return n<10 ? '0'+n : n;}
   352         }
   317         function fillrand(n) {
   353         function fillrand(n) {
   318             var _res = '';
   354             var _res = '';
   319             for (var i=0; i<n; i++) {
   355             for (var i=0; i<n; i++) {
   320                 _res += Math.floor(16*Math.random()).toString(16);
   356                 _res += Math.floor(16*Math.random()).toString(16);
   321             }
   357             }
   322             return _res;
   358             return _res;
   323         }
   359         }
   324         return _d.getUTCFullYear() + '-'  
   360         var _d = new Date(),
       
   361             ID_AUTO_INCREMENT = 0,
       
   362             ID_BASE = _d.getUTCFullYear() + '-'  
   325             + pad(_d.getUTCMonth()+1) + '-'  
   363             + pad(_d.getUTCMonth()+1) + '-'  
   326             + pad(_d.getUTCDate()) + '-'
   364             + pad(_d.getUTCDate()) + '-'
   327             + fillrand(16);
   365             + fillrand(16);
   328         
   366         return function(_base) {
   329     })(new Date()),
   367             var _n = (++ID_AUTO_INCREMENT).toString(16),
   330     getUID : function(_base) {
   368                 _base = (typeof _base === "undefined" ? "" : _base + "-" );
   331         
   369             while (_n.length < 4) { _n = '0' + _n; }
   332         var _n = (++this._ID_AUTO_INCREMENT).toString(16),
   370             return _base + this._ID_BASE + '-' + _n;
   333             _base = (typeof _base === "undefined" ? "" : _base + "-" );
   371         }
   334         while (_n.length < 4) {
   372     })(),
   335             _n = '0' + _n;
       
   336         }
       
   337         return _base + this._ID_BASE + '-' + _n;
       
   338         
       
   339     },
       
   340     getFullURL : function(url) {
   373     getFullURL : function(url) {
   341         
   374         
   342         if(typeof(url) == 'undefined' || url == null ) {
   375         if(typeof(url) == 'undefined' || url == null ) {
   343             return "";
   376             return "";
   344         }
   377         }
   362             if (typeof this._init == "function" && !this._initialized) {
   395             if (typeof this._init == "function" && !this._initialized) {
   363                 this._init.apply(this, Array.prototype.slice.call(arguments, 0));
   396                 this._init.apply(this, Array.prototype.slice.call(arguments, 0));
   364                 this._initialized = true;
   397                 this._initialized = true;
   365             }
   398             }
   366         };
   399         };
   367         Rkns._(_class.prototype).extend(_baseClass.prototype);
   400         _(_class.prototype).extend(_baseClass.prototype);
   368         return _class;
   401         return _class;
   369         
   402         
   370     }
   403     },
       
   404     regexpFromTextOrArray: (function() {
       
   405         var charsub = [
       
   406                 '[aáàâä]',
       
   407                 '[cç]',
       
   408                 '[eéèêë]',
       
   409                 '[iíìîï]',
       
   410                 '[oóòôö]',
       
   411                 '[uùûü]'
       
   412             ],
       
   413             removeChars = [
       
   414                 String.fromCharCode(768), String.fromCharCode(769), String.fromCharCode(770), String.fromCharCode(771), String.fromCharCode(807),
       
   415                 "{", "}", "(", ")", "[", "]", "【", "】", "、", "・", "‥", "。", "「", "」", "『", "』", "〜", ":", "!", "?", " ",
       
   416                 ",", " ", ";", "(", ")", ".", "*", "+", "\\", "?", "|", "{", "}", "[", "]", "^", "#", "/"
       
   417             ],
       
   418             remsrc = "[\\" + removeChars.join("\\") + "]",
       
   419             remrx = new RegExp(remsrc, "gm"),
       
   420             charsrx = _(charsub).map(function(c) {
       
   421                 return new RegExp(c);
       
   422             });
       
   423         
       
   424         function replaceText(_text) {
       
   425             var txt = _text.toLowerCase().replace(remrx,""), src = "";
       
   426             for (var j = 0; j < txt.length; j++) {
       
   427                 if (j) {
       
   428                     src += remsrc + "*";
       
   429                 }
       
   430                 var l = txt[j];
       
   431                 _(charsub).each(function(v, k) {
       
   432                     l = l.replace(charsrx[k], v);
       
   433                 });
       
   434                 src += l;
       
   435             }
       
   436             return src;
       
   437         }
       
   438         
       
   439         function getSource(inp) {
       
   440             switch (typeof inp) {
       
   441                 case "string":
       
   442                     return replaceText(inp);
       
   443                 case "object":
       
   444                     var src = '';
       
   445                     _(inp).each(function(v) {
       
   446                         var res = getSource(v);
       
   447                         if (res) {
       
   448                             if (src) {
       
   449                                 src += '|';
       
   450                             }
       
   451                             src += res;
       
   452                         }
       
   453                     });
       
   454                     return src;
       
   455             }
       
   456             return '';
       
   457         }
       
   458         
       
   459         return function(_textOrArray) {
       
   460             var source = getSource(_textOrArray);
       
   461             if (source) {
       
   462                 var testrx = new RegExp( source, "im"),
       
   463                     replacerx = new RegExp( '(' + source + ')', "igm")
       
   464                 return {
       
   465                     isempty: false,
       
   466                     source: source,
       
   467                     test: function(_t) { return testrx.test(_t) },
       
   468                     replace: function(_text, _replace) { return _text.replace(replacerx, _replace); }
       
   469                 }
       
   470             } else {
       
   471                 return {
       
   472                     isempty: true,
       
   473                     source: '',
       
   474                     test: function() { return true },
       
   475                     replace: function(_text) { return text }
       
   476                 }
       
   477             }
       
   478         }
       
   479     })()
   371 };
   480 };
   372 
   481 })(window);
   373           /* *********************************************************
   482 
   374                           end of        main.js
   483 /* END main.js */
   375           ************************************************************
       
   376           ************************************************************
       
   377                           start of      models.js
       
   378           ********************************************************* */
       
   379 
       
   380 (function() {
   484 (function() {
   381     
   485     "use strict";
   382     var root = this;
   486     var root = this;
   383         
   487         
   384     var Backbone = root.Backbone;
   488     var Backbone = root.Backbone;
   385     
   489     
   386     var Models = root.Rkns.Models = {};
   490     var Models = root.Rkns.Models = {};
   452             type: Backbone.HasOne,
   556             type: Backbone.HasOne,
   453             key: "created_by",
   557             key: "created_by",
   454             relatedModel: User
   558             relatedModel: User
   455         }],
   559         }],
   456         prepare: function(options) {
   560         prepare: function(options) {
   457             project = options.project;
   561             var project = options.project;
   458             this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
   562             this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
   459             options.description = options.description || "";
   563             options.description = options.description || "";
   460             return options;
   564             return options;
   461         },
   565         },
   462         toJSON: function() {
   566         toJSON: function() {
   494             key: "to",
   598             key: "to",
   495             relatedModel: Node
   599             relatedModel: Node
   496           },
   600           },
   497         ],
   601         ],
   498         prepare: function(options) {
   602         prepare: function(options) {
   499             project = options.project;
   603             var project = options.project;
   500             this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
   604             this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
   501             this.addReference(options, "from", project.get("nodes"), options.from);
   605             this.addReference(options, "from", project.get("nodes"), options.from);
   502             this.addReference(options, "to", project.get("nodes"), options.to);
   606             this.addReference(options, "to", project.get("nodes"), options.to);
   503             return options;
   607             return options;
   504         },
   608         },
   647     });
   751     });
   648     
   752     
   649 
   753 
   650 }).call(window);
   754 }).call(window);
   651 
   755 
   652 
       
   653           /* *********************************************************
       
   654                           end of        models.js
       
   655           ************************************************************
       
   656           ************************************************************
       
   657                           start of      defaults.js
       
   658           ********************************************************* */
       
   659 
       
   660 Rkns.defaults = {
   756 Rkns.defaults = {
   661     
   757     
   662     language: (navigator.language || navigator.userLanguage || "en"),
   758     language: (navigator.language || navigator.userLanguage || "en"),
   663         /* GUI Language */
   759         /* GUI Language */
   664     container: "renkan",
   760     container: "renkan",
   671         /* URL for static resources */
   767         /* URL for static resources */
   672     show_bins: true,
   768     show_bins: true,
   673         /* Show bins in left column */
   769         /* Show bins in left column */
   674     properties: [],
   770     properties: [],
   675         /* Semantic properties for edges */
   771         /* Semantic properties for edges */
       
   772     show_editor: true,
       
   773         /* Show the graph editor... Setting this to "false" only shows the bins part ! */
   676     read_only: false,
   774     read_only: false,
   677         /* Allows editing of renkan without changing the rest of the GUI. Can be switched on/off on the fly to block/enable editing */
   775         /* Allows editing of renkan without changing the rest of the GUI. Can be switched on/off on the fly to block/enable editing */
   678     editor_mode: true,
   776     editor_mode: true,
   679         /* Switch for Publish/Edit GUI. If editor_mode is false, read_only will be true.  */
   777         /* Switch for Publish/Edit GUI. If editor_mode is false, read_only will be true.  */
   680     snapshot_mode: false,
   778     snapshot_mode: false,
   690     element_delete_delay: 0,
   788     element_delete_delay: 0,
   691         /* Delay between clicking on the bin on an element and really deleting it
   789         /* Delay between clicking on the bin on an element and really deleting it
   692            Set to 0 for delete confirm */
   790            Set to 0 for delete confirm */
   693     autoscale_padding: 50,
   791     autoscale_padding: 50,
   694     
   792     
       
   793     /* TOP BAR BUTTONS */
       
   794     show_search_field: true,
       
   795     show_user_list: true,
       
   796     user_name_editable: true,
       
   797     user_color_editable: true,
       
   798     show_save_button: true,
       
   799     show_open_button: false,
       
   800     show_addnode_button: true,
       
   801     show_addedge_button: true,
       
   802     show_bookmarklet: true,
       
   803     show_fullscreen_button: true,
       
   804     home_button_url: false,
       
   805     home_button_title: "Home",
       
   806     
   695     /* MINI-MAP OPTIONS */
   807     /* MINI-MAP OPTIONS */
   696     
   808     
   697     show_minimap: true,
   809     show_minimap: true,
   698         /* Show a small map at the bottom right */
   810         /* Show a small map at the bottom right */
   699     minimap_width: 160,
   811     minimap_width: 160,
   760     show_node_editor_description: true,
   872     show_node_editor_description: true,
   761     show_node_editor_size: true,
   873     show_node_editor_size: true,
   762     show_node_editor_color: true,
   874     show_node_editor_color: true,
   763     show_node_editor_image: true,
   875     show_node_editor_image: true,
   764     show_node_editor_creator: true,
   876     show_node_editor_creator: true,
       
   877     uploaded_image_max_kb: 500,
   765     
   878     
   766     /* NODE TOOLTIP OPTIONS */
   879     /* NODE TOOLTIP OPTIONS */
   767     
   880     
   768     show_node_tooltip_uri: true,
   881     show_node_tooltip_uri: true,
   769     show_node_tooltip_description: true,
   882     show_node_tooltip_description: true,
   787     show_edge_tooltip_creator: true
   900     show_edge_tooltip_creator: true
   788     
   901     
   789     /* */
   902     /* */
   790     
   903     
   791 };
   904 };
   792 
       
   793           /* *********************************************************
       
   794                           end of        defaults.js
       
   795           ************************************************************
       
   796           ************************************************************
       
   797                           start of      i18n.js
       
   798           ********************************************************* */
       
   799 
       
   800 Rkns.i18n = {
   905 Rkns.i18n = {
   801     fr: {
   906     fr: {
   802         "Edit Node": "Édition d’un nœud",
   907         "Edit Node": "Édition d’un nœud",
   803         "Edit Edge": "Édition d’un lien",
   908         "Edit Edge": "Édition d’un lien",
   804         "Title:": "Titre :",
   909         "Title:": "Titre :",
   810         "Image URL:": "URL d'Image",
   915         "Image URL:": "URL d'Image",
   811         "Choose Image File:": "Choisir un fichier image",
   916         "Choose Image File:": "Choisir un fichier image",
   812         "Full Screen": "Mode plein écran",
   917         "Full Screen": "Mode plein écran",
   813         "Add Node": "Ajouter un nœud",
   918         "Add Node": "Ajouter un nœud",
   814         "Add Edge": "Ajouter un lien",
   919         "Add Edge": "Ajouter un lien",
   815         "Archive Project": "Archiver le projet",
   920         "Save Project": "Enregistrer le projet",
       
   921         "Open Project": "Ouvrir un projet",
   816         "Auto-save enabled": "Enregistrement automatique activé",
   922         "Auto-save enabled": "Enregistrement automatique activé",
   817         "Connection lost": "Connexion perdue",
   923         "Connection lost": "Connexion perdue",
   818         "Created by:": "Créé par :",
   924         "Created by:": "Créé par :",
   819         "Zoom In": "Agrandir l’échelle",
   925         "Zoom In": "Agrandir l’échelle",
   820         "Zoom Out": "Rapetisser l’échelle",
   926         "Zoom Out": "Rapetisser l’échelle",
   825         "Enlarge": "Agrandir",
   931         "Enlarge": "Agrandir",
   826         "Shrink": "Rétrécir",
   932         "Shrink": "Rétrécir",
   827         "Click on the background canvas to add a node": "Cliquer sur le fond du graphe pour rajouter un nœud",
   933         "Click on the background canvas to add a node": "Cliquer sur le fond du graphe pour rajouter un nœud",
   828         "Click on a first node to start the edge": "Cliquer sur un premier nœud pour commencer le lien",
   934         "Click on a first node to start the edge": "Cliquer sur un premier nœud pour commencer le lien",
   829         "Click on a second node to complete the edge": "Cliquer sur un second nœud pour terminer le lien",
   935         "Click on a second node to complete the edge": "Cliquer sur un second nœud pour terminer le lien",
   830         "Twitter": "Twitter",
       
   831         "Wikipedia": "Wikipédia",
   936         "Wikipedia": "Wikipédia",
   832         "Wikipedia in ": "Wikipédia en ",
   937         "Wikipedia in ": "Wikipédia en ",
   833         "French": "Français",
   938         "French": "Français",
   834         "English": "Anglais",
   939         "English": "Anglais",
   835         "Japanese": "Japonais",
   940         "Japanese": "Japonais",
   871         "(untitled)": "(sans titre)",
   976         "(untitled)": "(sans titre)",
   872         "Select contents:": "Sélectionner des contenus :",
   977         "Select contents:": "Sélectionner des contenus :",
   873         "Drag items from this website, drop them in Renkan": "Glissez des éléments de ce site web vers Renkan",
   978         "Drag items from this website, drop them in Renkan": "Glissez des éléments de ce site web vers Renkan",
   874         "Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan.": "Glissez ce bouton vers votre barre de favoris. Ensuite, depuis un site tiers, cliquez dessus pour activer 'Drag-to-Add' puis glissez des éléments de ce site vers Renkan"
   979         "Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan.": "Glissez ce bouton vers votre barre de favoris. Ensuite, depuis un site tiers, cliquez dessus pour activer 'Drag-to-Add' puis glissez des éléments de ce site vers Renkan"
   875     }
   980     }
   876 }
   981 };
   877 
   982 /* paper-renderer.js */
   878           /* *********************************************************
   983 
   879                           end of        i18n.js
   984 (function(root) {
   880           ************************************************************
   985 
   881           ************************************************************
   986 "use strict";
   882                           start of      paper-renderer.js
   987 
   883           ********************************************************* */
   988 var Rkns = root.Rkns,
   884 
   989     _ = Rkns._,
   885 Rkns.Renderer = {
   990     $ = Rkns.$;
   886     _MIN_DRAG_DISTANCE: 2,
   991 
   887     _NODE_BUTTON_WIDTH: 40,
   992 /* Rkns.Renderer Object */
   888     _EDGE_BUTTON_INNER: 2,
   993 
   889     _EDGE_BUTTON_OUTER: 40,
   994 /* This object contains constants, utility functions and classes for Renkan's Graph Manipulation GUI */
   890     _CLICKMODE_ADDNODE : 1,
   995 
   891     _CLICKMODE_STARTEDGE : 2,
   996 var Renderer = Rkns.Renderer = {},
   892     _CLICKMODE_ENDEDGE : 3,
   997         /* The minimum distance (in pixels) the mouse has to move to consider an element was dragged */
   893     _IMAGE_MAX_KB : 500,
   998     _MIN_DRAG_DISTANCE = 2,
   894     _NODE_SIZE_STEP: Math.LN2/4,
   999         /* Distance between the inner and outer radius of buttons that appear when hovering on a node */
   895     _MIN_SCALE: 1/20,
  1000     _NODE_BUTTON_WIDTH = 40,
   896     _MAX_SCALE: 20,
  1001     _EDGE_BUTTON_INNER = 2,
   897     _MOUSEMOVE_RATE: 80,
  1002     _EDGE_BUTTON_OUTER = 40,
   898     _DOUBLETAP_DELAY: 800,
  1003         /* Constants used to know if a specific action is to be performed when clicking on the canvas */
   899     _DOUBLETAP_DISTANCE: 20*20,
  1004     _CLICKMODE_ADDNODE = 1,
   900     _USER_PLACEHOLDER : function(_renkan) {
  1005     _CLICKMODE_STARTEDGE = 2,
       
  1006     _CLICKMODE_ENDEDGE = 3,
       
  1007         /* Node size step: Used to calculate the size change when clicking the +/- buttons */
       
  1008     _NODE_SIZE_STEP = Math.LN2/4,
       
  1009     _MIN_SCALE = 1/20,
       
  1010     _MAX_SCALE = 20,
       
  1011     _MOUSEMOVE_RATE = 80,
       
  1012     _DOUBLETAP_DELAY = 800,
       
  1013         /* Maximum distance in pixels (squared, to reduce calculations)
       
  1014          * between two taps when double-tapping on a touch terminal */
       
  1015     _DOUBLETAP_DISTANCE = 20*20,
       
  1016         /* A placeholder so a default colour is displayed when a node has a null value for its user property */
       
  1017     _USER_PLACEHOLDER = function(_renkan) {
   901         return {
  1018         return {
   902             color: _renkan.options.default_user_color,
  1019             color: _renkan.options.default_user_color,
   903             title: _renkan.translate("(unknown user)"),
  1020             title: _renkan.translate("(unknown user)"),
   904             get: function(attr) {
  1021             get: function(attr) {
   905                 return this[attr] || false;
  1022                 return this[attr] || false;
   906             }
  1023             }
   907         };
  1024         };
   908     },
  1025     },
   909     _BOOKMARKLET_CODE: function(_renkan) {
  1026         /* The code for the "Drag and Add Bookmarklet", slightly minified and with whitespaces removed, though
       
  1027          * it doesn't seem that it's still a requirement in newer browsers (i.e. the ones compatibles with canvas drawing)
       
  1028          */
       
  1029     _BOOKMARKLET_CODE = function(_renkan) {
   910         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;\">"
  1030         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;\">"
   911         + _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_")
  1031         + _renkan.translate("Drag items from this website, drop them in Renkan").replace(/ /g,"_")
   912         + "</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);})();";
  1032         + "</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);})();";
   913     },
  1033     },
   914     shortenText : function(_text, _maxlength) {
  1034         /* Shortens text to the required length then adds ellipsis */
       
  1035     shortenText = function(_text, _maxlength) {
   915         return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text);
  1036         return (_text.length > _maxlength ? (_text.substr(0,_maxlength) + '…') : _text);
   916     },
  1037     },
   917     drawEditBox : function(_options, _coords, _path, _xmargin, _selector) {
  1038         /* Drawing an edit box with an arrow and positioning the edit box according to the position of the node/edge being edited
       
  1039          * Called by Rkns.Renderer.NodeEditor and Rkns.Renderer.EdgeEditor */
       
  1040     drawEditBox = function(_options, _coords, _path, _xmargin, _selector) {
   918         _selector.css({
  1041         _selector.css({
   919             width: ( _options.tooltip_width - 2* _options.tooltip_padding ),
  1042             width: ( _options.tooltip_width - 2* _options.tooltip_padding ),
   920         });
  1043         });
   921         var _height = _selector.outerHeight() + 2* _options.tooltip_padding,
  1044         var _height = _selector.outerHeight() + 2* _options.tooltip_padding,
   922             _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
  1045             _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
   954         _selector.css({
  1077         _selector.css({
   955             left: (_options.tooltip_padding + Math.min(_left, _right)),
  1078             left: (_options.tooltip_padding + Math.min(_left, _right)),
   956             top: (_options.tooltip_padding + _top)
  1079             top: (_options.tooltip_padding + _top)
   957         });
  1080         });
   958         return _path;
  1081         return _path;
   959     }
  1082     };
   960 };
  1083 
   961 
  1084 /* Rkns.Renderer._BaseRepresentation Class */
   962 Rkns.Renderer._BaseRepresentation = function(_renderer, _model) {
  1085 
       
  1086 /* In Renkan, a "Representation" is a sort of ViewModel (in the MVVM paradigm) and bridges the gap between
       
  1087  * models (written with Backbone.js) and the view (written with Paper.js)
       
  1088  * Renkan's representations all inherit from Rkns.Renderer._BaseRepresentation '*/
       
  1089 
       
  1090 var _BaseRepresentation = Renderer._BaseRepresentation = function(_renderer, _model) {
   963     if (typeof _renderer !== "undefined") {
  1091     if (typeof _renderer !== "undefined") {
   964         this.renderer = _renderer;
  1092         this.renderer = _renderer;
   965         this.renkan = _renderer.renkan;
  1093         this.renkan = _renderer.renkan;
   966         this.project = _renderer.renkan.project;
  1094         this.project = _renderer.renkan.project;
   967         this.options = _renderer.renkan.options;
  1095         this.options = _renderer.renkan.options;
   989             this.model.on("unselect", this._unselectBinding );
  1117             this.model.on("unselect", this._unselectBinding );
   990         }
  1118         }
   991     }
  1119     }
   992 };
  1120 };
   993 
  1121 
   994 Rkns.Renderer._BaseRepresentation.prototype.super = function(_func) {
  1122 /* Rkns.Renderer._BaseRepresentation Methods */
   995     Rkns.Renderer._BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
  1123 
   996 };
  1124 _(_BaseRepresentation.prototype).extend({
   997 
  1125     _super: function(_func) {
   998 Rkns.Renderer._BaseRepresentation.prototype.redraw = function() {};
  1126         return _BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
   999 
  1127     },
  1000 Rkns.Renderer._BaseRepresentation.prototype.moveTo = function() {};
  1128     redraw: function() {},
  1001 
  1129     moveTo: function() {},
  1002 Rkns.Renderer._BaseRepresentation.prototype.show = function() {};
  1130     show: function() {},
  1003 
  1131     hide: function() {},
  1004 Rkns.Renderer._BaseRepresentation.prototype.hide = function() {};
  1132     select: function() {
  1005 
  1133         if (this.model) {
  1006 Rkns.Renderer._BaseRepresentation.prototype.select = function() {
  1134             this.model.trigger("selected");
  1007     if (this.model) {
  1135         }
  1008         this.model.trigger("selected");
  1136     },
  1009     }
  1137     unselect: function() {
  1010 };
  1138         if (this.model) {
  1011 
  1139             this.model.trigger("unselected");
  1012 Rkns.Renderer._BaseRepresentation.prototype.unselect = function() {
  1140         }
  1013     if (this.model) {
  1141     },
  1014         this.model.trigger("unselected");
  1142     highlight: function() {},
  1015     }
  1143     unhighlight: function() {},
  1016 };
  1144     mousedown: function() {},
  1017 
  1145     mouseup: function() {
  1018 Rkns.Renderer._BaseRepresentation.prototype.highlight = function() {};
  1146         if (this.model) {
  1019 
  1147             this.model.trigger("clicked");
  1020 Rkns.Renderer._BaseRepresentation.prototype.unhighlight = function() {};
  1148         }
  1021 
  1149     },
  1022 Rkns.Renderer._BaseRepresentation.prototype.mousedown = function() {};
  1150     destroy: function() {
  1023 
  1151         if (this.model) {
  1024 Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() {
  1152             this.model.off("change", this._changeBinding );
  1025     if (this.model) {
  1153             this.model.off("remove", this._removeBinding );
  1026         this.model.trigger("clicked");
  1154             this.model.off("select", this._selectBinding );
  1027     }
  1155             this.model.off("unselect", this._unselectBinding );
  1028 };
  1156         }
  1029 
  1157     }
  1030 Rkns.Renderer._BaseRepresentation.prototype.destroy = function() {
  1158 });
  1031     if (this.model) {
  1159 
  1032         this.model.off("change", this._changeBinding );
  1160 /* End of Rkns.Renderer._BaseRepresentation Class */
  1033         this.model.off("remove", this._removeBinding );
  1161 
  1034         this.model.off("select", this._selectBinding );
  1162 /* Rkns.Renderer._BaseButton Class */
  1035         this.model.off("unselect", this._unselectBinding );
  1163 
  1036     }
  1164 /* BaseButton is extended by contextual buttons that appear when hovering on nodes and edges */
  1037 };
  1165 
  1038 
  1166 var _BaseButton = Renderer._BaseButton = Rkns.Utils.inherit(_BaseRepresentation);
  1039 /* */
  1167 
  1040 
  1168 _(_BaseButton.prototype).extend({
  1041 Rkns.Renderer._BaseButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1169 moveTo: function(_pos) {
  1042 
       
  1043 Rkns.Renderer._BaseButton.prototype.moveTo = function(_pos) {
       
  1044     this.sector.moveTo(_pos);
  1170     this.sector.moveTo(_pos);
  1045 };
  1171 },
  1046 
  1172 show: function() {
  1047 Rkns.Renderer._BaseButton.prototype.show = function() {
       
  1048     this.sector.show();
  1173     this.sector.show();
  1049 };
  1174 },
  1050 
  1175 hide: function() {
  1051 Rkns.Renderer._BaseButton.prototype.hide = function() {
       
  1052     this.sector.hide();
  1176     this.sector.hide();
  1053 };
  1177 },
  1054 
  1178 select: function() {
  1055 Rkns.Renderer._BaseButton.prototype.select = function() {
       
  1056     this.sector.select();
  1179     this.sector.select();
  1057 };
  1180 },
  1058 
  1181 unselect: function(_newTarget) {
  1059 Rkns.Renderer._BaseButton.prototype.unselect = function(_newTarget) {
       
  1060     this.sector.unselect();
  1182     this.sector.unselect();
  1061     if (!_newTarget || (_newTarget !== this.source_representation && _newTarget.source_representation !== this.source_representation)) {
  1183     if (!_newTarget || (_newTarget !== this.source_representation && _newTarget.source_representation !== this.source_representation)) {
  1062         this.source_representation.unselect();
  1184         this.source_representation.unselect();
  1063     }
  1185     }
  1064 };
  1186 },
  1065 
  1187 destroy: function() {
  1066 Rkns.Renderer._BaseButton.prototype.destroy = function() {
       
  1067     this.sector.destroy();
  1188     this.sector.destroy();
  1068 };
  1189 }
  1069 
  1190 });
  1070 /* */
  1191 
  1071 
  1192 /* End of Rkns.Renderer._BaseButton Class */
  1072 Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1193 
  1073 
  1194 /* Rkns.Renderer.Node Class */
  1074 Rkns.Renderer.Node.prototype._init = function() {
  1195 
       
  1196 /* The representation for the node : A circle, with an image inside and a text label underneath.
       
  1197  * The circle and the image are drawn on canvas and managed by Paper.js.
       
  1198  * The text label is an HTML node, managed by jQuery. */
       
  1199 
       
  1200 var NodeRepr = Renderer.Node = Rkns.Utils.inherit(_BaseRepresentation);
       
  1201 
       
  1202 _(NodeRepr.prototype).extend({
       
  1203 _init: function() {
  1075     this.renderer.node_layer.activate();
  1204     this.renderer.node_layer.activate();
  1076     this.type = "Node";
  1205     this.type = "Node";
  1077     this.circle = new paper.Path.Circle([0, 0], 1);
  1206     this.circle = new paper.Path.Circle([0, 0], 1);
  1078     this.circle.__representation = this;
  1207     this.circle.__representation = this;
  1079     if (this.options.show_node_circles) {
  1208     if (this.options.show_node_circles) {
  1080         this.circle.strokeWidth = this.options.node_stroke_width;
  1209         this.circle.strokeWidth = this.options.node_stroke_width;
  1081         this.h_ratio = 1;
  1210         this.h_ratio = 1;
  1082     } else {
  1211     } else {
  1083         this.h_ratio = 0;
  1212         this.h_ratio = 0;
  1084     }
  1213     }
  1085     this.title = Rkns.$('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
  1214     this.title = $('<div class="Rk-Label">').appendTo(this.renderer.labels_$);
  1086     if (this.options.editor_mode) {
  1215     if (this.options.editor_mode) {
  1087         this.normal_buttons = [
  1216         this.normal_buttons = [
  1088             new Rkns.Renderer.NodeEditButton(this.renderer, null),
  1217             new NodeEditButton(this.renderer, null),
  1089             new Rkns.Renderer.NodeRemoveButton(this.renderer, null),
  1218             new NodeRemoveButton(this.renderer, null),
  1090             new Rkns.Renderer.NodeLinkButton(this.renderer, null),
  1219             new NodeLinkButton(this.renderer, null),
  1091             new Rkns.Renderer.NodeEnlargeButton(this.renderer, null),
  1220             new NodeEnlargeButton(this.renderer, null),
  1092             new Rkns.Renderer.NodeShrinkButton(this.renderer, null)
  1221             new NodeShrinkButton(this.renderer, null)
  1093         ];
  1222         ];
  1094         this.pending_delete_buttons = [
  1223         this.pending_delete_buttons = [
  1095             new Rkns.Renderer.NodeRevertButton(this.renderer, null)
  1224             new NodeRevertButton(this.renderer, null)
  1096         ];
  1225         ];
  1097         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
  1226         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
  1098         for (var i = 0; i < this.all_buttons.length; i++) {
  1227         for (var i = 0; i < this.all_buttons.length; i++) {
  1099             this.all_buttons[i].source_representation = this;
  1228             this.all_buttons[i].source_representation = this;
  1100         }
  1229         }
  1108         this.renderer.minimap.node_layer.activate();
  1237         this.renderer.minimap.node_layer.activate();
  1109         this.minimap_circle = new paper.Path.Circle([0, 0], 1);
  1238         this.minimap_circle = new paper.Path.Circle([0, 0], 1);
  1110         this.minimap_circle.__representation = this.renderer.minimap.miniframe.__representation;
  1239         this.minimap_circle.__representation = this.renderer.minimap.miniframe.__representation;
  1111         this.renderer.minimap.node_group.addChild(this.minimap_circle);
  1240         this.renderer.minimap.node_group.addChild(this.minimap_circle);
  1112     }
  1241     }
  1113 };
  1242 },
  1114 
  1243 redraw: function(_dontRedrawEdges) {
  1115 Rkns.Renderer.Node.prototype.redraw = function(_dontRedrawEdges) {
       
  1116     var _model_coords = new paper.Point(this.model.get("position")),
  1244     var _model_coords = new paper.Point(this.model.get("position")),
  1117         _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * Rkns.Renderer._NODE_SIZE_STEP);
  1245         _baseRadius = this.options.node_size_base * Math.exp((this.model.get("size") || 0) * _NODE_SIZE_STEP);
  1118     if (!this.is_dragging || !this.paper_coords) {
  1246     if (!this.is_dragging || !this.paper_coords) {
  1119         this.paper_coords = this.renderer.toPaperCoords(_model_coords);
  1247         this.paper_coords = this.renderer.toPaperCoords(_model_coords);
  1120     }
  1248     }
  1121     this.circle_radius = _baseRadius * this.renderer.scale;
  1249     this.circle_radius = _baseRadius * this.renderer.scale;
  1122     if (this.last_circle_radius !== this.circle_radius) {
  1250     if (this.last_circle_radius !== this.circle_radius) {
  1167     this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color;
  1295     this.circle.fillColor = this.highlighted ? this.options.highlighted_node_fill_color : this.options.node_fill_color;
  1168     
  1296     
  1169     this.circle.opacity = this.options.show_node_circles ? opacity : .01;
  1297     this.circle.opacity = this.options.show_node_circles ? opacity : .01;
  1170     
  1298     
  1171     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || "";
  1299     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_nodes) || "";
  1172     _text = Rkns.Renderer.shortenText(_text, this.options.node_label_max_length);
  1300     _text = shortenText(_text, this.options.node_label_max_length);
  1173     this.title.text(_text);
  1301     
       
  1302     if (typeof this.highlighted === "object") {
       
  1303         this.title.html(this.highlighted.replace(_(_text).escape(),'<span class="Rk-Highlighted">$1</span>'));
       
  1304     } else {
       
  1305         this.title.text(_text);
       
  1306     }
       
  1307     
  1174     this.title.css({
  1308     this.title.css({
  1175         left: this.paper_coords.x,
  1309         left: this.paper_coords.x,
  1176         top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,
  1310         top: this.paper_coords.y + this.circle_radius * this.h_ratio + this.options.node_label_distance,
  1177         opacity: opacity
  1311         opacity: opacity
  1178     });
  1312     });
  1179     var _color = this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
  1313     var _color = this.model.get("color") || (this.model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color");
  1180     this.circle.strokeColor = _color;
  1314     this.circle.strokeColor = _color;
  1181     var _pc = this.paper_coords;
  1315     var _pc = this.paper_coords;
  1182     this.all_buttons.forEach(function(b) {
  1316     this.all_buttons.forEach(function(b) {
  1183         b.moveTo(_pc);
  1317         b.moveTo(_pc);
  1184     });
  1318     });
  1199             minisize = new paper.Size([miniradius, miniradius]);
  1333             minisize = new paper.Size([miniradius, miniradius]);
  1200         this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2));
  1334         this.minimap_circle.fitBounds(minipos.subtract(minisize), minisize.multiply(2));
  1201     }
  1335     }
  1202     
  1336     
  1203     if (!_dontRedrawEdges) {
  1337     if (!_dontRedrawEdges) {
  1204         Rkns._.each(this.project.get("edges").filter(function (ed) { return ((ed.to === this.model) || (ed.from === this.model));}), function(edge, index, list){
  1338         var _this = this;
  1205             var repr = this.renderer.getRepresentationByModel(edge);
  1339         _.each(
  1206             if (repr && typeof repr.from_representation !== "undefined" && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
  1340             this.project.get("edges").filter(
  1207                 repr.redraw();
  1341                 function (ed) {
  1208             }
  1342                     return ((ed.get("to") === _this.model) || (ed.get("from") === _this.model));
  1209         }, this);
  1343                 }
  1210     }
  1344             ),
  1211 
  1345             function(edge, index, list) {
  1212 };
  1346                 var repr = _this.renderer.getRepresentationByModel(edge);
  1213 
  1347                 if (repr && typeof repr.from_representation !== "undefined" && typeof repr.from_representation.paper_coords !== "undefined" && typeof repr.to_representation !== "undefined" && typeof repr.to_representation.paper_coords !== "undefined") {
  1214 Rkns.Renderer.Node.prototype.showImage = function() {
  1348                     repr.redraw();
       
  1349                 }
       
  1350             }
       
  1351         );
       
  1352     }
       
  1353 
       
  1354 },
       
  1355 showImage: function() {
  1215     if (typeof this.renderer.image_cache[this.img] === "undefined") {
  1356     if (typeof this.renderer.image_cache[this.img] === "undefined") {
  1216         var _image = new Image();
  1357         var _image = new Image();
  1217         this.renderer.image_cache[this.img] = _image;
  1358         this.renderer.image_cache[this.img] = _image;
  1218         _image.src = this.img;
  1359         _image.src = this.img;
  1219     } else {
  1360     } else {
  1235                 minX = Infinity,
  1376                 minX = Infinity,
  1236                 minY = Infinity,
  1377                 minY = Infinity,
  1237                 maxX = -Infinity,
  1378                 maxX = -Infinity,
  1238                 maxY = -Infinity;
  1379                 maxY = -Infinity;
  1239                 
  1380                 
  1240             function transformCoords(tabc, relative) {
  1381             var transformCoords = function(tabc, relative) {
  1241                 var newCoords = tabc.slice(1).map(function(v, k) {
  1382                 var newCoords = tabc.slice(1).map(function(v, k) {
  1242                     var res = parseFloat(v),
  1383                     var res = parseFloat(v),
  1243                         isY = k % 2;
  1384                         isY = k % 2;
  1244                     if (isY) {
  1385                     if (isY) {
  1245                         res = ( res - .5 ) * height;
  1386                         res = ( res - .5 ) * height;
  1258                     }
  1399                     }
  1259                     return res;
  1400                     return res;
  1260                 });
  1401                 });
  1261                 lastCoords = newCoords.slice(-2);
  1402                 lastCoords = newCoords.slice(-2);
  1262                 return newCoords;
  1403                 return newCoords;
  1263             }
  1404             };
  1264             
  1405             
  1265             instructions.forEach(function(instr) {
  1406             instructions.forEach(function(instr) {
  1266                 var coords = instr.match(/([a-z]|[0-9.-]+)/ig) || [""];
  1407                 var coords = instr.match(/([a-z]|[0-9.-]+)/ig) || [""];
  1267                 switch(coords[0]) {
  1408                 switch(coords[0]) {
  1268                     case "M":
  1409                     case "M":
  1328         this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));
  1469         this.node_image.position = this.paper_coords.subtract(this.image_delta.multiply(this.circle_radius));
  1329         this.redraw();
  1470         this.redraw();
  1330         this.renderer.throttledPaperDraw();
  1471         this.renderer.throttledPaperDraw();
  1331     } else {
  1472     } else {
  1332         var _this = this;
  1473         var _this = this;
  1333         Rkns.$(_image).on("load", function() {
  1474         $(_image).on("load", function() {
  1334             _this.showImage();
  1475             _this.showImage();
  1335         });
  1476         });
  1336     }
  1477     }
  1337 }
  1478 },
  1338 
  1479 paperShift: function(_delta) {
  1339 Rkns.Renderer.Node.prototype.paperShift = function(_delta) {
       
  1340     if (this.options.editor_mode) {
  1480     if (this.options.editor_mode) {
  1341         if (!this.renkan.read_only) {
  1481         if (!this.renkan.read_only) {
  1342             this.is_dragging = true;
  1482             this.is_dragging = true;
  1343             this.paper_coords = this.paper_coords.add(_delta);
  1483             this.paper_coords = this.paper_coords.add(_delta);
  1344             this.redraw();
  1484             this.redraw();
  1345         }
  1485         }
  1346     } else {
  1486     } else {
  1347         this.renderer.paperShift(_delta);
  1487         this.renderer.paperShift(_delta);
  1348     }
  1488     }
  1349 };
  1489 },
  1350 
  1490 openEditor: function() {
  1351 Rkns.Renderer.Node.prototype.openEditor = function() {
       
  1352     this.renderer.removeRepresentationsOfType("editor");
  1491     this.renderer.removeRepresentationsOfType("editor");
  1353     var _editor = this.renderer.addRepresentation("NodeEditor",null);
  1492     var _editor = this.renderer.addRepresentation("NodeEditor",null);
  1354     _editor.source_representation = this;
  1493     _editor.source_representation = this;
  1355     _editor.draw();
  1494     _editor.draw();
  1356 };
  1495 },
  1357 
  1496 select: function() {
  1358 Rkns.Renderer.Node.prototype.select = function() {
       
  1359     this.selected = true;
  1497     this.selected = true;
  1360     this.circle.strokeWidth = this.options.selected_node_stroke_width;
  1498     this.circle.strokeWidth = this.options.selected_node_stroke_width;
  1361     if (this.renderer.isEditable()) {
  1499     if (this.renderer.isEditable()) {
  1362         this.active_buttons.forEach(function(b) {
  1500         this.active_buttons.forEach(function(b) {
  1363             b.show();
  1501             b.show();
  1364         });
  1502         });
  1365     }
  1503     }
  1366     var _uri = this.model.get("uri");
  1504     var _uri = this.model.get("uri");
  1367     if (_uri) {
  1505     if (_uri) {
  1368         Rkns.$('.Rk-Bin-Item').each(function() {
  1506         $('.Rk-Bin-Item').each(function() {
  1369             var _el = Rkns.$(this);
  1507             var _el = $(this);
  1370             if (_el.attr("data-uri") == _uri) {
  1508             if (_el.attr("data-uri") == _uri) {
  1371                 _el.addClass("selected");
  1509                 _el.addClass("selected");
  1372             }
  1510             }
  1373         });
  1511         });
  1374     }
  1512     }
  1378     
  1516     
  1379     if (this.renderer.minimap) {
  1517     if (this.renderer.minimap) {
  1380         this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight;
  1518         this.minimap_circle.strokeWidth = this.options.minimap_highlight_weight;
  1381         this.minimap_circle.strokeColor = this.options.minimap_highlight_color;
  1519         this.minimap_circle.strokeColor = this.options.minimap_highlight_color;
  1382     }
  1520     }
  1383     this.super("select");
  1521     this._super("select");
  1384 };
  1522 },
  1385 
  1523 unselect: function(_newTarget) {
  1386 Rkns.Renderer.Node.prototype.unselect = function(_newTarget) {
       
  1387     if (!_newTarget || _newTarget.source_representation !== this) {
  1524     if (!_newTarget || _newTarget.source_representation !== this) {
  1388         this.selected = false;
  1525         this.selected = false;
  1389         this.all_buttons.forEach(function(b) {
  1526         this.all_buttons.forEach(function(b) {
  1390             b.hide();
  1527             b.hide();
  1391         });
  1528         });
  1392         this.circle.strokeWidth = this.options.node_stroke_width;
  1529         this.circle.strokeWidth = this.options.node_stroke_width;
  1393         Rkns.$('.Rk-Bin-Item').removeClass("selected");
  1530         $('.Rk-Bin-Item').removeClass("selected");
  1394         if (this.renderer.minimap) {
  1531         if (this.renderer.minimap) {
  1395             this.minimap_circle.strokeColor = undefined;
  1532             this.minimap_circle.strokeColor = undefined;
  1396         }
  1533         }
  1397         this.super("unselect");
  1534         this._super("unselect");
  1398     }
  1535     }
  1399 };
  1536 },
  1400     
  1537 highlight: function(textToReplace) {
  1401 Rkns.Renderer.Node.prototype.highlight = function() {
  1538     var hlvalue = textToReplace || true;
  1402     if (this.highlighted) {
  1539     if (this.highlighted === hlvalue) {
  1403         return;
  1540         return;
  1404     }
  1541     }
  1405     this.highlighted = true;
  1542     this.highlighted = hlvalue;
  1406     this.redraw();
  1543     this.redraw();
  1407     this.renderer.throttledPaperDraw();
  1544     this.renderer.throttledPaperDraw();
  1408 };
  1545 },
  1409 
  1546 unhighlight: function() {
  1410 Rkns.Renderer.Node.prototype.unhighlight = function() {
       
  1411     if (!this.highlighted) {
  1547     if (!this.highlighted) {
  1412         return;
  1548         return;
  1413     }
  1549     }
  1414     this.highlighted = false;
  1550     this.highlighted = false;
  1415     this.redraw();
  1551     this.redraw();
  1416     this.renderer.throttledPaperDraw();
  1552     this.renderer.throttledPaperDraw();
  1417 };
  1553 },
  1418 
  1554 saveCoords: function() {
  1419 Rkns.Renderer.Node.prototype.saveCoords = function() {
       
  1420     var _coords = this.renderer.toModelCoords(this.paper_coords),
  1555     var _coords = this.renderer.toModelCoords(this.paper_coords),
  1421         _data = {
  1556         _data = {
  1422             position: {
  1557             position: {
  1423                 x: _coords.x,
  1558                 x: _coords.x,
  1424                 y: _coords.y
  1559                 y: _coords.y
  1425             }
  1560             }
  1426         };
  1561         };
  1427     if (this.renderer.isEditable()) {
  1562     if (this.renderer.isEditable()) {
  1428         this.model.set(_data);
  1563         this.model.set(_data);
  1429     }
  1564     }
  1430 };
  1565 },
  1431 
  1566 mousedown: function(_event, _isTouch) {
  1432 Rkns.Renderer.Node.prototype.mousedown = function(_event, _isTouch) {
       
  1433     if (_isTouch) {
  1567     if (_isTouch) {
  1434         this.renderer.unselectAll();
  1568         this.renderer.unselectAll();
  1435         this.select();
  1569         this.select();
  1436     }
  1570     }
  1437 };
  1571 },
  1438 
  1572 mouseup: function(_event, _isTouch) {
  1439 Rkns.Renderer.Node.prototype.mouseup = function(_event, _isTouch) {
       
  1440     if (this.renderer.is_dragging && this.renderer.isEditable()) {
  1573     if (this.renderer.is_dragging && this.renderer.isEditable()) {
  1441         this.saveCoords();
  1574         this.saveCoords();
  1442     } else {
  1575     } else {
  1443         if (!_isTouch && !this.model.get("delete_scheduled")) {
  1576         if (!_isTouch && !this.model.get("delete_scheduled")) {
  1444             this.openEditor();
  1577             this.openEditor();
  1446         this.model.trigger("clicked");
  1579         this.model.trigger("clicked");
  1447     }
  1580     }
  1448     this.renderer.click_target = null;
  1581     this.renderer.click_target = null;
  1449     this.renderer.is_dragging = false;
  1582     this.renderer.is_dragging = false;
  1450     this.is_dragging = false;
  1583     this.is_dragging = false;
  1451 };
  1584 },
  1452 
  1585 destroy: function(_event) {
  1453 Rkns.Renderer.Node.prototype.destroy = function(_event) {
  1586     this._super("destroy");
  1454     this.super("destroy");
       
  1455     this.all_buttons.forEach(function(b) {
  1587     this.all_buttons.forEach(function(b) {
  1456         b.destroy();
  1588         b.destroy();
  1457     });
  1589     });
  1458     this.circle.remove();
  1590     this.circle.remove();
  1459     this.title.remove();
  1591     this.title.remove();
  1461         this.minimap_circle.remove();
  1593         this.minimap_circle.remove();
  1462     }
  1594     }
  1463     if (this.node_image) {
  1595     if (this.node_image) {
  1464         this.node_image.remove();
  1596         this.node_image.remove();
  1465     }
  1597     }
  1466 };
  1598 }
       
  1599 });
  1467 
  1600 
  1468 /* */
  1601 /* */
  1469 
  1602 
  1470 Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1603 var Edge = Renderer.Edge = Rkns.Utils.inherit(_BaseRepresentation);
  1471 
  1604 
  1472 Rkns.Renderer.Edge.prototype._init = function() {
  1605 _(Edge.prototype).extend({
       
  1606 _init: function() {
  1473     this.renderer.edge_layer.activate();
  1607     this.renderer.edge_layer.activate();
  1474     this.type = "Edge";
  1608     this.type = "Edge";
  1475     this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
  1609     this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
  1476     this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
  1610     this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
  1477     this.bundle = this.renderer.addToBundles(this);
  1611     this.bundle = this.renderer.addToBundles(this);
  1484         [ 0, 0 ],
  1618         [ 0, 0 ],
  1485         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
  1619         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
  1486         [ 0, this.options.edge_arrow_width ]
  1620         [ 0, this.options.edge_arrow_width ]
  1487     );
  1621     );
  1488     this.arrow.__representation = this;
  1622     this.arrow.__representation = this;
  1489     this.text = Rkns.$('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
  1623     this.text = $('<div class="Rk-Label Rk-Edge-Label">').appendTo(this.renderer.labels_$);
  1490     this.arrow_angle = 0;
  1624     this.arrow_angle = 0;
  1491     if (this.options.editor_mode) {
  1625     if (this.options.editor_mode) {
  1492         this.normal_buttons = [
  1626         this.normal_buttons = [
  1493             new Rkns.Renderer.EdgeEditButton(this.renderer, null),
  1627             new EdgeEditButton(this.renderer, null),
  1494             new Rkns.Renderer.EdgeRemoveButton(this.renderer, null),
  1628             new EdgeRemoveButton(this.renderer, null),
  1495         ];
  1629         ];
  1496         this.pending_delete_buttons = [
  1630         this.pending_delete_buttons = [
  1497             new Rkns.Renderer.EdgeRevertButton(this.renderer, null)
  1631             new EdgeRevertButton(this.renderer, null)
  1498         ];
  1632         ];
  1499         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
  1633         this.all_buttons = this.normal_buttons.concat(this.pending_delete_buttons);
  1500         for (var i = 0; i < this.all_buttons.length; i++) {
  1634         for (var i = 0; i < this.all_buttons.length; i++) {
  1501             this.all_buttons[i].source_representation = this;
  1635             this.all_buttons[i].source_representation = this;
  1502         }
  1636         }
  1510         this.minimap_line = new paper.Path();
  1644         this.minimap_line = new paper.Path();
  1511         this.minimap_line.add([0,0],[0,0]);
  1645         this.minimap_line.add([0,0],[0,0]);
  1512         this.minimap_line.__representation = this.renderer.minimap.miniframe.__representation;
  1646         this.minimap_line.__representation = this.renderer.minimap.miniframe.__representation;
  1513         this.minimap_line.strokeWidth = 1;
  1647         this.minimap_line.strokeWidth = 1;
  1514     }
  1648     }
  1515 };
  1649 },
  1516 
  1650 redraw: function() {
  1517 Rkns.Renderer.Edge.prototype.redraw = function() {
       
  1518     var from = this.model.get("from"),
  1651     var from = this.model.get("from"),
  1519         to = this.model.get("to");
  1652         to = this.model.get("to");
  1520     if (!from || !to) {
  1653     if (!from || !to) {
  1521         return;
  1654         return;
  1522     }
  1655     }
  1536         _p0b = _p0a.add(_delta), /* Adding a 4 px difference */
  1669         _p0b = _p0a.add(_delta), /* Adding a 4 px difference */
  1537         _p1b = _p1a.add(_delta), /* to differentiate bundled links */
  1670         _p1b = _p1a.add(_delta), /* to differentiate bundled links */
  1538         _a = _v.angle,
  1671         _a = _v.angle,
  1539         _textdelta = _ortho.multiply(this.options.edge_label_distance),
  1672         _textdelta = _ortho.multiply(this.options.edge_label_distance),
  1540         _handle = _v.divide(3),
  1673         _handle = _v.divide(3),
  1541         _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
  1674         _color = this.model.get("color") || this.model.get("color") || (this.model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color");
  1542     
  1675     
  1543     if (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) {
  1676     if (this.model.get("delete_scheduled") || this.from_representation.model.get("delete_scheduled") || this.to_representation.model.get("delete_scheduled")) {
  1544         var opacity = .5;
  1677         var opacity = .5;
  1545         this.line.dashArray = [2, 2];
  1678         this.line.dashArray = [2, 2];
  1546     } else {
  1679     } else {
  1581     if (_a < -90) {
  1714     if (_a < -90) {
  1582         _a += 180;
  1715         _a += 180;
  1583         _textdelta = _textdelta.multiply(-1);
  1716         _textdelta = _textdelta.multiply(-1);
  1584     }
  1717     }
  1585     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_edges) || "";
  1718     var _text = this.model.get("title") || this.renkan.translate(this.options.label_untitled_edges) || "";
  1586     _text = Rkns.Renderer.shortenText(_text, this.options.node_label_max_length);
  1719     _text = shortenText(_text, this.options.node_label_max_length);
  1587     this.text.text(_text);
  1720     this.text.text(_text);
  1588     var _textpos = this.paper_coords.add(_textdelta);
  1721     var _textpos = this.paper_coords.add(_textdelta);
  1589     this.text.css({
  1722     this.text.css({
  1590         left: _textpos.x,
  1723         left: _textpos.x,
  1591         top: _textpos.y,
  1724         top: _textpos.y,
  1604     if (this.renderer.minimap) {
  1737     if (this.renderer.minimap) {
  1605         this.minimap_line.strokeColor = _color;
  1738         this.minimap_line.strokeColor = _color;
  1606         this.minimap_line.segments[0].point = this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get("position")));
  1739         this.minimap_line.segments[0].point = this.renderer.toMinimapCoords(new paper.Point(this.from_representation.model.get("position")));
  1607          this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position")));
  1740          this.minimap_line.segments[1].point = this.renderer.toMinimapCoords(new paper.Point(this.to_representation.model.get("position")));
  1608     }
  1741     }
  1609 };
  1742 },
  1610 
  1743 openEditor: function() {
  1611 Rkns.Renderer.Edge.prototype.openEditor = function() {
       
  1612     this.renderer.removeRepresentationsOfType("editor");
  1744     this.renderer.removeRepresentationsOfType("editor");
  1613     var _editor = this.renderer.addRepresentation("EdgeEditor",null);
  1745     var _editor = this.renderer.addRepresentation("EdgeEditor",null);
  1614     _editor.source_representation = this;
  1746     _editor.source_representation = this;
  1615     _editor.draw();
  1747     _editor.draw();
  1616 };
  1748 },
  1617 
  1749 select: function() {
  1618 Rkns.Renderer.Edge.prototype.select = function() {
       
  1619     this.selected = true;
  1750     this.selected = true;
  1620     this.line.strokeWidth = this.options.selected_edge_stroke_width;
  1751     this.line.strokeWidth = this.options.selected_edge_stroke_width;
  1621     if (this.renderer.isEditable()) {
  1752     if (this.renderer.isEditable()) {
  1622         this.active_buttons.forEach(function(b) {
  1753         this.active_buttons.forEach(function(b) {
  1623             b.show();
  1754             b.show();
  1624         });
  1755         });
  1625     }
  1756     }
  1626     if (!this.options.editor_mode) {
  1757     if (!this.options.editor_mode) {
  1627         this.openEditor();
  1758         this.openEditor();
  1628     }
  1759     }
  1629     this.super("select");
  1760     this._super("select");
  1630 };
  1761 },
  1631 
  1762 unselect: function(_newTarget) {
  1632 Rkns.Renderer.Edge.prototype.unselect = function(_newTarget) {
       
  1633     if (!_newTarget || _newTarget.source_representation !== this) {
  1763     if (!_newTarget || _newTarget.source_representation !== this) {
  1634         this.selected = false;
  1764         this.selected = false;
  1635         if (this.options.editor_mode) {
  1765         if (this.options.editor_mode) {
  1636             this.all_buttons.forEach(function(b) {
  1766             this.all_buttons.forEach(function(b) {
  1637                 b.hide();
  1767                 b.hide();
  1638             });
  1768             });
  1639         }
  1769         }
  1640         this.line.strokeWidth = this.options.edge_stroke_width;
  1770         this.line.strokeWidth = this.options.edge_stroke_width;
  1641         this.super("unselect");
  1771         this._super("unselect");
  1642     }
  1772     }
  1643 };
  1773 },
  1644 
  1774 mousedown: function(_event, _isTouch) {
  1645 Rkns.Renderer.Edge.prototype.mousedown = function(_event, _isTouch) {
       
  1646     if (_isTouch) {
  1775     if (_isTouch) {
  1647         this.renderer.unselectAll();
  1776         this.renderer.unselectAll();
  1648         this.select();
  1777         this.select();
  1649     }
  1778     }
  1650 };
  1779 },
  1651 
  1780 mouseup: function(_event, _isTouch) {
  1652 Rkns.Renderer.Edge.prototype.mouseup = function(_event, _isTouch) {
       
  1653     if (!this.renkan.read_only && this.renderer.is_dragging) {
  1781     if (!this.renkan.read_only && this.renderer.is_dragging) {
  1654         this.from_representation.saveCoords();
  1782         this.from_representation.saveCoords();
  1655         this.to_representation.saveCoords();
  1783         this.to_representation.saveCoords();
  1656         this.from_representation.is_dragging = false;
  1784         this.from_representation.is_dragging = false;
  1657         this.to_representation.is_dragging = false;
  1785         this.to_representation.is_dragging = false;
  1661         }
  1789         }
  1662         this.model.trigger("clicked");
  1790         this.model.trigger("clicked");
  1663     }
  1791     }
  1664     this.renderer.click_target = null;
  1792     this.renderer.click_target = null;
  1665     this.renderer.is_dragging = false;
  1793     this.renderer.is_dragging = false;
  1666 };
  1794 },
  1667 
  1795 paperShift: function(_delta) {
  1668 Rkns.Renderer.Edge.prototype.paperShift = function(_delta) {
       
  1669     if (this.options.editor_mode) {
  1796     if (this.options.editor_mode) {
  1670         if (!this.options.read_only) {
  1797         if (!this.options.read_only) {
  1671             this.from_representation.paperShift(_delta);
  1798             this.from_representation.paperShift(_delta);
  1672             this.to_representation.paperShift(_delta);
  1799             this.to_representation.paperShift(_delta);
  1673         }
  1800         }
  1674     } else {
  1801     } else {
  1675         this.renderer.paperShift(_delta);
  1802         this.renderer.paperShift(_delta);
  1676     }
  1803     }
  1677 };
  1804 },
  1678 
  1805 destroy: function() {
  1679 Rkns.Renderer.Edge.prototype.destroy = function() {
  1806     this._super("destroy");
  1680     this.super("destroy");
       
  1681     this.line.remove();
  1807     this.line.remove();
  1682     this.arrow.remove();
  1808     this.arrow.remove();
  1683     this.text.remove();
  1809     this.text.remove();
  1684     if (this.renderer.minimap) {
  1810     if (this.renderer.minimap) {
  1685         this.minimap_line.remove();
  1811         this.minimap_line.remove();
  1686     }
  1812     }
  1687     this.all_buttons.forEach(function(b) {
  1813     this.all_buttons.forEach(function(b) {
  1688         b.destroy();
  1814         b.destroy();
  1689     });
  1815     });
  1690     var _this = this;
  1816     var _this = this;
  1691     this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
  1817     this.bundle.edges = _(this.bundle.edges).reject(function(_edge) {
  1692         return _edge === _this;
  1818         return _edge === _this;
  1693     });
  1819     });
  1694 };
  1820 }
       
  1821 });
  1695 
  1822 
  1696 /* */
  1823 /* */
  1697 
  1824 
  1698 Rkns.Renderer.TempEdge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1825 var TempEdge = Renderer.TempEdge = Rkns.Utils.inherit(_BaseRepresentation);
  1699 
  1826 
  1700 Rkns.Renderer.TempEdge.prototype._init = function() {
  1827 _(TempEdge.prototype).extend({
       
  1828 _init: function() {
  1701     this.renderer.edge_layer.activate();
  1829     this.renderer.edge_layer.activate();
  1702     this.type = "Temp-edge";
  1830     this.type = "Temp-edge";
  1703     
  1831     
  1704     var _color = (this.project.get("users").get(this.renkan.current_user) || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color");
  1832     var _color = (this.project.get("users").get(this.renkan.current_user) || _USER_PLACEHOLDER(this.renkan)).get("color");
  1705     this.line = new paper.Path();
  1833     this.line = new paper.Path();
  1706     this.line.strokeColor = _color;
  1834     this.line.strokeColor = _color;
  1707     this.line.dashArray = [4, 2];
  1835     this.line.dashArray = [4, 2];
  1708     this.line.strokeWidth = this.options.selected_edge_stroke_width;
  1836     this.line.strokeWidth = this.options.selected_edge_stroke_width;
  1709     this.line.add([0,0],[0,0]);
  1837     this.line.add([0,0],[0,0]);
  1715         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
  1843         [ this.options.edge_arrow_length, this.options.edge_arrow_width / 2 ],
  1716         [ 0, this.options.edge_arrow_width ]
  1844         [ 0, this.options.edge_arrow_width ]
  1717     );
  1845     );
  1718     this.arrow.__representation = this;
  1846     this.arrow.__representation = this;
  1719     this.arrow_angle = 0;
  1847     this.arrow_angle = 0;
  1720 };
  1848 },
  1721 
  1849 redraw: function() {
  1722 Rkns.Renderer.TempEdge.prototype.redraw = function() {
       
  1723     var _p0 = this.from_representation.paper_coords,
  1850     var _p0 = this.from_representation.paper_coords,
  1724         _p1 = this.end_pos,
  1851         _p1 = this.end_pos,
  1725         _a = _p1.subtract(_p0).angle,
  1852         _a = _p1.subtract(_p0).angle,
  1726         _c = _p0.add(_p1).divide(2);
  1853         _c = _p0.add(_p1).divide(2);
  1727     this.line.segments[0].point = _p0;
  1854     this.line.segments[0].point = _p0;
  1728     this.line.segments[1].point = _p1;
  1855     this.line.segments[1].point = _p1;
  1729     this.arrow.rotate(_a - this.arrow_angle);
  1856     this.arrow.rotate(_a - this.arrow_angle);
  1730     this.arrow.position = _c;
  1857     this.arrow.position = _c;
  1731     this.arrow_angle = _a;
  1858     this.arrow_angle = _a;
  1732 };
  1859 },
  1733 
  1860 paperShift: function(_delta) {
  1734 Rkns.Renderer.TempEdge.prototype.paperShift = function(_delta) {
       
  1735     if (!this.renderer.isEditable()) {
  1861     if (!this.renderer.isEditable()) {
  1736         this.renderer.removeRepresentation(_this);
  1862         this.renderer.removeRepresentation(_this);
  1737         paper.view.draw();
  1863         paper.view.draw();
  1738         return;
  1864         return;
  1739     }
  1865     }
  1740     this.end_pos = this.end_pos.add(_delta);
  1866     this.end_pos = this.end_pos.add(_delta);
  1741     var _hitResult = paper.project.hitTest(this.end_pos);
  1867     var _hitResult = paper.project.hitTest(this.end_pos);
  1742     this.renderer.findTarget(_hitResult);
  1868     this.renderer.findTarget(_hitResult);
  1743     this.redraw();
  1869     this.redraw();
  1744 };
  1870 },
  1745 
  1871 mouseup: function(_event, _isTouch) {
  1746 Rkns.Renderer.TempEdge.prototype.mouseup = function(_event, _isTouch) {
       
  1747     var _hitResult = paper.project.hitTest(_event.point),
  1872     var _hitResult = paper.project.hitTest(_event.point),
  1748         _model = this.from_representation.model,
  1873         _model = this.from_representation.model,
  1749         _endDrag = true;
  1874         _endDrag = true;
  1750     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  1875     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  1751         var _target = _hitResult.item.__representation;
  1876         var _target = _hitResult.item.__representation;
  1773         this.renderer.click_target = null;
  1898         this.renderer.click_target = null;
  1774         this.renderer.is_dragging = false;
  1899         this.renderer.is_dragging = false;
  1775         this.renderer.removeRepresentation(this);
  1900         this.renderer.removeRepresentation(this);
  1776         paper.view.draw();
  1901         paper.view.draw();
  1777     }
  1902     }
  1778 };
  1903 },
  1779 
  1904 destroy: function() {
  1780 Rkns.Renderer.TempEdge.prototype.destroy = function() {
       
  1781     this.arrow.remove();
  1905     this.arrow.remove();
  1782     this.line.remove();
  1906     this.line.remove();
  1783 };
  1907 }
       
  1908 });
  1784 
  1909 
  1785 /* */
  1910 /* */
  1786 
  1911 
  1787 Rkns.Renderer._BaseEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  1912 var _BaseEditor = Renderer._BaseEditor = Rkns.Utils.inherit(_BaseRepresentation);
  1788 
  1913 
  1789 Rkns.Renderer._BaseEditor.prototype._init = function() {
  1914 _(_BaseEditor.prototype).extend({
       
  1915 _init: function() {
  1790     this.renderer.buttons_layer.activate();
  1916     this.renderer.buttons_layer.activate();
  1791     this.type = "editor";
  1917     this.type = "editor";
  1792     this.editor_block = new paper.Path();
  1918     this.editor_block = new paper.Path();
  1793     var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0];});
  1919     var _pts = _(_.range(8)).map(function() {return [0,0];});
  1794     this.editor_block.add.apply(this.editor_block, _pts);
  1920     this.editor_block.add.apply(this.editor_block, _pts);
  1795     this.editor_block.strokeWidth = this.options.tooltip_border_width;
  1921     this.editor_block.strokeWidth = this.options.tooltip_border_width;
  1796     this.editor_block.strokeColor = this.options.tooltip_border_color;
  1922     this.editor_block.strokeColor = this.options.tooltip_border_color;
  1797     this.editor_block.opacity = .8;
  1923     this.editor_block.opacity = .8;
  1798     this.editor_$ = Rkns.$('<div>')
  1924     this.editor_$ = $('<div>')
  1799         .appendTo(this.renderer.editor_$)
  1925         .appendTo(this.renderer.editor_$)
  1800         .css({
  1926         .css({
  1801             position: "absolute",
  1927             position: "absolute",
  1802             opacity: .8
  1928             opacity: .8
  1803         })
  1929         })
  1804         .hide();
  1930         .hide();
  1805 };
  1931 },
  1806 
  1932 destroy: function() {
  1807 Rkns.Renderer._BaseEditor.prototype.destroy = function() {
       
  1808     this.editor_block.remove();
  1933     this.editor_block.remove();
  1809     this.editor_$.remove();
  1934     this.editor_$.remove();
  1810 };
  1935 }
       
  1936 });
  1811 
  1937 
  1812 /* */
  1938 /* */
  1813 
  1939 
  1814 Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseEditor);
  1940 var NodeEditor = Renderer.NodeEditor = Rkns.Utils.inherit(_BaseEditor);
  1815 
  1941 
  1816 Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template(
  1942 _(NodeEditor.prototype).extend({
       
  1943 template: _.template(
  1817     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Node")%></span></h2>'
  1944     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Node")%></span></h2>'
  1818     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
  1945     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-node.title%>"/></p>'
  1819     + '<% if (options.show_node_editor_uri) { %><p><label><%-renkan.translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-node.uri%>"/><a class="Rk-Edit-Goto" href="<%-node.uri%>" target="_blank"></a></p><% } %>'
  1946     + '<% if (options.show_node_editor_uri) { %><p><label><%-renkan.translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-node.uri%>"/><a class="Rk-Edit-Goto" href="<%-node.uri%>" target="_blank"></a></p><% } %>'
  1820     + '<% if (options.show_node_editor_description) { %><p><label><%-renkan.translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p><% } %>'
  1947     + '<% if (options.show_node_editor_description) { %><p><label><%-renkan.translate("Description:")%></label><textarea class="Rk-Edit-Description"><%-node.description%></textarea></p><% } %>'
  1821     + '<% if (options.show_node_editor_size) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Size:")%></span><a href="#" class="Rk-Edit-Size-Down">-</a><span class="Rk-Edit-Size-Value"><%-node.size%></span><a href="#" class="Rk-Edit-Size-Up">+</a></p><% } %>'
  1948     + '<% if (options.show_node_editor_size) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Size:")%></span><a href="#" class="Rk-Edit-Size-Down">-</a><span class="Rk-Edit-Size-Value"><%-node.size%></span><a href="#" class="Rk-Edit-Size-Up">+</a></p><% } %>'
  1822     + '<% if (options.show_node_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-node.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
  1949     + '<% if (options.show_node_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Node color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-node.color%>;"><span class="Rk-Edit-ColorTip"></span></span>'
  1823     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
  1950     + '<%= renkan.colorPicker %><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
  1824     + '<% if (options.show_node_editor_image) { %><div class="Rk-Edit-ImgWrap"><div class="Rk-Edit-ImgPreview"><img src="<%-node.image || node.image_placeholder%>" />'
  1951     + '<% if (options.show_node_editor_image) { %><div class="Rk-Edit-ImgWrap"><div class="Rk-Edit-ImgPreview"><img src="<%-node.image || node.image_placeholder%>" />'
  1825     + '<% if (node.clip_path) { %><svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 1 1" preserveAspectRatio="none"><path style="stroke-width: .02; stroke:red; fill-opacity:.3; fill:red;" d="<%- node.clip_path %>"/></svg><% }%>'
  1952     + '<% if (node.clip_path) { %><svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewbox="0 0 1 1" preserveAspectRatio="none"><path style="stroke-width: .02; stroke:red; fill-opacity:.3; fill:red;" d="<%- node.clip_path %>"/></svg><% }%>'
  1826     + '</div></div><p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
  1953     + '</div></div><p><label><%-renkan.translate("Image URL:")%></label><input class="Rk-Edit-Image" type="text" value="<%-node.image%>"/></p>'
  1827     + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p><% } %>'    
  1954     + '<p><label><%-renkan.translate("Choose Image File:")%></label><input class="Rk-Edit-Image-File" type="file" accept="image/*"/></p><% } %>'    
  1828     + '<% if (options.show_node_editor_creator && node.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span> <span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(node.created_by_title, 25) %></p><% } %>'
  1955     + '<% if (options.show_node_editor_creator && node.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span> <span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- shortenText(node.created_by_title, 25) %></p><% } %>'
  1829 );
  1956 ),
  1830 
  1957 readOnlyTemplate: _.template(
  1831 Rkns.Renderer.NodeEditor.prototype.readOnlyTemplate = Rkns._.template(
       
  1832     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_node_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><% } %>'
  1958     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_node_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-node.color%>;"></span><% } %>'
  1833     + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>'
  1959     + '<span class="Rk-Display-Title"><% if (node.uri) { %><a href="<%-node.uri%>" target="_blank"><% } %><%-node.title%><% if (node.uri) { %></a><% } %></span></h2>'
  1834     + '<% if (node.uri && options.show_node_tooltip_uri) { %><p class="Rk-Display-URI"><a href="<%-node.uri%>" target="_blank"><%-node.short_uri%></a></p><% } %>'
  1960     + '<% if (node.uri && options.show_node_tooltip_uri) { %><p class="Rk-Display-URI"><a href="<%-node.uri%>" target="_blank"><%-node.short_uri%></a></p><% } %>'
  1835     + '<% if (options.show_node_tooltip_description) { %><p><%-node.description%></p><% } %>'
  1961     + '<% if (options.show_node_tooltip_description) { %><p class="Rk-Display-Description"><%-node.description%></p><% } %>'
  1836     + '<% if (node.image && options.show_node_tooltip_image) { %><img class="Rk-Display-ImgPreview" src="<%-node.image%>" /><% } %>'
  1962     + '<% if (node.image && options.show_node_tooltip_image) { %><img class="Rk-Display-ImgPreview" src="<%-node.image%>" /><% } %>'
  1837     + '<% if (node.has_creator && options.show_node_tooltip_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(node.created_by_title, 25) %></p><% } %>'
  1963     + '<% if (node.has_creator && options.show_node_tooltip_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-node.created_by_color%>;"></span><%- shortenText(node.created_by_title, 25) %></p><% } %>'
  1838 );
  1964 ),
  1839 
  1965 draw: function() {
  1840 Rkns.Renderer.NodeEditor.prototype.draw = function() {
       
  1841     var _model = this.source_representation.model,
  1966     var _model = this.source_representation.model,
  1842         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan),
  1967         _created_by = _model.get("created_by") || _USER_PLACEHOLDER(this.renkan),
  1843         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate ),
  1968         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate ),
  1844         _image_placeholder = this.options.static_url + "img/image-placeholder.png",
  1969         _image_placeholder = this.options.static_url + "img/image-placeholder.png",
  1845         _size = (_model.get("size") || 0);
  1970         _size = (_model.get("size") || 0);
  1846     this.editor_$
  1971     this.editor_$
  1847         .html(_template({
  1972         .html(_template({
  1848             node: {
  1973             node: {
  1849                 has_creator: !!_model.get("created_by"),
  1974                 has_creator: !!_model.get("created_by"),
  1850                 title: _model.get("title"),
  1975                 title: _model.get("title"),
  1851                 uri: _model.get("uri"),
  1976                 uri: _model.get("uri"),
  1852                 short_uri:  Rkns.Renderer.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
  1977                 short_uri:  shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
  1853                 description: _model.get("description"),
  1978                 description: _model.get("description"),
  1854                 image: _model.get("image") || "",
  1979                 image: _model.get("image") || "",
  1855                 image_placeholder: _image_placeholder,
  1980                 image_placeholder: _image_placeholder,
  1856                 color: _model.get("color") || _created_by.get("color"),
  1981                 color: _model.get("color") || _created_by.get("color"),
  1857                 clip_path: _model.get("clip-path") || false,
  1982                 clip_path: _model.get("clip-path") || false,
  1858                 created_by_color: _created_by.get("color"),
  1983                 created_by_color: _created_by.get("color"),
  1859                 created_by_title: _created_by.get("title"),
  1984                 created_by_title: _created_by.get("title"),
  1860                 size: (_size > 0 ? "+" : "") + _size
  1985                 size: (_size > 0 ? "+" : "") + _size
  1861             },
  1986             },
  1862             renkan: this.renkan,
  1987             renkan: this.renkan,
  1863             options: this.options
  1988             options: this.options,
       
  1989             shortenText: shortenText
  1864         }));
  1990         }));
  1865     this.redraw();
  1991     this.redraw();
  1866     var _this = this,
  1992     var _this = this,
  1867         closeEditor = function() {
  1993         closeEditor = function() {
  1868             _this.renderer.removeRepresentation(_this);
  1994             _this.renderer.removeRepresentation(_this);
  1869             paper.view.draw();
  1995             paper.view.draw();
  1870         };
  1996         };
  1871         
  1997         
  1872     this.editor_$.find(".Rk-CloseX").click(closeEditor);
  1998     this.editor_$.find(".Rk-CloseX").click(closeEditor);
  1873     
  1999     
       
  2000     this.editor_$.find(".Rk-Edit-Goto").click(function() {
       
  2001         if (!_model.get("uri")) {
       
  2002             return false;
       
  2003         }
       
  2004     });
       
  2005     
  1874     if (this.renderer.isEditable()) {
  2006     if (this.renderer.isEditable()) {
  1875         
  2007         
  1876         var onFieldChange = Rkns._(function() {
  2008         var onFieldChange = _(function() {
  1877             Rkns._(function() {
  2009             _(function() {
  1878                 if (_this.renderer.isEditable()) {
  2010                 if (_this.renderer.isEditable()) {
  1879                     var _data = {
  2011                     var _data = {
  1880                         title: _this.editor_$.find(".Rk-Edit-Title").val()
  2012                         title: _this.editor_$.find(".Rk-Edit-Title").val()
  1881                     };
  2013                     };
  1882                     if (_this.options.show_node_editor_uri) {
  2014                     if (_this.options.show_node_editor_uri) {
  1883                         _data.uri = _this.editor_$.find(".Rk-Edit-URI").val();
  2015                         _data.uri = _this.editor_$.find(".Rk-Edit-URI").val();
       
  2016                         _this.editor_$.find(".Rk-Edit-Goto").attr("href",_data.uri || "#");
  1884                     }
  2017                     }
  1885                     if (_this.options.show_node_editor_image) {
  2018                     if (_this.options.show_node_editor_image) {
  1886                         _data.image = _this.editor_$.find(".Rk-Edit-Image").val();
  2019                         _data.image = _this.editor_$.find(".Rk-Edit-Image").val();
  1887                         _this.editor_$.find(".Rk-Edit-ImgPreview").attr("src", _data.image || _image_placeholder);
  2020                         _this.editor_$.find(".Rk-Edit-ImgPreview").attr("src", _data.image || _image_placeholder);
  1888                     }
  2021                     }
  1912                     fr = new FileReader();
  2045                     fr = new FileReader();
  1913                 if (f.type.substr(0,5) !== "image") {
  2046                 if (f.type.substr(0,5) !== "image") {
  1914                     alert(_this.renkan.translate("This file is not an image"));
  2047                     alert(_this.renkan.translate("This file is not an image"));
  1915                     return;
  2048                     return;
  1916                 }
  2049                 }
  1917                 if (f.size > (Rkns.Renderer._IMAGE_MAX_KB * 1024)) {
  2050                 if (f.size > (_this.options.uploaded_image_max_kb * 1024)) {
  1918                     alert(_this.renkan.translate("Image size must be under ")+Rkns.Renderer._IMAGE_MAX_KB+_this.renkan.translate("KB"));
  2051                     alert(_this.renkan.translate("Image size must be under ") + _this.options.uploaded_image_max_kb + _this.renkan.translate("KB"));
  1919                     return;
  2052                     return;
  1920                 }
  2053                 }
  1921                 fr.onload = function(e) {
  2054                 fr.onload = function(e) {
  1922                     _this.editor_$.find(".Rk-Edit-Image").val(e.target.result);
  2055                     _this.editor_$.find(".Rk-Edit-Image").val(e.target.result);
  1923                     onFieldChange();
  2056                     onFieldChange();
  1945                 _e.preventDefault();
  2078                 _e.preventDefault();
  1946                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  2079                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  1947             },
  2080             },
  1948             function(_e) {
  2081             function(_e) {
  1949                 _e.preventDefault();
  2082                 _e.preventDefault();
  1950                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(_this.renkan)).get("color"));
  2083                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || _USER_PLACEHOLDER(_this.renkan)).get("color"));
  1951             }
  2084             }
  1952         ).click(function(_e) {
  2085         ).click(function(_e) {
  1953             _e.preventDefault();
  2086             _e.preventDefault();
  1954             if (_this.renderer.isEditable()) {
  2087             if (_this.renderer.isEditable()) {
  1955                 _model.set("color", $(this).attr("data-color"));
  2088                 _model.set("color", $(this).attr("data-color"));
  1958             } else {
  2091             } else {
  1959                 closeEditor();
  2092                 closeEditor();
  1960             }
  2093             }
  1961         });
  2094         });
  1962         
  2095         
  1963         function shiftSize(n) {
  2096         var shiftSize = function(n) {
  1964             if (_this.renderer.isEditable()) {
  2097             if (_this.renderer.isEditable()) {
  1965                 var _newsize = n+(_model.get("size") || 0);
  2098                 var _newsize = n+(_model.get("size") || 0);
  1966                 _this.editor_$.find(".Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize);
  2099                 _this.editor_$.find(".Rk-Edit-Size-Value").text((_newsize > 0 ? "+" : "") + _newsize);
  1967                 _model.set("size", _newsize);
  2100                 _model.set("size", _newsize);
  1968                 paper.view.draw();
  2101                 paper.view.draw();
  1969             } else {
  2102             } else {
  1970                 closeEditor();
  2103                 closeEditor();
  1971             }
  2104             }
  1972         }
  2105         };
  1973         
  2106         
  1974         this.editor_$.find(".Rk-Edit-Size-Down").click(function() {
  2107         this.editor_$.find(".Rk-Edit-Size-Down").click(function() {
  1975             shiftSize(-1);
  2108             shiftSize(-1);
  1976             return false;
  2109             return false;
  1977         });
  2110         });
  1978         this.editor_$.find(".Rk-Edit-Size-Up").click(function() {
  2111         this.editor_$.find(".Rk-Edit-Size-Up").click(function() {
  1979             shiftSize(1);
  2112             shiftSize(1);
  1980             return false;
  2113             return false;
  1981         });
  2114         });
       
  2115     } else {
       
  2116         if (typeof this.source_representation.highlighted === "object") {
       
  2117             var titlehtml = this.source_representation.highlighted.replace(_(_model.get("title")).escape(),'<span class="Rk-Highlighted">$1</span>');
       
  2118             this.editor_$.find(".Rk-Display-Title" + (_model.get("uri") ? " a" : "")).html(titlehtml);
       
  2119             if (this.options.show_node_tooltip_description) {
       
  2120                 this.editor_$.find(".Rk-Display-Description").html(this.source_representation.highlighted.replace(_(_model.get("description")).escape(),'<span class="Rk-Highlighted">$1</span>'));
       
  2121             }
       
  2122         }
  1982     }
  2123     }
  1983     this.editor_$.find("img").load(function() {
  2124     this.editor_$.find("img").load(function() {
  1984         _this.redraw();
  2125         _this.redraw();
  1985     });
  2126     });
  1986 };
  2127 },
  1987 
  2128 redraw: function() {
  1988 Rkns.Renderer.NodeEditor.prototype.redraw = function() {
       
  1989     var _coords = this.source_representation.paper_coords;
  2129     var _coords = this.source_representation.paper_coords;
  1990     Rkns.Renderer.drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * .75, this.editor_$);
  2130     drawEditBox(this.options, _coords, this.editor_block, this.source_representation.circle_radius * .75, this.editor_$);
  1991     this.editor_$.show();
  2131     this.editor_$.show();
  1992     paper.view.draw();
  2132     paper.view.draw();
  1993 };
  2133 }
       
  2134 });
  1994 
  2135 
  1995 /* */
  2136 /* */
  1996 
  2137 
  1997 Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseEditor);
  2138 var EdgeEditor = Renderer.EdgeEditor = Rkns.Utils.inherit(_BaseEditor);
  1998 
  2139 
  1999 Rkns.Renderer.EdgeEditor.prototype.template = Rkns._.template(
  2140 _(EdgeEditor.prototype).extend({
       
  2141 template: _.template(
  2000     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Edge")%></span></h2>'
  2142     '<h2><span class="Rk-CloseX">&times;</span><%-renkan.translate("Edit Edge")%></span></h2>'
  2001     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
  2143     + '<p><label><%-renkan.translate("Title:")%></label><input class="Rk-Edit-Title" type="text" value="<%-edge.title%>"/></p>'
  2002     + '<% if (options.show_edge_editor_uri) { %><p><label><%-renkan.translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-edge.uri%>"/><a class="Rk-Edit-Goto" href="<%-edge.uri%>" target="_blank"></a></p>'
  2144     + '<% if (options.show_edge_editor_uri) { %><p><label><%-renkan.translate("URI:")%></label><input class="Rk-Edit-URI" type="text" value="<%-edge.uri%>"/><a class="Rk-Edit-Goto" href="<%-edge.uri%>" target="_blank"></a></p>'
  2003     + '<% if (options.properties.length) { %><p><label><%-renkan.translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
  2145     + '<% if (options.properties.length) { %><p><label><%-renkan.translate("Choose from vocabulary:")%></label><select class="Rk-Edit-Vocabulary">'
  2004     + '<% _(options.properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- renkan.translate(ontology.label) %></option>'
  2146     + '<% _(options.properties).each(function(ontology) { %><option class="Rk-Edit-Vocabulary-Class" value=""><%- renkan.translate(ontology.label) %></option>'
  2005     + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>'
  2147     + '<% _(ontology.properties).each(function(property) { var uri = ontology["base-uri"] + property.uri; %><option class="Rk-Edit-Vocabulary-Property" value="<%- uri %>'
  2006     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>'
  2148     + '"<% if (uri === edge.uri) { %> selected<% } %>><%- renkan.translate(property.label) %></option>'
  2007     + '<% }) %><% }) %></select></p><% } } %>'
  2149     + '<% }) %><% }) %></select></p><% } } %>'
  2008     + '<% if (options.show_edge_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Edge color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-edge.color%>;"><span class="Rk-Edit-ColorTip"></span></span><ul class="Rk-Edit-ColorPicker">'
  2150     + '<% if (options.show_edge_editor_color) { %><div class="Rk-Editor-p"><span class="Rk-Editor-Label"><%-renkan.translate("Edge color:")%></span><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-Edit-Color" style="background:<%-edge.color%>;"><span class="Rk-Edit-ColorTip"></span></span>'
  2009     + '<% _(Rkns.pickerColors).each(function(c) { %><li data-color="<%=c%>" style="background: <%=c%>"></li><% }); %></ul><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
  2151     + '<%= renkan.colorPicker %><span class="Rk-Edit-ColorPicker-Text"><%- renkan.translate("Choose color") %></span></div></div><% } %>'
  2010     + '<% if (options.show_edge_editor_direction) { %><p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p><% } %>'
  2152     + '<% if (options.show_edge_editor_direction) { %><p><span class="Rk-Edit-Direction"><%- renkan.translate("Change edge direction") %></span></p><% } %>'
  2011     + '<% if (options.show_edge_editor_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- Rkns.Renderer.shortenText(edge.from_title, 25) %></p>'
  2153     + '<% if (options.show_edge_editor_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- shortenText(edge.from_title, 25) %></p>'
  2012     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- Rkns.Renderer.shortenText(edge.to_title, 25) %></p><% } %>'
  2154     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- shortenText(edge.to_title, 25) %></p><% } %>'
  2013     + '<% if (options.show_edge_editor_creator && edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(edge.created_by_title, 25) %></p><% } %>'
  2155     + '<% if (options.show_edge_editor_creator && edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- shortenText(edge.created_by_title, 25) %></p><% } %>'
  2014 );
  2156 ),
  2015 
  2157 readOnlyTemplate: _.template(
  2016 Rkns.Renderer.EdgeEditor.prototype.readOnlyTemplate = Rkns._.template(
       
  2017     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_edge_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><% } %>'
  2158     '<h2><span class="Rk-CloseX">&times;</span><% if (options.show_edge_tooltip_color) { %><span class="Rk-UserColor" style="background:<%-edge.color%>;"></span><% } %>'
  2018     + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>'
  2159     + '<span class="Rk-Display-Title"><% if (edge.uri) { %><a href="<%-edge.uri%>" target="_blank"><% } %><%-edge.title%><% if (edge.uri) { %></a><% } %></span></h2>'
  2019     + '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>'
  2160     + '<% if (options.show_edge_tooltip_uri && edge.uri) { %><p class="Rk-Display-URI"><a href="<%-edge.uri%>" target="_blank"><%-edge.short_uri%></a></p><% } %>'
  2020     + '<p><%-edge.description%></p>'
  2161     + '<p><%-edge.description%></p>'
  2021     + '<% if (options.show_edge_tooltip_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- Rkns.Renderer.shortenText(edge.from_title, 25) %></p>'
  2162     + '<% if (options.show_edge_tooltip_nodes) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("From:")%></span><span class="Rk-UserColor" style="background:<%-edge.from_color%>;"></span><%- shortenText(edge.from_title, 25) %></p>'
  2022     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- Rkns.Renderer.shortenText(edge.to_title, 25) %></p><% } %>'
  2163     + '<p><span class="Rk-Editor-Label"><%-renkan.translate("To:")%></span><span class="Rk-UserColor" style="background:<%-edge.to_color%>;"></span><%- shortenText(edge.to_title, 25) %></p><% } %>'
  2023     + '<% if (options.show_edge_tooltip_creator && edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- Rkns.Renderer.shortenText(edge.created_by_title, 25) %></p><% } %>'
  2164     + '<% if (options.show_edge_tooltip_creator && edge.has_creator) { %><p><span class="Rk-Editor-Label"><%-renkan.translate("Created by:")%></span><span class="Rk-UserColor" style="background:<%-edge.created_by_color%>;"></span><%- shortenText(edge.created_by_title, 25) %></p><% } %>'
  2024 );
  2165 ),
  2025 
  2166 draw: function() {
  2026 Rkns.Renderer.EdgeEditor.prototype.draw = function() {
       
  2027     var _model = this.source_representation.model,
  2167     var _model = this.source_representation.model,
  2028         _from_model = _model.get("from"),
  2168         _from_model = _model.get("from"),
  2029         _to_model = _model.get("to"),
  2169         _to_model = _model.get("to"),
  2030         _created_by = _model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan),
  2170         _created_by = _model.get("created_by") || _USER_PLACEHOLDER(this.renkan),
  2031         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate);
  2171         _template = (this.renderer.isEditable() ? this.template : this.readOnlyTemplate);
  2032     this.editor_$
  2172     this.editor_$
  2033         .html(_template({
  2173         .html(_template({
  2034             edge: {
  2174             edge: {
  2035                 has_creator: !!_model.get("created_by"),
  2175                 has_creator: !!_model.get("created_by"),
  2036                 title: _model.get("title"),
  2176                 title: _model.get("title"),
  2037                 uri: _model.get("uri"),
  2177                 uri: _model.get("uri"),
  2038                 short_uri:  Rkns.Renderer.shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
  2178                 short_uri:  shortenText((_model.get("uri") || "").replace(/^(https?:\/\/)?(www\.)?/,'').replace(/\/$/,''),40),
  2039                 description: _model.get("description"),
  2179                 description: _model.get("description"),
  2040                 color: _model.get("color") || _created_by.get("color"),
  2180                 color: _model.get("color") || _created_by.get("color"),
  2041                 from_title: _from_model.get("title"),
  2181                 from_title: _from_model.get("title"),
  2042                 to_title: _to_model.get("title"),
  2182                 to_title: _to_model.get("title"),
  2043                 from_color: _from_model.get("color") || (_from_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"),
  2183                 from_color: _from_model.get("color") || (_from_model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color"),
  2044                 to_color: _to_model.get("color") || (_to_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(this.renkan)).get("color"),
  2184                 to_color: _to_model.get("color") || (_to_model.get("created_by") || _USER_PLACEHOLDER(this.renkan)).get("color"),
  2045                 created_by_color: _created_by.get("color"),
  2185                 created_by_color: _created_by.get("color"),
  2046                 created_by_title: _created_by.get("title")
  2186                 created_by_title: _created_by.get("title")
  2047             },
  2187             },
  2048             renkan: this.renkan,
  2188             renkan: this.renkan,
  2049             options: this.options,
  2189             shortenText: shortenText,
       
  2190             options: this.options
  2050         }));
  2191         }));
  2051     this.redraw();
  2192     this.redraw();
  2052     var _this = this,
  2193     var _this = this,
  2053         closeEditor = function() {
  2194         closeEditor = function() {
  2054             _this.renderer.removeRepresentation(_this);
  2195             _this.renderer.removeRepresentation(_this);
  2055             paper.view.draw();
  2196             paper.view.draw();
  2056         };
  2197         };
  2057     this.editor_$.find(".Rk-CloseX").click(closeEditor);
  2198     this.editor_$.find(".Rk-CloseX").click(closeEditor);
       
  2199     this.editor_$.find(".Rk-Edit-Goto").click(function() {
       
  2200         if (!_model.get("uri")) {
       
  2201             return false;
       
  2202         }
       
  2203     });
  2058     
  2204     
  2059     if (this.renderer.isEditable()) {
  2205     if (this.renderer.isEditable()) {
  2060         
  2206         
  2061         var onFieldChange = Rkns._(function() {
  2207         var onFieldChange = _(function() {
  2062             Rkns._(function() {
  2208             _(function() {
  2063                 if (_this.renderer.isEditable()) {
  2209                 if (_this.renderer.isEditable()) {
  2064                     var _data = {
  2210                     var _data = {
  2065                         title: _this.editor_$.find(".Rk-Edit-Title").val()
  2211                         title: _this.editor_$.find(".Rk-Edit-Title").val()
  2066                     };
  2212                     };
  2067                     if (_this.options.show_edge_editor_uri) {
  2213                     if (_this.options.show_edge_editor_uri) {
  2068                         _data.uri = _this.editor_$.find(".Rk-Edit-URI").val();
  2214                         _data.uri = _this.editor_$.find(".Rk-Edit-URI").val();
  2069                     }
  2215                     }
  2070                     _this.editor_$.find(".Rk-Edit-Goto").attr("href",_data.uri);
  2216                     _this.editor_$.find(".Rk-Edit-Goto").attr("href",_data.uri || "#");
  2071                     _model.set(_data);
  2217                     _model.set(_data);
  2072                     paper.view.draw();
  2218                     paper.view.draw();
  2073                 } else {
  2219                 } else {
  2074                     closeEditor();
  2220                     closeEditor();
  2075                 }
  2221                 }
  2123                 _e.preventDefault();
  2269                 _e.preventDefault();
  2124                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  2270                 _this.editor_$.find(".Rk-Edit-Color").css("background", $(this).attr("data-color"));
  2125             },
  2271             },
  2126             function(_e) {
  2272             function(_e) {
  2127                 _e.preventDefault();
  2273                 _e.preventDefault();
  2128                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || Rkns.Renderer._USER_PLACEHOLDER(_this.renkan)).get("color"));
  2274                 _this.editor_$.find(".Rk-Edit-Color").css("background", _model.get("color") || (_model.get("created_by") || _USER_PLACEHOLDER(_this.renkan)).get("color"));
  2129             }
  2275             }
  2130         ).click(function(_e) {
  2276         ).click(function(_e) {
  2131             _e.preventDefault();
  2277             _e.preventDefault();
  2132             if (_this.renderer.isEditable()) {
  2278             if (_this.renderer.isEditable()) {
  2133                 _model.set("color", $(this).attr("data-color"));
  2279                 _model.set("color", $(this).attr("data-color"));
  2136             } else {
  2282             } else {
  2137                 closeEditor();
  2283                 closeEditor();
  2138             }
  2284             }
  2139         });
  2285         });
  2140     }
  2286     }
  2141 };
  2287 },
  2142 
  2288 redraw: function() {
  2143 Rkns.Renderer.EdgeEditor.prototype.redraw = function() {
       
  2144     var _coords = this.source_representation.paper_coords;
  2289     var _coords = this.source_representation.paper_coords;
  2145     Rkns.Renderer.drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
  2290     drawEditBox(this.options, _coords, this.editor_block, 5, this.editor_$);
  2146     this.editor_$.show();
  2291     this.editor_$.show();
  2147     paper.view.draw();
  2292     paper.view.draw();
  2148 };
  2293 }
       
  2294 });
  2149 
  2295 
  2150 /* */
  2296 /* */
  2151 
  2297 
  2152 Rkns.Renderer._NodeButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  2298 var _NodeButton = Renderer._NodeButton = Rkns.Utils.inherit(_BaseButton);
  2153 
  2299 
  2154 Rkns.Renderer._NodeButton.prototype.setSectorSize = function() {
  2300 _(_NodeButton.prototype).extend({
       
  2301 setSectorSize: function() {
  2155     var sectorInner = this.source_representation.circle_radius;
  2302     var sectorInner = this.source_representation.circle_radius;
  2156     if (sectorInner !== this.lastSectorInner) {
  2303     if (sectorInner !== this.lastSectorInner) {
  2157         if (this.sector) {
  2304         if (this.sector) {
  2158             this.sector.destroy();
  2305             this.sector.destroy();
  2159         }
  2306         }
  2160         this.sector = this.renderer.drawSector(
  2307         this.sector = this.renderer.drawSector(
  2161             this, 1 + sectorInner,
  2308             this, 1 + sectorInner,
  2162             Rkns.Renderer._NODE_BUTTON_WIDTH + sectorInner,
  2309             _NODE_BUTTON_WIDTH + sectorInner,
  2163             this.startAngle,
  2310             this.startAngle,
  2164             this.endAngle,
  2311             this.endAngle,
  2165             1,
  2312             1,
  2166             this.imageName,
  2313             this.imageName,
  2167             this.renkan.translate(this.text)
  2314             this.renkan.translate(this.text)
  2168         );
  2315         );
  2169         this.lastSectorInner = sectorInner;
  2316         this.lastSectorInner = sectorInner;
  2170     }
  2317     }
  2171 };
  2318 }
       
  2319 });
  2172 
  2320 
  2173 /* */
  2321 /* */
  2174 
  2322 
  2175 Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  2323 var NodeEditButton = Renderer.NodeEditButton = Rkns.Utils.inherit(_NodeButton);
  2176 
  2324 
  2177 Rkns.Renderer.NodeEditButton.prototype._init = function() {
  2325 _(NodeEditButton.prototype).extend({
       
  2326 _init: function() {
  2178     this.type = "Node-edit-button";
  2327     this.type = "Node-edit-button";
  2179     this.lastSectorInner = 0;
  2328     this.lastSectorInner = 0;
  2180     this.startAngle = -135;
  2329     this.startAngle = -135;
  2181     this.endAngle = -45;
  2330     this.endAngle = -45;
  2182     this.imageName = "edit";
  2331     this.imageName = "edit";
  2183     this.text = "Edit";
  2332     this.text = "Edit";
  2184 };
  2333 },
  2185 
  2334 mouseup: function() {
  2186 Rkns.Renderer.NodeEditButton.prototype.mouseup = function() {
       
  2187     if (!this.renderer.is_dragging) {
  2335     if (!this.renderer.is_dragging) {
  2188         this.source_representation.openEditor();
  2336         this.source_representation.openEditor();
  2189     }
  2337     }
  2190 };
  2338 }
       
  2339 });
  2191 
  2340 
  2192 /* */
  2341 /* */
  2193 
  2342 
  2194 Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  2343 var NodeRemoveButton = Renderer.NodeRemoveButton = Rkns.Utils.inherit(_NodeButton);
  2195 
  2344 
  2196 Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
  2345 _(NodeRemoveButton.prototype).extend({
       
  2346 _init: function() {
  2197     this.type = "Node-remove-button";
  2347     this.type = "Node-remove-button";
  2198     this.lastSectorInner = 0;
  2348     this.lastSectorInner = 0;
  2199     this.startAngle = 0;
  2349     this.startAngle = 0;
  2200     this.endAngle = 90;
  2350     this.endAngle = 90;
  2201     this.imageName = "remove";
  2351     this.imageName = "remove";
  2202     this.text = "Remove";
  2352     this.text = "Remove";
  2203 };
  2353 },
  2204 
  2354 mouseup: function() {
  2205 Rkns.Renderer.NodeRemoveButton.prototype.mouseup = function() {
       
  2206     this.renderer.click_target = null;
  2355     this.renderer.click_target = null;
  2207     this.renderer.is_dragging = false;
  2356     this.renderer.is_dragging = false;
  2208     this.renderer.removeRepresentationsOfType("editor");
  2357     this.renderer.removeRepresentationsOfType("editor");
  2209     if (this.renderer.isEditable()) {
  2358     if (this.renderer.isEditable()) {
  2210         if (this.options.element_delete_delay) {
  2359         if (this.options.element_delete_delay) {
  2218             if (confirm(this.renkan.translate('Do you really wish to remove node ') + '"' + this.source_representation.model.get("title") + '"?')) {
  2367             if (confirm(this.renkan.translate('Do you really wish to remove node ') + '"' + this.source_representation.model.get("title") + '"?')) {
  2219                 this.project.removeNode(this.source_representation.model);
  2368                 this.project.removeNode(this.source_representation.model);
  2220             }
  2369             }
  2221         }
  2370         }
  2222     }
  2371     }
  2223 };
  2372 }
       
  2373 });
  2224 
  2374 
  2225 /* */
  2375 /* */
  2226 
  2376 
  2227 Rkns.Renderer.NodeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  2377 var NodeRevertButton = Renderer.NodeRevertButton = Rkns.Utils.inherit(_NodeButton);
  2228 
  2378 
  2229 Rkns.Renderer.NodeRevertButton.prototype._init = function() {
  2379 _(NodeRevertButton.prototype).extend({
       
  2380 _init: function() {
  2230     this.type = "Node-revert-button";
  2381     this.type = "Node-revert-button";
  2231     this.lastSectorInner = 0;
  2382     this.lastSectorInner = 0;
  2232     this.startAngle = -135;
  2383     this.startAngle = -135;
  2233     this.endAngle = 135;
  2384     this.endAngle = 135;
  2234     this.imageName = "revert";
  2385     this.imageName = "revert";
  2235     this.text = "Cancel deletion";
  2386     this.text = "Cancel deletion";
  2236 };
  2387 },
  2237 
  2388 mouseup: function() {
  2238 Rkns.Renderer.NodeRevertButton.prototype.mouseup = function() {
       
  2239     this.renderer.click_target = null;
  2389     this.renderer.click_target = null;
  2240     this.renderer.is_dragging = false;
  2390     this.renderer.is_dragging = false;
  2241     if (this.renderer.isEditable()) {
  2391     if (this.renderer.isEditable()) {
  2242         this.source_representation.model.unset("delete_scheduled");
  2392         this.source_representation.model.unset("delete_scheduled");
  2243     }
  2393     }
  2244 };
  2394 }
       
  2395 });
  2245 
  2396 
  2246 /* */
  2397 /* */
  2247 
  2398 
  2248 Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  2399 var NodeLinkButton = Renderer.NodeLinkButton = Rkns.Utils.inherit(_NodeButton);
  2249 
  2400 
  2250 Rkns.Renderer.NodeLinkButton.prototype._init = function() {
  2401 _(NodeLinkButton.prototype).extend({
       
  2402 _init: function() {
  2251     this.type = "Node-link-button";
  2403     this.type = "Node-link-button";
  2252     this.lastSectorInner = 0;
  2404     this.lastSectorInner = 0;
  2253     this.startAngle = 90;
  2405     this.startAngle = 90;
  2254     this.endAngle = 180;
  2406     this.endAngle = 180;
  2255     this.imageName = "link";
  2407     this.imageName = "link";
  2256     this.text = "Link to another node";
  2408     this.text = "Link to another node";
  2257 };
  2409 },
  2258 
  2410 mousedown: function(_event, _isTouch) {
  2259 Rkns.Renderer.NodeLinkButton.prototype.mousedown = function(_event, _isTouch) {
       
  2260     if (this.renderer.isEditable()) {
  2411     if (this.renderer.isEditable()) {
  2261         var _off = this.renderer.canvas_$.offset(),
  2412         var _off = this.renderer.canvas_$.offset(),
  2262             _point = new paper.Point([
  2413             _point = new paper.Point([
  2263                 _event.pageX - _off.left,
  2414                 _event.pageX - _off.left,
  2264                 _event.pageY - _off.top
  2415                 _event.pageY - _off.top
  2265             ]);
  2416             ]);
  2266         this.renderer.click_target = null;
  2417         this.renderer.click_target = null;
  2267         this.renderer.removeRepresentationsOfType("editor");
  2418         this.renderer.removeRepresentationsOfType("editor");
  2268         this.renderer.addTempEdge(this.source_representation, _point);
  2419         this.renderer.addTempEdge(this.source_representation, _point);
  2269     }
  2420     }
  2270 };
  2421 }
       
  2422 });
  2271 
  2423 
  2272 /* */
  2424 /* */
  2273 
  2425 
  2274 Rkns.Renderer.NodeEnlargeButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  2426 var NodeEnlargeButton = Renderer.NodeEnlargeButton = Rkns.Utils.inherit(_NodeButton);
  2275 
  2427 
  2276 Rkns.Renderer.NodeEnlargeButton.prototype._init = function() {
  2428 _(NodeEnlargeButton.prototype).extend({
       
  2429 _init: function() {
  2277     this.type = "Node-enlarge-button";
  2430     this.type = "Node-enlarge-button";
  2278     this.lastSectorInner = 0;
  2431     this.lastSectorInner = 0;
  2279     this.startAngle = -45;
  2432     this.startAngle = -45;
  2280     this.endAngle = 0;
  2433     this.endAngle = 0;
  2281     this.imageName = "enlarge";
  2434     this.imageName = "enlarge";
  2282     this.text = "Enlarge";
  2435     this.text = "Enlarge";
  2283 };
  2436 },
  2284 
  2437 mouseup: function() {
  2285 Rkns.Renderer.NodeEnlargeButton.prototype.mouseup = function() {
       
  2286     var _newsize = 1 + (this.source_representation.model.get("size") || 0);
  2438     var _newsize = 1 + (this.source_representation.model.get("size") || 0);
  2287     this.source_representation.model.set("size", _newsize);
  2439     this.source_representation.model.set("size", _newsize);
  2288     this.source_representation.select();
  2440     this.source_representation.select();
  2289     this.select();
  2441     this.select();
  2290     paper.view.draw();
  2442     paper.view.draw();
  2291 };
  2443 }
       
  2444 });
  2292 
  2445 
  2293 /* */
  2446 /* */
  2294 
  2447 
  2295 Rkns.Renderer.NodeShrinkButton = Rkns.Utils.inherit(Rkns.Renderer._NodeButton);
  2448 var NodeShrinkButton = Renderer.NodeShrinkButton = Rkns.Utils.inherit(_NodeButton);
  2296 
  2449 
  2297 Rkns.Renderer.NodeShrinkButton.prototype._init = function() {
  2450 _(NodeShrinkButton.prototype).extend({
       
  2451 _init: function() {
  2298     this.type = "Node-shrink-button";
  2452     this.type = "Node-shrink-button";
  2299     this.lastSectorInner = 0;
  2453     this.lastSectorInner = 0;
  2300     this.startAngle = -180;
  2454     this.startAngle = -180;
  2301     this.endAngle = -135;
  2455     this.endAngle = -135;
  2302     this.imageName = "shrink";
  2456     this.imageName = "shrink";
  2303     this.text = "Shrink";
  2457     this.text = "Shrink";
  2304 };
  2458 },
  2305 
  2459 mouseup: function() {
  2306 Rkns.Renderer.NodeShrinkButton.prototype.mouseup = function() {
       
  2307     var _newsize = -1 + (this.source_representation.model.get("size") || 0);
  2460     var _newsize = -1 + (this.source_representation.model.get("size") || 0);
  2308     this.source_representation.model.set("size", _newsize);
  2461     this.source_representation.model.set("size", _newsize);
  2309     this.source_representation.select();
  2462     this.source_representation.select();
  2310     this.select();
  2463     this.select();
  2311     paper.view.draw();
  2464     paper.view.draw();
  2312 };
  2465 }
       
  2466 });
  2313 
  2467 
  2314 /* */
  2468 /* */
  2315 
  2469 
  2316 Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  2470 var EdgeEditButton = Renderer.EdgeEditButton = Rkns.Utils.inherit(_BaseButton);
  2317 
  2471 
  2318 Rkns.Renderer.EdgeEditButton.prototype._init = function() {
  2472 _(EdgeEditButton.prototype).extend({
       
  2473 _init: function() {
  2319     this.type = "Edge-edit-button";
  2474     this.type = "Edge-edit-button";
  2320     this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
  2475     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -270, -90, 1, "edit", this.renkan.translate("Edit"));
  2321 };
  2476 },
  2322 
  2477 mouseup: function() {
  2323 Rkns.Renderer.EdgeEditButton.prototype.mouseup = function() {
       
  2324     if (!this.renderer.is_dragging) {
  2478     if (!this.renderer.is_dragging) {
  2325         this.source_representation.openEditor();
  2479         this.source_representation.openEditor();
  2326     }
  2480     }
  2327 };
  2481 }
       
  2482 });
  2328 
  2483 
  2329 /* */
  2484 /* */
  2330 
  2485 
  2331 Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  2486 var EdgeRemoveButton = Renderer.EdgeRemoveButton = Rkns.Utils.inherit(_BaseButton);
  2332 
  2487 
  2333 Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
  2488 _(EdgeRemoveButton.prototype).extend({
       
  2489 _init: function() {
  2334     this.type = "Edge-remove-button";
  2490     this.type = "Edge-remove-button";
  2335     this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
  2491     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -90, 90, 1, "remove", this.renkan.translate("Remove"));
  2336 };
  2492 },
  2337 
  2493 mouseup: function() {
  2338 Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() {
       
  2339     this.renderer.click_target = null;
  2494     this.renderer.click_target = null;
  2340     this.renderer.is_dragging = false;
  2495     this.renderer.is_dragging = false;
  2341     this.renderer.removeRepresentationsOfType("editor");
  2496     this.renderer.removeRepresentationsOfType("editor");
  2342     if (this.renderer.isEditable()) {
  2497     if (this.renderer.isEditable()) {
  2343         if (this.options.element_delete_delay) {
  2498         if (this.options.element_delete_delay) {
  2351             if (confirm(this.renkan.translate('Do you really wish to remove edge ') + '"' + this.source_representation.model.get("title") + '"?')) {
  2506             if (confirm(this.renkan.translate('Do you really wish to remove edge ') + '"' + this.source_representation.model.get("title") + '"?')) {
  2352                 this.project.removeEdge(this.source_representation.model);
  2507                 this.project.removeEdge(this.source_representation.model);
  2353             }
  2508             }
  2354         }
  2509         }
  2355     }
  2510     }
  2356 };
  2511 }
       
  2512 });
  2357 
  2513 
  2358 /* */
  2514 /* */
  2359 
  2515 
  2360 Rkns.Renderer.EdgeRevertButton = Rkns.Utils.inherit(Rkns.Renderer._BaseButton);
  2516 var EdgeRevertButton = Renderer.EdgeRevertButton = Rkns.Utils.inherit(_BaseButton);
  2361 
  2517 
  2362 Rkns.Renderer.EdgeRevertButton.prototype._init = function() {
  2518 _(EdgeRevertButton.prototype).extend({
       
  2519 _init: function() {
  2363     this.type = "Edge-revert-button";
  2520     this.type = "Edge-revert-button";
  2364     this.sector = this.renderer.drawSector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
  2521     this.sector = this.renderer.drawSector(this, _EDGE_BUTTON_INNER, _EDGE_BUTTON_OUTER, -135, 135, 1, "revert", this.renkan.translate("Cancel deletion"));
  2365 };
  2522 },
  2366 
  2523 mouseup: function() {
  2367 Rkns.Renderer.EdgeRevertButton.prototype.mouseup = function() {
       
  2368     this.renderer.click_target = null;
  2524     this.renderer.click_target = null;
  2369     this.renderer.is_dragging = false;
  2525     this.renderer.is_dragging = false;
  2370     if (this.renderer.isEditable()) {
  2526     if (this.renderer.isEditable()) {
  2371         this.source_representation.model.unset("delete_scheduled");
  2527         this.source_representation.model.unset("delete_scheduled");
  2372     }
  2528     }
  2373 };
  2529 }
       
  2530 });
  2374 
  2531 
  2375 /* */
  2532 /* */
  2376 
  2533 
  2377 Rkns.Renderer.MiniFrame = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
  2534 var MiniFrame = Renderer.MiniFrame = Rkns.Utils.inherit(_BaseRepresentation);
  2378 
  2535 
  2379 Rkns.Renderer.MiniFrame.prototype.paperShift = function(_delta) {
  2536 _(MiniFrame.prototype).extend({
       
  2537 paperShift: function(_delta) {
  2380     this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
  2538     this.renderer.offset = this.renderer.offset.subtract(_delta.divide(this.renderer.minimap.scale).multiply(this.renderer.scale));
  2381     this.renderer.redraw();
  2539     this.renderer.redraw();
  2382 };
  2540 },
  2383 
  2541 mouseup: function(_delta) {
  2384 Rkns.Renderer.MiniFrame.prototype.mouseup = function(_delta) {
       
  2385     this.renderer.click_target = null;
  2542     this.renderer.click_target = null;
  2386     this.renderer.is_dragging = false;
  2543     this.renderer.is_dragging = false;
  2387 };
  2544 }
       
  2545 });
  2388 
  2546 
  2389 /* */
  2547 /* */
  2390 
  2548 
  2391 Rkns.Renderer.Scene = function(_renkan) {
  2549 var Scene = Renderer.Scene = function(_renkan) {
  2392     this.renkan = _renkan;
  2550     this.renkan = _renkan;
  2393     this.$ = Rkns.$(".Rk-Render");
  2551     this.$ = $(".Rk-Render");
  2394     this.representations = [];
  2552     this.representations = [];
  2395     this.$.html(this.template(_renkan));
  2553     this.$.html(this.template(_renkan));
  2396     this.onStatusChange();
  2554     this.onStatusChange();
  2397     this.canvas_$ = this.$.find(".Rk-Canvas");
  2555     this.canvas_$ = this.$.find(".Rk-Canvas");
  2398     this.labels_$ = this.$.find(".Rk-Labels");
  2556     this.labels_$ = this.$.find(".Rk-Labels");
  2399     this.editor_$ = this.$.find(".Rk-Editor");
  2557     this.editor_$ = this.$.find(".Rk-Editor");
  2400     this.notif_$ = this.$.find(".Rk-Notifications");
  2558     this.notif_$ = this.$.find(".Rk-Notifications");
  2401     paper.setup(this.canvas_$[0]);
  2559     paper.setup(this.canvas_$[0]);
  2402     this.scale = 1;
  2560     this.scale = 1;
       
  2561     this.initialScale = 1;
  2403     this.offset = paper.view.center;
  2562     this.offset = paper.view.center;
  2404     this.totalScroll = 0;
  2563     this.totalScroll = 0;
  2405     this.mouse_down = false;
  2564     this.mouse_down = false;
  2406     this.click_target = null;
  2565     this.click_target = null;
  2407     this.selected_target = null;
  2566     this.selected_target = null;
  2436         this.minimap.node_group.addChild(this.minimap.miniframe);
  2595         this.minimap.node_group.addChild(this.minimap.miniframe);
  2437         this.minimap.miniframe.fillColor = '#c0c0ff';
  2596         this.minimap.miniframe.fillColor = '#c0c0ff';
  2438         this.minimap.miniframe.opacity = .3;
  2597         this.minimap.miniframe.opacity = .3;
  2439         this.minimap.miniframe.strokeColor = '#000080';
  2598         this.minimap.miniframe.strokeColor = '#000080';
  2440         this.minimap.miniframe.strokeWidth = 3;
  2599         this.minimap.miniframe.strokeWidth = 3;
  2441         this.minimap.miniframe.__representation = new Rkns.Renderer.MiniFrame(this, null);
  2600         this.minimap.miniframe.__representation = new MiniFrame(this, null);
  2442     }
  2601     }
  2443     
  2602     
  2444     this.throttledPaperDraw = Rkns._(function() {
  2603     this.throttledPaperDraw = _(function() {
  2445         paper.view.draw();
  2604         paper.view.draw();
  2446     }).throttle(100);
  2605     }).throttle(100);
  2447     
  2606     
  2448     this.bundles = [];
  2607     this.bundles = [];
  2449     this.click_mode = false;
  2608     this.click_mode = false;
  2465         _this.icon_cache[imgname] = img;
  2624         _this.icon_cache[imgname] = img;
  2466     });
  2625     });
  2467     
  2626     
  2468     var throttledMouseMove = _.throttle(function(_event, _isTouch) {
  2627     var throttledMouseMove = _.throttle(function(_event, _isTouch) {
  2469         _this.onMouseMove(_event, _isTouch);
  2628         _this.onMouseMove(_event, _isTouch);
  2470     }, Rkns.Renderer._MOUSEMOVE_RATE);
  2629     }, _MOUSEMOVE_RATE);
  2471     
  2630         
  2472     this.canvas_$.on({
  2631     this.canvas_$.on({
  2473         mousedown: function(_event) {
  2632         mousedown: function(_event) {
  2474             _event.preventDefault();
  2633             _event.preventDefault();
  2475             _this.onMouseDown(_event, false);
  2634             _this.onMouseDown(_event, false);
  2476         },
  2635         },
  2491         touchstart: function(_event) {
  2650         touchstart: function(_event) {
  2492             _event.preventDefault();
  2651             _event.preventDefault();
  2493             var _touches = _event.originalEvent.touches[0];
  2652             var _touches = _event.originalEvent.touches[0];
  2494             if (
  2653             if (
  2495                 _renkan.options.allow_double_click
  2654                 _renkan.options.allow_double_click
  2496                 && new Date() - _lastTap < Rkns.Renderer._DOUBLETAP_DELAY
  2655                 && new Date() - _lastTap < _DOUBLETAP_DELAY
  2497                 && ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < Rkns.Renderer._DOUBLETAP_DISTANCE )
  2656                 && ( Math.pow(_lastTapX - _touches.pageX, 2) + Math.pow(_lastTapY - _touches.pageY, 2) < _DOUBLETAP_DISTANCE )
  2498             ) {
  2657             ) {
  2499                 _lastTap = 0;
  2658                 _lastTap = 0;
  2500                 _this.onDoubleClick(_touches);
  2659                 _this.onDoubleClick(_touches);
  2501             } else {
  2660             } else {
  2502                 _lastTap = new Date();
  2661                 _lastTap = new Date();
  2560         },
  2719         },
  2561         drop: function(_event) {
  2720         drop: function(_event) {
  2562             _event.preventDefault();
  2721             _event.preventDefault();
  2563             _allowScroll = true;
  2722             _allowScroll = true;
  2564             var res = {};
  2723             var res = {};
  2565             Rkns._(_event.originalEvent.dataTransfer.types).each(function(t) {
  2724             _(_event.originalEvent.dataTransfer.types).each(function(t) {
  2566                 try {
  2725                 try {
  2567                     res[t] = _event.originalEvent.dataTransfer.getData(t);
  2726                     res[t] = _event.originalEvent.dataTransfer.getData(t);
  2568                 } catch(e) {}
  2727                 } catch(e) {}
  2569             });
  2728             });
  2570             var text = _event.originalEvent.dataTransfer.getData("Text");
  2729             var text = _event.originalEvent.dataTransfer.getData("Text");
  2598                 res["text/uri-list"] = url;
  2757                 res["text/uri-list"] = url;
  2599             }
  2758             }
  2600             _this.dropData(res, _event.originalEvent);
  2759             _this.dropData(res, _event.originalEvent);
  2601         }
  2760         }
  2602     });
  2761     });
  2603     this.editor_$.find(".Rk-ZoomOut").click(function() {
  2762     
  2604         var _newScale = _this.scale * Math.SQRT1_2,
  2763     var bindClick = function(selector, fname) {
  2605             _offset = new paper.Point([
  2764         _this.$.find(selector).click(function(evt) {
  2606                 _this.canvas_$.width(),
  2765             _this[fname](evt);
  2607                 _this.canvas_$.height()
  2766             return false;
  2608             ]).multiply( .5 * ( 1 - Math.SQRT1_2 ) ).add(_this.offset.multiply( Math.SQRT1_2 ));
  2767         });
  2609         _this.setScale( _newScale, _offset );
  2768     };
  2610     });
  2769     
  2611     this.editor_$.find(".Rk-ZoomIn").click(function() {
  2770     bindClick(".Rk-ZoomOut", "zoomOut");
  2612         var _newScale = _this.scale * Math.SQRT2,
  2771     bindClick(".Rk-ZoomIn", "zoomIn");
  2613             _offset = new paper.Point([
       
  2614                 _this.canvas_$.width(),
       
  2615                 _this.canvas_$.height()
       
  2616             ]).multiply( .5 * ( 1 - Math.SQRT2 ) ).add(_this.offset.multiply( Math.SQRT2 ));
       
  2617         _this.setScale( _newScale, _offset );
       
  2618     });
       
  2619     this.$.find(".Rk-CurrentUser").mouseenter(
  2772     this.$.find(".Rk-CurrentUser").mouseenter(
  2620         function() { _this.$.find(".Rk-UserList").slideDown(); }
  2773         function() { _this.$.find(".Rk-UserList").slideDown(); }
  2621     );
  2774     );
  2622     this.$.find(".Rk-Users").mouseleave(
  2775     this.$.find(".Rk-Users").mouseleave(
  2623         function() { _this.$.find(".Rk-UserList").slideUp(); }
  2776         function() { _this.$.find(".Rk-UserList").slideUp(); }
  2624     );
  2777     );
  2625     this.$.find(".Rk-FullScreen-Button").click(function() {
  2778     bindClick(".Rk-FullScreen-Button", "fullScreen");
  2626         var _isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen,
  2779     bindClick(".Rk-AddNode-Button", "addNodeBtn");
  2627             _el = _this.renkan.$[0],
  2780     bindClick(".Rk-AddEdge-Button", "addEdgeBtn");
  2628             _requestMethods = ["requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen"],
  2781     bindClick(".Rk-Save-Button", "save");
  2629             _cancelMethods = ["cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen"];
  2782     bindClick(".Rk-Open-Button", "open");
  2630         if (_isFull) {
       
  2631             for (var i = 0; i < _cancelMethods.length; i++) {
       
  2632                 if (typeof document[_cancelMethods[i]] === "function") {
       
  2633                     document[_cancelMethods[i]]();
       
  2634                     break;
       
  2635                 }
       
  2636             }
       
  2637         } else {
       
  2638             for (var i = 0; i < _requestMethods.length; i++) {
       
  2639                 if (typeof _el[_requestMethods[i]] === "function") {
       
  2640                     _el[_requestMethods[i]]();
       
  2641                     break;
       
  2642                 }
       
  2643             }
       
  2644         }
       
  2645     });
       
  2646     this.$.find(".Rk-AddNode-Button").click(function() {
       
  2647         if (_this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
       
  2648             _this.click_mode = false;
       
  2649             _this.notif_$.hide();
       
  2650         } else {
       
  2651             _this.click_mode = Rkns.Renderer._CLICKMODE_ADDNODE;
       
  2652             _this.notif_$.text(_renkan.translate("Click on the background canvas to add a node")).fadeIn();
       
  2653         }
       
  2654     });
       
  2655     this.$.find(".Rk-AddEdge-Button").click(function() {
       
  2656         if (_this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE || _this.click_mode === Rkns.Renderer._CLICKMODE_ENDEDGE) {
       
  2657             _this.click_mode = false;
       
  2658             _this.notif_$.hide();
       
  2659         } else {
       
  2660             _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE;
       
  2661             _this.notif_$.text(_renkan.translate("Click on a first node to start the edge")).fadeIn();
       
  2662         }
       
  2663     });
       
  2664     this.$.find(".Rk-Bookmarklet-Button")
  2783     this.$.find(".Rk-Bookmarklet-Button")
  2665         .attr("href","javascript:" + Rkns.Renderer._BOOKMARKLET_CODE(_renkan))
  2784         .attr("href","javascript:" + _BOOKMARKLET_CODE(_renkan))
  2666         .click(function(){
  2785         .click(function(){
  2667             _this.notif_$
  2786             _this.notif_$
  2668                 .text(_renkan.translate("Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan."))
  2787                 .text(_renkan.translate("Drag this button to your bookmark bar. When on a third-party website, click it to enable drag-and-drop from the website to Renkan."))
  2669                 .fadeIn()
  2788                 .fadeIn()
  2670                 .delay(5000)
  2789                 .delay(5000)
  2671                 .fadeOut();
  2790                 .fadeOut();
  2672             return false;
  2791             return false;
  2673         });
  2792         });
  2674     this.$.find(".Rk-TopBar-Button").mouseover(function() {
  2793     this.$.find(".Rk-TopBar-Button").mouseover(function() {
  2675         Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
  2794         $(this).find(".Rk-TopBar-Tooltip").show();
  2676     }).mouseout(function() {
  2795     }).mouseout(function() {
  2677         Rkns.$(this).find(".Rk-TopBar-Tooltip").hide();
  2796         $(this).find(".Rk-TopBar-Tooltip").hide();
  2678     });
  2797     });
  2679     this.$.find(".Rk-Fold-Bins").click(function() {
  2798     bindClick(".Rk-Fold-Bins", "foldBins");
  2680         var bins = _renkan.$.find(".Rk-Bins");
       
  2681         if (bins.offset().left < 0) {
       
  2682             bins.animate({left: 0},250);
       
  2683             _this.$.animate({left: 300},250,function() {
       
  2684                 var w = _this.$.width();
       
  2685                 paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
       
  2686             });
       
  2687             $(this).html("&laquo;");
       
  2688         } else {
       
  2689             bins.animate({left: -300},250);
       
  2690             _this.$.animate({left: 0},250,function() {
       
  2691                 var w = _this.$.width();
       
  2692                 paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
       
  2693             });
       
  2694             $(this).html("&raquo;");
       
  2695         }
       
  2696     });
       
  2697     
  2799     
  2698     paper.view.onResize = function(_event) {
  2800     paper.view.onResize = function(_event) {
  2699         _this.offset = _this.offset.add(_event.delta.divide(2));
  2801         _this.offset = _this.offset.add(_event.delta.divide(2));
  2700         if (_this.minimap) {
  2802         if (_this.minimap) {
  2701             _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size);
  2803             _this.minimap.topleft = paper.view.bounds.bottomRight.subtract(_this.minimap.size);
  2703             _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
  2805             _this.minimap.cliprectangle.fitBounds(_this.minimap.topleft, _this.minimap.size);
  2704         }
  2806         }
  2705         _this.redraw();
  2807         _this.redraw();
  2706     };
  2808     };
  2707     
  2809     
  2708     var _thRedraw = Rkns._.throttle(function() {
  2810     var _thRedraw = _.throttle(function() {
  2709         _this.redraw();
  2811         _this.redraw();
  2710     },50);
  2812     },50);
  2711     
  2813     
  2712     this.addRepresentations("Node", this.renkan.project.get("nodes"));
  2814     this.addRepresentations("Node", this.renkan.project.get("nodes"));
  2713     this.addRepresentations("Edge", this.renkan.project.get("edges"));
  2815     this.addRepresentations("Edge", this.renkan.project.get("edges"));
  2717     
  2819     
  2718     this.$.find(".Rk-PadTitle").on("keyup input paste", function() {
  2820     this.$.find(".Rk-PadTitle").on("keyup input paste", function() {
  2719         _renkan.project.set({"title": $(this).val()});
  2821         _renkan.project.set({"title": $(this).val()});
  2720     });
  2822     });
  2721     
  2823     
  2722     this.renkan.project.get("users").each(function(_user) {
  2824     var _thRedrawUsers = _.throttle(function() {
  2723         _this.addUser(_user);
  2825         _this.redrawUsers();
  2724     });
  2826     }, 100);
  2725     
  2827     
  2726     this.renkan.project.on("add:users", function(_user) {
  2828     _thRedrawUsers();
  2727         _this.addUser(_user);
  2829     
  2728     });
  2830     this.renkan.project.on("add:users remove:users", _thRedrawUsers);
       
  2831     
  2729     this.renkan.project.on("add:nodes", function(_node) {
  2832     this.renkan.project.on("add:nodes", function(_node) {
  2730         _this.addRepresentation("Node", _node);
  2833         _this.addRepresentation("Node", _node);
  2731         _thRedraw();
  2834         _thRedraw();
  2732     });
  2835     });
  2733     this.renkan.project.on("add:edges", function(_edge) {
  2836     this.renkan.project.on("add:edges", function(_edge) {
  2763         $(window).resize(function() {
  2866         $(window).resize(function() {
  2764             _this.fixSize(false);
  2867             _this.fixSize(false);
  2765         });
  2868         });
  2766     }
  2869     }
  2767     
  2870     
       
  2871     if (_renkan.options.show_user_list && _renkan.options.user_color_editable) {
       
  2872         var $cpwrapper = this.$.find(".Rk-Users .Rk-Edit-ColorPicker-Wrapper"),
       
  2873             $cplist = this.$.find(".Rk-Users .Rk-Edit-ColorPicker");
       
  2874         
       
  2875         $cpwrapper.hover(
       
  2876             function(_e) {
       
  2877                 if (_this.isEditable()) {
       
  2878                     _e.preventDefault();
       
  2879                     $cplist.show();
       
  2880                 }
       
  2881             },
       
  2882             function(_e) {
       
  2883                 _e.preventDefault();
       
  2884                 $cplist.hide();
       
  2885             }
       
  2886         );
       
  2887         
       
  2888         $cplist.find("li").mouseenter(
       
  2889             function(_e) {
       
  2890                 if (_this.isEditable()) {
       
  2891                     _e.preventDefault();
       
  2892                     _this.$.find(".Rk-CurrentUser-Color").css("background", $(this).attr("data-color"));
       
  2893                 }
       
  2894             }
       
  2895         );
       
  2896     }
       
  2897     
       
  2898     if (_renkan.options.show_search_field) {
       
  2899         
       
  2900         var lastval = '';
       
  2901         
       
  2902         this.$.find(".Rk-GraphSearch-Field").on("keyup change paste input", function() {
       
  2903             var $this = $(this),
       
  2904                 val = $this.val();
       
  2905             if (val === lastval) {
       
  2906                 return;
       
  2907             }
       
  2908             lastval = val;
       
  2909             if (val.length < 2) {
       
  2910                 _renkan.project.get("nodes").each(function(n) {
       
  2911                     _this.getRepresentationByModel(n).unhighlight();
       
  2912                 });
       
  2913             } else {
       
  2914                 var rxs = Rkns.Utils.regexpFromTextOrArray(val);
       
  2915                 _renkan.project.get("nodes").each(function(n) {
       
  2916                     if (rxs.test(n.get("title")) || rxs.test(n.get("description"))) {
       
  2917                         _this.getRepresentationByModel(n).highlight(rxs);
       
  2918                     } else {
       
  2919                         _this.getRepresentationByModel(n).unhighlight(); 
       
  2920                     }
       
  2921                 });
       
  2922             }
       
  2923         });
       
  2924     }
       
  2925     
  2768     this.redraw();
  2926     this.redraw();
  2769     
  2927     
  2770     window.setInterval(function() {
  2928     window.setInterval(function() {
  2771         var _now = new Date().valueOf();
  2929         var _now = new Date().valueOf();
  2772         _this.delete_list.forEach(function(d) {
  2930         _this.delete_list.forEach(function(d) {
  2792         }, 2000);
  2950         }, 2000);
  2793     }
  2951     }
  2794 
  2952 
  2795 };
  2953 };
  2796 
  2954 
  2797 Rkns.Renderer.Scene.prototype.template = Rkns._.template(
  2955 _(Scene.prototype).extend({
       
  2956 template: _.template(
  2798     '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>'
  2957     '<% if (options.show_top_bar) { %><div class="Rk-TopBar"><% if (!options.editor_mode) { %><h2 class="Rk-PadTitle"><%- project.get("title") || translate("Untitled project")%></h2>'
  2799     + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>'
  2958     + '<% } else { %><input type="text" class="Rk-PadTitle" value="<%- project.get("title") || "" %>" placeholder="<%-translate("Untitled project")%>" /><% } %>'
  2800     + '<div class="Rk-Users"><div class="Rk-CurrentUser"><span class="Rk-CurrentUser-Color"></span><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div>'
  2959     + '<% if (options.show_user_list) { %><div class="Rk-Users"><div class="Rk-CurrentUser"><div class="Rk-Edit-ColorPicker-Wrapper"><span class="Rk-CurrentUser-Color"><% if (options.user_color_editable) { %><span class="Rk-Edit-ColorTip"></span><% } %></span>'
  2801     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div>'
  2960     + '<% if (options.user_color_editable) { print(colorPicker) } %></div><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div><% } %>'
       
  2961     + '<% if (options.home_button_url) {%><div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Home-Button" href="<%- options.home_button_url %>"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents">'
       
  2962     + '<%- translate(options.home_button_title) %></div></div></a><% } %>'
       
  2963     + '<% if (options.show_fullscreen_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Full Screen")%></div></div></div><% } %>'
  2802     + '<% if (options.editor_mode) { %>'
  2964     + '<% if (options.editor_mode) { %>'
  2803     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Node")%></div></div></div>'
  2965     + '<% if (options.show_addnode_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip">'
  2804     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Edge")%></div></div></div>'
  2966     + '<div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Node")%></div></div></div><% } %>'
  2805     + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-Save-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"> </div></div></div>'
  2967     + '<% if (options.show_addedge_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip">'
  2806     + '<div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="#"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents">'
  2968     + '<div class="Rk-TopBar-Tooltip-Contents"><%-translate("Add Edge")%></div></div></div><% } %>'
  2807     + '<%-translate("Renkan \'Drag-to-Add\' bookmarklet")%></div></div></a>'
  2969     + '<% if (options.show_save_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-Save-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents"> </div></div></div><% } %>'
  2808     + '<div class="Rk-TopBar-Separator"></div>'
  2970     + '<% if (options.show_open_button) { %><div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-Open-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents"><%-translate("Open Project")%></div></div></div><% } %>'
  2809     + '<% } %></div><% } %>'
  2971     + '<% if (options.show_bookmarklet) { %><div class="Rk-TopBar-Separator"></div><a class="Rk-TopBar-Button Rk-Bookmarklet-Button" href="#"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Contents">'
       
  2972     + '<%-translate("Renkan \'Drag-to-Add\' bookmarklet")%></div></div></a><% } %>'
       
  2973     + '<div class="Rk-TopBar-Separator"></div><% }; if (options.show_search_field) { %>'
       
  2974     + '<form action="#" class="Rk-GraphSearch-Form"><input type="search" class="Rk-GraphSearch-Field" placeholder="<%- translate("Search in graph") %>" /></form><div class="Rk-TopBar-Separator"></div><% } %></div><% } %>'
  2810     + '<div class="Rk-Editing-Space<% if (!options.show_top_bar) { %> Rk-Editing-Space-Full<% } %>">'
  2975     + '<div class="Rk-Editing-Space<% if (!options.show_top_bar) { %> Rk-Editing-Space-Full<% } %>">'
  2811     + '<div class="Rk-Labels"></div><canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
  2976     + '<div class="Rk-Labels"></div><canvas class="Rk-Canvas" resize></canvas><div class="Rk-Notifications"></div><div class="Rk-Editor">'
  2812     + '<% if (options.show_bins) { %><div class="Rk-Fold-Bins">&laquo;</div><% } %>'
  2977     + '<% if (options.show_bins) { %><div class="Rk-Fold-Bins">&laquo;</div><% } %>'
  2813     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>'
  2978     + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-translate("Zoom In")%>"></div><div class="Rk-ZoomOut" title="<%-translate("Zoom Out")%>"></div></div>'
  2814     + '</div></div>'
  2979     + '</div></div>'
  2815 );
  2980 ),
  2816 
  2981 fixSize: function(_autoscale) {
  2817 Rkns.Renderer.Scene.prototype.fixSize = function(_autoscale) {
       
  2818     var w = this.$.width(),
  2982     var w = this.$.width(),
  2819         h = this.$.height();
  2983         h = this.$.height();
  2820     if (this.renkan.options.show_top_bar) {
  2984     if (this.renkan.options.show_top_bar) {
  2821         h -= this.$.find(".Rk-TopBar").height();
  2985         h -= this.$.find(".Rk-TopBar").height();
  2822     }
  2986     }
  2828     paper.view.viewSize = new paper.Size([w, h]);
  2992     paper.view.viewSize = new paper.Size([w, h]);
  2829     
  2993     
  2830     if (_autoscale) {
  2994     if (_autoscale) {
  2831         this.autoScale();
  2995         this.autoScale();
  2832     }
  2996     }
  2833 };
  2997 },
  2834 
  2998 drawSector: function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgname, _caption) {
  2835 Rkns.Renderer.Scene.prototype.drawSector = function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgname, _caption) {
       
  2836     var _options = this.renkan.options,
  2999     var _options = this.renkan.options,
  2837         _startRads = _startAngle * Math.PI / 180,
  3000         _startRads = _startAngle * Math.PI / 180,
  2838         _endRads = _endAngle * Math.PI / 180,
  3001         _endRads = _endAngle * Math.PI / 180,
  2839         _img = this.icon_cache[_imgname],
  3002         _img = this.icon_cache[_imgname],
  2840         _span = _endRads - _startRads,
  3003         _span = _endRads - _startRads,
  2928         _grp.addChild(_raster);
  3091         _grp.addChild(_raster);
  2929     }
  3092     }
  2930     if (_img.width) {
  3093     if (_img.width) {
  2931         showImage();
  3094         showImage();
  2932     } else {
  3095     } else {
  2933         Rkns.$(_img).on("load",showImage);
  3096         $(_img).on("load",showImage);
  2934     }
  3097     }
  2935     
  3098     
  2936     return _res;
  3099     return _res;
  2937 };
  3100 },
  2938 
  3101 addToBundles: function(_edgeRepr) {
  2939 Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) {
  3102     var _bundle = _(this.bundles).find(function(_bundle) {
  2940     var _bundle = Rkns._(this.bundles).find(function(_bundle) {
       
  2941         return ( 
  3103         return ( 
  2942             ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
  3104             ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
  2943             || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
  3105             || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
  2944         );
  3106         );
  2945     });
  3107     });
  2950             from: _edgeRepr.from_representation,
  3112             from: _edgeRepr.from_representation,
  2951             to: _edgeRepr.to_representation,
  3113             to: _edgeRepr.to_representation,
  2952             edges: [ _edgeRepr ],
  3114             edges: [ _edgeRepr ],
  2953             getPosition: function(_er) {
  3115             getPosition: function(_er) {
  2954                 var _dir = (_er.from_representation === this.from) ? 1 : -1;
  3116                 var _dir = (_er.from_representation === this.from) ? 1 : -1;
  2955                 return _dir * ( Rkns._(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
  3117                 return _dir * ( _(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
  2956             }
  3118             }
  2957         };
  3119         };
  2958         this.bundles.push(_bundle);
  3120         this.bundles.push(_bundle);
  2959     }
  3121     }
  2960     return _bundle;
  3122     return _bundle;
  2961 };
  3123 },
  2962 
  3124 isEditable: function() {
  2963 Rkns.Renderer.Scene.prototype.isEditable = function() {
       
  2964     return (this.renkan.options.editor_mode && !this.renkan.read_only);
  3125     return (this.renkan.options.editor_mode && !this.renkan.read_only);
  2965 };
  3126 },
  2966 
  3127 onStatusChange: function() {
  2967 Rkns.Renderer.Scene.prototype.onStatusChange = function() {
       
  2968     var savebtn = this.$.find(".Rk-Save-Button"),
  3128     var savebtn = this.$.find(".Rk-Save-Button"),
  2969         tip = savebtn.find(".Rk-TopBar-Tooltip-Contents");
  3129         tip = savebtn.find(".Rk-TopBar-Tooltip-Contents");
  2970     if (this.renkan.read_only) {
  3130     if (this.renkan.read_only) {
  2971         savebtn.removeClass("disabled Rk-Save-Online").addClass("Rk-Save-ReadOnly");
  3131         savebtn.removeClass("disabled Rk-Save-Online").addClass("Rk-Save-ReadOnly");
  2972         tip.text(this.renkan.translate("Connection lost"));
  3132         tip.text(this.renkan.translate("Connection lost"));
  2973     } else {
  3133     } else {
  2974         if (this.renkan.options.snapshot_mode) {
  3134         if (this.renkan.options.snapshot_mode) {
  2975             savebtn.removeClass("Rk-Save-ReadOnly Rk-Save-Online");
  3135             savebtn.removeClass("Rk-Save-ReadOnly Rk-Save-Online");
  2976             tip.text(this.renkan.translate("Archive Project"));
  3136             tip.text(this.renkan.translate("Save Project"));
  2977         } else {
  3137         } else {
  2978             savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online");
  3138             savebtn.removeClass("disabled Rk-Save-ReadOnly").addClass("Rk-Save-Online");
  2979             tip.text(this.renkan.translate("Auto-save enabled"));
  3139             tip.text(this.renkan.translate("Auto-save enabled"));
  2980         }
  3140         }
  2981     }
  3141     }
  2982 };
  3142     this.redrawUsers();
  2983 
  3143 },
  2984 Rkns.Renderer.Scene.prototype.setScale = function(_newScale, _offset) {
  3144 setScale: function(_newScale, _offset) {
  2985     if (_newScale > Rkns.Renderer._MIN_SCALE && _newScale < Rkns.Renderer._MAX_SCALE) {
  3145     if ((_newScale/this.initialScale) > _MIN_SCALE && (_newScale/this.initialScale) < _MAX_SCALE) {
  2986         this.scale = _newScale;
  3146         this.scale = _newScale;
  2987         if (_offset) {
  3147         if (_offset) {
  2988             this.offset = _offset;
  3148             this.offset = _offset;
  2989         }
  3149         }
  2990         this.redraw();
  3150         this.redraw();
  2991     }
  3151     }
  2992 };
  3152 },
  2993 
  3153 autoScale: function() {
  2994 Rkns.Renderer.Scene.prototype.autoScale = function() {
       
  2995     var nodes = this.renkan.project.get("nodes");
  3154     var nodes = this.renkan.project.get("nodes");
  2996     if (nodes.length > 1) {
  3155     if (nodes.length > 1) {
  2997         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  3156         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  2998             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  3157             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  2999             _minx = Math.min.apply(Math, _xx),
  3158             _minx = Math.min.apply(Math, _xx),
  3000             _miny = Math.min.apply(Math, _yy),
  3159             _miny = Math.min.apply(Math, _yy),
  3001             _maxx = Math.max.apply(Math, _xx),
  3160             _maxx = Math.max.apply(Math, _xx),
  3002             _maxy = Math.max.apply(Math, _yy);
  3161             _maxy = Math.max.apply(Math, _yy);
  3003         var _scale = Math.max(Rkns.Renderer._MIN_SCALE, Math.min(Rkns.Renderer._MAX_SCALE, (paper.view.size.width - 2 * this.renkan.options.autoscale_padding) / (_maxx - _minx), (paper.view.size.height - 2 * this.renkan.options.autoscale_padding) / (_maxy - _miny)));
  3162         var _scale = Math.min( (paper.view.size.width - 2 * this.renkan.options.autoscale_padding) / (_maxx - _minx), (paper.view.size.height - 2 * this.renkan.options.autoscale_padding) / (_maxy - _miny));
       
  3163         this.initialScale = _scale;
  3004         this.setScale(_scale, paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale)));
  3164         this.setScale(_scale, paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale)));
  3005     }
  3165     }
  3006     if (nodes.length === 1) {
  3166     if (nodes.length === 1) {
  3007         this.setScale(1, paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y])));
  3167         this.setScale(1, paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y])));
  3008     }
  3168     }
  3009 };
  3169 },
  3010 
  3170 redrawMiniframe: function() {
  3011 Rkns.Renderer.Scene.prototype.redrawMiniframe = function() {
       
  3012     var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),
  3171     var topleft = this.toMinimapCoords(this.toModelCoords(new paper.Point([0,0]))),
  3013         bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));
  3172         bottomright = this.toMinimapCoords(this.toModelCoords(paper.view.bounds.bottomRight));
  3014     this.minimap.miniframe.fitBounds(topleft, bottomright);
  3173     this.minimap.miniframe.fitBounds(topleft, bottomright);
  3015 };
  3174 },
  3016 
  3175 rescaleMinimap: function() {
  3017 Rkns.Renderer.Scene.prototype.rescaleMinimap = function() {
       
  3018     var nodes = this.renkan.project.get("nodes");
  3176     var nodes = this.renkan.project.get("nodes");
  3019     if (nodes.length > 1) {
  3177     if (nodes.length > 1) {
  3020         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  3178         var _xx = nodes.map(function(_node) { return _node.get("position").x; }),
  3021             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  3179             _yy = nodes.map(function(_node) { return _node.get("position").y; }),
  3022             _minx = Math.min.apply(Math, _xx),
  3180             _minx = Math.min.apply(Math, _xx),
  3035     if (nodes.length === 1) {
  3193     if (nodes.length === 1) {
  3036         this.minimap.scale = .1;
  3194         this.minimap.scale = .1;
  3037         this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]).multiply(this.minimap.scale));
  3195         this.minimap.offset = this.minimap.size.divide(2).subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]).multiply(this.minimap.scale));
  3038     }
  3196     }
  3039     this.redraw();
  3197     this.redraw();
  3040 };
  3198 },
  3041 
  3199 toPaperCoords: function(_point) {
  3042 Rkns.Renderer.Scene.prototype.toPaperCoords = function(_point) {
       
  3043     return _point.multiply(this.scale).add(this.offset);
  3200     return _point.multiply(this.scale).add(this.offset);
  3044 };
  3201 },
  3045 
  3202 toMinimapCoords: function(_point) {
  3046 Rkns.Renderer.Scene.prototype.toMinimapCoords = function(_point) {
       
  3047     return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft);
  3203     return _point.multiply(this.minimap.scale).add(this.minimap.offset).add(this.minimap.topleft);
  3048 };
  3204 },
  3049 
  3205 toModelCoords: function(_point) {
  3050 Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) {
       
  3051     return _point.subtract(this.offset).divide(this.scale);
  3206     return _point.subtract(this.offset).divide(this.scale);
  3052 };
  3207 },
  3053 
  3208 addRepresentation: function(_type, _model) {
  3054 Rkns.Renderer.Scene.prototype.addRepresentation = function(_type, _model) {
  3209     var _repr = new Renderer[_type](this, _model);
  3055     var _repr = new Rkns.Renderer[_type](this, _model);
       
  3056     this.representations.push(_repr);
  3210     this.representations.push(_repr);
  3057     return _repr;
  3211     return _repr;
  3058 };
  3212 },
  3059 
  3213 addRepresentations: function(_type, _collection) {
  3060 Rkns.Renderer.Scene.prototype.addRepresentations = function(_type, _collection) {
       
  3061     var _this = this;
  3214     var _this = this;
  3062     _collection.forEach(function(_model) {
  3215     _collection.forEach(function(_model) {
  3063         _this.addRepresentation(_type, _model);
  3216         _this.addRepresentation(_type, _model);
  3064     });
  3217     });
  3065 };
  3218 },
  3066 
  3219 userTemplate: _.template(
  3067 Rkns.Renderer.Scene.prototype.userTemplate = Rkns._.template(
       
  3068     '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
  3220     '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
  3069 );
  3221 ),
  3070 
  3222 redrawUsers: function() {
  3071 Rkns.Renderer.Scene.prototype.addUser = function(_user) {
  3223     if (!this.renkan.options.show_user_list) {
  3072     if (_user.get("_id") === this.renkan.current_user) {
  3224         return;
  3073         this.$.find(".Rk-CurrentUser-Name").text(_user.get("title"));
  3225     }
  3074         this.$.find(".Rk-CurrentUser-Color").css("background", _user.get("color"));
  3226     var allUsers = [].concat((this.renkan.project.current_user_list || {}).models || [], (this.renkan.project.get("users") || {}).models || []),
  3075     } else {
  3227         ulistHtml = '',
  3076         this.$.find(".Rk-UserList").append(
  3228         $userpanel = this.$.find(".Rk-Users"),
  3077             Rkns.$(
  3229         $name = $userpanel.find(".Rk-CurrentUser-Name"),
  3078                 this.userTemplate({
  3230         $cpwrapper = $userpanel.find(".Rk-Edit-ColorPicker-Wrapper"),
  3079                     name: _user.get("title"),
  3231         $cpitems = $userpanel.find(".Rk-Edit-ColorPicker li"),
  3080                     background: _user.get("color")
  3232         $colorsquare = $userpanel.find(".Rk-CurrentUser-Color"),
  3081                 })
  3233         _this = this;
  3082             )
  3234     $name.off("click").text(this.renkan.translate("<unknown user>"));
  3083         );
  3235     $cpitems.off("mouseleave click");
  3084     }
  3236     allUsers.forEach(function(_user) {
  3085 };
  3237         if (_user.get("_id") === _this.renkan.current_user) {
  3086 
  3238             $name.text(_user.get("title"));
  3087 Rkns.Renderer.Scene.prototype.removeRepresentation = function(_representation) {
  3239             $colorsquare.css("background", _user.get("color"));
       
  3240             if (_this.isEditable()) {
       
  3241                 
       
  3242                 if (_this.renkan.options.user_name_editable) {
       
  3243                     $name.click(function() {
       
  3244                         var $this = $(this),
       
  3245                             $input = $('<input>').val(_user.get("title")).blur(function() {
       
  3246                                 _user.set("title", $(this).val());
       
  3247                                 _this.redrawUsers();
       
  3248                                 _this.redraw();
       
  3249                             });
       
  3250                         $this.empty().html($input);
       
  3251                         $input.select();
       
  3252                     });
       
  3253                 }
       
  3254                 
       
  3255                 if (_this.renkan.options.user_color_editable) {
       
  3256                     $cpitems.click(
       
  3257                         function(_e) {
       
  3258                             _e.preventDefault();
       
  3259                             if (_this.isEditable()) {
       
  3260                                 _user.set("color", $(this).attr("data-color"));
       
  3261                             }
       
  3262                             $(this).parent().hide();
       
  3263                         }
       
  3264                     ).mouseleave(function() {
       
  3265                         $colorsquare.css("background", _user.get("color"));
       
  3266                     });
       
  3267                 }
       
  3268             }
       
  3269             
       
  3270         } else {
       
  3271             ulistHtml += _this.userTemplate({
       
  3272                 name: _user.get("title"),
       
  3273                 background: _user.get("color")
       
  3274             });
       
  3275         }
       
  3276     });
       
  3277     $userpanel.find(".Rk-UserList").html(ulistHtml);
       
  3278 },
       
  3279 removeRepresentation: function(_representation) {
  3088     _representation.destroy();
  3280     _representation.destroy();
  3089     this.representations = Rkns._(this.representations).reject(
  3281     this.representations = _(this.representations).reject(
  3090         function(_repr) {
  3282         function(_repr) {
  3091             return _repr == _representation;
  3283             return _repr == _representation;
  3092         }
  3284         }
  3093     );
  3285     );
  3094 };
  3286 },
  3095 
  3287 getRepresentationByModel: function(_model) {
  3096 Rkns.Renderer.Scene.prototype.getRepresentationByModel = function(_model) {
       
  3097     if (!_model) {
  3288     if (!_model) {
  3098         return undefined;
  3289         return undefined;
  3099     }
  3290     }
  3100     return Rkns._(this.representations).find(function(_repr) {
  3291     return _(this.representations).find(function(_repr) {
  3101         return _repr.model === _model;
  3292         return _repr.model === _model;
  3102     });
  3293     });
  3103 };
  3294 },
  3104 
  3295 removeRepresentationsOfType: function(_type) {
  3105 Rkns.Renderer.Scene.prototype.removeRepresentationsOfType = function(_type) {
  3296     var _representations = _(this.representations).filter(function(_repr) {
  3106     var _representations = Rkns._(this.representations).filter(function(_repr) {
       
  3107             return _repr.type == _type;
  3297             return _repr.type == _type;
  3108         }),
  3298         }),
  3109         _this = this;
  3299         _this = this;
  3110     Rkns._(_representations).each(function(_repr) {
  3300     _(_representations).each(function(_repr) {
  3111         _this.removeRepresentation(_repr);
  3301         _this.removeRepresentation(_repr);
  3112     });
  3302     });
  3113 };
  3303 },
  3114 
  3304 highlightModel: function(_model) {
  3115 Rkns.Renderer.Scene.prototype.highlightModel = function(_model) {
       
  3116     var _repr = this.getRepresentationByModel(_model);
  3305     var _repr = this.getRepresentationByModel(_model);
  3117     if (_repr) {
  3306     if (_repr) {
  3118         _repr.highlight();
  3307         _repr.highlight();
  3119     }
  3308     }
  3120 };
  3309 },
  3121 
  3310 unhighlightAll: function(_model) {
  3122 Rkns.Renderer.Scene.prototype.unhighlightAll = function(_model) {
  3311     _(this.representations).each(function(_repr) {
  3123     Rkns._(this.representations).each(function(_repr) {
       
  3124         _repr.unhighlight();
  3312         _repr.unhighlight();
  3125     });
  3313     });
  3126 };
  3314 },
  3127 
  3315 unselectAll: function(_model) {
  3128 Rkns.Renderer.Scene.prototype.unselectAll = function(_model) {
  3316     _(this.representations).each(function(_repr) {
  3129     Rkns._(this.representations).each(function(_repr) {
       
  3130         _repr.unselect();
  3317         _repr.unselect();
  3131     });
  3318     });
  3132 };
  3319 },
  3133 
  3320 redraw: function() {
  3134 Rkns.Renderer.Scene.prototype.redraw = function() {
  3321     _(this.representations).each(function(_representation) {
  3135     Rkns._(this.representations).each(function(_representation) {
       
  3136         _representation.redraw(true);
  3322         _representation.redraw(true);
  3137     });
  3323     });
  3138     if (this.minimap) {
  3324     if (this.minimap) {
  3139         this.redrawMiniframe();
  3325         this.redrawMiniframe();
  3140     }
  3326     }
  3141     paper.view.draw();
  3327     paper.view.draw();
  3142 };
  3328 },
  3143 
  3329 addTempEdge: function(_from, _point) {
  3144 Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) {
       
  3145     var _tmpEdge = this.addRepresentation("TempEdge",null);
  3330     var _tmpEdge = this.addRepresentation("TempEdge",null);
  3146     _tmpEdge.end_pos = _point;
  3331     _tmpEdge.end_pos = _point;
  3147     _tmpEdge.from_representation = _from;
  3332     _tmpEdge.from_representation = _from;
  3148     _tmpEdge.redraw();
  3333     _tmpEdge.redraw();
  3149     this.click_target = _tmpEdge;
  3334     this.click_target = _tmpEdge;
  3150 };
  3335 },
  3151 
  3336 findTarget: function(_hitResult) {
  3152 Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) {
       
  3153     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  3337     if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  3154         var _newTarget = _hitResult.item.__representation;
  3338         var _newTarget = _hitResult.item.__representation;
  3155         if (this.selected_target !== _hitResult.item.__representation) {
  3339         if (this.selected_target !== _hitResult.item.__representation) {
  3156             if (this.selected_target) {
  3340             if (this.selected_target) {
  3157                 this.selected_target.unselect(_newTarget);
  3341                 this.selected_target.unselect(_newTarget);
  3163         if (this.selected_target) {
  3347         if (this.selected_target) {
  3164             this.selected_target.unselect();
  3348             this.selected_target.unselect();
  3165         }
  3349         }
  3166         this.selected_target = null;
  3350         this.selected_target = null;
  3167     }
  3351     }
  3168 };
  3352 },
  3169 
  3353 paperShift: function(_delta) {
  3170 Rkns.Renderer.Scene.prototype.paperShift = function(_delta) {
       
  3171     this.offset = this.offset.add(_delta);
  3354     this.offset = this.offset.add(_delta);
  3172     this.redraw();
  3355     this.redraw();
  3173 };
  3356 },
  3174 
  3357 onMouseMove: function(_event) {
  3175 Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) {
       
  3176     var _off = this.canvas_$.offset(),
  3358     var _off = this.canvas_$.offset(),
  3177         _point = new paper.Point([
  3359         _point = new paper.Point([
  3178             _event.pageX - _off.left,
  3360             _event.pageX - _off.left,
  3179             _event.pageY - _off.top
  3361             _event.pageY - _off.top
  3180         ]),
  3362         ]),
  3181         _delta = _point.subtract(this.last_point);
  3363         _delta = _point.subtract(this.last_point);
  3182     this.last_point = _point;
  3364     this.last_point = _point;
  3183     if (!this.is_dragging && this.mouse_down && _delta.length > Rkns.Renderer._MIN_DRAG_DISTANCE) {
  3365     if (!this.is_dragging && this.mouse_down && _delta.length > _MIN_DRAG_DISTANCE) {
  3184         this.is_dragging = true;
  3366         this.is_dragging = true;
  3185     }
  3367     }
  3186     var _hitResult = paper.project.hitTest(_point);
  3368     var _hitResult = paper.project.hitTest(_point);
  3187     if (this.is_dragging) {
  3369     if (this.is_dragging) {
  3188         if (this.click_target && typeof this.click_target.paperShift === "function") {
  3370         if (this.click_target && typeof this.click_target.paperShift === "function") {
  3192         }
  3374         }
  3193     } else {
  3375     } else {
  3194         this.findTarget(_hitResult);
  3376         this.findTarget(_hitResult);
  3195     }
  3377     }
  3196     paper.view.draw();
  3378     paper.view.draw();
  3197 };
  3379 },
  3198 
  3380 onMouseDown: function(_event, _isTouch) {
  3199 Rkns.Renderer.Scene.prototype.onMouseDown = function(_event, _isTouch) {
       
  3200     var _off = this.canvas_$.offset(),
  3381     var _off = this.canvas_$.offset(),
  3201         _point = new paper.Point([
  3382         _point = new paper.Point([
  3202             _event.pageX - _off.left,
  3383             _event.pageX - _off.left,
  3203             _event.pageY - _off.top
  3384             _event.pageY - _off.top
  3204         ]);
  3385         ]);
  3211         if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  3392         if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
  3212             this.click_target = _hitResult.item.__representation;
  3393             this.click_target = _hitResult.item.__representation;
  3213             this.click_target.mousedown(_event, _isTouch);
  3394             this.click_target.mousedown(_event, _isTouch);
  3214         } else {
  3395         } else {
  3215             this.click_target = null;
  3396             this.click_target = null;
  3216             if (this.isEditable() && this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
  3397             if (this.isEditable() && this.click_mode === _CLICKMODE_ADDNODE) {
  3217                 var _coords = this.toModelCoords(_point),
  3398                 var _coords = this.toModelCoords(_point),
  3218                     _data = {
  3399                     _data = {
  3219                         id: Rkns.Utils.getUID('node'),
  3400                         id: Rkns.Utils.getUID('node'),
  3220                         created_by: this.renkan.current_user,
  3401                         created_by: this.renkan.current_user,
  3221                         position: {
  3402                         position: {
  3227                 this.getRepresentationByModel(_node).openEditor();
  3408                 this.getRepresentationByModel(_node).openEditor();
  3228             }
  3409             }
  3229         }
  3410         }
  3230     }
  3411     }
  3231     if (this.click_mode) {
  3412     if (this.click_mode) {
  3232         if (this.isEditable() && this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
  3413         if (this.isEditable() && this.click_mode === _CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
  3233             this.removeRepresentationsOfType("editor");
  3414             this.removeRepresentationsOfType("editor");
  3234             this.addTempEdge(this.click_target, _point);
  3415             this.addTempEdge(this.click_target, _point);
  3235             this.click_mode = Rkns.Renderer._CLICKMODE_ENDEDGE;
  3416             this.click_mode = _CLICKMODE_ENDEDGE;
  3236             this.notif_$.fadeOut(function() {
  3417             this.notif_$.fadeOut(function() {
  3237                 Rkns.$(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
  3418                 $(this).html(_renkan.translate("Click on a second node to complete the edge")).fadeIn();
  3238             });
  3419             });
  3239         } else {
  3420         } else {
  3240             this.notif_$.hide();
  3421             this.notif_$.hide();
  3241             this.click_mode = false;
  3422             this.click_mode = false;
  3242         }
  3423         }
  3243     }
  3424     }
  3244     paper.view.draw();
  3425     paper.view.draw();
  3245 };
  3426 },
  3246 
  3427 onMouseUp: function(_event, _isTouch) {
  3247 Rkns.Renderer.Scene.prototype.onMouseUp = function(_event, _isTouch) {
       
  3248     this.mouse_down = false;
  3428     this.mouse_down = false;
  3249     if (this.click_target) {
  3429     if (this.click_target) {
  3250         var _off = this.canvas_$.offset();
  3430         var _off = this.canvas_$.offset();
  3251         this.click_target.mouseup(
  3431         this.click_target.mouseup(
  3252             {
  3432             {
  3263         if (_isTouch) {
  3443         if (_isTouch) {
  3264             this.unselectAll();
  3444             this.unselectAll();
  3265         }
  3445         }
  3266     }
  3446     }
  3267     paper.view.draw();
  3447     paper.view.draw();
  3268 };
  3448 },
  3269 
  3449 onScroll: function(_event, _scrolldelta) {
  3270 Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) {
       
  3271     this.totalScroll += _scrolldelta;
  3450     this.totalScroll += _scrolldelta;
  3272     if (Math.abs(this.totalScroll) >= 1) {
  3451     if (Math.abs(this.totalScroll) >= 1) {
  3273         var _off = this.canvas_$.offset(),
  3452         var _off = this.canvas_$.offset(),
  3274             _delta = new paper.Point([
  3453             _delta = new paper.Point([
  3275                 _event.pageX - _off.left,
  3454                 _event.pageX - _off.left,
  3280         } else {
  3459         } else {
  3281             this.setScale( this.scale * Math.SQRT1_2, this.offset.add(_delta.divide(Math.SQRT2)));
  3460             this.setScale( this.scale * Math.SQRT1_2, this.offset.add(_delta.divide(Math.SQRT2)));
  3282         }
  3461         }
  3283         this.totalScroll = 0;
  3462         this.totalScroll = 0;
  3284     }
  3463     }
  3285 };
  3464 },
  3286 
  3465 onDoubleClick: function(_event) {
  3287 Rkns.Renderer.Scene.prototype.onDoubleClick = function(_event) {
       
  3288     if (!this.isEditable()) {
  3466     if (!this.isEditable()) {
  3289         return;
  3467         return;
  3290     }
  3468     }
  3291     var _off = this.canvas_$.offset(),
  3469     var _off = this.canvas_$.offset(),
  3292         _point = new paper.Point([
  3470         _point = new paper.Point([
  3301                 created_by: this.renkan.current_user,
  3479                 created_by: this.renkan.current_user,
  3302                 position: {
  3480                 position: {
  3303                     x: _coords.x,
  3481                     x: _coords.x,
  3304                     y: _coords.y
  3482                     y: _coords.y
  3305                 }
  3483                 }
  3306             };
  3484             },
  3307             _node = this.renkan.project.addNode(_data);
  3485             _node = this.renkan.project.addNode(_data);
  3308             this.getRepresentationByModel(_node).openEditor();
  3486         this.getRepresentationByModel(_node).openEditor();
  3309     }
  3487     }
  3310     paper.view.draw();
  3488     paper.view.draw();
  3311 };
  3489 },
  3312 
  3490 dropData: function(_data, _event) {
  3313 Rkns.Renderer.Scene.prototype.dropData = function(_data, _event) {
       
  3314     if (!this.isEditable()) {
  3491     if (!this.isEditable()) {
  3315         return;
  3492         return;
  3316     }
  3493     }
  3317     if (_data["text/json"] || _data["application/json"]) {
  3494     if (_data["text/json"] || _data["application/json"]) {
  3318         try {
  3495         try {
  3322         catch(e) {}
  3499         catch(e) {}
  3323     }
  3500     }
  3324     var newNode = {};
  3501     var newNode = {};
  3325     switch(_data["text/x-iri-specific-site"]) {
  3502     switch(_data["text/x-iri-specific-site"]) {
  3326         case "twitter":
  3503         case "twitter":
  3327             var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]),
  3504             var snippet = $('<div>').html(_data["text/x-iri-selected-html"]),
  3328                 tweetdiv = snippet.find(".tweet");
  3505                 tweetdiv = snippet.find(".tweet");
  3329             newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
  3506             newNode.title = _renkan.translate("Tweet by ") + tweetdiv.attr("data-name");
  3330             newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
  3507             newNode.uri = "http://twitter.com/" + tweetdiv.attr("data-screen-name") + "/status/" + tweetdiv.attr("data-tweet-id");
  3331             newNode.image = tweetdiv.find(".avatar").attr("src");
  3508             newNode.image = tweetdiv.find(".avatar").attr("src");
  3332             newNode.description = tweetdiv.find(".js-tweet-text:first").text();
  3509             newNode.description = tweetdiv.find(".js-tweet-text:first").text();
  3333         break;
  3510         break;
  3334         case "google":
  3511         case "google":
  3335             var snippet = Rkns.$('<div>').html(_data["text/x-iri-selected-html"]);
  3512             var snippet = $('<div>').html(_data["text/x-iri-selected-html"]);
  3336             newNode.title = snippet.find("h3:first").text().trim();
  3513             newNode.title = snippet.find("h3:first").text().trim();
  3337             newNode.uri = snippet.find("h3 a").attr("href");
  3514             newNode.uri = snippet.find("h3 a").attr("href");
  3338             newNode.description = snippet.find(".st:first").text().trim();
  3515             newNode.description = snippet.find(".st:first").text().trim();
  3339         break;
  3516         break;
  3340         case undefined:
  3517         case undefined:
  3344             }
  3521             }
  3345             if (_data["text/plain"] || _data["text/x-iri-selected-text"]) {
  3522             if (_data["text/plain"] || _data["text/x-iri-selected-text"]) {
  3346                 newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
  3523                 newNode.description = (_data["text/plain"] || _data["text/x-iri-selected-text"]).replace(/[\s\n]+/gm,' ').trim();
  3347             }
  3524             }
  3348             if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
  3525             if (_data["text/html"] || _data["text/x-iri-selected-html"]) {
  3349                 var snippet = Rkns.$('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
  3526                 var snippet = $('<div>').html(_data["text/html"] || _data["text/x-iri-selected-html"]);
  3350                 var _svgimgs = snippet.find("image");
  3527                 var _svgimgs = snippet.find("image");
  3351                 if (_svgimgs.length) {
  3528                 if (_svgimgs.length) {
  3352                     newNode.image = _svgimgs.attr("xlink:href");
  3529                     newNode.image = _svgimgs.attr("xlink:href");
  3353                 }
  3530                 }
  3354                 var _svgpaths = snippet.find("path");
  3531                 var _svgpaths = snippet.find("path");
  3422     var _node = this.renkan.project.addNode(_nodedata),
  3599     var _node = this.renkan.project.addNode(_nodedata),
  3423         _repr = this.getRepresentationByModel(_node);
  3600         _repr = this.getRepresentationByModel(_node);
  3424     if (_event.type === "drop") {
  3601     if (_event.type === "drop") {
  3425         _repr.openEditor();
  3602         _repr.openEditor();
  3426     }
  3603     }
  3427 };
  3604 },
  3428 
  3605 fullScreen: function() {
  3429           /* *********************************************************
  3606     var _isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen,
  3430                           end of        paper-renderer.js
  3607         _el = this.renkan.$[0],
  3431           ************************************************************
  3608         _requestMethods = ["requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen"],
  3432           ************************************************************
  3609         _cancelMethods = ["cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen"];
  3433                           start of      full-json.js
  3610     if (_isFull) {
  3434           ********************************************************* */
  3611         for (var i = 0; i < _cancelMethods.length; i++) {
  3435 
  3612             if (typeof document[_cancelMethods[i]] === "function") {
       
  3613                 document[_cancelMethods[i]]();
       
  3614                 break;
       
  3615             }
       
  3616         }
       
  3617     } else {
       
  3618         for (var i = 0; i < _requestMethods.length; i++) {
       
  3619             if (typeof _el[_requestMethods[i]] === "function") {
       
  3620                 _el[_requestMethods[i]]();
       
  3621                 break;
       
  3622             }
       
  3623         }
       
  3624     }
       
  3625 },
       
  3626 zoomOut: function() {
       
  3627     var _newScale = this.scale * Math.SQRT1_2,
       
  3628         _offset = new paper.Point([
       
  3629             this.canvas_$.width(),
       
  3630             this.canvas_$.height()
       
  3631         ]).multiply( .5 * ( 1 - Math.SQRT1_2 ) ).add(this.offset.multiply( Math.SQRT1_2 ));
       
  3632     this.setScale( _newScale, _offset );
       
  3633 },
       
  3634 zoomIn: function() {
       
  3635     var _newScale = this.scale * Math.SQRT2,
       
  3636         _offset = new paper.Point([
       
  3637             this.canvas_$.width(),
       
  3638             this.canvas_$.height()
       
  3639         ]).multiply( .5 * ( 1 - Math.SQRT2 ) ).add(this.offset.multiply( Math.SQRT2 ));
       
  3640     this.setScale( _newScale, _offset );
       
  3641 },
       
  3642 addNodeBtn: function() {
       
  3643     if (this.click_mode === _CLICKMODE_ADDNODE) {
       
  3644         this.click_mode = false;
       
  3645         this.notif_$.hide();
       
  3646     } else {
       
  3647         this.click_mode = _CLICKMODE_ADDNODE;
       
  3648         this.notif_$.text(this.renkan.translate("Click on the background canvas to add a node")).fadeIn();
       
  3649     }
       
  3650     return false;
       
  3651 },
       
  3652 addEdgeBtn: function() {
       
  3653     if (this.click_mode === _CLICKMODE_STARTEDGE || this.click_mode === _CLICKMODE_ENDEDGE) {
       
  3654         this.click_mode = false;
       
  3655         this.notif_$.hide();
       
  3656     } else {
       
  3657         this.click_mode = _CLICKMODE_STARTEDGE;
       
  3658         this.notif_$.text(this.renkan.translate("Click on a first node to start the edge")).fadeIn();
       
  3659     }
       
  3660     return false;
       
  3661 },
       
  3662 foldBins: function() {
       
  3663     var foldBinsButton = this.$.find(".Rk-Fold-Bins"),
       
  3664         bins = this.renkan.$.find(".Rk-Bins");
       
  3665     if (bins.offset().left < 0) {
       
  3666         bins.animate({left: 0},250);
       
  3667         var _this = this;
       
  3668         this.$.animate({left: 300},250,function() {
       
  3669             var w = _this.$.width();
       
  3670             paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
       
  3671         });
       
  3672         foldBinsButton.html("&laquo;");
       
  3673     } else {
       
  3674         bins.animate({left: -300},250);
       
  3675         var _this = this;
       
  3676         this.$.animate({left: 0},250,function() {
       
  3677             var w = _this.$.width();
       
  3678             paper.view.viewSize = new paper.Size([w, _this.canvas_$.height()]);
       
  3679         });
       
  3680         foldBinsButton.html("&raquo;");
       
  3681     }
       
  3682 },
       
  3683 save: function() { },
       
  3684 open: function() { }
       
  3685 });
       
  3686 })(window);
       
  3687 
       
  3688 /* END paper-renderer.js */
  3436 /* Saves the Full JSON at each modification */
  3689 /* Saves the Full JSON at each modification */
  3437 
  3690 
  3438 Rkns.jsonIO = function(_renkan, _opts) {
  3691 Rkns.jsonIO = function(_renkan, _opts) {
  3439     var _proj = _renkan.project;
  3692     var _proj = _renkan.project;
  3440     if (typeof _opts.http_method == "undefined") {
  3693     if (typeof _opts.http_method == "undefined") {
  3474         _thrSave();
  3727         _thrSave();
  3475     });
  3728     });
  3476         
  3729         
  3477     _load();
  3730     _load();
  3478 };
  3731 };
  3479 
  3732 (function(Rkns) {
  3480           /* *********************************************************
  3733 "use strict";
  3481                           end of        full-json.js
  3734 
  3482           ************************************************************
  3735 var _ = Rkns._;
  3483           */
  3736 
       
  3737 var Ldt = Rkns.Ldt = {};
       
  3738 
       
  3739 var Bin = Ldt.Bin = function(_renkan, _opts) {
       
  3740     if (_opts.ldt_type) {
       
  3741         var resclass = Ldt[_opts.ldt_type+"Bin"];
       
  3742         if (resclass) {
       
  3743             return new resclass(_renkan, _opts);
       
  3744         }
       
  3745     }
       
  3746     console.error("No such LDT Bin Type");
       
  3747 };
       
  3748 
       
  3749 var ProjectBin = Ldt.ProjectBin = Rkns.Utils.inherit(Rkns._BaseBin);
       
  3750 
       
  3751 ProjectBin.prototype.tagTemplate = _.template(
       
  3752     '<li class="Rk-Bin-Item" draggable="true" data-image="<%- Rkns.Utils.getFullURL(static_url+\'img/ldt-tag.png\') %>" data-uri="<%=ldt_platform%>ldtplatform/ldt/front/search/?search=<%=encodedtitle%>&field=all" data-title="<%-title%>" data-description="Tag \'<%-title%>\'">'
       
  3753     + '<img class="Rk-Ldt-Tag-Icon" src="<%-static_url%>img/ldt-tag.png" /><h4><%=htitle%></h4><div class="Rk-Clear"></div></li>'
       
  3754 );
       
  3755 
       
  3756 ProjectBin.prototype.annotationTemplate = _.template(
       
  3757     '<li class="Rk-Bin-Item" draggable="true" data-image="<%- Rkns.Utils.getFullURL(image) %>" data-uri="<%=ldt_platform%>ldtplatform/ldt/front/player/<%=mediaid%>/#id=<%=annotationid%>" data-title="<%-title%>" data-description="<%-description%>">'
       
  3758     + '<img class="Rk-Ldt-Annotation-Icon" src="<%=image%>"/><h4><%=htitle%></h4><p><%=hdescription%></p><p>Start: <%=start%>, End: <%=end%>, Duration: <%=duration%></p><div class="Rk-Clear"></div></li>'
       
  3759 );
       
  3760 
       
  3761 ProjectBin.prototype._init = function(_renkan, _opts) {
       
  3762     this.renkan = _renkan;
       
  3763     this.proj_id = _opts.project_id;
       
  3764     this.ldt_platform = _opts.ldt_platform || "http://ldt.iri.centrepompidou.fr/";
       
  3765     this.title_$.html(_opts.title);
       
  3766     this.title_icon_$.addClass('Rk-Ldt-Title-Icon');
       
  3767     this.refresh();
       
  3768 };
       
  3769 
       
  3770 ProjectBin.prototype.render = function(searchbase) {
       
  3771     var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
       
  3772     function highlight(_text) {
       
  3773         var _e = _(_text).escape();
       
  3774         return search.isempty ? _e : search.replace(_e, "<span class='searchmatch'>$1</span>");
       
  3775     }
       
  3776     function convertTC(_ms) {
       
  3777         function pad(_n) {
       
  3778             var _res = _n.toString();
       
  3779             while (_res.length < 2) {
       
  3780                 _res = '0' + _res;
       
  3781             }
       
  3782             return _res;
       
  3783         }
       
  3784         var _totalSeconds = Math.abs(Math.floor(_ms/1000)),
       
  3785             _hours = Math.floor(_totalSeconds / 3600),
       
  3786             _minutes = (Math.floor(_totalSeconds / 60) % 60),
       
  3787             _seconds = _totalSeconds % 60,
       
  3788             _res = '';
       
  3789         if (_hours) {
       
  3790             _res += pad(_hours) + ':';
       
  3791         }
       
  3792         _res += pad(_minutes) + ':' + pad(_seconds);
       
  3793         return _res;
       
  3794     }
       
  3795     
       
  3796     var _html = '<li><h3>Tags</h3></li>',
       
  3797         _projtitle = this.data.meta["dc:title"],
       
  3798         _this = this,
       
  3799         count = 0;
       
  3800     _this.title_$.text('LDT Project: "' + _projtitle + '"');
       
  3801     _(_this.data.tags).map(function(_tag) {
       
  3802         var _title = _tag.meta["dc:title"];
       
  3803         if (!search.isempty && !search.test(_title)) {
       
  3804             return;
       
  3805         }
       
  3806         count++;
       
  3807         _html += _this.tagTemplate({
       
  3808             ldt_platform: _this.ldt_platform,
       
  3809             title: _title,
       
  3810             htitle: highlight(_title),
       
  3811             encodedtitle : encodeURIComponent(_title),
       
  3812             static_url: _this.renkan.options.static_url
       
  3813         });
       
  3814     });
       
  3815     _html += '<li><h3>Annotations</h3></li>';
       
  3816     _(_this.data.annotations).map(function(_annotation) {
       
  3817         var _description = _annotation.content.description,
       
  3818             _title = _annotation.content.title.replace(_description,"");
       
  3819         if (!search.isempty && !search.test(_title) && !search.test(_description)) {
       
  3820             return;
       
  3821         }
       
  3822         count++;
       
  3823         var _duration = _annotation.end - _annotation.begin,
       
  3824             _img = (
       
  3825                 (_annotation.content && _annotation.content.img && _annotation.content.img.src)
       
  3826                 ? _annotation.content.img.src
       
  3827                 : ( _duration ? _this.renkan.options.static_url+"img/ldt-segment.png" : _this.renkan.options.static_url+"img/ldt-point.png" )
       
  3828             );
       
  3829         _html += _this.annotationTemplate({
       
  3830             ldt_platform: _this.ldt_platform,
       
  3831             title: _title,
       
  3832             htitle: highlight(_title),
       
  3833             description: _description,
       
  3834             hdescription: highlight(_description),
       
  3835             start: convertTC(_annotation.begin),
       
  3836             end: convertTC(_annotation.end),
       
  3837             duration: convertTC(_duration),
       
  3838             mediaid: _annotation.media,
       
  3839             annotationid: _annotation.id,
       
  3840             image: _img,
       
  3841             static_url: _this.renkan.options.static_url
       
  3842         });
       
  3843     });
       
  3844     
       
  3845     this.main_$.html(_html);
       
  3846     if (!search.isempty && count) {
       
  3847         this.count_$.text(count).show();
       
  3848     } else {
       
  3849         this.count_$.hide();
       
  3850     }
       
  3851     if (!search.isempty && !count) {
       
  3852         this.$.hide();
       
  3853     } else {
       
  3854         this.$.show();
       
  3855     }
       
  3856     this.renkan.resizeBins();
       
  3857 };
       
  3858 
       
  3859 ProjectBin.prototype.refresh = function() {
       
  3860     var _this = this;
       
  3861     Rkns.$.ajax({
       
  3862         url: this.ldt_platform + 'ldtplatform/ldt/cljson/id/' + this.proj_id,
       
  3863         dataType: "jsonp",
       
  3864         success: function(_data) {
       
  3865             _this.data = _data;
       
  3866             _this.render();
       
  3867         }
       
  3868     });
       
  3869 };
       
  3870 
       
  3871 var Search = Ldt.Search = function(_renkan, _opts) {
       
  3872     this.renkan = _renkan;
       
  3873     this.lang = _opts.lang || "en";
       
  3874 };
       
  3875 
       
  3876 Search.prototype.getBgClass = function() {
       
  3877     return "Rk-Ldt-Icon";
       
  3878 };
       
  3879 
       
  3880 Search.prototype.getSearchTitle = function() {
       
  3881     return this.renkan.translate("Lignes de Temps");
       
  3882 };
       
  3883 
       
  3884 Search.prototype.search = function(_q) {
       
  3885     this.renkan.tabs.push(
       
  3886         new ResultsBin(this.renkan, {
       
  3887             search: _q
       
  3888         })
       
  3889     );
       
  3890 };
       
  3891 
       
  3892 var ResultsBin = Ldt.ResultsBin = Rkns.Utils.inherit(Rkns._BaseBin);
       
  3893 
       
  3894 ResultsBin.prototype.segmentTemplate = _.template(
       
  3895     '<li class="Rk-Bin-Item" draggable="true" data-image="<%- Rkns.Utils.getFullURL(image) %>" data-uri="<%=ldt_platform%>ldtplatform/ldt/front/player/<%=mediaid%>/#id=<%=annotationid%>" data-title="<%-title%>" data-description="<%-description%>">'
       
  3896     + '<img class="Rk-Ldt-Annotation-Icon" src="<%=image%>"/><h4><%=htitle%></h4><p><%=hdescription%></p><p>Start: <%=start%>, End: <%=end%>, Duration: <%=duration%></p><div class="Rk-Clear"></div></li>'
       
  3897 );
       
  3898 
       
  3899 ResultsBin.prototype._init = function(_renkan, _opts) {
       
  3900     this.renkan = _renkan;
       
  3901     this.ldt_platform = _opts.ldt_platform || "http://ldt.iri.centrepompidou.fr/";
       
  3902     this.max_results = _opts.max_results || 50;
       
  3903     this.search = _opts.search;
       
  3904     this.title_$.html('Lignes de Temps: "' + _opts.search + '"');
       
  3905     this.title_icon_$.addClass('Rk-Ldt-Title-Icon');
       
  3906     this.refresh();
       
  3907 };
       
  3908 
       
  3909 ResultsBin.prototype.render = function(searchbase) {
       
  3910     if (!this.data) {
       
  3911         return;
       
  3912     }
       
  3913     var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
       
  3914     var highlightrx = (search.isempty ? Rkns.Utils.regexpFromTextOrArray(this.search) : search);
       
  3915     function highlight(_text) {
       
  3916         return highlightrx.replace(_(_text).escape(), "<span class='searchmatch'>$1</span>");
       
  3917     }
       
  3918     function convertTC(_ms) {
       
  3919         function pad(_n) {
       
  3920             var _res = _n.toString();
       
  3921             while (_res.length < 2) {
       
  3922                 _res = '0' + _res;
       
  3923             }
       
  3924             return _res;
       
  3925         }
       
  3926         var _totalSeconds = Math.abs(Math.floor(_ms/1000)),
       
  3927             _hours = Math.floor(_totalSeconds / 3600),
       
  3928             _minutes = (Math.floor(_totalSeconds / 60) % 60),
       
  3929             _seconds = _totalSeconds % 60,
       
  3930             _res = '';
       
  3931         if (_hours) {
       
  3932             _res += pad(_hours) + ':';
       
  3933         }
       
  3934         _res += pad(_minutes) + ':' + pad(_seconds);
       
  3935         return _res;
       
  3936     }
       
  3937     
       
  3938     var _html = '',
       
  3939         _this = this,
       
  3940         count = 0;
       
  3941     _(this.data.objects).each(function(_segment) {
       
  3942         var _description = _segment.abstract,
       
  3943             _title = _segment.title;
       
  3944         if (!search.isempty && !search.test(_title) && !search.test(_description)) {
       
  3945             return;
       
  3946         }
       
  3947         count++;
       
  3948         var _duration = _segment.duration,
       
  3949             _begin = _segment.start_ts,
       
  3950             _end = + _segment.duration + _begin,
       
  3951             _img = (
       
  3952                 _duration
       
  3953                 ? _this.renkan.options.static_url + "img/ldt-segment.png"
       
  3954                 : _this.renkan.options.static_url + "img/ldt-point.png"
       
  3955             );
       
  3956         _html += _this.segmentTemplate({
       
  3957             ldt_platform: _this.ldt_platform,
       
  3958             title: _title,
       
  3959             htitle: highlight(_title),
       
  3960             description: _description,
       
  3961             hdescription: highlight(_description),
       
  3962             start: convertTC(_begin),
       
  3963             end: convertTC(_end),
       
  3964             duration: convertTC(_duration),
       
  3965             mediaid: _segment.iri_id,
       
  3966             //projectid: _segment.project_id,
       
  3967             //cuttingid: _segment.cutting_id,
       
  3968             annotationid: _segment.element_id,
       
  3969             image: _img
       
  3970         });
       
  3971     });
       
  3972     
       
  3973     this.main_$.html(_html);
       
  3974     if (!search.isempty && count) {
       
  3975         this.count_$.text(count).show();
       
  3976     } else {
       
  3977         this.count_$.hide();
       
  3978     }
       
  3979     if (!search.isempty && !count) {
       
  3980         this.$.hide();
       
  3981     } else {
       
  3982         this.$.show();
       
  3983     }
       
  3984     this.renkan.resizeBins();
       
  3985 };
       
  3986 
       
  3987 ResultsBin.prototype.refresh = function() {
       
  3988     var _this = this;
       
  3989     Rkns.$.ajax({
       
  3990         url: this.ldt_platform + 'ldtplatform/api/ldt/1.0/segments/search/',
       
  3991         data: {
       
  3992             format: "jsonp",
       
  3993             q: this.search,
       
  3994             limit: this.max_results
       
  3995         },
       
  3996         dataType: "jsonp",
       
  3997         success: function(_data) {
       
  3998             _this.data = _data;
       
  3999             _this.render();
       
  4000         }
       
  4001     });
       
  4002 };
       
  4003 
       
  4004 })(window.Rkns);
       
  4005 Rkns.ResourceList = {};
       
  4006 
       
  4007 Rkns.ResourceList.Bin = Rkns.Utils.inherit(Rkns._BaseBin);
       
  4008 
       
  4009 Rkns.ResourceList.Bin.prototype.resultTemplate = Rkns._.template(
       
  4010     '<li class="Rk-Bin-Item Rk-ResourceList-Item" draggable="true" data-uri="<%-url%>" '
       
  4011     + 'data-title="<%-title%>" data-description="<%-description%>" '
       
  4012     + '<% if (image) { %>data-image="<%- Rkns.Utils.getFullURL(image) %>"<% } else { %>data-image=""<% } %> >'
       
  4013     + '<% if (image) { %><img class="Rk-ResourceList-Image" src="<%-image%>"/><% } %><h4 class="Rk-ResourceList-Title">'
       
  4014     + '<% if (url) { %><a href="<%-url%>" target="_blank"><% } %><%=htitle%><% if (url) { %></a><% } %></h4>'
       
  4015     + '<% if (description) { %><p class="Rk-ResourceList-Description"><%=hdescription%></p><% } %><% if (image) { %><div style="clear: both;"></div><% } %></li>'
       
  4016 );
       
  4017 
       
  4018 Rkns.ResourceList.Bin.prototype._init = function(_renkan, _opts) {
       
  4019     this.renkan = _renkan;
       
  4020     this.title_$.html(_opts.title);
       
  4021     if (_opts.list) {
       
  4022         this.data = _opts.list;
       
  4023     }
       
  4024     this.refresh();
       
  4025 };
       
  4026 
       
  4027 Rkns.ResourceList.Bin.prototype.render = function(searchbase) {
       
  4028     var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
       
  4029     function highlight(_text) {
       
  4030         var _e = _(_text).escape();
       
  4031         return search.isempty ? _e : search.replace(_e, "<span class='searchmatch'>$1</span>");
       
  4032     }
       
  4033     var _html = "",
       
  4034         _this = this,
       
  4035         count = 0;
       
  4036     Rkns._(this.data).each(function(_item) {
       
  4037         if (typeof _item === "string") {
       
  4038             if (/^(https?:\/\/|www)/.test(_item)) {
       
  4039                 var _element = { url: _item };
       
  4040             } else {
       
  4041                 var _element = { title: _item.replace(/[:,]?\s?(https?:\/\/|www)[\d\w\/.&?=#%-_]+\s?/,'').trim() },
       
  4042                     _match = _item.match(/(https?:\/\/|www)[\d\w\/.&?=#%-_]+/);
       
  4043                 if (_match) {
       
  4044                     _element.url = _match[0];
       
  4045                 }
       
  4046                 if (_element.title.length > 80) {
       
  4047                     _element.description = _element.title;
       
  4048                     _element.title = _element.title.replace(/^(.{30,60})\s.+$/,'$1…');
       
  4049                 }
       
  4050             }
       
  4051         } else {
       
  4052             var _element = _item;
       
  4053         }
       
  4054         var title = _element.title || (_element.url || "").replace(/^https?:\/\/(www\.)?/,'').replace(/^(.{40}).+$/,'$1…'),
       
  4055             url = _element.url || "",
       
  4056             description = _element.description || "",
       
  4057             image = _element.image || "";
       
  4058         if (url && !/^https?:\/\//.test(url)) {
       
  4059             url = 'http://' + url;
       
  4060         }
       
  4061         if (!search.isempty && !search.test(title) && !search.test(description)) {
       
  4062             return;
       
  4063         }
       
  4064         count++;
       
  4065         _html += _this.resultTemplate({
       
  4066             url: url,
       
  4067             title: title,
       
  4068             htitle: highlight(title),
       
  4069             image: image,
       
  4070             description: description,
       
  4071             hdescription: highlight(description),
       
  4072             static_url: _this.renkan.options.static_url
       
  4073         });
       
  4074     });
       
  4075     _this.main_$.html(_html);
       
  4076     if (!search.isempty && count) {
       
  4077         this.count_$.text(count).show();
       
  4078     } else {
       
  4079         this.count_$.hide();
       
  4080     }
       
  4081     if (!search.isempty && !count) {
       
  4082         this.$.hide();
       
  4083     } else {
       
  4084         this.$.show();
       
  4085     }
       
  4086     this.renkan.resizeBins();
       
  4087 };
       
  4088     
       
  4089 Rkns.ResourceList.Bin.prototype.refresh = function() {
       
  4090     if (this.data) {
       
  4091         this.render();
       
  4092     }
       
  4093 };Rkns.Wikipedia = {
       
  4094 };
       
  4095 
       
  4096 Rkns.Wikipedia.Search = function(_renkan, _opts) {
       
  4097     this.renkan = _renkan;
       
  4098     this.lang = _opts.lang || "en";
       
  4099 };
       
  4100 
       
  4101 Rkns.Wikipedia.Search.prototype.getBgClass = function() {
       
  4102     return "Rk-Wikipedia-Search-Icon Rk-Wikipedia-Lang-" + this.lang;
       
  4103 };
       
  4104 
       
  4105 Rkns.Wikipedia.Search.prototype.getSearchTitle = function() {
       
  4106     var langs = {
       
  4107         "fr": "French",
       
  4108         "en": "English",
       
  4109         "ja": "Japanese"
       
  4110     };
       
  4111     if (langs[this.lang]) {
       
  4112         return this.renkan.translate("Wikipedia in ") + this.renkan.translate(langs[this.lang]);
       
  4113     } else {
       
  4114         return this.renkan.translate("Wikipedia") + " [" + this.lang + "]";
       
  4115     }
       
  4116 };
       
  4117 
       
  4118 Rkns.Wikipedia.Search.prototype.search = function(_q) {
       
  4119     this.renkan.tabs.push(
       
  4120         new Rkns.Wikipedia.Bin(this.renkan, {
       
  4121             lang: this.lang,
       
  4122             search: _q
       
  4123         })
       
  4124     );
       
  4125 };
       
  4126 
       
  4127 Rkns.Wikipedia.Bin = Rkns.Utils.inherit(Rkns._BaseBin);
       
  4128 
       
  4129 Rkns.Wikipedia.Bin.prototype.resultTemplate = Rkns._.template(
       
  4130     '<li class="Rk-Wikipedia-Result Rk-Bin-Item" draggable="true" data-uri="<%-url%>" '
       
  4131     + 'data-title="Wikipedia: <%-title%>" data-description="<%-description%>" data-image="<%- Rkns.Utils.getFullURL( static_url + \'img/wikipedia.png\' ) %>">'
       
  4132     + '<img class="Rk-Wikipedia-Icon" src="<%-static_url%>img/wikipedia.png"></div><h4 class="Rk-Wikipedia-Title"><a href="<%-url%>" target="_blank"><%=htitle%></a></h4>'
       
  4133     + '<p class="Rk-Wikipedia-Snippet"><%=hdescription%></p></li>'
       
  4134 );
       
  4135 
       
  4136 Rkns.Wikipedia.Bin.prototype._init = function(_renkan, _opts) {
       
  4137     this.renkan = _renkan;
       
  4138     this.search = _opts.search;
       
  4139     this.lang = _opts.lang || "en";
       
  4140     this.title_icon_$.addClass('Rk-Wikipedia-Title-Icon Rk-Wikipedia-Lang-' + this.lang);
       
  4141     this.title_$.html(this.search).addClass("Rk-Wikipedia-Title");
       
  4142     this.refresh();
       
  4143 };
       
  4144 
       
  4145 Rkns.Wikipedia.Bin.prototype.render = function(searchbase) {
       
  4146     var search = searchbase || Rkns.Utils.regexpFromTextOrArray();
       
  4147     var highlightrx = (search.isempty ? Rkns.Utils.regexpFromTextOrArray(this.search) : search);
       
  4148     function highlight(_text) {
       
  4149         return highlightrx.replace(_(_text).escape(), "<span class='searchmatch'>$1</span>");
       
  4150     }
       
  4151     var _html = "",
       
  4152         _this = this,
       
  4153         count = 0;
       
  4154     Rkns._(this.data.query.search).each(function(_result) {
       
  4155         var title = _result.title,
       
  4156             url = "http://" + _this.lang + ".wikipedia.org/wiki/" + encodeURI(title.replace(/ /g,"_")),
       
  4157             description = Rkns.$('<div>').html(_result.snippet).text();
       
  4158         if (!search.isempty && !search.test(title) && !search.test(description)) {
       
  4159             return;
       
  4160         }
       
  4161         count++;
       
  4162         _html += _this.resultTemplate({
       
  4163             url: url,
       
  4164             title: title,
       
  4165             htitle: highlight(title),
       
  4166             description: description,
       
  4167             hdescription: highlight(description),
       
  4168             static_url: _this.renkan.options.static_url
       
  4169         });
       
  4170     });
       
  4171     _this.main_$.html(_html);
       
  4172     if (!search.isempty && count) {
       
  4173         this.count_$.text(count).show();
       
  4174     } else {
       
  4175         this.count_$.hide();
       
  4176     }
       
  4177     if (!search.isempty && !count) {
       
  4178         this.$.hide();
       
  4179     } else {
       
  4180         this.$.show();
       
  4181     }
       
  4182     this.renkan.resizeBins();
       
  4183 };
       
  4184     
       
  4185 Rkns.Wikipedia.Bin.prototype.refresh = function() {
       
  4186     var _this = this;
       
  4187     Rkns.$.ajax({
       
  4188         url: "http://" + _this.lang + ".wikipedia.org/w/api.php?action=query&list=search&srsearch=" + encodeURIComponent(this.search) + "&format=json",
       
  4189         dataType: "jsonp",
       
  4190         success: function(_data) {
       
  4191             _this.data = _data;
       
  4192             _this.render();
       
  4193         }
       
  4194     });
       
  4195 };