123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- /*
- SpacedeckBoardArtifacts
- This module contains functions dealing with absolute positioned Board Section Artifacts.
- */
- var SpacedeckBoardArtifacts = {
- update_board_artifact_viewmodel: function(a) {
- var mt = this.artifact_major_type(a);
- a.view = {
- _id: a._id,
- classes: this.artifact_classes(a),
- style: this.artifact_style(a),
- grid_style: this.artifact_style(a, true),
- inner_style: this.artifact_inner_style(a),
- text_cell_style: this.artifact_text_cell_style(a),
- vector_svg: this.artifact_vector_svg(a),
- payload_uri: a.payload_uri,
- thumbnail_uri: this.artifact_thumbnail_uri(a),
- major_type: mt,
- text_blank: this.artifact_is_text_blank(a),
- payload_alternatives: a.payload_alternatives,
- filename: this.artifact_filename(a),
- oembed_html: this.artifact_oembed_html(a),
- link: this.artifact_link(a),
- link_caption: this.artifact_link_caption(a),
- interactive: 0
- };
- if ((mt == "audio" || mt == "video") && !a.player_view) {
- a.player_view = {
- state: "stop",
- current_time_string: "",
- total_time_string: "",
- current_time_float: 0.0,
- inpoint_float: 0.0,
- outpoint_float: 0.0
- };
- }
- if ("medium_for_object" in this) {
- var medium = this.medium_for_object[a._id];
- if (medium && a._id != this.editing_artifact_id) {
- medium.value(a.description.toString());
- }
- }
- },
- is_artifact_audio: function(a) {
- if (a) {
- return a.mime.match("audio");
- } else return false;
- },
- artifact_filename: function(a) {
- if (a.payload_uri) {
- return a.payload_uri.replace(/.*\//g,"");
- } else {
- return "";
- }
- },
- artifact_link: function(a) {
- if (a.link_uri) {
- return a.link_uri;
- } else {
- return "";
- }
- },
- artifact_link_caption: function(a) {
- if (a.link_uri) {
- var parts = a.link_uri.split("/");
- // scheme://domain.foo/...
- // 0 1 2
- if (parts.length>2) {
- return parts[2];
- }
- return "Link";
- } else {
- return "";
- }
- },
- artifact_is_selected: function(a) {
- if (!a) return false;
- return !!this.selected_artifacts_dict[a._id];
- },
- artifact_is_text_blank: function(a) {
- if (a.description) {
- desc = a.description.toString();
- var filtered = desc.replace(/<[^>]+>/g,"").replace(/\s/g,"");
- return (filtered.length<1);
- } else {
- return false;
- }
- },
- artifact_classes: function(a) {
- clzs = ["artifact", "artifact-"+this.artifact_major_type(a), a.mime.replace("/","-")];
- if (this.artifact_is_selected(a) && this.editing_artifact_id!=a._id) clzs.push("selected");
- if (!a._id) clzs.push("creating");
- if (a.align) clzs.push("align-"+a.align);
- if (a.valign) clzs.push("align-"+a.valign);
-
- clzs.push("state-"+a.state);
- if (this.artifact_is_text_blank(a)) {
- clzs.push("text-blank");
- }
- if (a.locked) {
- clzs.push("locked");
- }
-
- return clzs.join(" ");
- },
- artifact_inner_style: function(a) {
- var styles = [];
- //if (a.style) {
- var svg_style = ((a.mime.match("vector") || a.mime.match("shape")) && a.shape!="square");
- if (!svg_style) {
- if (a.stroke) {
- styles.push("border-width:"+a.stroke+"px");
- styles.push("border-style:"+(a.stroke_style||"solid"));
- }
- if (a.stroke_color) {
- styles.push("border-color:"+a.stroke_color);
- }
- if (a.border_radius) {
- styles.push("border-radius:"+a.border_radius+"px");
- }
- }
- if (a.fill_color && !svg_style) {
- styles.push("background-color:"+a.fill_color);
- }
- if (a.text_color) {
- styles.push("color:"+a.text_color);
- }
- var filters = [];
- if (!isNaN(a.brightness) && a.brightness != 100) {
- filters.push("brightness("+a.brightness+"%)");
- }
- if (!isNaN(a.contrast) && a.contrast != 100) {
- filters.push("contrast("+a.contrast+"%)");
- }
- if (!isNaN(a.opacity) && a.opacity != 100) {
- filters.push("opacity("+a.opacity+"%)");
- }
- if (!isNaN(a.hue) && a.hue) {
- filters.push("hue-rotate("+a.hue+"deg)");
- }
- if (!isNaN(a.saturation) && a.saturation != 100) {
- filters.push("saturate("+a.saturation+"%)");
- }
- if (!isNaN(a.blur) && a.blur) {
- filters.push("blur("+a.blur+"px)");
- }
- if (filters.length) {
- styles.push("-webkit-filter:"+filters.join(" "));
- styles.push("filter:"+filters.join(" "));
- }
- //}
- return styles.join(";");
- },
- artifact_text_cell_style: function(a, for_text_editor) {
- var styles = [];
- if (a.padding_left) styles.push("padding-left:"+a.padding_left+"px");
- if (a.padding_right) styles.push("padding-right:"+a.padding_right+"px");
- if (a.padding_top) styles.push("padding-top:"+a.padding_top+"px");
- if (a.padding_bottom) styles.push("padding-bottom:"+a.padding_bottom+"px");
- return styles.join(";");
- },
- artifact_style: function(a, for_grid) {
- var styles = [];
- var z = 0;
- z = a.z;
- if (z<0) z=0; // fix negative z-index
-
- styles = [
- "left:" +a.x+"px",
- "top:" +a.y+"px",
- "width:" +a.w+"px",
- "height:"+a.h+"px",
- "z-index:"+z
- ];
- if (a.margin_left) styles.push("margin-left:"+a.margin_left+"px");
- if (a.margin_right) styles.push("margin-right:"+a.margin_right+"px");
- if (a.margin_top) styles.push("margin-top:"+a.margin_top+"px");
- if (a.margin_bottom) styles.push("margin-bottom:"+a.margin_bottom+"px");
-
- // FIXME: via class logic?
- if (a.mime.match("vector")) {
- styles.push("overflow:visible");
- }
- return styles.join(";");
- },
- artifact_major_type: function(a) {
- if (a.mime.match("oembed")) return "oembed";
- if (a.mime.match("zone")) return "zone";
- if (a.mime.match("svg")) return "svg";
- if (a.mime.match("image")) return "image";
- if (a.mime.match("pdf")) return "image";
- if (a.mime.match("video")) return "video";
- if (a.mime.match("audio")) return "audio";
- if (a.mime.match("website")) return "website";
- if (a.mime.match("vector")) return "vector";
- if (a.mime.match("shape")) return "shape";
- if (a.mime.match("placeholder")) return "placeholder";
- if (a.mime.match("text") || a.mime.match("note")) return "text";
- return "file";
- },
- artifact_thumbnail_uri: function(a) {
- if (a.payload_thumbnail_big_uri && a.board) {
- if (a.w>800) {
- return a.payload_thumbnail_big_uri;
- }
- }
- return a.payload_thumbnail_medium_uri || a.payload_thumbnail_big_uri || a.payload_thumbnail_web_uri || "";
- },
- artifact_oembed_html: function(a) {
- if (this.artifact_major_type(a) != "oembed") return "";
- var parts = a.mime.split("/")[1].split("-");
- var type = parts[0];
- var provider = parts[1];
- if (!a.link_uri) {
- console.log("missing meta / link_uri: ",a);
- console.log("type/provider: ",type,provider);
- return ("missing metadata: "+a._id);
- }
- if (provider=="youtube") {
- var vid = a.link_uri.match(/(v=|\/)([a-zA-Z0-9\-_]{11})/);
- if (vid && vid.length>2) {
- var uri = "https://youtube.com/embed/"+vid[2];
- return "<iframe frameborder=0 allowfullscreen src=\""+uri+"?showinfo=0&rel=0&controls=0\"></iframe>";
- } else return "Can't resolve: "+a.payload_uri;
- } else if (provider=="dailymotion") {
- var match = a.link_uri.match(/dailymotion.com\/video\/([^<]*)/);
- if (match && match.length>1) {
- var uri = "https://www.dailymotion.com/embed/video/"+match[1];
- return "<iframe frameborder=0 allowfullscreen src=\""+uri+"\"></iframe>";
- } else return "Can't resolve: "+a.payload_uri;
- } else if (provider=="vimeo") {
- var match = a.link_uri.match(/https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/);
- if (match) {
- var uri = "https://player.vimeo.com/video/"+match[2];
- return "<iframe frameborder=0 allowfullscreen src=\""+uri+"\"></iframe>";
- } else return "Can't resolve: "+a.payload_uri;
- } else if (provider=="soundcloud") {
- return '<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url='+a.link_uri.replace(":", "%3A")+'"></iframe>';
- } else if (provider=="spacedeck") {
- return ""; //<iframe frameborder=0 allowfullscreen src=\""+ a.meta.link_uri+"\"></iframe>
- } else {
- return "Don't know how to embed "+a.mime+".";
- }
- },
- artifact_vector_svg: function(a) {
- var mtype = this.artifact_major_type(a);
- if (mtype != "vector" && mtype != "shape") return "";
- var shape = a.shape || "";
- var padding = 32 + a.stroke*2;
- var path_svg;
- var fill = "";
- if (mtype == "vector") {
- path_svg = render_vector_drawing(a, padding);
- fill = "fill:none";
- } else {
- path_svg = render_vector_shape(a, padding);
- fill = "fill:"+a.fill_color+";";
- padding = 0;
- }
- var margin = padding;
- var svg = "<svg xmlns='http://www.w3.org/2000/svg' width='"+(a.w+2*padding)+"' height='"+(a.h+2*padding)+"' ";
- svg += "style='margin-left:"+(-margin)+"px;margin-top:"+(-margin)+"px;stroke-width:"+a.stroke+";stroke:"+a.stroke_color+";"+fill+"'>";
- svg += path_svg;
- svg += "</svg>";
- return svg;
- },
- /* whiteboard layouting functions */
- artifact_enclosing_rect: function(arts) {
- if (arts.length==0) return null;
- r = {
- x1: parseInt(_.min(arts.map(function(a){return a.x}))),
- y1: parseInt(_.min(arts.map(function(a){return a.y}))),
- x2: parseInt(_.max(arts.map(function(a){return a.x+a.w}))),
- y2: parseInt(_.max(arts.map(function(a){return a.y+a.h})))
- };
- r.x=r.x1;
- r.y=r.y1;
- r.w=r.x2-r.x1;
- r.h=r.y2-r.y1;
- return r;
- },
- artifact_selection_rect: function() {
- return this.artifact_enclosing_rect(this.selected_artifacts());
- },
- rects_intersecting: function(r1,r2) {
- if ( (r1.x+r1.w < r2.x)
- || (r1.x > r2.x+r2.w)
- || (r1.y+r1.h < r2.y)
- || (r1.y > r2.y+r2.h) ) return false;
- return true;
- },
- artifacts_in_rect: function(rect) {
- return _.filter(this.active_space_artifacts, function(a) {
- return this.rects_intersecting(a, rect);
- }.bind(this));
- },
- layout_stack_top: function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- var overlapping = _.filter(this.artifacts_in_rect(rect), function(a){return !this.is_selected(a)}.bind(this));
- var max_z = _.max(overlapping,function(a){ return a.z; });
- if (max_z.board) {
- max_z = max_z.z + 1;
- } else {
- max_z = 1;
- }
-
- this.update_selected_artifacts(function(a) {
- return { z: max_z };
- });
- },
- layout_stack_bottom: function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- var overlapping = _.filter(this.artifacts_in_rect(rect), function(a){return !this.is_selected(a);}.bind(this));
- var min_z = _.min(overlapping,function(a){ return a.z; });
- if (min_z.board) {
- min_z = min_z.z - 1;
- } else {
- min_z = 0;
- }
- var my_z = _.max(this.selected_artifacts(),function(a){ return a.z; });
- if (my_z.board) {
- my_z = my_z.z - 1;
- } else {
- my_z = 0;
- }
- // TODO: move all other items up in this case?
- if (min_z < 0) {
- this.update_artifacts(overlapping, function(a) {
- return { z: (my_z + a.z + 1) };
- });
- return;
- }
- this.update_selected_artifacts(function(a) {
- return { z: min_z };
- });
- },
- layout_align_left:function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- this.update_selected_artifacts(function(a) {
- return { x: rect.x1 };
- });
- },
- layout_align_top: function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- this.update_selected_artifacts(function(a) {
- return { y: rect.y1 };
- });
- },
- layout_align_right: function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- this.update_selected_artifacts(function(a) {
- return { x: rect.x2 - a.w };
- });
- },
- layout_align_bottom: function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- this.update_selected_artifacts(function(a) {
- return { y: rect.y2 - a.h };
- });
- },
- layout_align_center: function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- var cx = rect.x1 + (rect.x2-rect.x1)/2;
- this.update_selected_artifacts(function(a) {
- return { x: cx - a.w/2 };
- });
- },
- layout_align_middle: function() {
- this.begin_transaction();
- var rect = this.artifact_selection_rect();
- var cy = rect.y1 + (rect.y2-rect.y1)/2;
- this.update_selected_artifacts(function(a) {
- return { y: cy - a.h/2 };
- });
- },
- layout_match_size_horiz:function() {
- this.begin_transaction();
- var arts = this.selected_artifacts();
- if (arts.length<2) return;
- var totalw = _.reduce(arts, function(sum, a) { return sum + a.w }, 0);
- var avgw = totalw / arts.length;
- this.update_selected_artifacts(function(a) {
- return { w: avgw };
- });
- },
- layout_match_size_vert:function() {
- this.begin_transaction();
- var arts = this.selected_artifacts();
- if (arts.length<2) return;
- var totalh = _.reduce(arts, function(sum, a) { return sum + a.h }, 0);
- var avgh = totalh / arts.length;
- this.update_selected_artifacts(function(a) {
- return { h: avgh };
- });
- },
- layout_match_size_both:function() {
- this.layout_match_size_horiz();
- this.layout_match_size_vert();
- },
- layout_distribute_horizontal: function() {
- this.begin_transaction();
- var selected = this.selected_artifacts();
- if (selected.length<3) return;
- var sorted = _.sortBy(selected, function(a) { return a.x });
- var startx = sorted[0].x + sorted[0].w/2;
- var stopx = _.last(sorted).x + _.last(sorted).w/2;
- var step = (stopx-startx)/(sorted.length-1);
- for (var i=1; i<sorted.length-1; i++) {
- var a = sorted[i];
- var x = startx + step*i - a.w/2;
- this.update_artifacts([a],function(a) {
- return { x: x }
- });
- }
- },
- layout_distribute_vertical: function() {
- this.begin_transaction();
- var selected = this.selected_artifacts();
- if (selected.length<3) return;
- var sorted = _.sortBy(selected, function(a) { return a.y });
- var starty = sorted[0].y + sorted[0].h/2;
- var stopy = _.last(sorted).y + _.last(sorted).h/2;
- var step = (stopy-starty)/(sorted.length-1);
- for (var i=1; i<sorted.length-1; i++) {
- var a = sorted[i];
- var y = starty + step*i - a.h/2;
- this.update_artifacts([a],function(a) {
- return { y: y }
- });
- }
- },
- layout_distribute_horizontal_spacing: function() {
- this.begin_transaction();
- var selected = this.selected_artifacts();
- if (selected.length<3) return;
- var sorted = _.sortBy(selected, function(a) { return a.x });
- var startx = sorted[0].x;
- var stopx = _.last(sorted).x + _.last(sorted).w;
- var range = stopx - startx;
- var totalw = _.reduce(sorted, function(sum, a) { return sum + a.w }, 0);
- var avgs = (range - totalw) / (sorted.length-1);
- var prevend = startx + sorted[0].w;
- for (var i=1; i<sorted.length-1; i++) {
- var a = sorted[i];
- var x = prevend + avgs;
- this.update_artifacts([a],function(a) {
- return { x: x }
- });
- prevend = x+a.w;
- }
- },
- layout_distribute_vertical_spacing: function() {
- this.begin_transaction();
- var selected = this.selected_artifacts();
- if (selected.length<3) return;
- var sorted = _.sortBy(selected, function(a) { return a.y });
- var starty = sorted[0].y;
- var stopy = _.last(sorted).y + _.last(sorted).h;
- var range = stopy - starty;
- var totalh = _.reduce(sorted, function(sum, a) { return sum + a.h }, 0);
- var avgs = (range - totalh) / (sorted.length-1);
- var prevend = starty + sorted[0].h;
- for (var i=1; i<sorted.length-1; i++) {
- var a = sorted[i];
- var y = prevend + avgs;
- this.update_artifacts([a],function(a) {
- return { y: y }
- });
- prevend = y+a.h;
- }
- },
- layout_auto: function() {
- this.begin_transaction();
- var selected = this.selected_artifacts();
- if (selected.length<2) return;
- var sorted = _.sortBy(selected, function(a) { return a.x+a.y*this.active_space.width }.bind(this));
- var minx = sorted[0].x;
- var miny = sorted[0].y;
- var sorted = _.sortBy(selected, function(a) { return -Math.max(a.w,a.h) }.bind(this));
-
- var blocks = [];
- var padding = 10;
- for (var i=0; i<sorted.length; i++) {
- var a = sorted[i];
- blocks.push({
- w: a.w+padding,
- h: a.h+padding,
- a: a
- });
- }
-
- var packer = new GrowingPacker();
- packer.fit(blocks);
- for (var i=0; i<blocks.length; i++) {
- var block = blocks[i];
- if (block.fit) {
- var a = block.a;
- this.update_artifacts([a],function(a) {
- return {
- x: minx+block.fit.x,
- y: miny+block.fit.y
- }
- });
- }
- }
- },
-
- show_artifact_comments: function(evt) {
- evt.preventDefault();
- evt.stopPropagation();
- var artifact = this.selected_artifacts()[0];
- this.selected_artifact = artifact;
- this.activate_modal('artifact');
- },
- create_artifact_comment: function(artifact, comment) {
- var data = {
- artifact_id: artifact._id,
- space_id: this.active_space._id,
- message: comment,
- user: this.user
- };
- save_comment(this.active_space._id, data, function(comment) {
- this.active_space_messages.push(comment);
- this.artifact_comment = "";
- }.bind(this), function(xhr){
- console.error(xhr);
- }.bind(this));
- },
- remove_artifact_comment: function(comment) {
- delete_comment(this.active_space._id, comment._id, function(comment) {
- this.active_space_messages.pop(comment);
- }.bind(this), function(xhr){
- console.error(xhr);
- }.bind(this));
- }
- }
- if (typeof(window) == 'undefined') {
- exports.SpacedeckBoardArtifacts = SpacedeckBoardArtifacts;
- }
|