Is there a way to align the first node at the top instead of at the middle? - orgchart

I am using BalkanGraph plugin and I'm trying to align the first parent node of the orgchart to the top of the svg instead of the center of it.
I tried to set a negative "margin-top" and increases the height of the whole svg, but then the click goes with it, and it doesn't work well.
My only css is this:
#tree {
width: 100%;
height: 630px;
border: 1px solid lightgray;
background-color: #fff;
}
and the things I am using in Orgchart are these:
var chart = new OrgChart(document.getElementById("tree"), {
mouseScroolBehaviour: BALKANGraph.action.zoom,
nodeMouseClickBehaviour: BALKANGraph.action.none,
scaleInitial: BALKANGraph.match.boundary,
collapse: {
level: 2,
allChildren: true
},
});

Set align option to BALKANGraph.ORIENTATION
var chart = new OrgChart(document.getElementById("tree"), {
align: BALKANGraph.ORIENTATION,
...
});

Related

On click, animate the div element to the top and make it sticky

I have a parent div, that contains multiple child divs inside it, On clicking any child element,I am trying to animate that child element from its current position to the top position according to its current parent, then after moving to the top with proper animation, I want that child element to be sticky, so that other child elements can be easily scrolled underneath it and then, if any other child element is clicked then it will animate to top and the recent child element will move back to its old position.
Any help using angular and/or html and css will be really appreciative.
I am also attaching stackblitz angular project link for my initial code.
https://stackblitz.com/edit/angular-ivy-abbnjo
Thanks
I find this question interesting, so I did a quick sample of how you can do this via jQuery. There are certainly libraries there that probably does this already, but with the interest of sharing the logic behind it, here's a quick demo in JSFiddle. It may need some more love though.
I hope this helps!
JSFiddle Link: https://jsfiddle.net/qo6x42za/1/
HTML
<div>
<div class="sticky"></div>
<div class="container">
<div class="box" data-order="1">Box1</div>
<div class="box" data-order="2">Box2</div>
<div class="box" data-order="3">Box3</div>
<div class="box" data-order="4">Box4</div>
<div class="box" data-order="5">Box5</div>
</div>
</div>
CSS
.container {
position: relative;
height: 250px;
overflow-y: scroll;
border: 1px solid #000;
}
.box {
width: 100px;
height: 50px;
padding: 20px;
background-color: #595959;
color: #fff;
border: 1px solid #c90000;
}
Javascript
$('.box').each(function(index) {
$(this).on('click', function() {
const target = $(this);
const sticky = $('.sticky');
const container = $('.container');
const position = $(sticky).position();
// after animation completes
const options = {
complete: () => {
// detach previous item from sticky container and place back to original position
if ($(sticky).children().length > 0) {
const firstChild = $(sticky).children().first();
const order = $(firstChild).data('order');
const previousChild = order - 1;
if (order > 1) {
$(firstChild).detach().insertAfter($(`[data-order=${previousChild}]`));
} else {
$(firstChild).detach();
$(container).prepend($(firstChild));
}
}
// attach item to sticky container
$(sticky).append($(target));
// remove the style attribute as we no longer need it
$(target).removeAttr('style');
}
};
// animate to position
$(target).css({ position: 'absolute'});
$(target).animate({
top: position.top
}, options);
});
})

How to apply nth-child either odd or even in reversed order?

I have a list of alternating colored divs (red or green).
I am inserting new divs at the top of the list and I want the existing divs to keep their color.
Is there any way to apply nth:child(odd) to the list of divs but in reverse? The way it works now is that the top div will always be green and the bottom div will change color using nth:child odd or even.
Use :nth-last-child.
It uses the same logic as :nth-child, but reversed.
Working example (I can't use SASS here, so please see the equivalent CSS):
const parent = document.querySelector('#parent');
const button = document.querySelector('#button');
let count = 0;
button.addEventListener('click', function(){
const child = document.createElement('div');
child.classList.add('child');
child.textContent = ++count;
parent.insertBefore(child, parent.firstChild);
});
#parent {
margin-top: 1em;
}
.child {
width: 100px;
height: 25px;
text-align: center;
line-height: 25px;
color: white;
}
.child:nth-last-child(odd) {
background-color: green;
}
.child:nth-last-child(even) {
background-color: red;
}
<button id="button">Add Child</button>
<div id="parent">
<div class="child">0</div>
</div>

How to make a fixed floating button to stop at footer in angularjs

