What is wrong with my coffeescript translation of this JS? - coffeescript

Trying to improve my Coffeescript skills, so thought I'd covert this jcrop demo. However it's not working as expect. Specifically, the redraw function does not appear to be being called.
This works fine.
// Create a new Selection object extended from Selection
var CircleSel = function(){ };
// Set the custom selection's prototype object to be an instance
// of the built-in Selection object
CircleSel.prototype = new $.Jcrop.component.Selection();
// Then we can continue extending it
$.extend(CircleSel.prototype,{
zoomscale: 1,
attach: function(){
this.frame.css({
background: 'url(' + $('#target')[0].src.replace('750','750') + ')'
});
},
positionBg: function(b){
var midx = ( b.x + b.x2 ) / 2;
var midy = ( b.y + b.y2 ) / 2;
var ox = (-midx*this.zoomscale)+(b.w/2);
var oy = (-midy*this.zoomscale)+(b.h/2);
//this.frame.css({ backgroundPosition: ox+'px '+oy+'px' });
this.frame.css({ backgroundPosition: -(b.x+1)+'px '+(-b.y-1)+'px' });
},
redraw: function(b){
// Call original update() method first, with arguments
$.Jcrop.component.Selection.prototype.redraw.call(this,b);
this.positionBg(this.last);
return this;
},
prototype: $.Jcrop.component.Selection.prototype
});
But when I try to write this in Coffescript it fails
CircleSel.prototype = new ($.Jcrop.component.Selection)
$.extend CircleSel.prototype,
zoomscale: 1
attach: ->
#frame.css background: 'url(' + $('#target')[0].src.replace('750', '750') + ')'
return
positionBg: (b) ->
midx = (b.x + b.x2) / 2
midy = (b.y + b.y2) / 2
ox = -midx * #zoomscale + b.w / 2
oy = -midy * #zoomscale + b.h / 2
#frame.css backgroundPosition: -(b.x + 1) + 'px ' + -b.y - 1 + 'px'
return
# this redraw function is not being called, everything else appears to work fine
redraw: (b) ->
$.Jcrop.component.Selection::redraw.call this, b
#positionBg #last
this
prototype: $.Jcrop.component.Selection.prototype
What have I done wrong?

Related

Getting undefined when selecting html element in Javascript

