PhantomJs with Node - javascript

I m trying to use phantomjs with node to get screen shots on a webpage.
I have almost all of it but I face issue in scrolling.
I have used scroll-position but it does not scroll correctly.
phantom.create()
.then(instance => {
return instance.createPage();
})
.then(page => {
_pageInstance = page;
return _pageInstance.open('xyz')})
.then(){ () => {
detailPage = _pageInstance.evaluate(function() {
var pageSettings = {
scrollToPos: [],
elementHeight: [],
offsetLeft: []
};
jQuery('li.diff-comment-activity').each(function(index, item) {
var offsetTop = jQuery('li.diff-comment-activity .detail')[index].offsetTop;
var elmntHeight = jQuery('li.diff-comment-activity .detail')[index].offsetHeight;
var offsetLeft = jQuery('li.diff-comment-activity')[index].offsetLeft;
pageSettings.scrollToPos.push(offsetTop);
pageSettings.elementHeight.push(elmntHeight);
pageSettings.offsetLeft.push(offsetLeft);
});
return pageSettings;
});
setTimeout(function() {
console.log('Getting your screen shots...');
detailPage.then(function(detail) {
_details = detail;
_pageInstance.property('viewportSize', {
width: 1920,
height: 1040
});
_details.scrollToPos.forEach(function(value, index) {
_pageInstance.property('scrollPosition', {
top: value
});
_pageInstance.property('clipRect', {
top: 10,
left: 300,
width: 1400,
height: _details.elementHeight[index]
});
console.log('value ' + value);
_pageInstance.render('Image_' + index + '.jpeg', {
format: 'jpeg',
quality: '100'
});
});
});
console.log('Done');
}, 5000);
}
Here i have used jquery to get the offset top of all the elements and then used scrollposition to reach that element and then clip rect to get the screen shot.
But for few screen shots the page just scroll beyond the offset top.
*
The intresting part is when I run the code using only phamtomJS it
works fine.
*
Any help ..

Related

interact.js prevent resizable elements from overlapping

I am using the interact.js library for drag-and-dropping elements inside a grid. Once it is inside my grid I want to be able to resize them which is working, but what is the recommend way for preventing two resizable elements from overlapping. I basically want to stop the resizable move listener when it hits another resizable element. I already know when one resizable elements hits another, But how do I prevent the user from being able to overlap them?
full function for resizing elements:
function resizeZone(target, parentContainer, minHeight, width) {
if (interact.isSet(target) == false) {
interact(target)
.resizable({
edges: { top: true, left: false, bottom: true, right: false },
listeners: {
start: function (event) {
startDataSet = event.target.dataset;
startDeltaRect = event.deltaRect;
startRect = event.rect;
},
move: function (event) {
var elementsAtDragLocation = document.elementsFromPoint(event.x0, event.client.y);
for (let elementId in elementsAtDragLocation) {
var result = elementsAtDragLocation[elementId].getAttribute('free-schedule');
var isFalseSet = (result === 'false');
if (isFalseSet) {
let dragLocationRoutineId = elementsAtDragLocation[elementId].id;
let routineId = event.target.id;
// if user drags element past other element they will overlap, because the isFalseSet check won't work =(
if (dragLocationRoutineId !== routineId) {
return;
}
}
}
let { x, y } = event.target.dataset
x = (parseFloat(x) || 0) + event.deltaRect.left
y = (parseFloat(y) || 0) + event.deltaRect.top
Object.assign(event.target.style, {
width: `${event.rect.width}px`,
height: `${event.rect.height}px`,
transform: `translate(${x}px, ${y}px)`
});
Object.assign(event.target.dataset, { x, y });
},
end: async function (event) {
let routineId = event.target.id;
ResizeTaskTrigger(routineId, event.rect.height, event.deltaRect);
},
},
modifiers: [
interact.modifiers.restrictSize({
min: { width: width, height: minHeight },
}),
interact.modifiers.restrictRect({
restriction: parentContainer
}),
],
});
}
}

Jqgrid frozen columns - can't get them to freeze unless I manually resize the grid

I have read every post I can find on Frozen columns in jqgrid. And have implemented the following code.
The result... when I go to my spreadsheet grid in my app the 3 cols are NOT frozen. BUt if I drag the little resize icon in the lower left ever so slightly then POP they 3 columns are now frozen.
Why doesn't it work when the spreadsheet is first drawn?
Here's the code:
var $grid = $("#list4");
var resizeColumnHeader = function () {
var rowHight, resizeSpanHeight,
// get the header row which contains
headerRow = $(this).closest("div.ui-jqgrid-view")
.find("table.ui-jqgrid-htable>thead>tr.ui-jqgrid-labels");
// reset column height
headerRow.find("span.ui-jqgrid-resize").each(function () {
this.style.height = '';
});
// increase the height of the resizing span
resizeSpanHeight = 'height: ' + headerRow.height() + 'px !important; cursor: col-resize;';
headerRow.find("span.ui-jqgrid-resize").each(function () {
this.style.cssText = resizeSpanHeight;
});
// set position of the dive with the column header text to the middle
rowHight = headerRow.height();
headerRow.find("div.ui-jqgrid-sortable").each(function () {
var $div = $(this);
$div.css('top', (rowHight - $div.outerHeight()) / 2 + 'px');
});
};
var fixPositionsOfFrozenDivs = function () {
var $rows;
if (this.grid === undefined) {
return;
}
if (this.grid.fbDiv !== undefined) {
$rows = $('>div>table.ui-jqgrid-btable>tbody>tr', this.grid.bDiv);
$('>table.ui-jqgrid-btable>tbody>tr', this.grid.fbDiv).each(function (i) {
var rowHight = $($rows[i]).height(), rowHightFrozen = $(this).height();
if ($(this).hasClass("jqgrow")) {
$(this).height(rowHight);
rowHightFrozen = $(this).height();
if (rowHight !== rowHightFrozen) {
$(this).height(rowHight + (rowHight - rowHightFrozen));
}
}
});
$(this.grid.fbDiv).height(this.grid.bDiv.clientHeight+1);
$(this.grid.fbDiv).css($(this.grid.bDiv).position());
}
if (this.grid.fhDiv !== undefined) {
$rows = $('>div>table.ui-jqgrid-htable>thead>tr', this.grid.hDiv);
$('>table.ui-jqgrid-htable>thead>tr', this.grid.fhDiv).each(function (i) {
var rowHight = $($rows[i]).height(), rowHightFrozen = $(this).height();
$(this).height(rowHight);
rowHightFrozen = $(this).height();
if (rowHight !== rowHightFrozen) {
$(this).height(rowHight + (rowHight - rowHightFrozen));
}
});
$(this.grid.fhDiv).height(this.grid.hDiv.clientHeight);
$(this.grid.fhDiv).css($(this.grid.hDiv).position());
}
};
var fixGboxHeight = function () {
var gviewHeight = $("#gview_" + $.jgrid.jqID(this.id)).outerHeight(),
pagerHeight = $(this.p.pager).outerHeight();
$("#gbox_" + $.jgrid.jqID(this.id)).height(gviewHeight + pagerHeight);
gviewHeight = $("#gview_" + $.jgrid.jqID(this.id)).outerHeight();
pagerHeight = $(this.p.pager).outerHeight();
$("#gbox_" + $.jgrid.jqID(this.id)).height(gviewHeight + pagerHeight);
};
$grid.jqGrid({
datatype: "local",
shrinkToFit:false,
autowidth:true,
height: 450,
hoverrows: true,
sortable: false,
colNames:[' <br> <br> <br> <br>Year',
' <br> <br> <br>Your<br>Age',
' <br> <br> <br>Spouse<br>Age',
'Your Annual<br>Job<br>Income',
'Spouse Annual<br>Job<br>Income'
colModel:[
{name:'year',index:'year', width:50, align:"center",sortable:false, sorttype:"int",classes:'spreadsheet_cell0', frozen:true},
{name:'age0',index:'age0', width:50, align:"center",sortable:false, sorttype:"int",frozen:true},
{name:'age1',index:'age1', width:50, align:"center",sortable:false, sorttype:"int",frozen:true},
{name:'salary0',index:'salary0', width:100, align:"right",sortable:false,sorttype:"float",formatter:'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 0, prefix: "$"}},
{name:'salary1',index:'salary1', width:100, align:"right",sortable:false,sorttype:"float",formatter:'currency', formatoptions:{decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 0, prefix: "$"}}
],
multiselect: false,
rowNum:20,
rowList:[10,20],
altRows:false,
onSelectRow: function (id) {
if (id && id!=previous_row) {
previous_row=id;
}
},
loadComplete: function () {
fixPositionsOfFrozenDivs.call(this);
}
});
// ADD DATA TO THE GRID
addData();
$grid.jqGrid('gridResize', {
minWidth: 450,
stop: function () {
fixPositionsOfFrozenDivs.call(this);
fixGboxHeight.call(this);
}
});
$grid.bind("jqGridResizeStop", function () {
resizeColumnHeader.call(this);
fixPositionsOfFrozenDivs.call(this);
fixGboxHeight.call(this);
});
$(window).on("resize", function () {
// apply the fix an all grids on the page on resizing of the page
$("table.ui-jqgrid-btable").each(function () {
fixPositionsOfFrozenDivs.call(this);
//fixGboxHeight.call(this);
});
});
// after all that freeze the cols and fix the divs
resizeColumnHeader.call($grid[0]);
$grid.jqGrid('setFrozenColumns');
$grid.triggerHandler("jqGridAfterGridComplete");
fixPositionsOfFrozenDivs.call($grid[0]);

Fabric.js - Constrain Resize/Scale to Canvas/Object

How can an object be constrained to being resized/scaled only within the bounds of the canvas (or another object in my case) when using Fabric.js?
Currently, I'm handling the object:scaling event:
// Typescript being used;
onObjectScaling = (event): boolean => {
// Prevent scaling object outside of image
var object = <fabric.IObject>event.target;
var objectBounds: BoundsHelper;
var imageBounds: BoundsHelper;
object.setCoords();
objectBounds = new BoundsHelper(object);
imageBounds = new BoundsHelper(this.imageManipulatorContext.getImageObject());
if (objectBounds.left < imageBounds.left || objectBounds.right > imageBounds.right) {
console.log('horizontal bounds exceeded');
object.scaleX = this.selectedObjectLastScaleX;
object.lockScalingX = true;
object.setCoords();
} else {
this.selectedObjectLastScaleX = object.scaleX;
}
if (objectBounds.top < imageBounds.top || objectBounds.bottom > imageBounds.bottom) {
console.log('vertical bounds exceeded');
object.scaleY = this.selectedObjectLastScaleY;
object.lockScalingY = true;
object.setCoords();
} else {
this.selectedObjectLastScaleY = object.scaleY;
}
return true;
}
**edit The BoundsHelper class is just a helper for wrapping up the math of calculating the right/bottom sides of the bounding box for an object.
import fabric = require('fabric');
class BoundsHelper {
private assetRect: { left: number; top: number; width: number; height: number; };
get left(): number { return this.assetRect.left; }
get top(): number { return this.assetRect.top; }
get right(): number { return this.assetRect.left + this.assetRect.width; }
get bottom(): number { return this.assetRect.top + this.assetRect.height; }
get height(): number { return this.assetRect.height; }
get width(): number { return this.assetRect.width; }
constructor(asset: fabric.IObject) {
this.assetRect = asset.getBoundingRect();
}
}
export = BoundsHelper;
I also make use of the onBeforeScaleRotate callback to disable the scaling lock added by the above:
onObjectBeforeScaleRotate = (targetObject: fabric.IObject): boolean => {
targetObject.lockScalingX = targetObject.lockScalingY = false;
return true;
}
The issue I observe is that it seems like Fabric doesn't redraw the object fast enough for me to accurately detect that scale is passing the image's boundary. In other words, if I scale slowly, then life is good; if I scale quickly, then I can scale outside of the image's bounds.
It is not about speed.
Events are discrete sampling of something you are doing with the mouse.
Even if you move pixel by pixel virtually, the mouse has its own sample rate and the javascript event do not fire every pixel you move when you go fast.
So if you limit your application to stop scaling when you overcome a limit, when you overcome this limit you will stop your scaling, some pixel after the limit, simply because the last check you were 1 pixel before bound, the event after you are 10 pixel after it.
I changed the code, that is not perfect at all, but gives you idea for dealing with the issue.
When you overcome the limit, instead of lock scaling, calculate the correct scaling to be inside the image and apply that scale.
This logic has problems when you are completely outside the image, so i placed the rect already in, just to demonstrate the different approach.
var BoundsHelper = (function () {
function BoundsHelper(asset) {
this.assetRect = asset.getBoundingRect();
}
Object.defineProperty(BoundsHelper.prototype, "left", {
get: function () {
return this.assetRect.left;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundsHelper.prototype, "top", {
get: function () {
return this.assetRect.top;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundsHelper.prototype, "right", {
get: function () {
return this.assetRect.left + this.assetRect.width;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundsHelper.prototype, "bottom", {
get: function () {
return this.assetRect.top + this.assetRect.height;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundsHelper.prototype, "height", {
get: function () {
return this.assetRect.height;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BoundsHelper.prototype, "width", {
get: function () {
return this.assetRect.width;
},
enumerable: true,
configurable: true
});
return BoundsHelper;
})();
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
var canvas = new fabric.Canvas('c');
var rectangle = new fabric.Rect({
fill: 'black',
originX: 'left',
originY: 'top',
stroke: 'false',
opacity: 1,
left: 180,
top: 180,
height: 50,
width: 50
});
var rectangleBounds = new BoundsHelper(rectangle);
var image = new fabric.Image(i, {
selectable: false,
borderColor: 'black',
width: 200,
height: 200
});
canvas.on("object:scaling", function (event) {
var object = event.target;
var objectBounds = null;
var imageBounds = null;
var desiredLength;
object.setCoords();
objectBounds = new BoundsHelper(object);
imageBounds = new BoundsHelper(image);
if (objectBounds.left < imageBounds.left) {
object.lockScalingX = true;
// now i have to calculate the right scaleX factor.
desiredLength =objectBounds.right - imageBounds.left;
object.scaleX = desiredLength / object.width;
}
if (objectBounds.right > imageBounds.right) {
object.lockScalingX = true;
desiredLength = imageBounds.right - objectBounds.left;
object.scaleX = desiredLength / object.width;
}
if (objectBounds.top < imageBounds.top) {
object.lockScalingY = true;
desiredLength = objectBounds.bottom - imageBounds.top;
object.scaleY = desiredLength / object.height;
}
if (objectBounds.bottom > imageBounds.bottom) {
object.lockScalingY = true;
desiredLength = imageBounds.bottom - objectBounds.top;
object.scaleY = desiredLength / object.height;
}
return true;
});
canvas.onBeforeScaleRotate = function (targetObject) {
targetObject.lockScalingX = targetObject.lockScalingY = false;
return true;
};
canvas.on('after:render', function() {
canvas.contextContainer.strokeStyle = '#555';
var bound = image.getBoundingRect();
canvas.contextContainer.strokeRect(
bound.left + 0.5,
bound.top + 0.5,
bound.width,
bound.height
);
});
canvas.add(image);
canvas.centerObject(image);
image.setCoords();
canvas.add(rectangle);
canvas.renderAll();
img {
display: none;
}
canvas {
border: solid black 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.12/fabric.min.js"></script>
<img id="i" src="http://fabricjs.com/assets/ladybug.png" />
<canvas id="c" width="500" height="500"></canvas>
https://jsfiddle.net/84zovnek/2/
if (objectBounds.left < imageBounds.left) {
//object.lockScalingX = true;
// now i have to calculate the right scaleX factor.
desiredLength = imageBounds.left - objectBounds.right;
object.scaleX = desiredLength / object.width;
}
Other that, you should update to latest version

CasperJS viewport & viewportSize not resizing browser

Is anyone having any issues lately with the CasperJS or PhantomJS viewport or viewportSize?
I've tried using
page.viewportSize = {width: 1280, height: 1024};
casper.start()
.viewport(800, 600);
casper.options.viewportSize = {width: 1290, height: 1024};
No matter where I put them in the code the browser size still stays the default 300, 400.
/*jshint strict:false*/
/*global CasperError, console, phantom, require*/
var links = [];
var casper = require("casper").create();
var w = window.innerWidth;
var h = window.innerHeight;
function getLinks() {
var links = document.querySelectorAll("h3.r a");
return Array.prototype.map.call(links, function(e) {
try {
// google handles redirects hrefs to some script of theirs
return (/url\?q=(.*)&sa=U/).exec(e.getAttribute("href"))[1];
} catch (err) {
return e.getAttribute("href");
}
});
}
casper.options.viewportSize = {width: 1600, height: 950};
casper.start("http://google.fr/", function() {
// search for 'casperjs' from google form
this.viewport(900, 800);
this.fill('form[action="/search"]', { q: "casperjs" }, true);
});
casper.then(function() {
// aggregate results for the 'casperjs' search
links = this.evaluate(getLinks);
// now search for 'phantomjs' by fillin the form again
this.fill('form[action="/search"]', { q: "phantomjs" }, true);
});
casper.then(function() {
// aggregate results for the 'phantomjs' search
links = links.concat(this.evaluate(getLinks));
});
console.log("Height==> " + h);
console.log("Width==> " + w);
casper.run(function() {
// echo results in some pretty fashion
this.echo(links.length + " links found:");
this.echo(" - " + links.join("\n - "));
this.exit();
});

How can a restart a loop in an animation?

I am trying to build a game like space invader (since I only started coding 5 days ago) where if a shoe hits the zombie, the zombie will disappear and reappear at the top of the screen (coming down again). I just can't seem to make the zombie go back to the top (they remain at the lowest point of the animation)
Below is the test for the collision:
function zombietestCollision(position1, size1, position2, size2) {
if (((position1.left + size1.width) > position2.left) &&
((position1.top + size1.height) > position2.top) &&
((position2.left + size2.width) > position1.left) &&
((position2.top + size2.height) > position1.top)) {
function loop () {
movedown($zombie);
moveup($zombie);
};
$(function zombieloop() {
setInterval( loop, 1 );
});
}
}
I have encompassed this test in my downward movement of the zombie
// down movement of the zombies
function movedown($zombie) {
$zombie.animate({
'left': 300,
}, {
duration:5000,
step:function(){
$.each($("#zombie"), function(index,zombie) {
var $zombie = $(zombie);
var $shoe = $("#shoe");
var shoeSize = {
height: $shoe.height(),
width : $shoe.width()
};
var zombieSize = {
height: $zombie.height(),
width : $zombie.width()
};
zombietestCollision($shoe.position(), shoeSize, $zombie.position(), zombieSize);
});
}
When I run this, the screen is just blank. What have I done in correctly?
If needed here is the full code: http://jsfiddle.net/JKd9K/7/
Sorry but I am completely new to programming, so it's hard for me to understand which part I did wrong. Cheers!
You need to be careful with how you're closing functions. Take a look at this http://jsfiddle.net/JKd9K/2/
Your movedown function should be like this
function movedown($zombie) {
$zombie.animate({
'left': 300
}, {
duration: 5000,
step: function() {
$.each($("#zombie"), function(index, zombie) {
var $zombie = $(zombie);
var $shoe = $("#shoe");
var shoeSize = {
height: $shoe.height(),
width: $shoe.width()
};
var zombieSize = {
height: $zombie.height(),
width: $zombie.width()
};
zombietestCollision(
$shoe.position(),
shoeSize,
$zombie.position(),
zombieSize);
});
}
});
}
Note that there's a bunch of extra braces at the end.

Categories

Resources