I would like to create a button using that floats until footer and then stops
1) Button should be poisition: fixed; bottom: 0px when footer is not visible
2) When footer becomes visible, button should just sit on top of footer
The button should handle following cases.
when states change in angular, when we get data from server the footer is visible for a moment and then the page expands, what will happen then?
when the page has less content and footer is visible, button should sit on top of footer.
How can i do this?
Here is the plunker i started to play around with
http://plnkr.co/edit/SoCBjkUjFICiuTeTPxDB?p=preview
I came across this post when searching for a similar solution. Without a ready answer, this is what I ended up doing, based on this post https://ngmilk.rocks/2015/04/09/angularjs-sticky-navigation-directive/ .
Basicly you need a $scope.$watch to watch for scope change, and an event handler attached to the onscroll event.
angular.module('myApp')
.directive('stickyBottom', function($window) {
return {
restrict: 'A',
scope: {},
link: function (scope, elem, attrs) {
// the element box saved for later reference
var elemRect;
// element height
var height = elem[0].clientHeight;
// element top, will be changed as scope is updated
var top = 0;
// updates element's original position
scope.$watch(function(){
elemRect = elem[0].getBoundingClientRect();
return elemRect.top + $window.pageYOffset;
}, function(newVal, oldVal){
// this is the original element position, save it
if(!elem.hasClass('fixed-bottom')){
top = newVal;
}
// properly position the element even in `fixed` display
elem.css('width', elemRect.width);
elem.css('left', elemRect.left);
// check position
toggleClass();
});
// toggle `fixed-bottom` class based on element's position
var toggleClass = function() {
// the element is hidden
if (elem[0].getBoundingClientRect().top + height > $window.innerHeight) {
elem.addClass('fixed-bottom');
}
// the element is visible
else {
// the element is visible in its original position
if (top - $window.pageYOffset + height < $window.innerHeight && elem.hasClass('fixed-bottom')) {
elem.removeClass('fixed-bottom');
}
}
}
// bind to `onscroll` event
$window.onscroll = function() {
toggleClass();
};
}
};
})
;
And here's some css:
.fixed-bottom {
position: fixed;
top: auto;
bottom: 0;
}
You can accomplish this affect without using angular at all by modifying your style.css. The simplest solution in this case is just to set the bottom parameter of the #to-top element to be at minimum higher than the footer, for example:
#to-top {
position:fixed;
bottom: 60px;
right: 10px;
width: 100px;
padding: 5px;
border: 1px solid #ccc;
background: red;
color: white;
font-weight: bold;
text-align: center;
cursor: pointer;
}

Absolute div overlay iframe borders?

I'm wondering if there is a way to have a div, absolutely positioned, hover over the border of the iframe that div is in. Can this be done?
My case:
I have an iframe with a list of files in it, on the right end of each file there is a button. I want to have a div-popup with some functions like a contextmenu. But because this button is at the edge of the iframe the absolutely positioned div is put behind/outside the iframe viewport. I want it to overlay in the rest of my document, outside the iframe.
​<iframe width="100" height="100">
div would be in here, say 300 x 100 px.
</iframe>
overlayed div should be visible here as well, basically the div should overlay the iframe.​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
Well, technically you can't do that. However, if you hijack the events in the iframe, you can recreate the context menu in the main window and use the relative position of the div within the iframe + the absolute position of the iframe itself.
So, to sum up, the context menu can be outside the iframe, and manipulated by the events from within the iframe.
Let me show you how it can be done. I don't have your code, so I'm just making a very crude proof of concept. :)
Example | Code
HTML
<iframe id='my_frame'></iframe>
<div id='copy_to_frame'>
<ul id='files_list'>
<li>data.dat</li>
<li>manual.html</li>
<li>readme.txt</li>
<li>model1.obj</li>
<li>human_model.obj</li>
</ul>
</div>
<div class='context_menu'>
<ul>
<li>Delete</li><li>Open</li><li>Move</li><li>Copy</li>
</ul>
</div>
Javascript
//Declare the necessary variables, good practice
var frame = $("#my_frame"),
frame_contents = frame.contents(),
frame_body = frame_contents .find("body"),
copy_list = $("#copy_to_frame"),
context_menu = $(".context_menu");
var bInside = false;
//Fill the iframe with a list
frame_body.html(copy_list.html());
copy_list.hide();
paint();
//Attach event handler for context menu popup etc.
$("#files_list li", frame_body).click(function(e){
var $this = $(this);
var rel_x = $this.position().left + $this.outerWidth() + 5,
rel_y = $this.position().top + $this.outerHeight()/2 - context_menu.outerHeight()/2 - frame_body.scrollTop(),
abs_x = frame.offset().left,
abs_y = frame.offset().top;
e.stopPropagation();
context_menu.css({
top: rel_y + abs_y,
left: rel_x + abs_x
});
//Show the context menu in this window
context_menu.show();
paint($this);
});
//Hide when clicking outside the context menu
$(document).add(frame_body).click(function(){
if(!bInside){
context_menu.hide();
paint();
}
});
//Determine if mouse is inside context menu
context_menu.mouseenter(function(){
bInside = true;
}).mouseleave(function(){
bInside = false;
});
function paint(el){
$("#files_list li", frame_body).css({
"background-color": "white",
"border": "1px solid transparent"
});
if(el){
el.css({
"background-color": "#ddecfd",
"border": "1px solid #7da2ce"
});
}
}
CSS
#my_frame{
position: absolute;
border: 1px solid gray;
width: 200px;
height: 100px;
top: 50%; left: 50%;
margin-top: -62.5px;
margin-left: -100px;
z-index: 1;
}
.context_menu{
display: none;
position: absolute;
top: 0;
left: 0;
background-color: white;
z-index: 2;
}
.context_menu ul{
border: 1px solid black;
border-right: 0;
display: inline-block;
}
.context_menu li{
display: inline-block;
border-right: 1px solid black;
padding: 2px;
text-align: center;
margin: 0px;
cursor: default;
}
.context_menu li:hover{
background-color: lightgray;
}
This is a bit of a guess based on the minimal information that was provided, but...
You can manipulate the contents of an <iframe> from within the parent document using jQuery, like so:
$('#myFrame').contents().find('a').click(function() { /*...*/ });
This allows you to detect when the user has clicked inside the <iframe>. Then you can work out where to position your overlay <div>.
Your overlay <div> will need to have position: fixed set. You can use jQuery's .offset() method to get the coordinates of the <iframe> and the link that was clicked inside the <iframe>. You can use these two values to calculate where to position the overlay <div> in the parent document. For example, to position the overlay to the left of the <iframe> and on the same vertical level as the link that was clicked you can do this:
$('#overlayDiv')
.offset({
left: $('#myFrame').offset().left - $('#overlayDiv').width(),
top: $('#myFrame').offset().top + $(this).offset().top
})
See this fiddle for a basic example of how it could work: http://jsfiddle.net/Gxd3M/2/
(Note that this assumes that the contents of the parent document and the iframe both come from the same server, i.e. they have the same origin.)