I have a number of tv display clones loaded onto my page. After the clone is made, it will create a new TV object at the end of the loop definition, but for some reason, when it tries to access the index based canvas element from the page, it returns undefined. I tested that when hardcoding cnvs[0] from inside the constructor, it will return the canvas element. Indexing cnvs1 will return undefined; however, I see the tv has already been cloned before this line is executed. Shouldn't there then be a second canvas element of class ".static" that can be selected? In addition to the code, I attached a screenshot of my debugger screen in Chrome to see what the scope reads following "this.cnv = cnvs1", which should dynamically be cnvs[this.index]. Thanks in advance!
const container = document.getElementsByTagName("main")[0];
const template = document.getElementsByClassName("tv-set")
const cnvs = $(".static");
/**TBD**/
class TV {
constructor (id = "tv-0", name = "Blank Slate") {
this.id = id;
this.name = name;
console.log("NEW TV CREATED: ", this);
console.log("ID: ", this.id);
this.gifArr = gifCarousel_dict[this.name];
console.log("Media selection for this tv: ", this.gifArr);
// this.cnv = $(this.id).find('.static')[0];
// this.cnv = document.querySelector("[data-name=" + CSS.escape(this.id) + "]");
this.index = getSecondPart(id);
// this.cnv = $(".static")[this.index + 1];
this.cnv = cnvs[1];
console.log(this.cnv);
this.cnv.setAttribute("c", this.cnv.getContext("2d"));
this.cnv.setAttribute("cw", this.cnv.offsetWidth);
this.cnv.setAttribute("ch", this.cnv.offsetHeight);
this.staticScrn = this.cnv.getAttribute("c").createImageData(this.cnv.setAttribute("ch"), this.cnv.setAttribute("cw"));
console.log("This canvas element: ", this.cnv);
//Static display
this.isStatic = true;
}
showStatic() {
console.log(`Printing the tv name from the prototype fxn: ${this.name}`);
// this.isStatic = true;
c.clearRect(0, 0, cw, ch);
for (var i = 0; i < staticScrn.data.length; i += 4) {
let shade = 127 + Math.round(Math.random() * 128);
staticScrn.data[0 + i] = shade;
staticScrn.data[1 + i] = shade;
staticScrn.data[2 + i] = shade;
staticScrn.data[3 + i] = 255;
}
c.putImageData(staticScrn, 0, 0);
staticTO = setTimeout(runStatic, 1e3 / staticFPS);
}
}
for (let i = 0; i < phases.length; i++) {
const clone = template[i].cloneNode(true);
clone.setAttribute("id", "tv-" + (i + 1))
console.log("clone id: ", clone.getAttribute("id"))
clone.setAttribute("data-channel", 0)
clone.setAttribute("name", phases[i])
// clone.style.backgroundColor = phases[i].channels[0]
container.appendChild(clone)
var tvName = 'tvPhase' + clone.getAttribute("name");
//Instantiate TV object
window['tvPhase' + clone.getAttribute("name")] = new TV(clone.getAttribute("id"), clone.getAttribute("name"));
console.log("New Tv Created: ", tvName)
}
As I was about to post this question, I caught my bug...but I figured perhaps someone could learn from my stupid mistake! Turns out, it was because of line const cnvs = $(".static"); Setting this constant prior to the cloning operation means it will contain only the first canvas element and cannot be changed even after clones are created since it's a constant (face palm). The solution, of course, is to just define this.cnv = $(".static")[this.index]; directly or set the global cnvs as a var/let cnvs, still wrapping my head around when to use which.

Create Shape / Drag and Drop

I'm trying to work with a createjs canvas to add new states (circles) on empty spots of stage on click, but drag existing points on click. I'm assuming the problem is that when I try to remove the stagemousemove event in handleMove it doesn't properly remove since it doesn't have a dedicated static handler, but I'm not sure how I'd even create that handler.
// create new state (circle)
function createState(e) {
x = e.stageX
y = e.stageY
if (stage.children.every(el =>
!(el.hitTest(x, y)) &&
!(el.hitTest(x + 30, y + 30)) &&
!(el.hitTest(x + 30, y - 30)) &&
!(el.hitTest(x - 30, y + 30)) &&
!(el.hitTest(x - 30, y - 30))
)) {
state = new createjs.Shape()
state.graphics.ss(3)
.s('#777')
.f('#eaeaea')
.dc(x, y, 30)
stage.addChild(state)
state.on('mousedown', handleMove)
stage.update()
}
}
// drag and drop
function handleMove(e) {
el = stage.getObjectUnderPoint(stage.mouseX, stage.mouseY);
var offset = {
x: el.x - e.stageX,
y: el.y - e.stageY
}
stage.on('stagemousemove', (evt) => {
el.x = offset.x + evt.stageX
el.y = offset.y + evt.stageY
stage.update()
})
stage.on('stagemouseup', (e) => {
stage.off('stagemousemove', (evt) => {
el.x = offset.x + evt.stageX
el.y = offset.y + evt.stageY
stage.update()
})
})
}
// determines whether to create new point
function handler(e) {
if (stage.getObjectUnderPoint(stage.mouseX, stage.mouseY) == null)
createState(e)
}
stage.on('stagemousedown', handler)
When you use the off() method, you must pass a reference to the result of the on() call.
let listener = stage.on('stagemousemove', (evt) => {
el.x = offset.x + evt.stageX
el.y = offset.y + evt.stageY
stage.update()
});
stage.on('stagemouseup', (e) => {
stage.off('stagemousemove', listener);
});
The on method creates a function closure for you automatically to maintain scope, which ES5 JavaScript does not do. This lets you pass a scope parameter to on so this is the expected scope.
When using arrow functions, this closure happens during ES5 transpiling. You can not just pass a similar function to the off, since they are not equal.
Hope that helps!

