Controlling location of SVG image on web page with CSS - css

I am working with an SVG drawing. This has been created by another developer and delivered to me for use on a web site.
It uses the raphael.js vector graphics library to draw the map and animations.
It is inserted into the web page with two lines of javascript:
<script type="text/javascript" src="raphael.js"></script>
<script type="text/javascript" src="maine_map.js"></script>
My challenge is that I cannot get this svg file to appear where I need it to in the page. It needs to appear to the right of the slide show on this demo page:
http://owlpress.net/work/
Rather than appearing in the parent div I created for it, it appears floating at the bottom of the page. I've played with the CSS every which way, and I'm stumped. If anyone can help point me in the right direction, that would be wonderful.
Susan

In main_map.js you have:
// Insert the <div> into the body document.
document.body.appendChild(div);
This is the reason why it is generated after everything.
Create your own div + id and appendChild() to it instead body tag.
DEMO
var apme = document.getElementById('ap');
// Create the div we'll be slotting the map into and set it to the correct size.
var div = document.createElement('div');
div.setAttribute('id', "mobilize_maine_map");
div.style.width = "200px";
div.style.height = "200px";
div.style.borderWidth = "1px";
div.style.borderColor = "#000";
div.style.borderStyle = "solid";
// Insert the <div> into the heml document.
apme.appendChild(div);
Now , this div is inserted inside the div#ap. this div can be anywhere you wish inside your markup.
<edit>
you did :
// Create the div we'll be slotting the map into and set it to the correct size.
var div = document.createElement('div');
div.setAttribute('id', "mobilize_maine_map");
div.style.width = divWidth+"px";
div.style.height = divHeight+"px";
// div.style.borderWidth = "0px";
// div.style.borderColor = "#000";
// div.style.borderStyle = "solid";
// Insert the <div> into the heml document.
document.body.appendChild(div);
var apme = document.getElementById('map');
// Create the div we'll be slotting the map into and set it to the correct size.
var div = document.createElement('div');
div.setAttribute('id', "mobilize_maine_map");
div.style.width = "203px";
div.style.height = "306px";
div.style.borderWidth = "0px";
div.style.borderColor = "#000";
div.style.borderStyle = "solid";
// Insert the <div> into the heml document.
apme.appendChild(div);
This makes 2 div with same id and this is not what you look for :).
You should have removed this :
// Create the div we'll be slotting the map into and set it to the correct size.
var div = document.createElement('div');
div.setAttribute('id', "mobilize_maine_map");
div.style.width = divWidth+"px";
div.style.height = divHeight+"px";
// div.style.borderWidth = "0px";
// div.style.borderColor = "#000";
// div.style.borderStyle = "solid";
// Insert the <div> into the heml document.
document.body.appendChild(div);
and replace it with :
var apme = document.getElementById('map');
// Create the div we'll be slotting the map into and set it to the correct size.
var div = document.createElement('div');
div.setAttribute('id', "mobilize_maine_map");
div.style.width = divWidth+"px";
div.style.height = divHeight+"px";
// Insert the <div> into the heml document.
apme.appendChild(div);

I tried on the svg itself position: relative, left:1050, and bottom:909; and I at least got in the right general area.

Related

$timeout in a directive link function

So I'm using this directive to collapse a variable height card in Ionic. The directive grabs the auto height and changes it to a defined height so it can then be collapsed to 0 with a css animation. It was working fine for my needs, but now I need to use ng-src to dynamically load an image within the card. What's happening is the image is being loaded after the directive, so the image loads and overflows the card.
Directive:
.directive('collapse', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, ngElement, attributes) {
var element = ngElement[0];
$timeout(function(){
$scope.$watch(attributes.collapse, function (collapse) {
var newHeight = collapse ? 0 : getElementAutoHeight();
element.style.height = newHeight +"px";
ngElement.toggleClass('collapsed', collapse);
});
function getElementAutoHeight() {
var currentHeight = getElementCurrentHeight();
element.style.height = 'auto';
var autoHeight = getElementCurrentHeight();
element.style.height = currentHeight +"px";
getElementCurrentHeight(); // Force the browser to recalc height after moving it back to normal
return autoHeight;
}
function getElementCurrentHeight() {
return element.offsetHeight
}
});
}
};
}])
and HTML:
<div ng-repeat="item in items | orderBy : '-'" collapse="item.deleted">
<div class="list card">
<img class="full-image" ng-src="{{item.image}}"/>
</div>
</div>
As you can see I've injected $timeout and leaving the interval blank in hopes it will wait until the DOM is loaded, but it seems no matter how I use it, the directive still explicitly sets the height of the element in css before the image child element is rendered. How can I delay the setting of element height until after ng-src is loaded in each ng-repeat item?
First thing, angular $timeout without an $interval will not wait for the DOM tree to load, basically, what it does is waiting for the current digest cycle to finish before executing the function in the first parameter. By doing so, it will allow the your code to wait till the directive finish compile and render before calculating the height of the div.
However, there is no guarantee that the image will be loaded by that time. Images are loaded by the browser independently from DOM rendering, therefore, to calculate the height of the container having images precisely, you should make use of JS Image Object and the load event. Once the images are fully loaded, then you can update the height.
Also, for your directive, I don't think you need to calculate the height every times the collapse variable changed (inside the watch), you can simply wait till the image being loaded, calculate the height once, store it inside the scope object, and reuse it whenever the collapse variable change.
Okay, so thanks to Thai's input, I have a working solution:
.directive('collapse', [function () {
return {
restrict: 'A',
link: function ($scope, ngElement, attributes) {
var element = ngElement[0];
var img = element.querySelector('.full-image');
angular.element(img).bind('load', function() {
var autoHeight = getElementAutoHeight();
element.style.height = autoHeight + "px";
});
$scope.$watch(attributes.collapse, function (collapse) {
var newHeight = collapse ? 0 : getElementAutoHeight();
element.style.height = newHeight +"px";
ngElement.toggleClass('collapsed', collapse);
});
function getElementAutoHeight() {
var currentHeight = getElementCurrentHeight();
element.style.height = 'auto';
var autoHeight = getElementCurrentHeight();
element.style.height = currentHeight +"px";
getElementCurrentHeight(); // Force the browser to recalc height after moving it back to normal
return autoHeight;
}
function getElementCurrentHeight() {
return element.offsetHeight
}
}
};
}])