Center Aligning the Google charts

I am trying to center align my google chart but have been unsuccessful in doing so. I have played with padding to move it to the center but I don't want to sit there and play with firebug for long time and figure out the correct position. Is there any simpler such as aligning text text-align: center. Obviously it doesn't work with google charts. (I am new to all of this)
var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
...some code ...
<div id='chart_div' style='width: 900px; height: 400px;'></div>
although I did this padding-left: 140px but is there any better way like align: center
Give the chart_div: display: block and margin: 0 auto;
You could also do <div id='chart_div' align='center'> This worked for me, although now my chart hovering function isn't working. Anyone else get this problem? I'm talking about when you hover the mouse over a point on the graph. It usually shows the point such as Jan Sales 440. Anyone know of a fix?
I have been facing the same issue with a google gauge. Checking the code generated I realized that the next thing inside the <div id='chart_div'> is a table with margin 0 set as inline style.
So in order to override it I used the following css:
div.chart_div table {
width: auto;
margin: 0 auto !important;
}
And this worked.
The accepted answer is broken; you have to use display: inline-block to center align your chart.
Since width is fixed, try setting margin-left and margin-right to auto. It should work assuming that the position is relative.
Any of these answers doesn't work for me so i did that:
<div class="chart_box">
<div id="chart_div" style='width: 900px; height: 400px;'></div>
</div>
.chart_box {
width: 900px;
margin: 0 auto;
}
You need to use same width for chart_div and chart_box.
Set chart_div to following properties:
#chart_div{
display: inline-block;
margin: 0 auto;
}
Notice: when you remove the side menu ("legend: 'none'") the width should be altered.
This happens mostly when you go "legend: 'none'" because it leaves the side space that was there to hold that menu, not adjusting the width automatically. You need to re set the width and NARROW it, to manipulate its alignment:
var options = {
title: 'center alignment',
width: 350,
height: 350,
legend: 'none'
};
I combined a few of the answers here, as follows:
Create a css class:
.customChartStyle{
border:1px solid #eee;
text-align:center !important;
}
and add it to the table's cells by adding the following to my table.draw() call:
'allowHtml': true, 'cssClassNames': {'tableCell': 'customChartStyle'}}
I'm new to google charts but the key for me was adding !important to the text-align style (thanks thanassis). For my case I needed the border style because overriding the tableCell style removed that otherwise. Also I prefer defining the class and letting the charts api apply it instead of overriding the styles generated by the api.
Subscribe to the ready event to modify the CSS with JavaScript. Something like below will do the trick.
google.charts.load('current', {
'packages': ['gauge']
});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
['Memory', 80],
['CPU', 55],
['Network', 68]
]);
var guageOptions = {
width: 400,
height: 120,
redFrom: 90,
redTo: 100,
yellowFrom: 75,
yellowTo: 90,
minorTicks: 5
};
var guage = new google.visualization.Gauge(document.getElementById('my-div'));
// HERE'S HOW TO SUBSCRIBE TO THE EVENT
google.visualization.events.addListener(guage, 'ready', resetTableStyle);
guage.draw(data, guageOptions);
// HERE'S THE JAVASCRIPT TO SET YOUR CSS
// NOTE TOGGLING A CSS CLASS HERE IS PROBABLY CLEANEST
function resetTableStyle(){
var myDiv = document.getElementById('my-div');
var myTable = myDiv.getElementsByTagName('table')[0];
myTable.style.margin = 'auto';
}
Below code works for me:
width:fit-content;
margin:0 auto;
By implementing a class to my div, it can now be centered.
HTML
<div id="chart_div2" class="chart_hum"></div>
CSS
.chart_hum {
margin: 0 auto;
display: inline-block;
}