I'm starting to use JsPanel in a project at work and I have some doubts on why the 'autoposition' is not being applied between some panels.
I have 4 panels: A, B, C and D.
A panel:
jsPanel.create({
id: 'A',
theme: 'primary',
headerTitle: 'A panel',
position: { my: 'left-top',
at: 'left-top',
offsetX: '0px',
offsetY: '0px',
autoposition: 'down'
},
contentSize: '450 250',
content: '<p> Test test test</p>',
callback: function () {
this.content.style.padding = '20px';
},
onbeforeclose: function () {
return confirm('Are you sure?');
}
});
B panel:
jsPanel.create({
id: 'B',
theme: 'primary',
headerTitle: 'B panel',
position: { my: 'center-top',
at: 'center-top',
offsetX: '0px',
offsetY: '0px',
autoposition: 'down'
},
contentSize: '450 250',
content: '<p> Test test test</p>',
callback: function () {
this.content.style.padding = '20px';
},
onbeforeclose: function () {
return confirm('Are you sure?');
}
});
C panel:
jsPanel.create({
id: 'C',
theme: 'primary',
headerTitle: 'C panel',
position: { my: 'right-top',
at: 'right-top',
offsetX: '0px',
offsetY: '0px',
autoposition: 'down'
},
contentSize: '450 250',
content: '<p> Test test test</p>',
callback: function () {
this.content.style.padding = '20px';
},
onbeforeclose: function () {
return confirm('Are you sure?');
}
});
D panel:
jsPanel.create({
id: 'D',
theme: 'primary',
headerTitle: 'D panel',
position: { my: 'left-top',
at: 'left-bottom',
of: '#A',
autoposition: 'up'
},
contentSize: '450 250',
content: '<p>Test test test</p>',
callback: function () {
this.content.style.padding = '20px';
},
onbeforeclose: function () {
return confirm('Are you sure?');
}
});
Reading the documentation of the 'position' option, specifically the 'autoposition' attribute, says that you can set a value to add a gap between panels to prevent them from piling up on each other:
'down' for panels positioned using either 'left-top', 'center-top' or 'right-top' for both my: and at: setting autoposition to 'down' will automatically add a vertical offset downwards to each elmt in order to prevent them from piling up on each other. Removing a jsPanel will automatically reposition the remaining panel in the same stack.
'up' for panels positioned using either 'left-bottom', 'center-bottom' or 'right-bottom' for both my: and at: setting autoposition to 'up' will automatically add a vertical offset upwards to each elmt in order to prevent them from piling up on each other. Removing a jsPanel will automatically reposition the remaining panel in the same stack.
but for me it's not being applied. I've tried to remove the autoposition in A or D but no result.
So what am I doing wrong or what have I misunderstood?
Regards.
-- Edit 1:
I have achieved the separation adding:
offsetY: '8px',
to panel D but I think that this is not the correct solution...
I have found the problem. It was a misunderstanding with positions. Seeing example number 5 that adds panels one below the other the positions are:
my: 'right-top',
at: 'right-top',
and then you set:
autoposition: 'down',
So in panel D I had to change:
position: { my: 'left-top',
at: 'left-bottom',
of: '#A',
autoposition: 'up'
},
to
position: { my: 'left-top',
at: 'left-top',
of: '#A',
autoposition: 'down',
offsetY: 4px
},
The offsetY is optional. By default JsPanel adds a 4px separation but if you look on the image, the horizontal separation is 4px + 4px so I add 4 extra pixels to match visually the horizontal separation with the vertically separation.
Regards!
Related
I need to change the value of both anim_img and anim_text in the scrolltrigger() function. In theory, everything should be simple, but somehow it does not work out.
const anim_img = document.querySelectorAll('.info__block_img');
const anim_text = document.querySelectorAll('.info__block_text');
for (var i = 0; i < anim_text.length; i++) {
gsap.to(anim_img[i], {
scrollTrigger: {
trigger: anim_text[i],
markers: true,
start: '-40% center',
end: 'center center',
scrub: 1
},
scale: 1,
opacity: 1
})
gsap.to(anim_text[i], {
scrollTrigger: {
trigger: anim_text[i],
markers: true,
start: '-40% center',
end: 'center center',
scrub: 1
},
margin: 0,
opacity: 1
})
I saw the same values for the variables and decided to combine them into one function, but nothing happened. The videos and documentation say nothing about this.
For combining both the variable you need to keep both in one loop together when you are adding to gsap.to.
here is the possible solution.
const anim_img = document.querySelectorAll('.info__block_img');
const anim_text = document.querySelectorAll('.info__block_text');
for (var i = 0; i < anim_text.length; i++) {
gsap.to([anim_img[i], anim_text[i]], {
scrollTrigger: {
trigger: anim_text[i],
markers: true,
start: '-40% center',
end: 'center center',
scrub: 1
},
opacity: 1,
onUpdate: function () {
gsap.to(anim_img[i], {
scale: 1,
});
gsap.to(anim_text[i], {
margin: 0,
});
}
});
}
I am building a charting tool in ember using cytoscape js and I can render chart data however I do not know how to set each node to display with a image that has other images/buttons that function within it. Basically I want it to look like this:
In the image there are two buttons (I will most likely add icons as well) and also there are labels that exist within the node which I don't know how to do either.
Here is the code I currently have.
Template:
<div class="container" >
<div id="cy"></div>
</div>
Component JS:
import Ember from 'ember';
export default Ember.Component.extend({
tagName: '',
map: Ember.computed('model.map_data', function()
{
if(this.get('model.map_data')){
return JSON.parse(this.get('model.map_data').data)
} else {
return {};
}
}),
cytoscape_data: Ember.computed('model.sub_apps.[]',function() {
var ret = {
nodes: [],
edges: []
};
var red = 50;//replace with threshold
var green = 25;//replace with threshold
var _this = this;
this.get("model").map_data.forEach(function(node) {
var y= 0;
var x = 0;
var color = 'green';
if(node.value >= red ){
color = 'red';
}else {
if(node.value > green){
color = 'orange';
}
}
var position = _this.get("map")["app" + node.id];
if(position){
x = parseInt(position.split(',')[0]);
y = parseInt(position.split(',')[1]);
}
ret["nodes"].push({
data: {
id: node.id,
label: node.name,
node_type: 'app',
tooltip: node.description,
color: color
},
position: {
x: x,
y: y
}
});
if(node.relations) {
node.relations.forEach(function(parent) {
ret["edges"].push({
data: {
source: node.id,
target: parent.app_to_id
}
});
});
}
});
return ret;
}),
didInsertElement: function() {
this._super();
var cy = cytoscape({
container: Ember.$('#cy')[0],
elements: this.get("cytoscape_data"),
zoom: 1,
pan: { x: 0, y: 0 },
fit: true,
randomize: false,
layout: {
name: 'preset'
},
style: [
{
selector: 'node',
style: {
'content': 'data(label)',
'text-opacity': 0.8,
'text-valign': 'center',
'text-halign': 'right',
'width': '200px',
'height': '200px',
'border-color': 'green',
'border-width': 3,
'border-opacity': 0.5,
'background-image': 'url(../assets/images/base_node_image.svg)'
// 'background-color': 'data(color)'
}
},
{
selector: 'edge',
style: {
'width': 6,
'border-color': 'green',
'target-arrow-shape': 'triangle',
'target-arrow-color': 'red',
'opacity': 1,
'curve-style': 'bezier'
}
},
{
selector: ':selected',
style: {
'background-color': 'orange',
'opacity': 1
}
},
{
selector: '.faded',
style: {
'opacity': 0.0,
'text-opacity': 0
}
},
],
});
Ember.run.scheduleOnce('afterRender', this, function(){
cy;
});
cy.on('click', 'node', function(evt){
var node = evt.target;
console.log( 'clicked ' + node.data('label') );
});
},
});
The chart this code renders looks like this:
I can display a background-image however it displays in a circle which I dont know how to get rid of. The color of the circle is determined by some logic above which was a test to see if it works and that is fine (going to use that for one of the icons on the node later). I can also display the label for the node but I don't know how to display that within the node itself.
Any help is appreciated, thanks!
It is not so trivial to achieve what you want if not impossible. You say "set each node to display with a image that has other images/buttons that function within it."; this means you need to render html into a canvas; because what cytoscape puts as drawing area is an HTML canvas.
See #maxfranz's (author of cytoscape.js) for a relevant question; where he basically says "It's not possible to render HTML in a canvas, nor would you probably want to for performance".
This means putting html buttons, URLs might not be what you desire. See also MDN Web Docs for further explanation.
That said; I think you can still manage to achieve what you want; but with a different approach. You can make use of cytoscape's compound nodes. You can define the images and buttons as simple nodes and define compound nodes as surrounding containers. I have created a working example for you at the follwoing github repository.
The final result I got is as follows:
I hope this helps.
I have a tooltop in my area map that I've done which I'm using http://qtip2.com/
my code when I call the tooltip is the same one in this question Tooltip on map area tag
jQuery(document).ready(function (e) {
jQuery('area').qtip({
style: {
classes: 'qtip-dark'
},
events: {
show: function(event, api) {
api.set({
'content.text': api.elements.target.attr('title')
});
}
}
});
});
But my tooltip is always on the bottom right corner of my area, is there any way I can let it on my top right corner instead?
Find the below answer it will helpful to you.
jQuery(document).ready(function (e)
{
jQuery('area').qtip({
style:
{
classes: 'qtip-default qtip qtip-light qtip-rounded',
width: '250px',
height: '70px',
tip: true
},
position:
{
my : 'bottom left',
at: 'top right',
adjust: {
method: 'none none', // Requires Viewport plugin
resize: true
},
},
events:
{
show: function(event, api)
{
api.set
({
'content.text': api.elements.target.attr('title')
});
}
}
});
});
Thanks to Chiral Patel's comment I've found a way, thank you!
jQuery(document).ready(function (e)
{
jQuery('area').qtip({
style:
{
classes: 'qtip-default qtip qtip-light qtip-rounded',
width: '250px',
height: '70px',
},
position:
{
my : 'bottom left',
at: 'top right',
method:'none'
},
events:
{
show: function(event, api)
{
api.set
({
'content.text': api.elements.target.attr('title')
});
}
}
});
});
I'm working with jQuery fullcalendar (version 2.7.1).
This is what I want to do:
Now I can set the background to red but the text doesn't appear. This is what I'm doing:
var m = moment('2016-09-19');
$('#calendar').fullCalendar({
// put your options and callbacks here
left: 'title',
center: '',
right: 'prev,next',
weekends: false,
weekNumbers: true,
defaultView: 'month',
defaultDate: m,
events: [
{
start: '2016-09-19',
allDay : true,
rendering: 'background',
backgroundColor: '#F00',
title: 'full',
textColor: '#000'
},
{
start: '2016-09-20',
allDay : true,
rendering: 'background',
backgroundColor: '#F00',
title: 'full',
textColor: '#000'
}
]
});
This is how it looks:
So the text isn't added... . And the color is much lighter than the specified color.
As you can see I also didn't add 'today' to my right navigation but it's added anyway ... .
I also wonder how I can limit the navigation of months. That they for example only can select months september, october, november in 2016.. .
Can anyone help me with this questions?
You can use eventAfterRender callback. In this callback append string FULL to element parameter. You can apply CSS styling to this using event-full class.
The background-color is lighter because there is an opacity of 0.3; change it to 1 using event-full class.
To hide today button you have to set left, center, right properties in header object.
To limit the navigation of months you can use viewRender callback.
JS
var m = moment('2016-09-19');
$('#calendar').fullCalendar({
// put your options and callbacks here
header: {
left: 'title',
center: '',
right: 'prev,next'
},
weekends: false,
weekNumbers: true,
defaultView: 'month',
defaultDate: m,
events: [{
start: '2016-09-19',
allDay: true,
rendering: 'background',
backgroundColor: '#F00',
title: 'full',
textColor: '#000',
className: 'event-full'
}, {
start: '2016-09-20',
allDay: true,
rendering: 'background',
backgroundColor: '#F00',
title: 'full',
textColor: '#000',
className: 'event-full'
}],
eventAfterRender: function (event, element, view) {
element.append('FULL');
},
viewRender: function (view, element) {
var start = new Date("2016-09-01");
var end = new Date("2016-11-30");
if (end < view.end) {
$("#calendar .fc-next-button").hide();
return false;
} else {
$("#calendar .fc-next-button").show();
}
if (view.start < start) {
$("#calendar .fc-prev-button").hide();
return false;
} else {
$("#calendar .fc-prev-button").show();
}
}
});
CSS
.event-full {
color: #fff;
vertical-align: middle !important;
text-align: center;
opacity: 1;
}
WORKING DEMO
I'm using a CSS-driven solution since it seems easier in this case to just let the library do what it is intended to do and work around it. The "Today" button has a specific class so I'd display: none that. The Event objects can accept a className prop. Using that, I positioned a :before element to create the "FULL" text. Lastly, your color variation is due to an opacity of 0.3 on those cells. Setting that to 1 shows the full red background-color that is being applied. \
.fc-today-button {
display: none;
}
.event-full {
position: relative;
opacity: 1;
&:before {
content: "FULL";
position: absolute;
color: #fff;
top: 50%;
transform: translateY(-50%) translateX(-50%);
left: 50%;
}
}
and the JS:
var m = moment('2016-09-19');
$('#calendar').fullCalendar({
// put your options and callbacks here
left: 'title',
center: '',
right: 'prev,next',
weekends: false,
weekNumbers: true,
defaultView: 'month',
defaultDate: m,
events: [
{
start: '2016-09-19',
allDay : true,
rendering: 'background',
backgroundColor: '#F00',
title: 'full',
textColor: '#000',
className: 'event-full'
},
{
start: '2016-09-20',
allDay : true,
rendering: 'background',
backgroundColor: '#F00',
title: 'full',
textColor: '#000',
className: 'event-full'
}
]
});
http://codepen.io/amishstripclub/pen/zqQqxx
I would use the disabled attribute instead of showing and hidding buttons:
https://jsfiddle.net/uz0mx059/
viewRender: function(view, element) {
var start = new Date("2016-09-01");
var end = new Date("2016-11-30");
if (end < view.end) {
$("#calendar .fc-next-button").attr('disabled',true);
return false;
} else {
$("#calendar .fc-next-button").attr('disabled',false);
}
if (view.start < start) {
$("#calendar .fc-prev-button").attr('disabled',true);
return false;
} else {
$("#calendar .fc-prev-button").attr('disabled',false);
}
}
Plus a bit of css:
button:disabled {
color: grey;
}
I have QTips:
eventRender: function (event, element, view) {
element.qtip({
content: event.title + event.hours,
position:{
target: 'mouse'
},
// show: { event: 'click' },
hide: { event: 'mousedown mouseleave' },
style: {
width: 200,
padding: 5,
color: 'black',
textAlign: 'left',
border: {
width: 1,
radius: 3
},
classes: 'custSideTip'
}
});
}
CSS:
.custSideTip
{
position:fixed !important;
right:0 !important;
max-width:200px !important;
}
But they go off the page...
I tried right and fixed position and nothing seems to work...
The right coordinate of the tip should never exceed the body.right / page.right... if that makes sense..
Thanks
Taken from here.
You can try to use viewport config:
position: { viewport: $(window) }
This worked for me and other examples didn't with some error in jQuery code. Perhaps some version discrepancy?
position: { viewport: $(document.body) }