I'm trying to create a simple qUnit test that should run in grunt and phantomJs using grunt-contrib-qunit.
The test runs fine in qUnit, but fails when using grunt and phantomJS.
The test code is:
test("testing the filter", function() {
var img = new Image(3, 2);
// this is a 3x2 image
img.src = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAIAAAASFvFNAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wIFDScubGmL8QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAG0lEQVQI1wXBAQ0AAAwCINz7hzKZhwzDLjTaPDVzBUhAyQZRAAAAAElFTkSuQmCC";
var canvas = document.createElement('canvas');
canvas.width = 3,
canvas.height = 2;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
ok(ctx.getImageData(0,0,1,1).data[0] === 255, 'Expected red-pixel to be 255, actually is ' + ctx.getImageData(0,0,1,1).data[0])
})
When I run this in a browser based qUnit, the test passes. When I run this in Grunt, using PhantomJS and qUnit, the test fails. As best I can tell, drawImage is failing silently, so it's not writing the pixels.
Everything else seems to be working correctly. All my other tests run fine, including DOM manipulation tests. It's just this one function that doesn't appear to work correctly.
It turns out that I was making this much more complex than it had to be. The image simply wasn't loaded at the time I was trying to draw the canvas. Fortunately, there is a way to do an asynchronous test in qUnit, so all I had to do was run the test after the image was loaded.
The weirdness was that it was running correctly in the browser based qUnit tests, but not phantomJs.
The working code is below:
test("testing the filter", function( assert ) {
var done = assert.async();
var img = document.createElement('img');
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 3,
canvas.height = 2;
img.addEventListener("load", function() {
ctx.drawImage(img, 0, 0);
ok(ctx.getImageData(0,0,1,1).data[0] === 255, 'Expected red-pixel to be 255, actually is ' + ctx.getImageData(0,0,1,1).data[0]);
done();
})
// this is a 3x2 image
img.src = "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAIAAAASFvFNAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wIFDScubGmL8QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAG0lEQVQI1wXBAQ0AAAwCINz7hzKZhwzDLjTaPDVzBUhAyQZRAAAAAElFTkSuQmCC";
})
Related
I'm trying to build a widget in Jupyter Notebook that uses Fabric.js (http://fabricjs.com/), however I'm getting an error that is a blocker for me. The most basic solution I need is just to make the widget output a canvas with an interactive red rectangle, like what you find on the Fabric.js homepage:
What I've tried so far:
I started from the basic "Hello World" tutorial (https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Custom.html) which is the basis for the four cells below, and I tried to add a simple example from the fabric node webpage to create a red rectangle. Here are the cells I have in Jupyter notebook:
Cell 1:
%%HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min.js" type="text/javascript"></script>
Cell 2:
import ipywidgets as widgets
from traitlets import Unicode, validate
class HelloWidget(widgets.DOMWidget):
_view_name = Unicode('HelloView').tag(sync=True)
_view_module = Unicode('hello').tag(sync=True)
_view_module_version = Unicode('0.1.0').tag(sync=True)
Cell 3:
%%javascript
require.undef('hello');
define('hello', ["#jupyter-widgets/base"], function(widgets) {
var HelloView = widgets.DOMWidgetView.extend({
render: function() {
var canvas = document.createElement('canvas');
canvas.id = 'canvas';
canvas.width = 1000;
canvas.height = 500;
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
this.el.appendChild(canvas);
var fabricCanvas = new fabric.Canvas(canvas);
var rect = new fabric.Rect({
top : 100,
left : 100,
width : 60,
height : 70,
fill : 'red'
});
fabricCanvas.add(rect);
},
});
return {
HelloView : HelloView
};
});
Cell 4:
HelloWidget()
However, I unfortunately get the following error in the JS console and it doesn't make the red square:
Please help me fix the code to make it work!
My problem was I didn't understand how require.js works... :/
Here's how I fixed the problem:
%%javascript
require.undef('hello');
require.config({
//Define 3rd party plugins dependencies
paths: {
fabric: "https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min"
}
});
define('hello', ["#jupyter-widgets/base", 'fabric'], function(widgets) {...
I wonder how can I use css/javascript to adjust the blinking cursor inside the search box with CSS?
Is it possible to replace default blinkig caret to horizontal blinking icon
I don't think it is so hard. I made a quick example, which works in most modern browsers except Safari.
It draws the caret on a canvas, and sets it as a background of the input, on a position calculated from the browsers caret position.
It checks if the browser supports the caret-color css property, and if it doesn't it doesn't do anything, because both the system caret, and our caret will be visible in the same time. From the browsers I tested, only Safari doesn't support it.
$("input").on('change blur mouseup focus keydown keyup', function(evt) {
var $el = $(evt.target);
//check if the carret can be hidden
//AFAIK from the modern mainstream browsers
//only Safari doesn't support caret-color
if (!$el.css("caret-color")) return;
var caretIndex = $el[0].selectionStart;
var textBeforeCarret = $el.val().substring(0, caretIndex);
var bgr = getBackgroundStyle($el, textBeforeCarret);
$el.css("background", bgr);
clearInterval(window.blinkInterval);
//just an examplethis should be in a module scope, not on window level
window.blinkInterval = setInterval(blink, 600);
})
function blink() {
$("input").each((index, el) => {
var $el = $(el);
if ($el.css("background-blend-mode") != "normal") {
$el.css("background-blend-mode", "normal");
} else {
$el.css("background-blend-mode", "color-burn");
}
});
}
function getBackgroundStyle($el, text) {
var fontSize = $el.css("font-size");
var fontFamily = $el.css("font-family");
var font = fontSize + " " + fontFamily;
var canvas = $el.data("carretCanvas");
//cache the canvas for performance reasons
//it is a good idea to invalidate if the input size changes because of the browser text resize/zoom)
if (canvas == null) {
canvas = document.createElement("canvas");
$el.data("carretCanvas", canvas);
var ctx = canvas.getContext("2d");
ctx.font = font;
ctx.strokeStyle = $el.css("color");
ctx.lineWidth = Math.ceil(parseInt(fontSize) / 5);
ctx.beginPath();
ctx.moveTo(0, 0);
//aproximate width of the caret
ctx.lineTo(parseInt(fontSize) / 2, 0);
ctx.stroke();
}
var offsetLeft = canvas.getContext("2d").measureText(text).width + parseInt($el.css("padding-left"));
return "#fff url(" + canvas.toDataURL() + ") no-repeat " +
(offsetLeft - $el.scrollLeft()) + "px " +
($el.height() + parseInt($el.css("padding-top"))) + "px";
}
input {
caret-color: transparent;
padding: 3px;
font-size: 15px;
color: #2795EE;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
If there is interest, I can clean it a bit and wrap it in a jQuery plugin.
Edit: forgot about the blinking, so I added it. A better way will be to add it as css animation, in this case the caret should be in a separate html element positioned over the input.
Changing the color of the caret is supported by the latest standards. But not changing its width is not, which I think is a shame because it is a question of accessibility for vision-impaired people.
One approach for implementing such a change yourself is first trying to figure out what is the position the caret is blinking at, then overlaying it with an element that looks like the caret but is perhaps wider etc.
Here's an article on how to go about doing such a thing. It's a good article but the end-solution is kind of complicated as a whole. But see if it solves your problem:
https://medium.com/#jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
Here is perhaps a simpler explanation for how to find the care x-y position:
How do I get the (x, y) pixel coordinates of the caret in text boxes?
I'm trying to export the html part as a pdf file using html2canvas and jsPDF libraries. However, this functionality is working fine in IE and the contents that are available in the window scope is available in the exported pdf where the content inside the scroll bar is not available in chrome. The part has multiple rows where each row is iterated using angularjs ng-repeat and each row has customized css part. Each row should be exported with the applied css and the dynamic data that is available in the screen. Posting the codefor your reference,
Chrome Image
IE Image
Script Code:
$scope.exportFunctionViewData = function(){
html2canvas(document.getElementById('functionViewExport') , {
onrendered: function (canvas) {
var content = canvas.toDataURL('image/jpeg');
var imgWidth = 210;
var pageHeight = 295;
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
var doc = new jsPDF('p', 'mm');
var position = 0;
doc.addImage(content, 'JPEG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(content, 'JPEG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
}
doc.save($scope.title + '-FunctionView.pdf');
}
});
};
I'm trying to enable infinite scroll for an angular-meteor app I'm working on that draws objects from a meteor/mongo collection.
I've adapted step 12 of the angular-meteor tutorial to use pagination for the app I'm working on, and now I'd like to convert to infinite scrolling. I've been trying to adapt both the code from the tutorial and this example from ngInfiniteScroll for my purposes.
I imagine I'll need to use reactive variables, autorun, etc. similar to the tutorial, but I don't really know how to adapt it for infinite scroll. Considering the example below, how should I adjust my controller for it to use infinite scrolling, drawing from a database, with good angular-meteor practices for production?
Demo ngInfiniteScroll HTML:
<div infinite-scroll='loadMore()' infinite-scroll-distance='2'>
<img ng-repeat='image in images' ng-src='http://placehold.it/225x250&text={{image}}'>
</div>
Demo ngInfiniteScroll Function inside controller:
$scope.images = [1, 2, 3, 4, 5, 6, 7, 8];
$scope.loadMore = function() {
var last = $scope.images[$scope.images.length - 1];
for(var i = 1; i <= 8; i++) {
$scope.images.push(last + i);
}
};
My angular-meteor pagination code inside controller:
$scope.page = 1;
$scope.perPage = 1;
$scope.sort = {'_id': -1};
$scope.orderProperty = '1';
$scope.images = $meteor.collection(function() {
return Images.find({}, {
sort : $scope.getReactively('sort')
});
});
$meteor.autorun($scope, function() {
$meteor.subscribe('images', {
limit: parseInt($scope.getReactively('perPage')),
skip: (parseInt($scope.getReactively('page')) - 1) * parseInt($scope.getReactively('perPage')),
sort: $scope.getReactively('sort')
}).then(function(){
$scope.imagesCount = $meteor.object(Counts ,'numberOfImages', false);
});
});
$scope.pageChanged = function(newPage) {
$scope.page = newPage;
};
Please look at this basic example https://github.com/barbatus/ng-infinite-scroll.
Controller there re-subscribes every time onLoadMore is executed.
There is also a deployed demo http://ng-infinite-scroll.meteor.com.
Make sure this time angular.module('infinite-scroll').value('THROTTLE_MILLISECONDS', 500) is set properly (not very small) to avoid very frequent requests.
I'm trying to take a div and basically put it in a child window. The domains are going to be the same so I figure I could do the flowing ( where parm win is the div ).
popOut = function ( win )
{
var newWindow = window.open( "about:blank", "", "toolbar=yes, scrollbars=yes, resizable=yes, top=500, left=500, width=400, height=400", false );
newWindow.onload = function ()
{
this.focus
this.document.body.appendChild( win );
};
}
This seems to do the job but the css is clobbered. In thinking about this, the new window certainly knows nothing of the includes and css files. Can I copy or inject this info over somehow?
Would I be correct in assuming the new window knows nothing of its parent, thus no function can be ran from child to parent?
New window is definitely aware of its opener as well as opener aware of the popup. If the problem is new window not seeing opener styles, the following code should copy styles from opener to popup.
Place this after var newWindow = window.open(...)
var linkrels = document.getElementsByTagName('link');
for (var i = 0, max = linkrels.length; i < max; i++) {
if (linkrels[i].rel && linkrels[i].rel == 'stylesheet') {
var thestyle = document.createElement('link');
var attrib = linkrels[i].attributes;
for (var j = 0, attribmax = attrib.length; j < attribmax; j++) {
thestyle.setAttribute(attrib[j].nodeName, attrib[j].nodeValue);
}
newWindow.document.documentElement.appendChild(thestyle);
}
}
I haven't got a chance to test it, but something like this should work.