I am trying to add text on screenshot. So my code is:
var system = require('system');
var args = system.args;
var WebPage = require('webpage');
page = WebPage.create();
page.viewportSize = { width: 480, height: 800 };
page.clipRect = { top: 0, left: 0, width: 1024, height: 768 };
page.open(args[1].toString());
page.onLoadFinished = function() {
page.render(args[1] + '.png');
phantom.exit();
}
I want to know how can i modify html content before rendering in order to add some text? I tried to use page.content but unsuccessfully.
Thanks.
You can modify html content with function "page.evaluate". With the function you can run a javascript on the page. Some simple examples can be found at http://phantomjs.org/api/webpage/method/evaluate.html.
Try to add something like the statement below before the render:
page.evaluate(function(str) {
document.querySelector('h2').textContent = str;
}, 'title');
Related
I have a jquery function that works out the width and height of an image I upload through umbraco. How can I call this.width and this.height into my img src in html at the bottom of the page?
<script>
function getMeta(varA, varB) {
if (typeof varB !== 'undefined') {
alert(varA + ' width ' + varB + ' height');
} else {
var img = new Image();
img.src = varA;
img.onload = function () {
getMeta(this.width, this.height);
}
}
}
getMeta("#image.Url()")
</script>
<img src="#image.Url()" width="" height="" border="0" alt="#Model.Value("mapImage")
mapImage" usemap="#Map" />
I've left the width and height empty but that's where I want it to equal this.width and this.height. I need it to automatically call it for other functions I have as it needs to change depending on the size of the image uploaded.
Thanks in advance for any help :)
Well.. good news - this is native JS - no jquery used the code you've posted
Second - you don't need to send the width and height to your data model - just update your image element. so...
img.onload = function () {
const imgElement = document.querySelector('img'); // select the image element in you HTML page
imgElement.style.width = `${this.width}px`; // set a proper with using pixels as unit
imgElement.style.height = `${this.height}px`; // set height the same way
}
This should update your image proportions to be an exact fit to the image provided
Assuming that I understood you well and you have an uploaded pic (that you get its source by calling #image.Url()), and you want to apply its dimensions of another pic (with id templateImg), this is the code:
<img id="templateImg" src="https://cdn.vox-cdn.com/thumbor/prZDWmD_4e4Js7KCRJ2JDrJOqO0=/0x0:939x704/1400x1050/filters:focal(0x0:939x704):format(jpeg)/cdn.vox-cdn.com/uploads/chorus_image/image/49610677/homersimpson.0.0.jpg" />
<script type = "text/javascript">
var uploadedPic = 'https://i.pinimg.com/736x/dd/50/38/dd5038cdbfde2a8f1583bd84f992f862.jpg';
function getMeta(src) {
return new Promise(resolve => {
var img = new Image();
img.src = src;
img.onload = function () {
resolve({
width: this.width,
height: this.height
});
}
})
}
getMeta(uploadedPic)
.then(dimensions => {
document.getElementById('templateImg').style.width = `${dimensions.width}px`;
document.getElementById('templateImg').style.height = `${dimensions.height}px`;
});
</script>
It was working example with real pictures, now you just replace the line var uploadedPic... with this Razor code:
<text>
var uploadedPic = '#image.Url()';
</text>
(assuming this is the path to your uploaded picture) and you'll be fine.
I have a very lengthy form in angular and i need to convert it into pdf. Since it is a very lengthy form i have to divide it into smaller chunks and show it in multiple pages in pdf. How can i achieve it. And i also need to add header and footer for every page.
I am using jsPDF and dom-to-image packages for pfd conversion.
Following is the code i wrote for pdf conversion:
exportPdf(){
var doc = new jsPDF('potrait','px','a4');
let imageData= new Image();
imageData.src='../../assets/images/testimg.png';
var filename="application";
var options={};
var img;
var newImage;
var node = document.getElementById('formContent');
var numRowsToCut=3;
var imagePieces=[];
domtoimage.toPng(node, { }).then(function(dataUrl)
{
img = new Image();
img.src = dataUrl;
newImage = img.src;
img.onload = function(){
var pdfWidth = img.width;
console.log("image width "+pdfWidth);
var pdfHeight = (img.height)/3;
var width = doc.internal.pageSize.getWidth();
console.log("width "+width);
var height = doc.internal.pageSize.getHeight();
for(var y = 0; y < numRowsToCut; ++y) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.drawImage(newImage, 0, y *pdfHeight, pdfWidth,pdfHeight, 0, 0,pdfWidth,pdfHeight);
imagePieces.push(canvas.toDataURL());
}
var docDefinition = {
content: [{
image: imagePieces[0],
width: 500,
pagebreak:'after'
},
{
image: imagePieces[1],
width: 500,
pagebreak:'after'
},
{
image: imagePieces[0],
width: 500,
pagebreak:'after'
}],
pageBreakBefore: function(currentNode) {
return currentNode.style && currentNode.style.indexOf('myDivClass') > -1;
}
};
pdfMake.createPdf(docDefinition).download(filename);
};
})
.catch(function(error) {
// Error Handling
console.log(error);
});
}
Any help will be appreciated.
I got the solution from a tutorial. Posting it here since it may help someone else.
Generate Multipage PDF using Single Canvas of HTML Document using jsPDF
How to Create Multipage PDF from HTML Using jsPDF and html2Canvas
I am adding background images to my div like this
ng-style="{'background-image' : 'url('+ myvariable.for.image +')'}">
where myvariable.for.image is a url like /examplesite/image/id
This works fine with one exception, if the image is not there it just doesnt do anything and my background looks too bla...If the image doesnt exist I want to be able to replace it with a default image.
But I cant seem to figure out how
Instead of ngStyle I'd use a custom directive for this. Such as the following. This checks to see if an attribute is provided, if so it attempts to load that image. If it loads an image then we set the background image to it, otherwise we use a default image.
myApp.directive('bgImage', function () {
return {
link: function(scope, element, attr) {
attr.$observe('bgImage', function() {
if (!attr.bgImage) {
// No attribute specified, so use default
element.css("background-image","url("+scope.defaultImage+")");
} else {
var image = new Image();
image.src = attr.bgImage;
image.onload = function() {
//Image loaded- set the background image to it
element.css("background-image","url("+attr.bgImage+")");
};
image.onerror = function() {
//Image failed to load- use default
element.css("background-image","url("+scope.defaultImage+")");
};
}
});
}
};
});
Used like this:
<div bg-image="{{person.src}}">
demo fiddle
<div err-bg-src='{{default_business_logo_wd}}' ng-style="{'background-image' : 'url('+ifNull(place.logo_wd,default_business_logo_wd)+')'}" id="perfilEstablecimiento-container10" class="place-header">
<div id="perfilEstablecimiento-container13" class="place-title-container">
<h4 id="perfilEstablecimiento-heading1" class="place-title">{{place.name}}</h4>
</div>
</div>
Using a $timeout inside that custom directive worked for me.
.directive
(
'errBgSrc',
function($timeout)
{
return {
link: function(scope, element, attrs)
{
$timeout
(
function()
{
if(window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage=='none'||window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage==null)
{
document.getElementById(attrs.id).style.backgroundImage='url('+attrs.errBgSrc+')';
}
else
{
var image = new Image();
var style=window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage;
var url=style.slice(5,style.length-2);
image.src = url;
image.onerror = function()
{
document.getElementById(attrs.id).style.backgroundImage='url('+attrs.errBgSrc+')';
};
}
},
500
);
}
}
}
)
I am having unexpected problems with a couple of Nvd3 charts. I coded them withouht using the nvd3 css file (nv.d3.min.css). Without it everything was ok but when I added it suddendly the second chart took a lot of space (1500x1500). The normal size was 450x450 but now it is
If i look in the console of chrome and uncheck the style atributes "width: 100%;" and "height: 100%;" it works (actually with only one). The other thing that changes de css atributes is the "user agent stylesheet".
I canĀ“t understand why because i thought that the size was explicitely coded while the configuration of the chart
HTML
<div id="charts">
<div id="piechart" ><svg></svg></div>
<div id="chart"><svg></svg></div>
</div>
NVD3
function setupGraph(data_graph) {
nv.addGraph(function() {
var pieChart = nv.models.pieChart();
pieChart.margin({top: 30, right: 60, bottom: 20, left: 60});
var datum = data_graph[0].values;
pieChart.tooltipContent(function(key, y, e, graph) {
var x = String(key);
var y = String(y);
tooltip_str = '<center><b>'+x+'</b></center>' + y;
return tooltip_str;
});
pieChart.showLabels(true);
pieChart.donut(false);
pieChart.showLegend(true);
pieChart
.x(function(d) { return d.label })
.y(function(d) { return d.value });
pieChart.width(450);
pieChart.height(450);
d3.select('#piechart svg')
.datum(datum)
.transition().duration(350)
.attr('width',450)
.attr('height',450)
.call(pieChart);
nv.utils.windowResize(chart.update);
return chart;
});
}
function setupGraph2(data_graph) {
nv.addGraph(function() {
var chart = nv.models.discreteBarChart()
.x(function(d) { return d.label }) //Specify the data accessors.
.y(function(d) { return d.value })
//.valueFormat(d3.format(',.2f'))
.staggerLabels(true) //Too many bars and not enough room? Try staggering labels.
.tooltips(false) //Don't show tooltips
.showValues(true) //...instead, show the bar value right on top of each bar.
.transitionDuration(350)
;
chart.width(450);
chart.height(450);
d3.select('#chart svg')
.datum(data_graph)
.attr('width',450)
.attr('height', 450)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
Can anybody see what is happening?
Just override the default width and height properties of the nvd3.css stylesheet, creating a rule in your stylesheet, and ensuring it is loaded after the nvd3 stylesheet.
The last rule (with the same specificity) wins:
svg {
width : auto;
height : auto;
}
or create a more specific rule to act on your svgs only, like:
#charts svg {
width : 450px;
height : 450px;
}
I'm having problems with resizing cells and built-in mxGraph layouts.
If I put a cell on canvas, and I try to resize it, even for a pixel, it grows huge, something like 50000px x 30000px, so it streches my whole canvas, and of course it is unusable.
If I load a graph from an xml file from the database, I can resize cells without any problems.
Similar thing happens with the built in layouts. I'd like to use compact tree layout (the reason I like it beacuse it aligns my whole horizontal).
When I draw a graph and try to use that layout, my graph goes wild, also streching to 50000px x 30000 px (example dimensions, but the scroll is so tiny I can barely aim it with the mouse).
If I load a graph from xml from a database, compact tree layout works perfect. But as soon as I add another cell in it, and try to use compact tree layout again, it goes wild, again.
I use absolute positioning for div which holds the canvas, as same as on the example here (http://jgraph.github.io/mxgraph/javascript/examples/editors/workfloweditor.html)
This is my css and html :
<head>
<style type="text/css">
#graphContainer {
background: url('../../resources/jgraph/src/images/grid.gif');
left: 20px;
right: 20px;
top: 65px;
bottom: 20px;
position: absolute;
border: 1px solid #F2F2F2;
white-space: nowrap;
font-family: Arial;
font-size: 8pt;
display: block;
}
</style>
</head>
<body>
<div id="graphContainer"></div>
<script>
$(document).ready(function(){
mc.init(document.getElementById('graphContainer'));
});
</script>
</body>
</html>
And this is my javascript for graph initialization (along with the couple of events, beacuse I'm not sure if they are the problem):
mxConnectionHandler.prototype.connectImage = new mxImage('../../resources/jgraph/src/images/connector.gif', 14, 14);
if (!mxClient.isBrowserSupported()) {
mxUtils.error('Browser is not supported!', 200, false);
} else {
var root = new mxCell();
root.insert(new mxCell());
var model = new mxGraphModel(root);
if (mxClient.IS_QUIRKS)
{
document.body.style.overflow = 'hidden';
new mxDivResizer(graphContainer);
}
var editor = new mxEditor();
editor.setGraphContainer(graphContainer);
editor.readGraphModel(model);
var graph = editor.graph;
graph.setConnectable(true);
new mxRubberband(graph);
/* CODE FOR ADDING THE TOOLBAR, excluded from example */
//code for writing out the node name
graph.convertValueToString = function(cell)
{
if (mxUtils.isNode(cell.value))
{
var outValue = cell.value.getAttribute('nodeName');
if (outValue != null && outValue.length > 0)
{
return outValue;
}
return '';
}
return '';
};
//defining on select event
graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt)
{
events.cellSelectionChanged(graph, graph.getSelectionCell());
});
//triggering the on select event
events.cellSelectionChanged(graph);
//cells added event
graph.addListener(mxEvent.CELLS_ADDED, function(sender, evt) {
var vertex = evt.getProperties().cells[0];
if(vertex.isVertex()){
var decoder = new mxCodec();
var nodeModel = decoder.decode(vertex.value);
if(nodeModel.type=='node' || nodeModel.type=='branch'){
utils.changeCellAttribute(vertex, 'nodeName', 'Node_' + vertex.id);
}else if(nodeModel.type=='start'){
utils.changeCellAttribute(vertex, 'nodeName', 'START');
}else if(nodeModel.type=='end'){
utils.changeCellAttribute(vertex, 'nodeName', 'END');
}else if(nodeModel.type=='form'){
utils.changeCellAttribute(vertex, 'nodeName', 'Form');
}
}
});
//on connect event
graph.connectionHandler.addListener(mxEvent.CONNECT, function(sender, evt){
var model = graph.getModel();
var edge = evt.getProperty('cell');
var source = model.getTerminal(edge, true);
var target = model.getTerminal(edge, false);
});
}
Any thoughts what the problem might be?
Solution:
Complete graph and cell configuration is loaded from the database (in this example), including the width and height for the cells.
The problem was adding toolbar items for certain cell types, more precise, dropped cell default width and height. As I said we are loading the configuration from the database, it is completely string-ified, so were the width and height.
They both had to be cast to JavaScript Number object for resize and layout to behave properly.