I'm using Backbone to render a square tile element in which I set the height and then dynamically set the width to match the height. However, when trying to fetch the elements height, I get 0 returned.
Here is my code:
var app = app || {};
app.ClassModelView = Backbone.View.extend({
className: 'tile',
template: _.template('<%= name %>'),
render: function() {
var dim = 'calc(' + parseInt(100 / app.global.rows) + '% - ' + app.global.margin * (app.global.rows + 1) + 'px)'; //e.g. "30% - 20px"
this.$el.append(this.template(this.model.attributes)).css({
margin: app.global.margin + 'px',
height: dim,
}).css({
width: this.$el.height() + 'px',
});
return this;
}
})
How would I set the width of $el to the height? I'm not sure if I'm doing something syntactically wrong or if it is the way I'm using Backbone that is resulting in my problem.
I've ran into similar issues in the past. In most cases, it was because my view had rendered but had not yet been inserted into the DOM. This is pretty common when dealing with nested views.
You can test for this by setting a break point in your onRender method and checking this.$el.parent(). You might want to go up a few parents to make sure the parent elements are in the DOM.
You can get around this by binding to the DOMNodeInserted event:
this.$el.on('DOMNodeInserted', function(e) { console.log($(e.target).outerHeight()); })
Related
I'm currently using Gridster.js (http://gridster.net/) in combination with CKEditor.
Once the user saves their content with CKEditor, this content is put into the widget. However the widgets do not automatically resize themselves to fit the content, and while the user is able to resize it themselves, it would be more convienient for the userbase to have it be done for them the moment they press save.
I have tried a few things, but none to any avail. I'm having trouble getting the size of the current content, and then resizing the gridster respectively.
In my code, I have two values to work with. the gridster element (widget), and the value that will be put into it (contents). I have to determine the height of the contents. Once this is done successfully, I will be able to determine if my code for getting the x and y values work.
My current code looks like this:
// Initialization of the gridster element.
// The base dimensions are relevant to understand how we
// calculate the multipliers, later on.
gridster = $(".gridster > ul").gridster({
widget_margins: [10, 10],
widget_base_dimensions: [100, 50],
draggable: {
handle: 'header'
},
resize: {
enabled: true,
max_size: [20, 10],
min_size: [2, 1]
}
}).data('gridster');
And (the relevant bits of) my JavaScript class that handles saving and resizing:
// Saves the content from CKEditor to the gridster widget
this.save = function (data) {
var lastContents = this.default_html + data + '</div>';
$(this.editor).removeClass('gs-w-new');
this.resize_widget(this.editor, lastContents);
$(this.editor).html(lastContents);
this.modal.modal('hide');
};
/* #TODO: resize_widget function */
// if the new content from ckeditor is larger than the
// original size of the widget, we need to make it larger.
this.resize_widget = function(widgetId, contents) {
var element = $('<div>')
.addClass('fake-div-gs-w-resize')
/*
.fake-div-gs-w-resize {
position: absolute;
display: none;
height: auto;
width: auto;
white-space: nowrap;
}
*/
.css('display', 'block')
.html(contents);
var widget = $(widgetId);
var elementWidth = $(element).width(), // I am expecting this to return the width of the content, but it returns 0.
elementHeight = $(element).height(), // As you might imagine, this also returns 0.
width = widget.width(),
height = widget.height();
$(element).css('display', 'none');
console.log(widgetId, widget, width, height, elementWidth, elementHeight);
// this code never gets past here, because element{Height,Width} returns 0.
if (elementHeight > height || elementWidth > width) {
var width_multiplier = 100, // data-x = 1 === width_multiplier px
height_multiplier = 50; // from "widget_base_dimensions: [100, 50],"
var x = Math.round(width / width_multiplier),
y = Math.round(height / height_multiplier),
eX = Math.ceil(elementWidth / width_multiplier),
eY = Math.ceil(elementHeight / height_multiplier);
console.log("setting to x:" + eX + ", y:" + eY + " with width:" + width + ", height:" + height);
if (eX >= x && eY >= y)
gridster.resize_widget(widget, eX, eY);
}
};
Whilst I am not completely confident in my logic for determining the sizes; the main focus of this question is with determining the size of the HTML contents, as what I gathered from other SO posts did not seem to help in my case.
You need to actually add the element to the DOM for the width() and height() functions to work. In your example, the element is not added to the document.
See this JS Fiddle as an example https://jsfiddle.net/y1yf1zzp/10/
I had the same challenge, i.e. dynamic content appearing inside the new tile caused an overflow and appeared outside the tile boundaries. We used the '.scrollHeight' of the tile contents in combination with Zartus' code:
var contentHeight = $widgit.firstChild.scrollHeight;
var tileHeight = $widgit.firstChild.clientHeight;
I'm trying to match the height of background div to the combined height of divs in front. I used simple jQuery height function and it kind of worked:
var originalHeight = $("#topbg").height() + $("#menurowbg").height() + $("#headerbg").height() + $("#contentareabg").height() + $("#footerbg").height();
$("#wrapper").height(originalHeight);
The problem is, the height needs to change dynamically if one of those divs is resized to keep matching. I tried to put the setTimeout function, but failed. I'm obviously missing something but can't figure it out. Please help this jQuery rookie. Here's my current code:
var originalHeight = $("#topbg").height() + $("#menurowbg").height() + $("#headerbg").height() + $("#contentareabg").height() + $("#footerbg").height();
setTimeout function checkHeight() {
if(originalHeight < ($("#topbg").height() + $("#menurowbg").height() + $("#headerbg").height() + $("#contentareabg").height() + $("#footerbg").height()))
{
originalHeight = $("#topbg").height() + $("#menurowbg").height() + $("#headerbg").height() + $ ("#contentareabg").height() + $("#footerbg").height();
}
}, 500);
$("#wrapper").height(originalHeight);
There are three scenarios:
1) Use setInterval() rather than setTimeout() to execute code ever X amount of milliseconds:
setInterval(function() {
setContainerSize();
}, 1000);
Example: http://jsfiddle.net/XWmdL/3/
2) The containing div is the parent of the divs being resized. In that case, You don't have to add all the heights together and reset the container's height. You can just set the container's width and height attributes to auto:
#container {
width: auto;
height: auto;
}
Example: http://jsfiddle.net/XWmdL/1/
3) If your child divs are being resized when the window size changes, you need to use the $(window).resize() event. Change the viewing window size in the following example and you'll see the red background size change as the yellow div changes.
Example: http://jsfiddle.net/XWmdL/2/
Hope this helps!
First the condition is wrong
setTimeout function checkHeight() {
if(originalHeight < (jQuery("#topbg").height() + jQuery("#menurowbg").height() + jQuery("#headerbg").height() + jQuery("#contentareabg").height() + jQuery("#footerbg").height())) {
originalHeight = jQuery("#topbg").height() + jQuery("#menurowbg").height() + jQuery("#headerbg").height() + jQuery("#contentareabg").height()+jQuery("#footerbg").height();
jQuery("#wrapper").height(originalHeight);
}, 500);
I want to create a directive that is applied to elements to set their max height equal to the window height minus the distance from the top of the element to the top of the window.
I was trying it like this
.directive('resize', function ($window) {
return function (scope, element) {
var w = angular.element($window);
scope.getWindowDimensions = function() {
return { 'h': w.height() };
};
scope.$watch(scope.getWindowDimensions, function(newValue, oldValue) {
//get header height including margins
var headerHeight = $('.page-header').outerHeight(true);
scope.windowHeight = newValue.h;
scope.style = function() {
return {
'height': (scope.windowHeight - headerHeight) + 'px',
'max-height': (scope.windowHeight - headerHeight) + 'px'
};
};
}, true);
w.bind('resize', function() {
scope.$apply();
});
}
})
But I would have to add a var for every element that is above the element whose height I want to set. So I believe using
var scrollTop = $(window).scrollTop(),
elementOffset = $('#my-element').offset().top,
distance = (elementOffset - scrollTop);
would be better as it does all the measurements relative to the element its setting but how do I access this element from within the directive without adding any extra classes or identifiers?
Also do I need to create an isolate scope for me to use this more than once on a single page?
My goal is to basically have my web apps body element equal to the height of the window and any containing divs that are higher than that height to have scroll bars.
1)It would be better if you have isolate scope. so that the directive can be user multiple elements with different heights.
2) Send an array of elements (Which are above the required element) as an attribute to the directive. And calculate the height to be deducted from window height.
I have a set of div's generated by php, and they all have the same class. when I click one, it calls a jQuery function that gets its id (defined by MySQL database) and increases its size (height and width) by 110%. The problem i think I'm having, is when I retrieve its css properties by class, it gets the size of the first thing it sees with that class.
theres not much code to show, but its:
var height = parseInt($(".divClass").css("height"));
var width = parseInt($(".divClass").css("width"));
$(".divClass").css({"height":height + "px","width":width + "px"});
$("#" + id).css({"height":height * 1.1 + "px","width":width * 1.1 + "px"});
id is created when the function is called, and is the id of each individual div.
A: Am i even correct about my assumptions? B: How would i go about getting the css properties for the majority of elements with the same property instead of the first one. What is happening is when i click the first element, it, and the rest grow. Any help would be greatly appreciated.
My suggestion would be to do:
var height, width;
$('.divClass').click(function() {
height = $(this).height();
width = $(this).width();
$(this).css({ 'height': ( height * 1.1 ) + 'px', 'width': ( width * 1.1 ) + 'px' });
});
I haven't tested my code by the way so let me know how it works for you and I'll tweak as necessary.
There's this image on a page I'm coding which should be resized and horizontally and vertically centered depending on some variables. I can't use the CSS sheet for this, as the width and height variables are dynamic. Therefore I want to have javascript add two extra arguments (top and left) to the style of this specific image.
I've tried this (which to me looked quite sensible)
function getStyleSheet() {
for(var i=0; i<document.styleSheets.length; i++) {
var sheet = document.styleSheets[i];
if(sheet.title == 'StyleSheet') {
return sheet;}
}
}
var rule_sheet = getStyleSheet();
function changeText() {
rule_sheet.insertRule(".className { top:" (-(.5*newHeight))+ "; left:" +(-(.5*newWidth))+ ";}");
showRules();
}
I've also tried to add an inline style to the image like so: (in the function where the image was resized)
$(this).style.top= (-(.5*newHeight));
$(this).style.left= (-(.5*newWidth));
Neither solution worked, while to me both methods seemed plausible. What am I missing?
EDIT: I realized I didn't add the suffix 'px' to this, but after doing so, it still doesn't work :(
EDIT II:
After NickFitz hints, I rewrote the last bit of code to this:
$(".className").each(function() {
$(this).css("top", (-(.5*newHeight)), 2);
$(this).css("left", (-(.5*newWidth)), 2);
});
This actually does change the way it looks. Not the way I want it, but at least I'ma tad closer to a solution.
If you're using jQuery, you want the CSS-related methods. $(this) returns a jQuery object, and setting the style property of that isn't going to do anything.
Try this:
$(this).css( 'top', (-(.5*newHeight))+'px' );
$(this).css( 'left', (-(.5*newWidth))+'px' );
You should try something like (using val on the end of the variables)
$(this).css({top: topval + "px", left : leftval + "px", width : widthval + "px", height : heightval + "px"});
or you could use:
$(this).width(widthval);
Can you just get a wrapped set containing the <img> and then use the .css() command to set the appropriate values for it?
$('#img').css({ 'width' : calculatedWidth + 'px', 'height' : calculatedHeight + 'px' });