What the script does is, when you click on any child of this #viewPlan div it, I get the index of that child, and I show the same index div in the next sibling of #viewPlan
Following is the code, the problem is the callback function doesn't work when you click first time, it works fine from second click:
Y.all('#viewPlan > div').each(function(node, index){
var planHeading = Y.one('#viewPlan').get('children');
var planContent = Y.one('#viewPlan').next();
var firstTime = true;
planContent.get('children').addClass('display-none');
node.on('click',function(em){
em.currentTarget.addClass('active').siblings().removeClass('active');
planContent.get('children').item(index).siblings().transition({
'easing': 'ease-out',
'duration': 0.5,
'opacity': 0
}, function() { // problem starts here
planContent.get('children').item(index).siblings().addClass('display-none');
planContent.get('children').item(index).removeClass('display-none');
planContent.get('children').item(index).transition({
'easing': 'ease-out',
'duration': 0.5,
'opacity': 1
});
});
});
});
If something is not clear, please let me know.
Related
I need to position text inputs at various places on a KonvaJS layer. I found the following code at https://konvajs.github.io/docs/sandbox/Editable_Text.html and I'm trying to understand the textPosition, stageBox, and areaPosition vars in this code. I want my stage centered in the browser window, but when I do that, the textarea (activated on dblclick) pops up way off to the left. I can't get a console readout of the x/y coordinates, so I can't visualize how the positioning works &, thus, how to change it. Can anyone explain, or point me in the right direction?
var text_overlay = new Konva.Layer();
stage.add(text_overlay);
var textNode = new Konva.Text({
text: 'Some text here',
x: 20,
y: 50,
fontSize: 20
});
text_overlay.add(textNode);
text_overlay.draw();
textNode.on('dblclick', () => {
// create textarea over canvas with absolute position
// first we need to find its position
var textPosition = textNode.getAbsolutePosition();
var stageBox = stage.getContainer().getBoundingClientRect();
var areaPosition = {
x: textPosition.x + stageBox.left,
y: textPosition.y + stageBox.top
};
// create textarea and style it
var textarea = document.createElement('textarea');
document.body.appendChild(textarea);
textarea.value = textNode.text();
textarea.style.position = 'absolute';
textarea.style.top = areaPosition.y + 'px';
textarea.style.left = areaPosition.x + 'px';
textarea.style.width = textNode.width();
textarea.focus();
textarea.addEventListener('keydown', function (e) {
// hide on enter
if (e.keyCode === 13) {
textNode.text(textarea.value);
text_overlay.draw();
document.body.removeChild(textarea);
}
});
})
// add the layer to the stage
stage.add(text_overlay);
UPDATE: I solved part of the problem--the textarea showing up way out of position. You need to use 2 divs in the HTML file instead of one, like so:
<div id="containerWrapper" align="center"><div id="container"></div></div>
Thanks to Frens' answer on Draw border edges of the Konvajs container Stage in html for that one!
I am using node/npm blessed to create a screen to monitor a particular application and I want the monitor tool to look/act like linux top. The problem I have, which I think is relatively simple (but I cant find the answer anywhere), is to have blessed clear the screen at startup as well as at particular points based upon user input.
Right now I can use blessed to paint the screen properly (sample program below), but the problem is I need the screen to be cleared at startup (right now the first line of output just appends right after you start up the program):
var blessed = require('blessed');
var screen = blessed.screen(),
body = blessed.box({
top: 0,
left: 0,
width: '100%',
height: '100%',
tags: true
});
var items = [];
screen.append(body);
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
function log(text) {
items.push(text);
var MAX = 10;
if( items.length > MAX+1 ){
items.shift();
}
for (var i=1; i<MAX; i++){
body.setLine(i, items[i]);
}
screen.render();
}
function status(text) {
body.setLine(0, text );
screen.render();
}
var counter = 1;
setInterval(function() {
status((new Date()).toISOString());
log('Line number: ' + (counter++));
}, 1000);
For completeness, the solution to this question is provided below, and is very simple. To clear the screen, issue the following code at the start of the program:
screen.render();
The sample program that I referenced in the original post can be modified as follows and now works:
var blessed = require('blessed');
var screen = blessed.screen(),
body = blessed.box({
top: 0,
left: 0,
width: '100%',
height: '100%',
tags: true
});
// The following line clears the screen
screen.render();
:
:
I am creating a circle using SVG
var gauge = mapSvg.circle(center['x'], center['y'], 85).attr({'stroke-width': 3, 'stroke': 'black', 'fill': 'white'});
It is in for loop, this circle created three times. I have added ontouchstart on its click
gauge.node.ontouchstart = function () { alert("hi>>>>>") }
but this alert is not showing.
This should work...
var r = Raphael("blah",200,200);
var c = r.circle(100,100,100).attr({fill: 'red' }).touchstart( function() { alert('hi') });
jsfiddle http://jsfiddle.net/7c56E/
I am trying to do 2 actions on one click on the element using Masonry library. It should work the way that when I click on the element it expands (I am adding class to have box bigger) and in the meantime the page is scrolling to that box. The problem is that when you expand the box it may drop a line down and that means the function called to scroll will scroll to wrong place. It should do the layout and get new position of the element and then move...
I got it almost working. It is expanding the box and doing new layout and when finished it scrolls the page to the box... but it looks a little bit strange and it first moves all the boxes for new layout, then stops and strars moving the page. I would prefer that to be done in one move. It that possible.
Here is my code:
$(document).ready(function() {
var $container = $('#container');
// initialize
var msnry = new Masonry( container, {
columnWidth: 280,
itemSelector: '.item'
} );
$('.openBoks').on('click', function() {
// this is my element
var thisBox = $(this).parent().parent();
// adding the class to expand it
thisBox.addClass('opened');
// calling method to do new layout
msnry.layout();
msnry.on( 'layoutComplete', function( msnryInstance, laidOutItems )
{
$('html, body').animate({
scrollTop: (thisBox.offset().top-10)
}, 700);
return true;
});
});
});
In case you or someone else is still looking for an answer to this, I did a little workaround this problem. The idea was basically the same, to do the scroll and the masonry repositioning simultaneously. It's not the most elegant solution since I added a couple of lines inside the masonry script.
Inside masonry.pkgd.js, there is a function _processLayoutQueue that positions the masonry items stored in the queue array, calling the _positionItem for each of the items.
Outlayer.prototype._processLayoutQueue = function( queue ) {
for ( var i=0, len = queue.length; i < len; i++ ) {
var obj = queue[i];
this._positionItem( obj.item, obj.x, obj.y, obj.isInstant );
}
};
What I did was check through the iteration for the item with the identifying masonry class, in your case ".opened". So when that item is found, I immediately activate the page scroll using a cointainer div ("#container_div_id" for this example) for the offset and adding the items "y" position (obj.y). At the end, the code looks something like this:
Outlayer.prototype._processLayoutQueue = function( queue ) {
for ( var i=0, len = queue.length; i < len; i++ ) {
var obj = queue[i];
this._positionItem( obj.item, obj.x, obj.y, obj.isInstant );
/* ADDED CODE */
if( $(obj.item.element).hasClass('opened')){
$('html, body').animate({
scrollTop: $('#container_div_id').offset().top+obj.y
}, 600);
}
/* END OF ADDED CODE */
}
};
This makes the scrolling start right after the positioning of the item, without having to wait for the layoutComplete event. As I said, its not the most elegant solution, but it is pretty solid, It works fine for my case.
Hope it helps someone!
I have an SVG canvas with text that I would like to respond to clicks. The code below isn't getting the job done:
var MyView = Backbone.View.extend({
tagName : "text",
events : {
"click" : "clickhandler"
},
initialize : function() {
this.centerX = this.options.centerX;
this.centerY = this.options.centerY;
this.svg = this.options.svg;
this.tagText = this.model.get("tag_name");
this.render();
},
clickhandler : function(event) {
console.log("I was clicked!"); //This is not firing on click
},
render : function() {
this.el = this.svg.text(this.centerX, this.centerY, this.tagText, {});
return this;
}
});
This is being called in the render function of another view as such :
container.svg({
onLoad : function(svg) {
for ( var i = 1; i < that.relatedTags.length; i++) {
tagView = new MyView({
model : this.relatedTags.at(i),
centerX : 100,
centerY : 200,
svg : svg
});
}
container.append(tagView);
}
});
It shows up just fine and if I throw this in at the end of the for loop :
$(tagView.el).click(function() {
alert("xx");
});
Then the clicking works but I need to access the Backbone Model associated with the view so I'd much prefer the backbone event to a straight JQuery event.
The problem here is, that you set the element of the view in the render method. But backbone tries to add the events on initialization. So when backbone tries to add the events there is no element in you case. So either you have to start your view with your svg text, or you add the events by hand in your render method.
Maybe you can add the events on the svg itself and jquery is clever enough to handle the delegation. But I'm not sure in this case.