ng-grid first line rendered only, and cannot catch selection event

I'm working on my own project using angurarjs and ag-grid.
I have 2 problems:
1. is that i cannot refresh a status bar in case of selection in ag-rig. I can catch the event, and the function is running, but statusText scope element is reresshed only after navigation is happend to an other page. Very strange behaviour.
2. only the first 3 lines of grid is rendered, and only after scrolling the rest is shown.
Could anyone help me?
Code:
$scope[page + 'GridOptions'] = {
columnDefs: [],
rowData: null,
onGridReady: $scope.fillGrid,
rowSelection: 'single',
onSelectionChanged: function(){
$scope.selectRow()
}
}
$scope.selectRow = function(){
localStorageService.set(page + 'SelectedRow', $scope[page + 'GridOptions'].api.getSelectedRows()[0])
console.log($scope[page + 'GridOptions'].api.getSelectedRows()[0])
$scope.statusText = "selected item's id: " + $scope[page + 'GridOptions'].api.getSelectedRows()[0]._id
for(i=0; i<$scope[page + 'GridColumns'].length; i++){
localStorageService.set($scope[page + 'GridColumns'][i].field, $scope[page + 'SelectedRow'][$scope[page + 'GridColumns'][i].field])
$scope[$scope[page + 'GridColumns'][i].field] = localStorageService.get($scope[page + 'GridColumns'][i].field)
}
console.log(page)
localStorageService.set(page + 'DisableButton', false)
$scope[page + 'DisableButton'] = eval(localStorageService.get(page + 'DisableButton'))
$scope[page + 'GridOptions'].api.refreshView()
}

Removing items from leaflet markercluster

I have two functions that load markers into my map. (Both functions are called on success of an ajax call)
First Function is like this:
function loadEpsMarkers(data) {
for (var i = 0; i < data.length; i++) {
var plateNo = data[i].PLATE_NUMBER;
var permitNo = data[i].PERMITINFOID;
var inventoryId = data[i].INVENTORY_ID;
var icon = epsiconR;
if (data[i].INVENTORY_STATUS === 'Complete') {
icon = epsiconC;
}
var popup = '<h5>EPS</h5>' + 'Plate:' + plateNo + '<br/>' +
' Permit: <a class=\'link\' data-inventoryId="' + inventoryId + '" href=' + url + '>' + permitNo + '</a>' +
'<p style=\"color:blue\">' + '' + '<a class=\'link\' href=' + url + '>' +
'Import' + '</a>' + '<br/>' + '<a class=\'link\' href=' + url + '>' +
'Duplicate' + '</a>' + '<br/>' + '<a class=\'link\' href=' + url + '>' +
'Removed' + '</a>' + '<br/>' + '</p>';
var m = L.marker([data[i].REF_LATITUDE, data[i].REF_LONGITUDE], { icon: icon, draggable: 'true' })
.bindPopup(popup);
markerClusters.addLayer(m);
}
map.addLayer(markerClusters);
map.invalidateSize(false);
}
The second Function is same except the data is different.
This works fine and I get the clustered markers as expected.
Now I have a button, when I click this button, it should hide the markers from the first call.
The easy way out is to remove layers and then redo just the second call. But that seems like an inefficient way of doing this.
This gets more complex if I have 4 such data calls and I want to toggle markers from each of those calls.
I have tried something like this as well:
$('#dvEpsOnlyMarkers').click(function () {
markerClusters.removeLayer(m);
});
But that isn't working. Any ideas on how I can make this work ?
Thanks in advance
A very simple way of achieving what you describe is to store references to markers of each group in arrays, and manipulate those arrays to add / remove the layers into MCG:
var markersCall1 = [],
markersCall2 = [],
markersCall3 = [],
markersCall4 = [];
function loadEpsMarkersX(data) { // Replace X by 1...4
for (var i = 0; i < data.length; i++) {
// Convert data...
var m = L.marker(/* latLng, options, popup... */);
markersCallX.push(m); // Replace X by 1...4
}
// Actually add to MarkerClusterGroup.
// Replace X by 1...4
markerClusters.addLayers(markersCallX); // note the addLayers with "s".
}
$('#dvEpsOnlyMarkersX').click(function (event) { // Replace X by 1...4
// Assuming it is a checkbox, you can use it to toggle.
if (this.checked) {
// Replace X by 1...4
markerClusters.addLayers(markersCallX); // note the "s".
} else {
// Replace X by 1...4
markerClusters.removeLayers(markersCallX); // note the "s".
}
});
When you have batches of markers to add / remove like in your case, you can conveniently use the MarkerClusterGroup methods addLayers and removeLayers (with a trailing s) with an array of the markers to process. These methods are much more efficient than adding / removing markers one by one.

