I am adding background images to my div like this
ng-style="{'background-image' : 'url('+ myvariable.for.image +')'}">
where myvariable.for.image is a url like /examplesite/image/id
This works fine with one exception, if the image is not there it just doesnt do anything and my background looks too bla...If the image doesnt exist I want to be able to replace it with a default image.
But I cant seem to figure out how
Instead of ngStyle I'd use a custom directive for this. Such as the following. This checks to see if an attribute is provided, if so it attempts to load that image. If it loads an image then we set the background image to it, otherwise we use a default image.
myApp.directive('bgImage', function () {
return {
link: function(scope, element, attr) {
attr.$observe('bgImage', function() {
if (!attr.bgImage) {
// No attribute specified, so use default
element.css("background-image","url("+scope.defaultImage+")");
} else {
var image = new Image();
image.src = attr.bgImage;
image.onload = function() {
//Image loaded- set the background image to it
element.css("background-image","url("+attr.bgImage+")");
};
image.onerror = function() {
//Image failed to load- use default
element.css("background-image","url("+scope.defaultImage+")");
};
}
});
}
};
});
Used like this:
<div bg-image="{{person.src}}">
demo fiddle
<div err-bg-src='{{default_business_logo_wd}}' ng-style="{'background-image' : 'url('+ifNull(place.logo_wd,default_business_logo_wd)+')'}" id="perfilEstablecimiento-container10" class="place-header">
<div id="perfilEstablecimiento-container13" class="place-title-container">
<h4 id="perfilEstablecimiento-heading1" class="place-title">{{place.name}}</h4>
</div>
</div>
Using a $timeout inside that custom directive worked for me.
.directive
(
'errBgSrc',
function($timeout)
{
return {
link: function(scope, element, attrs)
{
$timeout
(
function()
{
if(window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage=='none'||window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage==null)
{
document.getElementById(attrs.id).style.backgroundImage='url('+attrs.errBgSrc+')';
}
else
{
var image = new Image();
var style=window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage;
var url=style.slice(5,style.length-2);
image.src = url;
image.onerror = function()
{
document.getElementById(attrs.id).style.backgroundImage='url('+attrs.errBgSrc+')';
};
}
},
500
);
}
}
}
)
Related
I have a jquery function that works out the width and height of an image I upload through umbraco. How can I call this.width and this.height into my img src in html at the bottom of the page?
<script>
function getMeta(varA, varB) {
if (typeof varB !== 'undefined') {
alert(varA + ' width ' + varB + ' height');
} else {
var img = new Image();
img.src = varA;
img.onload = function () {
getMeta(this.width, this.height);
}
}
}
getMeta("#image.Url()")
</script>
<img src="#image.Url()" width="" height="" border="0" alt="#Model.Value("mapImage")
mapImage" usemap="#Map" />
I've left the width and height empty but that's where I want it to equal this.width and this.height. I need it to automatically call it for other functions I have as it needs to change depending on the size of the image uploaded.
Thanks in advance for any help :)
Well.. good news - this is native JS - no jquery used the code you've posted
Second - you don't need to send the width and height to your data model - just update your image element. so...
img.onload = function () {
const imgElement = document.querySelector('img'); // select the image element in you HTML page
imgElement.style.width = `${this.width}px`; // set a proper with using pixels as unit
imgElement.style.height = `${this.height}px`; // set height the same way
}
This should update your image proportions to be an exact fit to the image provided
Assuming that I understood you well and you have an uploaded pic (that you get its source by calling #image.Url()), and you want to apply its dimensions of another pic (with id templateImg), this is the code:
<img id="templateImg" src="https://cdn.vox-cdn.com/thumbor/prZDWmD_4e4Js7KCRJ2JDrJOqO0=/0x0:939x704/1400x1050/filters:focal(0x0:939x704):format(jpeg)/cdn.vox-cdn.com/uploads/chorus_image/image/49610677/homersimpson.0.0.jpg" />
<script type = "text/javascript">
var uploadedPic = 'https://i.pinimg.com/736x/dd/50/38/dd5038cdbfde2a8f1583bd84f992f862.jpg';
function getMeta(src) {
return new Promise(resolve => {
var img = new Image();
img.src = src;
img.onload = function () {
resolve({
width: this.width,
height: this.height
});
}
})
}
getMeta(uploadedPic)
.then(dimensions => {
document.getElementById('templateImg').style.width = `${dimensions.width}px`;
document.getElementById('templateImg').style.height = `${dimensions.height}px`;
});
</script>
It was working example with real pictures, now you just replace the line var uploadedPic... with this Razor code:
<text>
var uploadedPic = '#image.Url()';
</text>
(assuming this is the path to your uploaded picture) and you'll be fine.
I'm trying to apply a background image to a span tag by using the angular ng-style , when span tag is clicked it calls chgImg but it doesn't seem to be working. Its working if I am directly replacing {{img}} with /images/chk.svg
<span ng-style="{'background-image':'url({{img}})'}" ng-click="chgImg()" class="Pollchoice--radio">{{img}}
</span>
AngularCode:
app.controller('HomeCtrl', ['$scope', 'posts',
function($scope, posts) {
$scope.posts = posts.posts;
$scope.chgImg = function(){
$scope.img = "/images/chk.svg";
};
}
]);
Please use $scope.apply as below:
$scope.chgImg = function(){
$scope.$apply(function () {
$scope.img = "/images/chk.svg";
});
};
I'm using HTML2Canvas to convert my DIV to a PNG. It is going well, but when my DIV is larger than the screen, only the visible part of the DIV in the screen is rendered in the image.
Is there any workaround so I can render the whole DIV into the image?
Here is my code:
html2canvas(divDrop, {
onrendered: function (canvas) {
imgMap.style.display = "";
imgMap.src = canvas.toDataURL("image/png");
},
width: divDrop.clientWidth,
height: divDrop.clientHeight
});
As described in the comments, I'm posting the working link below:
JSFiddle example
$(function() {
$("#btnSave").click(function() {
html2canvas($("#widget"), {
onrendered: function(canvas) {
theCanvas = canvas;
document.body.appendChild(canvas);
// Convert and download as image
Canvas2Image.saveAsPNG(canvas);
$("#img-out").append(canvas);
// Clean up
//document.body.removeChild(canvas);
}
});
});
});
I have a simple span element with some text. I want paste in my html just tag "span" with any text and directive "text-type". Every 100 ms a new symbol will appear. So, first, i have to save span text in some variable and then show text with my directive:
<span data-text-type>Just a text</span>
And I want to change text in my directive
app.directive('textType', function() {
return {
restrict: 'A',
template: '{{newText}}',
scope:{},
link: function(scope, element) {
var text = element.text().split(''); /*will be '{{newText}}', but not 'Just a text'*/
scope.newText = '';
(function fn () {
if (text.length) {
scope.textStr += text.shift();
$timeout(fn, 100);
}
}());
}
}
});
So, how can I save text before the directive will change it?
I find that it was needed use compile function that return link function, and change "scope:{}" to "scope:true" to use isolate scope for each element.
return {
restrict: 'A',
scope:true,
compile: function(element, attrs) {
var string = element.text().split(''),
max = string.length;
element[0].innerHTML ='<span class="tt-text">{{textStr}}</span><span class="tt-heading">{{textHeading}}</span>';
return function(scope, element, attrs, controller) {
var dur = 200;
scope.textStr = '';
scope.textHeading = string[0];
(function fn() {
if (string.length) {
head.stop().fadeOut(0).fadeIn(dur, function() {
scope.textStr += string.shift();
scope.textHeading = string[0];
scope.$apply();
fn();
});
} else {
scope.textHeading = '';
}
}());
}
}
}
I want to write a directive that change an image depending on the attribute value "name". The image is shown but it doesn't update when the "name" attribute changes.
HTML:
<img test name="{{finder.name}}"
JS:
.directive("test", function() {
return {
restrict: "A",
scope: {
name: '#'
},
link: function(scope, element, attrs) {
scope.$watch("name", function(value) {
if (angular.isDefined(value))
var replaceName = value.replace(/[ \/]+/g, "_")
.toLowerCase();
var tag = '<img src="/images/banner_' +
replaceName + '.jpg" class="img-responsive"/>'
element.replaceWith(tag);
})
}}}
);
Thanks!
Here is what I did on my simple image directive.. to generate dynamic image source..
link: function(scope, element, attrs) {
// this will replace the value of your image source
var setImagrSRC = function() {
element.attr('src','some source value here..')
}
// this will observe if there is changes on your name directive
// and will trigger the function setImageSRC above
attrs.$observe('name',setImageSRC);
}}}
That's because you overwrite the element with the new element with that replaceWith method. Your directive will destroyed with it. Don't replace the element, just replace the attribute :
link: function(scope, element, attrs){
scope.$watch('name', function(value){
...
var imageUrl = value.replace(...);
element.attr('src', imageUrl);
});
}