html2canvas is working in IE, not working in google chrome

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');
}
});
};

What element is jQuery UI draggable being dragged over in an iframe

Here is my code, where I'm trying to detect the element, which a jQuery UI draggable is hovering over. I need to get the element's object and attributes, such as class names (in this case .sortable-grid,.sortable-table,.sortable-row,.sortable-cell).
The answers found here only show how to get the draggable item itself (ui.helper or event.target), but not the element it is hovering above.
The best way to answer would be using the prepared JSFiddle, since my code uses an iframe, which would not work if the full code is posted here:
JSFiddle
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0-beta.1/jquery-ui.js"></script>
<div style="background-color:grey;display:inline;cursor:move" id="draggable">DRAG ME</div>
<iframe src="https://fiddle.jshell.net/piglin/UAcC7/1869/show/" id="frame" style="width:100%;overflow:visible" seamless="seamless" scrolling="no"></iframe>
JS:
$("#draggable").draggable({
drag: function(event, ui) {
//Some code here
}
}
It was possible by modifying the function from another answer to fit this purpose. After adapting it to use the contentWindow of the iframe and adding offset calculation it works now.
Solution
function allElementsFromPointIframe(x, y, offsetX, offsetY) {
var element, elements = [];
var old_visibility = [];
while (true) {
element = document.getElementById('frame').contentWindow.document.elementFromPoint(x - offsetX, y - offsetY);
if (!element || element === document.getElementById('frame').contentWindow.document.documentElement) {
break;
}
elements.push(element);
old_visibility.push(element.style.visibility);
element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
}
for (var k = 0; k < elements.length; k++) {
elements[k].style.visibility = old_visibility[k];
}
elements.reverse();
return elements;
}
var selected = $('');
var tmpColor = 'transparent';
$("#draggable").draggable({
drag: function(event, ui) {
var el = $(allElementsFromPointIframe(event.pageX, event.pageY, $(frame).offset().left, $(frame).offset().top));
var div = $(el).filter('ul, li').not($(this));
selected.css({'backgroundColor': tmpColor});
selected = div.last()
tmpColor = selected.css('backgroundColor');
selected.css({'backgroundColor': 'red'});
console.dir(div);
},
iframeFix: true,
iframeOffset: $('#iframe').offset()
});

How to position an element absolute to the window regardless of its DOM position?

I am creating a pop-up overlay modal and am having problems getting the positioning/scrolling working correctly.
I can set my modal to be position:fixed but then if the modal's height is too much, then the modal overflows off of the window and you cannot see the bottom of it.
If I set the modal to be position:absolute then the element becomes positioned relative to the closest ancestor with position:relative, correct? (or at least thats what it appears to do) Instead I want the modal to ALWAYS be relative to the window so that I can center it easily.
Is there a way to make the below .modal positioned relative to the window ( or element) even if the element is nested deep inside the DOM like this:
<body ng-app="myapp" ng-controller="mycontroller">
<div>
<div>
<div ui-view>
<div class=".modal"></div>
</div>
</div>
</div>
</body>
If you insist on having it in that same markup and nested in the same manner, your best bet is in JavaScript.
Here's some JS code that gives a good method of accomplishing what you asked for:
function ShowDivInCenter()
{
try
{
divWidth = 100;
divHeight = 100;
divId = 'divLogin'; // id of the div that you want to show in center
// Get the x and y coordinates of the center in output browser's window
var centerX, centerY;
if (self.innerHeight)
{
centerX = self.innerWidth;
centerY = self.innerHeight;
}
else if (document.documentElement && document.documentElement.clientHeight)
{
centerX = document.documentElement.clientWidth;
centerY = document.documentElement.clientHeight;
}
else if (document.body)
{
centerX = document.body.clientWidth;
centerY = document.body.clientHeight;
}
var offsetLeft = (centerX - divWidth) / 2;
var offsetTop = (centerY - divHeight) / 2;
// The initial width and height of the div can be set in the
// style sheet with display:none; divid is passed as an argument to // the function
var ojbDiv = document.getElementById(divId);
ojbDiv.style.position = 'absolute';
ojbDiv.style.top = offsetTop + 'px';
ojbDiv.style.left = offsetLeft + 'px';
ojbDiv.style.display = "block";
}
catch (e) {}
}
You can then call the function through any event, for example:
<body onload='ShowDivInCenter();' onresize='ShowDivInCenter();'>
if you want it to be dynamic.

Display an icon for a google maps marker from a html image element

I want to display an image for a google marker from an html image element NOT from an URL.
How can I do this?
The below code does not show any image on the google maps.
The code with the outcomment URL does show an image on the google maps.
var image = document.createElement('img');
image.src = "data:image/png;base64," + base64Data;
image.height = "40px";
image.width = "40px";
var icon = image; // Instead of "../Content/images/Root.jpeg";
var markerOptions = {
position: bound,
map: map,
icon: icon
};
var marker = new google.maps.Marker(markerOptions);

Resources