jssor size adjustor without maintaining aspect ratio

Since one of our organization's client asked us to change the slide show height slightly not width (reason on maintaining aspect ratio in small screen device the slider gets very small).
I know about this jssor function $ScaleWidth(width); but only have to adjust height.
So created the following function to resize based on the scale value of transform css property of jssor instantiated object's tag id, which is passed as parameter for the following function.
function jssorResolutionAdjustor(id)
{
setTimeout(function() {
var idObj = $('#' + id);
var immediateChild = idObj.children('div');
var transformMatrix = '';
var transformMatrixValues = '';
var transformCss = '';
transformMatrix = immediateChild.css('transform');
transformMatrixValues = transformMatrix.match(/-?[\d\.]+/g);
var scaleXValue = transformMatrixValues[0];
var scaleXValueFixed = parseFloat(scaleXValue).toFixed(2);
var scaleYValue = (scaleXValue * 1.2).toFixed(2);
if (scaleXValueFixed >= 0.75)
{
scaleYValue = 1;
}
if ('WebkitTransform' in document.body.style)
{
transformCss = {'-webkit-transform': 'scale(' + scaleXValue + ',' + scaleYValue + ')',
'transform': ''};
}
else if ('MozTransform' in document.body.style)
{
transformCss = {'-moz-transform': 'scale(' + scaleXValue + ',' + scaleYValue + ')'};
}
else if ('transform' in document.body.style)
{
transformCss = {'tansform': 'scale(' + scaleXValue + ',' + scaleYValue + ')'};
}
$(immediateChild).css(transformCss);
}, 0);
}
It worked flawlessly in desktop browser (firefox, chrome only I checked) but if opened on mobile phone (iphone, android) means it scaled to too big size. Also I checked the value in mobile and in desktop by adjusting browser screen size to phone screen size same value is returned in alert('scaleXValue=' + scaleXValue + '<-->' + 'scaleXValueFixed=' + scaleXValueFixed + '<-->' + 'scaleYValue=' + scaleYValue);.
I can't get any clue so here I attach the screen shot of failed solution in mobile.
And I call this function on loading and resizing the window.
jssorResolutionAdjustor('jssor_image_gallery');
$(window).resize(function() {
jssorResolutionAdjustor('jssor_image_gallery');
});
jssor_image_gallery is the id given in jssor instance
jssor_slider_image = new $JssorSlider$('jssor_image_gallery', options);
Updated (1):
Here is my jssor function
function imageJssor()
{
var _CaptionTransitions = [];
_CaptionTransitions["MCLIP|B"] = {$Duration: 600, $Clip: 8, $Move: true, $Easing: $JssorEasing$.$EaseOutExpo};
var options = {
$AutoPlay: false,
$ThumbnailNavigatorOptions: {
$Class: $JssorThumbnailNavigator$,
$ChanceToShow: 2,
$Cols: 6,
$Align: 260,
$SpacingX: 3, //[Optional] Horizontal space between each thumbnail in pixel, default value is 0
$ArrowNavigatorOptions: {
$Class: $JssorArrowNavigator$, //[Requried] Class to create arrow navigator instance
$ChanceToShow: 2, //[Required] 0 Never, 1 Mouse Over, 2 Always
$Steps: 6 //[Optional] Steps to go for each navigation request, default value is 1
}
},
$ArrowNavigatorOptions: {
$Class: $JssorArrowNavigator$,
$ChanceToShow: 2
},
$CaptionSliderOptions: {//[Optional] Options which specifies how to animate caption
$Class: $JssorCaptionSlider$, //[Required] Class to create instance to animate caption
$CaptionTransitions: _CaptionTransitions, //[Required] An array of caption transitions to play caption, see caption transition section at jssor slideshow transition builder
$PlayInMode: 0, //[Optional] 0 None (no play), 1 Chain (goes after main slide), 3 Chain Flatten (goes after main slide and flatten all caption animations), default value is 1
$PlayOutMode: 0 //[Optional] 0 None (no play), 1 Chain (goes before main slide), 3 Chain Flatten (goes before main slide and flatten all caption animations), default value is 1
}
};
jssor_slider_image = new $JssorSlider$('jssor_image_gallery', options);
//responsive code begin
//you can remove responsive code if you don't want the slider scales while window resizes
function ScaleSlider() {
/* var windowWidth = $(window).width();
if (windowWidth) {
var windowHeight = $(window).height();
var originalWidth = jssor_slider_image.$OriginalWidth();
var originalHeight = jssor_slider_image.$OriginalHeight();
var scaleWidth = windowWidth;
if (originalWidth / windowWidth > originalHeight / windowHeight) {
scaleWidth = Math.ceil(windowHeight / originalHeight * originalWidth);
alert(scaleWidth);
}
jssor_slider_image.$ScaleWidth(scaleWidth);
}
else
window.setTimeout(ScaleSlider, 30);
var bodyWidth = document.body.clientWidth;
alert(bodyWidth);
if (bodyWidth)
jssor_slider_image.$ScaleWidth(Math.min(bodyWidth-150, 1920));
else
window.setTimeout(ScaleSlider, 30); */
var parentWidth = jssor_slider_image.$Elmt.parentNode.clientWidth;
//alert(parentWidth);
if (parentWidth)
jssor_slider_image.$ScaleWidth(Math.min(parentWidth, 720));
else
window.setTimeout(ScaleSlider, 30);
}
ScaleSlider();
$(window).bind("load", ScaleSlider);
$(window).bind("resize", ScaleSlider);
$(window).bind("orientationchange", ScaleSlider);
//responsive code end
}
imageJssor();
$(document).on('click', '#one li', function() {
var imageStartFrom = $(this).index();
$('#image_gallery').hide();
$('#jssor_image_gallery').show();
jssor_slider_image.$PlayTo(imageStartFrom);
jssor_slider_image.$Pause();
jssorResolutionAdjustor('jssor_image_gallery');
$(window).resize(function() {
jssorResolutionAdjustor('jssor_image_gallery');
});
});
Updated (2):
Here in both images (web & mobile) the default scale ratio and my calculated values or looking same but as shown below image its working properly in website in desktop browser but not in mobile. Here I attached that image too for reference.
Here in the above image on left side the deer image get scaled to high with compare to right side image which is took from desktop browser.
Updated (3):
Please see below image's alert to verify the parentWidth both represents the same value only
Also I attach my html dom structure with id which is used in jssor is highlighted in blue background.
I found the solution that if -webkit-transform was set means instead emptying the transform css property have to check browser (gecko, webkit, etc) engine also have transform. If it exist the priority will goes to transform while rendering the dom compared to -webkit-transform.
FROM:
if ('WebkitTransform' in document.body.style)
{
transformCss = {'-webkit-transform': 'scale(' + scaleXValue + ',' + scaleYValue + ')',
'transform': ''};
}
TO:
if ('WebkitTransform' in document.body.style)
{
transformCss = {'-webkit-transform': 'scale(' + scaleXValue + ',' + scaleYValue + ')'};
if ('transform' in document.body.style)
{
transformCss = {'tansform': 'scale(' + scaleXValue + ',' + scaleYValue + ')'};
}
}