--- a/client/css/renkan.css Fri Aug 17 12:50:00 2012 +0200
+++ b/client/css/renkan.css Fri Aug 17 18:36:12 2012 +0200
@@ -46,11 +46,15 @@
}
.Rk-Bins {
- background: #F0F0F0; position: absolute; left: 0; top: 0; width: 200px; bottom: 0;
+ background: #F0F0F0; position: absolute; left: 0; top: 0; width: 300px; bottom: 0; overflow: hidden;
}
.Rk-Render {
- position: absolute; left: 200px; top: 0; right: 0; bottom: 0;
+ position: absolute; left: 300px; top: 0; right: 0; bottom: 0;
+}
+
+.Rk-Canvas {
+ position: absolute; left: 0; top: 0; right: 0; bottom: 0;
}
.Rk-Editor {
@@ -105,13 +109,47 @@
background-position: -21px -20px;
}
-ul.Rk-TabButtons {
+.Rk-Search-Input, .Rk-Search-Select {
+ border-radius: 5px; margin: 2px; padding: 2px; font-size: 13px;
+}
+
+.Rk-Search-Input {
+ width: 180px;
+}
+
+.Rk-Search-Select {
+ width: 100px;
+}
+
+.Rk-Bin-Title {
+ border-top: 1px solid #cccccc; border-bottom: 1px solid #ffffff; background: #f0f0f0;
+ font-size: 14px; font-weight: bold; padding: 2px; cursor: pointer;
+}
+
+.Rk-Bin-Main {
+ overflow: auto;
}
-li.Rk-TabButton {
- float: left; padding: 2px; font-size: 13px; border-top-left-radius: 5px; border-top-right-radius: 5px; background: #CCCCCC;
+.Rk-Twitter-Tweet {
+ padding: 2px; background: #f8f8f8; border-bottom: 1px solid #cccccc; min-height: 55px;
+}
+
+.Rk-Twitter-TwImage {
+ float: left; width: 48px; height: 48px; margin: 2px 0;
+}
+
+.Rk-Twitter-TwTitle, .Rk-Twitter-TwDate, .Rk-Twitter-TwText, .Rk-Twitter-TwActions {
+ margin: 2px 0 2px 50px;
}
-.Rk-TabDiv {
- width: 100%; clear: both; overflow: auto; border-top: 1px solid #ccc;
+.Rk-Twitter-TwTitle {
+ font-size: 13px; font-weight: bold;
}
+
+.Rk-Twitter-TwDate {
+ font-size: 11px; font-style: italic;
+}
+
+.Rk-Twitter-TwText {
+ font-size: 12px;
+}
\ No newline at end of file
--- a/client/js/main.js Fri Aug 17 12:50:00 2012 +0200
+++ b/client/js/main.js Fri Aug 17 18:36:12 2012 +0200
@@ -79,63 +79,102 @@
Rkns.Bins = {}
-Rkns.Bins._Base = function(_project) {
- if (typeof _project !== "undefined") {
- this._project = _project;
+Rkns.Bins._Base = function(_renkan, _opts) {
+ if (typeof _renkan !== "undefined") {
+ this.renkan = _renkan;
+ this.renkan.$.find(".Rk-Bin-Main").hide();
+ this.$ = Rkns.$('<li>')
+ .addClass("Rk-Bin")
+ .appendTo(_renkan.$.find(".Rk-Bin-List"));
+ this.title_$ = Rkns.$('<h2>')
+ .addClass("Rk-Bin-Title")
+ .appendTo(this.$);
+ this.main_$ = Rkns.$('<div>')
+ .addClass("Rk-Bin-Main")
+ .appendTo(this.$);
+ this.renkan.resizeBins();
}
}
-
-Rkns.Bins._Base.prototype.baseTemplate = '';
-
-Rkns.Bins._Base.prototype.addTab = function(_title) {
- var _tabDiv = Rkns.$('<div>');
- _tabDiv.addClass('Rk-TabDiv')
- .css("display","none")
- .appendTo('.Rk-TabDivs');
- var _tabButton = Rkns.$('<li>');
- _tabButton.addClass('Rk-TabButton')
- .html(_title)
- .click(function() {
- Rkns.$('.Rk-TabButton').removeClass("active");
- Rkns.$(this).addClass("active");
- Rkns.$('.Rk-TabDiv').hide();
- _tabDiv.show();
- })
- .appendTo('.Rk-TabButtons');
- return {
- button: _tabButton,
- contents: _tabDiv
- }
-}
-
/* Point of entry */
Rkns.Renkan = function(_opts) {
- if (typeof _opts.remotemodel == "undefined") {
- _opts.remotemodel = "BasicJson";
+ if (typeof _opts.remotemodel !== "string") {
+ _opts.remotemodel = "FullJson";
}
- if (typeof _opts.language == "undefined" || typeof Rkns.i18n[_opts.language] == "undefined") {
+ if (typeof _opts.language !== "string" || typeof Rkns.i18n[_opts.language] == "undefined") {
_opts.language = "en";
}
- if (typeof _opts.container == "undefined") {
+ if (typeof _opts.container !== "string") {
_opts.container = "renkan";
}
+ if (typeof _opts.search !== "object" || !_opts.search) {
+ _opts.search = [];
+ }
this.project = new Rkns.ViewModel.Project();
this.project.l10n = Rkns.i18n[_opts.language];
if (typeof _opts.user === "object") {
this.current_user = this.project.addUser(_opts.user)
}
- Rkns.$("#" + _opts.container).html(this.template());
- this.project.remotemodel = new Rkns.RemoteModels[_opts.remotemodel](this.project, _opts);
- this.project.renderer = new Rkns.Renderer.Scene(this.project, _opts);
+ this.$ = Rkns.$("#" + _opts.container);
+ this.$.html(this.template());
+ this.remotemodel = this.project.remotemodel = new Rkns.RemoteModels[_opts.remotemodel](this.project, _opts);
+ this.renderer = this.project.renderer = new Rkns.Renderer.Scene(this.project, _opts);
+ this.renderer.renkan = this;
+ this.tabs = [];
+ this.selected_bin_item = undefined;
+ this.mousedown = false;
var _this = this;
-/* if (typeof _opts.bins === "object") {
- this.bins = Rkns._(_opts.bins).map(function(_type) {
- return new Rkns.Bins[_type](_this);
+ this.$.mouseup(function() {
+ _this.selected_bin_item = undefined;
+ });
+ if (!_opts.search.length) {
+ this.$.find(".Rk-Search-Form").detach();
+ } else {
+ var _tmpl = Rkns._.template('<option value="<%= name %>"><%= name %></option>');
+ this.$.find(".Rk-Search-Select").html(
+ Rkns._(_opts.search).map(function(_name) {
+ return _tmpl({name:_name});
+ }).join("")
+ );
+ }
+ this.$.find(".Rk-Search-Form").submit(function() {
+ _this.tabs.push(
+ new Rkns.Bins[_this.$.find(".Rk-Search-Select").val()](
+ _this,
+ {
+ search: _this.$.find(".Rk-Search-Input").val()
+ }
+ )
+ );
+ return false;
+ });
+ this.$.find(".Rk-Bins")
+ .click(function(_e) {
+ if (_e.target.className == "Rk-Bin-Title") {
+ var _mainDiv = Rkns.$(_e.target).siblings(".Rk-Bin-Main");
+ if (_mainDiv.is(":hidden")) {
+ _this.$.find(".Rk-Bin-Main").slideUp();
+ _mainDiv.slideDown();
+ }
+ }
+ }).mousedown(function(_e) {
+ var _t = Rkns.$(_e.target);
+ while (!_t.is(".Rk-Bins,.Rk-Bin-Item")) {
+ _t = _t.parent();
+ }
+ if (_t.is(".Rk-Bin-Item")) {
+ _this.selected_bin_item = {
+ uri : $(_t).attr("data-uri"),
+ title : $(_t).attr("data-title"),
+ description : $(_t).attr("data-description")
+ }
+ return false;
+ }
});
- Rkns.$('.Rk-TabButton:last').addClass("active");
- Rkns.$('.Rk-TabDiv:last').show();
-} */
+ Rkns.$(window).resize(function() {
+ _this.resizeBins();
+ })
+
this.project.remotemodel.onLoad(function() {
if (typeof _this.project.current_user === "undefined") {
_this.project.current_user = _this.project.users[0];
@@ -145,9 +184,20 @@
}
Rkns.Renkan.prototype.template = Rkns._.template(
- '<div class="Rk-Bins"></div><div class="Rk-Render"></div>'
+ '<div class="Rk-Bins">'
+ + '<form class="Rk-Search-Form"><input class="Rk-Search-Input" type="search" placeholder="Search" /><select class="Rk-Search-Select"></select></form>'
+ + '<ul class="Rk-Bin-List"></ul></div><div class="Rk-Render"></div>'
);
+
+Rkns.Renkan.prototype.resizeBins = function() {
+ var _titles = this.$.find(".Rk-Bin-Title"),
+ _d = _titles.length * _titles.outerHeight() + this.$.find(".Rk-Search-Form").outerHeight();
+ this.$.find(".Rk-Bin-Main").css({
+ height: this.$.find(".Rk-Bins").height() - _d
+ });
+}
+
/* Utility functions */
Rkns.Utils = {
--- a/client/js/paper-renderer.js Fri Aug 17 12:50:00 2012 +0200
+++ b/client/js/paper-renderer.js Fri Aug 17 18:36:12 2012 +0200
@@ -380,7 +380,8 @@
Rkns.Renderer.TempEdge.prototype.paperShift = function(_delta) {
this.end_pos = this.end_pos.add(_delta);
- this._renderer.onMouseMove({point: this.end_pos});
+ var _hitResult = paper.project.hitTest(this.end_pos);
+ this._renderer.findTarget(_hitResult);
this.redraw();
}
@@ -779,15 +780,18 @@
_tool.onMouseDrag = function(_event) {
_this.onMouseDrag(_event);
}
- _tool.onMouseUp = function(_event) {
+ this.canvas_$.mouseup(function(_event) {
_this.onMouseUp(_event);
- }
+ });
this.canvas_$.mousewheel(function(_event, _delta) {
_this.onScroll(_event, _delta);
- })
+ });
this.canvas_$.dblclick(function(_event) {
_this.onDoubleClick(_event);
});
+ this.canvas_$.mouseenter(function(_event) {
+ _this.onMouseEnter(_event);
+ });
this.editor_$.find(".Rk-ZoomOut").click(function() {
_this.offset = new paper.Point([
_this.canvas_$.width(),
@@ -882,8 +886,7 @@
this.click_target = _tmpEdge;
}
-Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) {
- var _hitResult = paper.project.hitTest(_event.point);
+Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) {
if (_hitResult && typeof _hitResult.item.__controller !== "undefined") {
var _newTarget = _hitResult.item.__controller;
if (this.selected_target !== _hitResult.item.__controller) {
@@ -901,6 +904,20 @@
}
}
+Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) {
+ var _hitResult = paper.project.hitTest(_event.point);
+ if (this.is_dragging) {
+ if (this.click_target && typeof this.click_target.paperShift === "function") {
+ this.click_target.paperShift(_event.delta);
+ } else {
+ this.offset = this.offset.add(_event.delta);
+ this.redraw();
+ }
+ } else {
+ this.findTarget(_hitResult);
+ }
+}
+
Rkns.Renderer.Scene.prototype.onMouseDown = function(_event) {
this.is_dragging = false;
var _hitResult = paper.project.hitTest(_event.point);
@@ -919,17 +936,20 @@
Rkns.Renderer.Scene.prototype.onMouseDrag = function(_event) {
this.is_dragging = true;
- if (this.click_target && typeof this.click_target.paperShift === "function") {
- this.click_target.paperShift(_event.delta);
- } else {
- this.offset = this.offset.add(_event.delta);
- this.redraw();
- }
+ this.onMouseMove(_event);
}
Rkns.Renderer.Scene.prototype.onMouseUp = function(_event) {
if (this.click_target) {
- this.click_target.mouseup(_event);
+ var _off = this.canvas_$.offset();
+ this.click_target.mouseup(
+ {
+ point: new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ])
+ }
+ );
}
this.is_dragging = false;
this.click_target = null;
@@ -974,3 +994,26 @@
}
paper.view.draw();
}
+
+Rkns.Renderer.Scene.prototype.onMouseEnter = function(_event) {
+ var _newEl = this.renkan.selected_bin_item;
+ if (_newEl) {
+ var _off = this.canvas_$.offset(),
+ _point = new paper.Point([
+ _event.pageX - _off.left,
+ _event.pageY - _off.top
+ ]),
+ _coords = this.toModelCoords(_point),
+ _node = this._project.addNode({
+ uri: _newEl.uri,
+ title: _newEl.title,
+ description: _newEl.description,
+ position: {
+ x: _coords.x,
+ y: _coords.y
+ }
+ }, Rkns._RENDER_AND_SAVE);
+ this.is_dragging = true;
+ this.click_target = _node.__controller;
+ }
+}
\ No newline at end of file
--- a/client/js/random-data.js Fri Aug 17 12:50:00 2012 +0200
+++ b/client/js/random-data.js Fri Aug 17 18:36:12 2012 +0200
@@ -2,8 +2,8 @@
Rkns.RemoteModels.RandomData.prototype._init = function() {
this._USER_COUNT = 5;
- this._NODE_COUNT = 20;
- this._EDGE_COUNT = 40;
+ this._NODE_COUNT = 50;
+ this._EDGE_COUNT = 100;
this.user_colors = ["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"];
this.load();
}
@@ -24,10 +24,10 @@
title: "Node #"+(1+i),
created_by: "user-" + Math.floor(this._USER_COUNT*Math.random()),
position: {
-// x: 200 * Math.random(),
-// y: 150 * Math.random()
- x: 100 * Math.cos(2 * Math.PI * i / this._NODE_COUNT),
- y: 100 * Math.sin(2 * Math.PI * i / this._NODE_COUNT)
+ x: 200 * Math.random(),
+ y: 150 * Math.random()
+// x: 100 * Math.cos(2 * Math.PI * i / this._NODE_COUNT),
+// y: 100 * Math.sin(2 * Math.PI * i / this._NODE_COUNT)
}
}));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/js/twitter-bin.js Fri Aug 17 18:36:12 2012 +0200
@@ -0,0 +1,89 @@
+Rkns.Bins.Twitter = Rkns.Utils.inherit(Rkns.Bins._Base);
+
+Rkns.Bins.Twitter.prototype.tweetTemplate = Rkns._.template(
+ '<li class="Rk-Twitter-Tweet Rk-Bin-Item" data-uri="http://twitter.com/<%=tweet.from_user%>/status/<%=tweet.id_str%>" '
+ + 'data-title="Tweet by @<%=tweet.from_user%>" data-description="<%-tweet.text%>">'
+ + '<img class="Rk-Twitter-TwImage" src="<%=tweet.profile_image_url%>" />'
+ + '<h4 class="Rk-Twitter-TwTitle"><a href="http://twitter.com/<%=tweet.from_user%>" target="_blank">@<%=tweet.from_user%></a> (<%=tweet.from_user_name%>)</h4>'
+ + '<p class="Rk-Twitter-TwDate"><%=date%></p>'
+ + '<p class="Rk-Twitter-TwText"><%=text%></p>'
+ + '<p class="Rk-Twitter-TwActions"><a class="Rk-Twitter-TwAction" href="http://twitter.com/<%=tweet.from_user%>/status/<%=tweet.id_str%>" target="_blank">show original</a> · '
+ + '<a href="http://twitter.com/intent/tweet?in_reply_to=<%=tweet.id_str%>" target="_blank">reply</a> · '
+ + '<a href="http://twitter.com/intent/retweet?tweet_id=<%=tweet.id_str%>" target="_blank">retweet</a> · '
+ + '<a href="http://twitter.com/intent/favorite?tweet_id=<%=tweet.id_str%>" target="_blank">favorite</a></p></li>'
+);
+
+Rkns.Bins.Twitter.prototype._init = function(_renkan, _opts) {
+ this.search = _opts.search;
+ this.title_$.html('Twitter: "' + this.search + '"')
+ var _this = this;
+ Rkns.$.getJSON(
+ "http://search.twitter.com/search.json?q=" + encodeURIComponent(this.search) + "&callback=?",
+ function(_data) {
+ var _html = Rkns._(_data.results).map(function(_result) {
+ var _entities = [],
+ _users = _result.text.match(/@[\w_]+/gm),
+ _lastpos = 0;
+ if (_users) {
+ for (var _i = 0; _i < _users.length; _i++) {
+ var _m = _users[_i],
+ _start = _lastpos + _result.text.substr(_lastpos).search(_m),
+ _lastpos = _start + _m.length;
+ _entities.push({
+ "text" : _m,
+ "start" : _start,
+ "end" : _lastpos,
+ "link" :'<a href="http://twitter.com/' + _m.substr(1) + '" onclick="filtrerTexte(\'' + _m + '\'); return false;" target="_blank">',
+ });
+ }
+ }
+ var _hashes = _result.text.match(/([^&]|^)#[^\s,.!?=#@&;()]+/gm),
+ _lastpos = 0;
+ if (_hashes) {
+ for (var _i = 0; _i < _hashes.length; _i++) {
+ var _m = _hashes[_i],
+ _h = ( _m[0] == '#' ? _m : _m.substr(1) ),
+ _start = _lastpos + _result.text.substr(_lastpos).search(_h),
+ _lastpos = _start + _h.length;
+ _entities.push({
+ "text" : _h,
+ "start" : _start,
+ "end" : _lastpos,
+ "link" :'<a href="http://twitter.com/search?q=' + encodeURIComponent(_h) + '" onclick="filtrerTexte(\'' + _.escape(_h) + '\'); return false;" target="_blank">',
+ });
+ }
+ }
+
+ var _urls = _result.text.match(/(www\.|https?:\/\/)[\w./_\-]+/gim),
+ _lastpos = 0;
+ if (_urls) {
+ for (var _i = 0; _i < _urls.length; _i++) {
+ var _m = _urls[_i],
+ _start = _lastpos + _result.text.substr(_lastpos).search(_m),
+ _lastpos = _start + _m.length;
+ _entities.push({
+ "text" : _m,
+ "start" : _start,
+ "end" : _lastpos,
+ "link" :'<a href="' + _m + '" target="_blank">',
+ });
+ }
+ }
+ _entities = Rkns._(_entities).sortBy(function(a) { return a.start });
+ var _lastend = 0,
+ _text = Rkns._(_entities).map(function(_e) {
+ var _txt = _result.text.substring(_lastend, _e.start) + _e.link + _e.text + '</a>';
+ _lastend = _e.end;
+ return _txt;
+ }).join("") + _result.text.substring(_lastend);
+
+ return _this.tweetTemplate({
+ tweet: _result,
+ date: new Date(_result.created_at.replace(/(\+|-)/,'UTC$1')).toLocaleString(),
+ text: _text
+ });
+ }).join("");
+ _this.main_$.html(_html);
+ }
+ );
+}
--- a/client/render-test.html Fri Aug 17 12:50:00 2012 +0200
+++ b/client/render-test.html Fri Aug 17 18:36:12 2012 +0200
@@ -14,6 +14,7 @@
<script src="js/i18n.js"></script>
<script src="js/view-model.js"></script>
<script src="js/full-json.js"></script>
+ <script src="js/random-data.js"></script>
<script src="js/twitter-bin.js"></script>
<script src="js/paper-renderer.js"></script>
<script type="text/javascript">
@@ -22,17 +23,20 @@
_proj = new Rkns.Renkan({
url: "data/simple-persist.php",
remotemodel: "FullJson",
+ search: [
+ "Twitter"
+ ],
user: {
- id: "anonymous",
+ id: "u-anonymous",
title: "anonymous",
- color: "#0000ff"
+ color: "#dd00dd"
}
});
});
</script>
<link rel="stylesheet" href="css/renkan.css" />
<style type="text/css">
- #topbar { position: absolute; left: 0; top: 0; right: 0; height: 40px; background: #f0f0f0; font-size: 20px; color: #a0a0a0; }
+ #topbar { position: absolute; left: 0; top: 0; right: 0; height: 40px; background: #f8f8f8; font-size: 20px; color: #a0a0a0; }
#renkan {
position: absolute; left: 0; top: 40px; width: 200px; bottom: 0;
}