/** * @jsx React.DOM */ window.aperture = React.createClass({displayName: "aperture", statics: { count: 0 }, getInitialState: function(){ return { prefix: "svg-aperture-react_" + (window.aperture.count++) }; }, getMaskStyle: function(){ return { 'clipPath': 'url(#'+this.state.prefix+'_mask)' }; }, broadcastToAngular: function(){ if(this.props.svgModel.type == 'image-text') this.props.scope.$emit('svgAperture.click', [this.props.svgModel, {}]); }, render: function() { return React.createElement("svg", {style: {'overflow': 'visible'}, onClick: this.broadcastToAngular, onTouchStart: this.broadcastToAngular}, React.createElement("defs", null, React.createElement("clipPath", {id: this.state.prefix+'_mask'}, React.createElement("rect", {width: this.props.svgModel.width, height: this.props.svgModel.height, x: "0", y: "0"}) ) ), React.createElement("g", {width: this.props.svgModel.width, height: this.props.svgModel.height, transform: 'translate('+this.props.svgModel.x+', '+this.props.svgModel.y+')', style: this.getMaskStyle() }, React.createElement("g", null, this.props.children) ) ); } }); window.imageAperture = React.createClass({displayName: "imageAperture", getInitialState: function(){ var self = this; self._data = {}; self._data.actualImageWidth = 0; self._data.actualImageHeight = 0; return { imageLoaded: false }; }, getDefaultProps: function(){ return { svgModel: { point: {x:0.5,y:0.5}, rotate: 90, zoom: 0 } }; }, componentWillReceiveProps: function(nextProps) { this.loadImage(); }, componentWillMount: function(){ this.loadImage(); }, loadImage: function(){ var self = this; if(!self.props.src) return; $('') .attr('src', self.props.src) .load(function(){ var that = this; if(self.props.svgModel) { self.props.svgModel.imgWidth = that.width; self.props.svgModel.imgHeight = that.height; } self._data.actualImageWidth = that.width; self._data.actualImageHeight = that.height; self.state.imageLoaded = true; self.forceUpdate(); }); }, calculateImageTagData: function(){ var self = this; if(!self.state.imageLoaded || typeof self.props.apertureData != 'object') { self._data.imageTag = { x: 0, y: 0, width: 0, height: 0, rotate: 0, rotationPoint: {x:0, y:0} }; return; } self._data.imageTag = angular.copy(self._data.image); var iT = self._data.imageTag; if(iT.rotate%360 == 90 || iT.rotate%360 == 270 || iT.rotate%360 == -90 || iT.rotate%360 == -270) { //swap(iT.width, iT.height); var tmp = iT.width; iT.width = iT.height; iT.height = tmp; } iT.x = 0; iT.y = 0; iT.rotationPoint = {x:0,y:0}; if(iT.rotate%360 == 90 || iT.rotate%360 == -270) { iT.y -= iT.height; } if(iT.rotate%360 == 180 || iT.rotate%360 == -180) { iT.y -= iT.height; iT.x -= iT.width; } if(iT.rotate%360 == 270 || iT.rotate%360 == -90) { iT.x -= iT.width; } }, calculateImageData: function(){ var self = this; if(!self.state.imageLoaded || typeof self.props.apertureData != 'object') { self._data.image = { x: 0, y: 0, width: 0, height: 0, rotate: 0, rotationPoint: {x:0, y:0} }; return; } if(self.props.svgModel && self.props.svgModel.rotate) var rotate = self.props.svgModel.rotate; if(rotate%360 == 90 || rotate%360 == 270 || rotate%360 == -90 || rotate%360 == -270) var imgR = self._data.actualImageHeight / self._data.actualImageWidth; else var imgR = self._data.actualImageWidth / self._data.actualImageHeight; var frameR = self.props.apertureData.width / self.props.apertureData.height; if(imgR > frameR) { var height = self.props.apertureData.height; var width = height * imgR; } else { var width = self.props.apertureData.width; var height = width / imgR; } if(self.props.svgModel && self.props.svgModel.zoom < 1) self.props.svgModel.zoom = 1; width = self.props.svgModel.zoom * width; height = self.props.svgModel.zoom * height; var p = self.props.svgModel.point; var x = (self.props.apertureData.width/2 - (p.x * width)); var y = (self.props.apertureData.height/2 - (p.y * height)); var rotationPoint = { x: (self.props.apertureData.width)/2, y: (self.props.apertureData.height)/2 }; self._data.image = { x: x, y: y, width: width, height: height, rotate: rotate, rotationPoint: rotationPoint }; }, render: function() { this.calculateImageData(); this.calculateImageTagData(); var self = this; return React.createElement("svg", {"data-id": this.props.apertureData.asset_table_id, "data-table": this.props.apertureData.asset_table, "data-type": "svg-aperture-image"}, React.createElement("g", null, this.state.imageLoaded ? React.createElement("svg", { viewBox: '0 0 '+self._data.image.width+' '+self._data.image.height, x: self._data.image.x, y: self._data.image.y, height: self._data.image.height, width: self._data.image.width, dangerouslySetInnerHTML: {__html: ''} } ) : null, self.props.apertureData.hover ? React.createElement("rect", {scale: self.props.scale, opacity: "0.7", fill: "#00ff12", stroke: "#00ff12", strokeWidth: "0", width: self.props.apertureData.width, height: self.props.apertureData.height}) : null ) ) } }); window.textAperture = React.createClass({displayName: "textAperture", getFontFamily: function() { if(this.props.svgModel) return this.props.svgModel.fontFamily; else return ''; }, getStyle: function() { // var style = "font-family: '" + this.getFontFamily() + "';"; var style = {"fontFamily": "'"+this.getFontFamily()+"'"}; if(this.props.svgModel && this.props.svgModel.fontVariant) { var fontVariant = this.props.svgModel.fontVariant; if(fontVariant.indexOf('italic') != -1) style.fontStyle = "italic"; // style += 'font-style: italic;'; fontVariant = fontVariant.replace('italic', ''); if(fontVariant != 'regular') { style.fontWeight = "'"+fontVariant+"'"; // style += 'font-weight: '+fontVariant+';'; } } return style; }, getVertAlign: function() { if(this.props.type == "large_dates") return true; return false; }, getVertAlignHeight: function() { if(this.props.type == "large_dates") return this.props.apertureData.height; return false; }, getWeekendWeight: function() { if(!this.props.svgModel.weekendWeight) return 'normal'; return this.props.svgModel.weekendWeight; }, getFontSize: function() { if(!this.props.dpi || isNaN(this.props.dpi)) this.props.dpi = 72; return (this.props.svgModel.fontSize) * (parseFloat(this.props.dpi)/72); }, getPosition: function() { var y = this.props.svgModel.fontSize; var x = 0; if(!this.props.alignmentPadding) this.props.alignmentPadding = 0; if(!this.props.type) this.props.type = false; if(this.props.type == 'large_dates') this.props.svgModel.alignment = 'center'; switch(this.props.svgModel.alignment) { case 'left': x = 0 + parseInt(this.props.alignmentPadding); break; case 'center': x = this.props.apertureData.width/2; break; case 'right': x = this.props.apertureData.width - parseInt(this.props.alignmentPadding); break; } return {x:x, y:y}; }, textAnchor: function() { switch(this.props.svgModel.alignment) { case 'left': return 'start'; break; case 'center': return 'middle'; break; case 'right': return 'end'; break; } }, render: function() { return React.createElement("svg", null, React.createElement("g", {className: "text-locked"}, React.createElement(window.textWrap, {textWrapWidth: this.props.apertureData.width, textWrapX: this.getPosition().x, textWrapY: this.getPosition().y, textWrapVerticalAlign: this.getVertAlign(), textWrapHeight: this.getVertAlignHeight(), textWrapLineHeight: this.getFontSize(), textWrapCaption: this.props.svgModel.caption, textWrapWeekendWeight: this.getWeekendWeight()}, React.createElement("text", {style: this.getStyle(), fill: this.props.svgModel.color, fontSize: this.getFontSize(), textAnchor: this.textAnchor()}) ) ) ); } }); window.textWrap = React.createClass({displayName: "textWrap", compile: function() { var domElem = this.getDOMNode(); var elem = $(domElem); elem.attr('x',this.props.textWrapX); elem.attr('y',this.props.textWrapY); elem.empty(); var textWrapCaption = this.props.textWrapCaption + ''; if(!textWrapCaption) return; textWrapCaption = textWrapCaption.replace(new RegExp("\n", 'g'), " \n"); var captionsArray = textWrapCaption.split(" "); var lines = []; var tempText = ""; for (var i=0; i (this.props.textWrapWidth*0.9) || captionsArray[i].indexOf("\n") == 0) { if(tempText.indexOf(" ") == 0) tempText = tempText.substr(1); lines.push(tempText); tempText = captionsArray[i]; } else { tempText += " " + captionsArray[i]; } } if(tempText.indexOf(" ") == 0) tempText = tempText.substr(1); lines.push(tempText); elem.empty(); var y = 0; for(i in lines) { if(lines[i] == '' || lines[i] == ' ') continue; y = y + parseFloat(this.props.textWrapLineHeight); var el = document.createElementNS('http://www.w3.org/2000/svg', 'tspan'); el.setAttribute('x', this.props.textWrapX); el.setAttribute('y', y); el.style.fontWeight = this.props.textWrapWeekendWeight; //el.style.filter = 'alpha(opacity='+this.props.textWrapWeekendWeight+')'; var textNode = document.createTextNode(lines[i].trim()); el.appendChild(textNode); elem.append(el); } this.props.textWrapDimension = domElem.getBBox(); if(this.props.textWrapVerticalAlign && this.props.textWrapHeight) { var height = this.props.textWrapDimension.height; var dy = (parseFloat(this.props.textWrapHeight) - height)/2; //dy = dy - parseFloat(this.props.textWrapLineHeight) + parseFloat(this.props.textWrapFontSize); elem.find('tspan').each(function(){ $(this).attr('y', parseFloat($(this).attr('y')) + dy); }); } }, componentDidUpdate: function(){ var that = this; setTimeout(function(){ if(that.isMounted()) that.compile(); }, 100); }, componentDidMount: function(){ var that = this; setTimeout(function(){ if(that.isMounted()) that.compile(); }, 100); }, render: function() { return this.props.children; } }); window.googleWebFontsImporter = React.createClass({displayName: "googleWebFontsImporter", compile: function() { var domElem = this.getDOMNode(); var importedFonts = []; var elem = $(domElem); if(!this.props.layers) return; var html = ''; for(var i in this.props.layers) { if(!this.props.layers[i]) continue; if((this.props.layers[i].type == 'text' || this.props.layers[i].type == 'image-text') && this.props.layers[i].text) { if(_.indexOf(importedFonts, this.props.layers[i].text.fontFamily)!=-1) continue; html += '@import url(https://fonts.googleapis.com/css?family='+this.props.layers[i].text.fontFamily.replace(/ /g, '+')+':'+this.props.layers[i].text.fontVariant+');'; importedFonts.push(this.props.layers[i].text.fontFamily); } } elem.empty(); elem.append(html); }, componentDidUpdate: function() { var that = this; setTimeout(function(){ if(that.isMounted()) that.compile(); }, 100); }, componentDidMount: function() { var that = this; setTimeout(function(){ if(that.isMounted()) that.compile(); }, 100); }, render: function() { return this.props.children; } }); window.calendarRenderer = React.createClass({displayName: "calendarRenderer", render: function() { var that = this; return React.createElement("svg", {style: {overflow: 'visible'} }, React.createElement("rect", {x: this.props.apertureData.x, y: this.props.apertureData.y, width: this.props.apertureData.width, height: this.props.apertureData.height, style: {'opacity': this.props.apertureData.calBackgroundOpacity}, fill: this.props.apertureData.calBackgroundColor}), this.props.apertureData.sub_type == 'no_events' ? React.createElement(window.googleWebFontsImporter, {layers: this.props.dateGridCoordinates}, React.createElement("style", {type: "text/css"} ) ) :null, _.map(this.props.dateGridCoordinates, function(row, i){ return React.createElement("g", {className: "g-row", key: i}, that.props.apertureData.sub_type == 'default' || that.props.apertureData.sub_type == 'large_dates' ? React.createElement("g", null, React.createElement(window.googleWebFontsImporter, {layers: row}, React.createElement("style", {type: "text/css"} ) ), _.map(row, function(cell, j){ if(!cell || !cell.x) return null; return React.createElement("g", {className: "g-cell", key: j}, cell.dateType!='day' && that.props.apertureData.sub_type == 'default' ? React.createElement("g", null, React.createElement("line", { style: cell.dateType=='date' ? { 'strokeWidth':'2', 'stroke': that.props.apertureData.calLineColor } : { 'strokeWidth':'2', 'stroke': '#757575' }, x1: cell.x + cell.width, y1: cell.y, x2: cell.x + cell.width, y2: cell.y + cell.height}), React.createElement("line", { style: cell.dateType=='date' ? { 'strokeWidth':'2', 'stroke': that.props.apertureData.calLineColor } : { 'strokeWidth':'2', 'stroke': '#757575' }, x1: cell.x, y1: cell.y + cell.height, x2: cell.x + cell.width, y2: cell.y + cell.height}) ) : null, ((cell.dateType=='date' || cell.dateType=='day')) ? React.createElement("g", null, React.createElement(window.aperture, {svgModel: cell, scope: that.props.scope}, that.props.apertureData.sub_type == 'default' ? React.createElement("rect", {width: cell.width, height: cell.height, fillOpacity: "0"}) : null, cell.dateType=='date' ? React.createElement(window.imageAperture, {src: cell.src, apertureData: cell, svgModel: cell.image, scale: that.props.scale}) : null, React.createElement(window.textAperture, {apertureData: cell, svgModel: cell.text, scale: that.props.scale, dpi: that.props.dpi, type: that.props.apertureData.sub_type, alignmentPadding: 10}) ) ) : null ); }) ) : React.createElement("g", null, React.createElement(window.aperture, {svgModel: row, scope: that.props.scope}, React.createElement(window.textAperture, {apertureData: row, svgModel: row.text, scale: that.props.scale, dpi: that.props.dpi}) ) ) ); }) ); } });