I'm trying to create a template where a user can drag programmable IOT items around in a room and save the template. As you will see in the code below the room is simply a div with a background image which the user has uploaded to the server. When the user opens the page again at a later time, I want to be able to load the dragged items in their saved positions. I understand how to save the data, I don't know how actually calculate where the item should be displayed on the screen in a multi-browser compatible format. I'm using the jQuery UI for dragging the IOT devices around the room.
Here is my HTML:
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="room" class="room" style="background-image:url('<%= url_for(#room.background) %>')">
<div class="device draggable">
<div class="content md">
</div>
</div>
</div>
</div>
</div>
</div>
And my jQuery:
$(function() {
$( ".draggable" ).draggable();
});
You can get x and y coordinate in the drag event and persist it as shown below.
$(".draggable").draggable({
containment: "parent",
drag: function () {
var $this = $(this),
x = this.offsetLeft / (body.clientWidth - $this.width()),
y = this.offsetTop / (body.clientHeight - $this.height());
}
});
While user open page again, later on, you can assign left and top property for the element.
document.getElementsByClassName("draggable").style.left = (body.clientWidth - $shape.width()) * x + "px";
document.getElementsByClassName("draggable").style.top = (body.clientHeight - $shape.height()) * y + "px";
Here, body means window.document.body. This is what I have done to calculate the position when I want to persist the position and it works for all scenarios like browser if restored or maximize and for also for all the browsers.
Related
I have created a way to scroll through divs, one has a menu and the others have divs with blanks but one has a video.
At the top of the page is a navigation menu that contains "next", "previous", "reload" and "start".
Those commands are warped in functions,
$("#next-item").on("click", function(){,
The page looks like this:
<div class="webcam-left">
<div class="bottom-panel">
<div class="center" id="content">
<div class="bottom-panel-post internal start"></div>
<div class="bottom-panel-post internal video-post"><video src="https://ia800606.us.archive.org/12/items/ACTV_News_open/ACTV_News_open.mp4"></video></div>
<div class="bottom-panel-post internal"></div>
</div>
</div>
</div>
<div class="nav-right nav-main">
<div class="rundown-panel">rundown</div>
<div class="rundown-items">
<div class="irl-today first"><div class="current">Welcome</div></div>
<div class="irl-today override">Category name</div>
<div class="irl-today">the end</div>
</div>
</div>
</div>
What I'm trying to do is when scrolling down the list, how do you trigger play on a video when a video is shown?
When scrolling down, I added classes to the divs that contain a video.
The left side has .override and the video side has .video-post.
I tried doing if hasClass() but it plays on the first click:
if ( $('.rundown-items').is('.override') ) {
if ($( '.bottom-panel-post' ).has('video')) {
$('video').trigger('play');
};
};
Working code - https://jsfiddle.net/openbayou/paonbxcL/8/
I figured it out, the problem was that it was looking for a class across all items and not each one individually so I added an .each function to look for a class on each individual div.
$(".slider-slide-wrap").each(function (i) {
var posLeft = $(this).position().left
var w = $(this).width();
// add shown class on a div
if (scrollLeft >= posLeft && scrollLeft < posLeft + w) {
$(this).addClass('shown').siblings().removeClass('shown');
}
// if .shown has .play-video, trigger play
if ($('.shown').is(".play-video")) {
$('video').trigger('play');
};
});
I have an application where I am locating all the employees on the office layout. I have an Office layout image and the Json for each employee would have an x and y co-ordinate to indicate the location of the employee on the layout. The image is placed in a panel and when I resize the window the image also resizes accordingly. But the location of the employees do not resize. Following is my code:
<div class='col-lg-7 col-md-6 col-sm-12'>
<div class='row'>
<div class='col-xs-12'>
<div class='panel panel-default'>
<div class='panel-body'>
<div id="empMap">
<img rel="prefetch" alt="Image is not found" ng-src="{{officeImage}}" id="empMap" style="width: 100%;height: 100%; z-index: -1" onerror="this.src='/img/OfficeImageNotAvailable.png'">
<div>
<div ng-repeat="emp in employees">
<span class="glyphicon glyphicon-oil" id="{{emp.empId}}" ng-click="empDisplay($event)" ng-dblclick="empInfo($event)"
ng-style="{'cursor': 'pointer','color':'green','position': 'absolute',
'left': xValue + emp.location.xcoordinate, 'top': yValue - emp.location.ycoordinate, 'z-index': '2'}"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Code in the controller:
$("#empMap").load(function() {//loading the image of the plant
img_width = this.width;
img_height = this.height;
console.log("getting the values of the images");
var img_left = $("#empMap").position().left;
var img_top = $("#empMap").position().top;
var y = img_height + img_top;
$scope.xValue = img_left;
$scope.yValue = y -14;
});
What I am doing in the above code is that I am calculating the xValue and yValue from top,left height and width values of the image and in my html I am adding the x and y co-ordinate values to this values.
I am not sure how I can move the location accordingly when the image is resized based. Also the location of the employee is not displayed properly. So could you let me know what I am missing here and what would be the better approach in this scenario.
Your function is only run when the page is initially loaded, to recalculate the positions when the browser window is resized you need to call the function again.
$( window ).resize(function() {
Actions Go Here
});
Your best bet would probably be to establish your position calculation as a function on its own then call it from both .load and .resize so that your code is DRY.
Trying to dynamically resize the div (col with pad) with JavaScript so that it is vertically middle of the parent div (row).
The text blocks vary in size as do the images and there are many of these divs within the page.
I'm quite close to achieving this with the provided code, but the loop seems to be repeating more times than it should and sets the height incorrectly on the last pass, almost like it is halving the space over and over again.
Is there a way to make the JavaScript only run once?
<div class="row">
<div class="col pad">
<p>Text here</p>
</div>
<div class="col">
<img src="image.jpg">
</div>
</div>
$(window).load(function(){
$('.row').each(function() {
var parentDiv = $(this).height();
$('.pad').each(function() {
var childDiv = $(this).height();
var space = parentDiv - childDiv;
var half = space/2;
$(this).css('paddingTop', half + 'px');
alert(half);
});
});
});
I'm unable to use css to achieve this as col are floated.
I am creating a project where I want to be able to drag a div (a drawer) that is (mostly) positioned off the bottom of the screen a fixed distance on the Y axis. The distance I want to move is the height of the div (drawer - minus the drawer handle).
It was pretty easy to get this working from top to bottom, but reversing it is posing to be quite a challenge. I feel like it might just be a simple math error.
I have put together a fiddle to better illustrate the issues I'm having.
http://jsfiddle.net/q8DE6/2/
Here's my code:
HTML
<div id="panelWrapper">
<div id="panel" class="panel">
<p> The height of this drawer is dynamic, and will slide the appropriate amounted based on the height of the content. </p>
<p> Any type of content can be included in here. The body of the drawer and the drawer pull tab can also be styled as you see fit, just modify the css/styles.css file. </p>
<!--necessary div for slide tab, modify as needed, but don't delete -->
<div class="slide">
<a id="drawerSlide" href="#" class="drawer-slide">
<table id="sTab" class="slideTab">
<tr>
<td id="stText1"></td>
<td id="stImg">Pull here.</td>
<td id="stText2"></td>
</tr>
</table>
</a>
</div>
</div><!--/panel -->
</div><!--/panelWrapper -->
<div id="content">
<div id="header">
<div id="menuBar">
<h3>Header Bar Text.</h3>
</div>
</div>
<div id="container">
</div>
<div id="footer">
<p>Footer Area.</p>
</div>
</div><!--/content -->
Slide Function:
JS:
function drawerSlide(slideDir) {
switch (slideDir) {
case 'bottomToTop':
//drawer styling
$('.panel, .slide').addClass('botToTop');
$('.panel').addClass('panelTB');
$('.slide').addClass('slideBotToTop');
$('#sTab').addClass('slideTab');
$('.panel p').filter(":first").css('padding-top','50px');
//hide overflown Y axis content. Hopefully this won't cause any conflicts with your existing code/page.
$('body').css('overflow-y','hidden');
botStartPos = $(window).height() - 50;
offset = $('#panel').offset();
panelHeight = $('#panel').outerHeight();
topEndPos = botStartPos - panelHeight +50;
yPos = botStartPos;
// if you need a different drawer starting point, adjust the starting position here (50).
panelHeight = parseFloat(panelHeight) - 50;
console.log("botStartPos:" + botStartPos);
console.log("topEndPos:" + topEndPos);
console.log("yPos:" + yPos);
$('.panel').css('top', botStartPos);
$('#panel').draggable({
axis: "y",
containment: [0, botStartPos, 0, topEndPos] //0, botStartPos, 300, topEndPos
},
{
drag: function( event, ui ) {
if (yPos > botStartPos || yPos < topEndPos) {
return false;
}
else {
offset = $(this).offset();
yPos = offset.top;
console.log(yPos);
}
}
});
}
}
$(document).ready(function() {
drawerSlide("bottomToTop");
});
I'm thinking the issue might be with the way I'm using the offset.top command to move the drawer, but I'm stumped as to how to do it correctly.
Right now what is happening, is when you click/hold the handle, it "jumps" up the fixed distance, instead of being able to drag it. Also, you can't drag down to put the drawer away, but you can drag up once again and it "jumps" down the fixed distance. Not really what I'm after.
The desired result I'm looking for is one of a typical "drawer" behavior. When the user clicks and holds on the handle, they can "pull" the drawer up the fixed distance, and then "push" it back down the same fixed distance, so the handle never falls off screen.
My guess is it that it's a math problem with the containment function. I still don't fully understand it well, so the problem may lie within the coordinates I'm using?
Any advice would be most appreciated. :)
The following code does what it should perfectly, however I need to add 30% more height to the containing element .boxy on top of the added variable heights.
I've tried searching for ways to add a percentage to the equation, but so far I've just found vague answers or non-applicable methodologies.
$(".exPand a").click(function (event) {
event.preventDefault();
var postHeight = $(this).closest('.boxy').find('.articleImageThumb').height();
var excHeight = $(this).closest('.boxy').find('.initialPostLoad').height();
$(this).closest('.boxy').animate({height: postHeight+excHeight}, 1000);
});
Live output:
<div class="boxy">
<div class="boxGrad"></div>
<div class="postmetadata"></div>
<div class="articleTitle"></div>
<div class="rightCtrls"></div>
<div class="ajaxBoxLoadSource"></div>
<div class="articleImageThumb"></div>
<div class="initialPostLoad"></div>
</div>
Just multiply by 1.3
$(this).closest('.boxy').animate({height: (postHeight * 1.3)+excHeight}, 1000);
Move the * 1.3 to the appropriate place depending on which height you want 30% of.