How to dynamically shift a DIV down based on predecessor - javascript

I've got a series of DIVs, all with the same class (.ms-acal-item). What I'm trying to do is get the position of each one, compare it to the one above it, and shift it down if needed. This is to correct an issue on a SharePoint 2013 calendar where event tiles are overlapping. Here's my code so far:
$(function() {
$('.ms-acal-item').each(function(i, obj) {
var tile = jQuery(this);
var prev = tile.prev();
var prevPos = prev.position();
var tilePOs = tile.position();
var curTop = parseInt(tilePos.top);
var newTop = parseInt(prevPos.top) + 30;
if(curtop !== newTop){
tile.css('top', newTop);
}
});
});
And here's an example of what the SharePoint-generated content looks like:
Each tile is 20px high and positioned absolutely in-line. What I need to do is compare the position of each tile to its predecessor and then move it down 30px if it isn't already there (20px for the tile and 10px between them). So far it's not working - my code seems to have no effect on the tile positions.
What am I doing wrong?

There is a problem in the logic, while processing the first element we do not have any previous element, so we need to ignore it and few typo(variable case issues) mistakes in your code. Below is the revamp code.(To see the changes effect i changed style from top to margin-left, correct it afterwards)
$(function() {
$('.ms-acal-item').each(function(i, obj) {
var tile = $(this);
var prev = tile.prev();
if (typeof prev.position() !== "undefined") {
var prevPos = JSON.parse(JSON.stringify(prev.position()));
var tilePos = JSON.parse(JSON.stringify(tile.position()));
var curTop = parseInt(tilePos.top);
var newTop = parseInt(prevPos.top) + 30;
if(curTop !== newTop){
tile.css('margin-left', newTop);
}
}
});
});

Related

Positioning a div in js

Wonder if anyone could give me some guidance. I'm trying to reposition a div based on:
if fpd-actions-wrapper has a class of fpd-pos-outside then position in body.
else position (as below) in main wrapper.
//set action button to specific position
var _setActionButtons = function(pos) {
fpdInstance.$mainWrapper.append('<div class="fpd-actions-wrapper fpd-pos-'+pos+'"></div>');
var posActions = instance.currentActions[pos];
for(var i=0; i < posActions.length; ++i) {
var actionName = posActions[i],
$action = $actions.children('[data-action="'+actionName+'"]');
fpdInstance.$mainWrapper.children('.fpd-actions-wrapper.fpd-pos-'+pos).append($action.clone());
}
};
I've tried below and it does get .fpd-actions-wrapper out of the main wrapper but it's empty - can't work out the last line.
//set action button to specific position
var _setActionButtons = function(pos) {
$body = $('body');
$body.append('<div class="fpd-actions-wrapper fpd-pos-'+pos+'"></div>');
var posActions = instance.currentActions[pos];
for(var i=0; i < posActions.length; ++i) {
var actionName = posActions[i],
$action = $actions.children('[data-action="'+actionName+'"]');
fpdInstance.$mainWrapper.children('.fpd-actions-wrapper.fpd-pos-
'+pos).append($action.clone());
}
};
You need to add position:aboslute; top:10px; left:10px to you div tag. Only divisions with fixed or absolute positions can be moved pro-grammatically. You must define x (distance to left side) and y (distance to top of screen) motion independently. I only defined the 'top' position. You need to add a 'left' point of reference as well. It may not be a simple 'left:'+pos+'px;', so I did not add that code for you except in the div tag.Notice that the actual commands to change position are very much 'css' like. The div tag uses css syntax, so must your code.
//set action button to specific position
var _setActionButtons = function(pos) {
fpdInstance.$mainWrapper.append('<div class="fpd-actions-wrapper fpd-pos-'top:'+pos+'px; fpd-pos-'left:'+pos+'px;"></div>');
var posActions = instance.currentActions['top':+pos+"px;"];
for(var i=0; i < posActions.length; ++i) {
var actionName = posActions[i],
$action = $actions.children('[data-action="'+actionName+'"]');
fpdInstance.$mainWrapper.children('.fpd-actions-wrapper.fpd-pos-':'+pos'px;').append($action.clone());
}
};

SVG Camera Pan - Translate keeps resetting to 0 evertime?

Well i have this SVG canvas element, i've got to the point so far that once a user clicks and drags the canvas is moved about and off-screen elements become on screen etc....
However i have this is issue in which when ever the user then goes and click and drags again then the translate co-ords reset to 0, which makes the canvas jump back to 0,0.
Here is the code that i've Got for those of you whio don't wanna use JS fiddle
Here is the JSfiddle demo - https://jsfiddle.net/2cu2jvbp/2/
edit: Got the solution - here is a JSfiddle DEMO https://jsfiddle.net/hsqnzh5w/
Any and all sugesstion will really help.
var states = '', stateOrigin;
var root = document.getElementById("svgCanvas");
var viewport = root.getElementById("viewport");
var storeCo =[];
function setAttributes(element, attribute)
{
for(var n in attribute) //rool through all attributes that have been created.
{
element.setAttributeNS(null, n, attribute[n]);
}
}
function setupEventHandlers() //self explanatory;
{
setAttributes(root, {
"onmousedown": "mouseDown(evt)", //do function
"onmouseup": "mouseUp(evt)",
"onmousemove": "mouseMove(evt)",
});
}
setupEventHandlers();
function setTranslate(element, x,y,scale) {
var m = "translate(" + x + "," + y+")"+ "scale"+"("+scale+")";
element.setAttribute("transform", m);
}
function getMousePoint(evt) { //this creates an SVG point object with the co-ords of where the mouse has been clicked.
var points = root.createSVGPoint();
points.x = evt.clientX;
points.Y = evt.clientY;
return points;
}
function mouseDown(evt)
{
var value;
if(evt.target == root || viewport)
{
states = "pan";
stateOrigin = getMousePoint(evt);
console.log(value);
}
}
function mouseMove(evt)
{
var pointsLive = getMousePoint(evt);
if(states == "pan")
{
setTranslate(viewport,pointsLive.x - stateOrigin.x, pointsLive.Y - stateOrigin.Y, 1.0); //is this re-intializing every turn?
storeCo[0] = pointsLive.x - stateOrigin.x
storeCo[1] = pointsLive.Y - stateOrigin.Y;
}
else if(states == "store")
{
setTranslate(viewport,storeCo[0],storeCo[1],1); // store the co-ords!!!
stateOrigin = pointsLive; //replaces the old stateOrigin with the new state
states = "stop";
}
}
function mouseUp(evt)
{
if(states == "pan")
{
states = "store";
if(states == "stop")
{
states ='';
}
}
}
In your mousedown function, you are not accounting for the fact that the element might already have a transform and you are just overwriting it.
You are going to need to either look for, and parse, any existing transform. Or an easier approach would be to keep a record of the old x and y offsets and when a new mousedown happens add them to the new offset.

how to check whether crop div covers rotated image?

I want to check whether cropping div covers images in it.Everything works fine when image is not rotated but after rotating image crop does not shows error msg...
Here is fiddle : Fiddle
function isCropValid(){
var $selector = $("#resizeDiv"); // cropping Div
var $img = $("#rotateDiv"); // image div
var $selectorW = $selector.width();
var $selectorH = $selector.height();
var $selectorX = $selector.offset().left ;
var $selectorY = $selector.offset().top ;
var $imgW = $img.width();
var $imgH = $img.height();
var $imgX = $img.offset().left;
var $imgY = $img.offset().top;
var diff_X = $selectorX - $imgX;
var diff_Y = $selectorY - $imgY;
if(diff_X+$selectorW > $imgW){
return false;
} else if(diff_Y+$selectorH > $imgH){
return false;
} else if($selectorX<$imgX){
return false;
} else if($selectorY<$imgY){
return false;
}
else {
return true;
}
}
or another function
function isCropValid(){
var el1 = document.getElementById("resizeDiv"); // cropDiv
var el2 = document.getElementById("rotateDiv"); // imageDiv
var cropdiv = el1.getBoundingClientRect();
var imgdiv = el2.getBoundingClientRect();
return (
((imgdiv.top <= cropdiv.top) && (cropdiv.top <= imgdiv.bottom)) &&
((imgdiv.top <= cropdiv.bottom) && (cropdiv.bottom <= imgdiv.bottom)) &&
((imgdiv.left <= cropdiv.left) && (cropdiv.left <= imgdiv.right)) &&
((imgdiv.left <= cropdiv.right) && (cropdiv.right <= imgdiv.right))
);
}
I above code i have one image inside div.if crop div gets out of this div i m showing label bg color red meaning crop is not correct otherwise i m showing label color green means crop is correct..
I think what you'll have to do is to calculate the positions of each of the 4 points of the image top-left top-right bottom-right and bottom-left, then do the same thing for the crop div something like this:
var $topLeftX=$selectorX-($selectorW/2)-($selectorH/2);
var $topLeftY=$selectorY-($selectorH/2)-($selectorW/2);
var $bottomLeftX=$selectorX-($selectorW/2)+($selectorH/2);
var $bottomLeftY=$selectorY+($selectorH/2)-($selectorW/2);
var $topRightX=$selectorX+($selectorW/2)-($selectorH/2);
var $topRightY=$selectorY-($selectorH/2)+($selectorW/2);
var $bottomRightX=$selectorX+($selectorW/2)+($selectorH/2);
var $bottomRightY=$selectorY+($selectorH/2)+($selectorW/2);
Then compare the corner points.
now the issue is with the corners of the image, as after rotation this will need some sine/cosine calculations.
you might want to take a look at this post: Find the coordinates of the corners of a rotated object in fabricjs
I think it will make your life much easier
So this is gonna be a big hack, but hey :-) The idea is to put the cut out behind the image, and then see whether the image overlaps the cut out on all four corners.
function cutoutIsOK() {
// Grab the cutout element and position it behind the image
var cutout = document.querySelector('#resizeDiv');
cutout.style.zIndex = -1;
// Grab the image
var image = document.querySelector('#rotateDiv img');
// Take the four corners of the cutout element
var cutoutRect = cutout.getBoundingClientRect();
var pos = [
[cutoutRect.left, cutoutRect.top],
[cutoutRect.right - 1, cutoutRect.top],
[cutoutRect.left, cutoutRect.bottom - 1],
[cutoutRect.right - 1, cutoutRect.bottom - 1]
];
// And verify that the image overlaps all four corners
var ok = pos.every(function(p) {
return document.elementFromPoint(p[0], p[1]) === image;
});
// Reset the cutout's z-index to make it visible again
cutout.style.zIndex = 0;
return ok;
}

webGL story sphere popups

I am trying to adapt the really cool looking WebGL Story Sphere, source code and css here. There's one big problem: once you click on a news article, the text of the article in the popup is always the same. I want to modify the code so that when you click on an article, the right text appears in the popup.
I'm working from a set of article texts that I specify in the code, e.g. var captions = ["good","better","best"]. Though the article titles and images populate correctly in the popup, I can't get the text to do so. Can you help me?? Here's what I've got:
// function code
var passvar = null; // failed attempt to store texts for later
function initialize() {
math = tdl.math;
fast = tdl.fast;
canvas = document.getElementById("canvas");
g_fpsTimer = new tdl.fps.FPSTimer();
hack();
canvas.addEventListener("mousedown", handleMouseDown, false);
canvas.addEventListener("mousemove", handleMouseMove, false);
canvas.addEventListener("mouseup", handleMouseUp, false);
// Create a canvas 2d for making textures with text.
g_canvas2d = document.createElement('canvas');
window.two2w = window.two2h = g_tilesize;
g_canvas2d.width = two2w;
g_canvas2d.height = two2h;
g_ctx2d = g_canvas2d.getContext("2d");
window.gl = wu.create3DContext(canvas);
if (g_debug) {
gl = wd.makeDebugContext(gl, undefined, LogGLCall);
}
//gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, gl.TRUE);
// Here is where I specify article titles, images, captions
// Titles and images populate the popup correctly, captions don't...
var titles = ["a","b","c"];
var captions = ["good","better","best"];
var images = ['imagesphere/assets/1.jpg',
'imagesphere/assets/bp/2.png',
'imagesphere/assets/bp/3.png'
];
var headlines = titles.concat( titles);
var blurbs = captions.concat( captions);
var tmpImages = [];
var tmpHeadlines = [];
var tmpCaptions = [];
// make a bunch of textures.
for (var ii = 0; ii < g_imagesDownGrid; ++ii) {
var textures = [];
for (var jj = 0; jj < g_imagesAcrossGrid; ++jj) {
var imgTexture = new ImgTexture();
textures.push(imgTexture);
if (tmpImages.length == 0) {
tmpImages = images.slice();
}
if (tmpHeadlines.length == 0) {
tmpHeadlines = headlines.slice();
}
if (tmpCaptions.length == 0) {
tmpCaptions = blurbs.slice();
}
var rando = math.randomInt(tmpImages.length);
var img = tmpImages.splice(rando, 1)[0];
var headline = tmpHeadlines.splice(rando, 1)[0];
var caption = tmpCaptions.splice(rando, 1)[0];
passvar = caption;
if (img.indexOf('videoplay.jpg') > -1){
window.vidtexture = imgTexture;
images = images.slice(1); // dont use that thumb again.
headlines = 'WebGL Brings Video To the Party as Well'
}
imgTexture.load(img, /* "[" + jj + "/" + ii + "]" + */ headline);
}
g_textures.push(textures);
}
// And here's where I try to put this in a popup, finally
// But passvar, the stored article text, never refreshes!!!
<div id="story" class="prettybox" style="display:none">
<img class="close" src="imagesphere/assets/close.png">
<div id="storyinner">
<input id = "mytext">
<script>document.getElementById("mytext").value = passvar;</script>
</div>
</div>
And here is my click handler code:
function sphereClick(e){
window.console && console.log('click!', e, e.timeStamp);
var selected = g_textures[sel.y][sel.x];
window.selected = selected;
animateGL('eyeRadius', glProp('eyeRadius'), 4, 500);
var wwidth = $(window).width(),
wheight = $(window).height(),
story = $('#story').width( ~~(wwidth / 7 * 4) ).height( ~~(wheight / 6 * 5) ),
width = story.width(),
height = story.height(),
miniwidth = 30;
story.detach()
.find('#storyinner').find('h3,img,caption').remove().end().end()
.show();
story.css({
left : e.pageX,
top : e.pageY,
marginLeft : - width / 2,
marginTop : - height / 2
}).appendTo($body); // we remove and put back on the DOM to reset it to the correct position.
$('style.anim.story').remove();
$('<style class="anim story">')
.text( '.storyopen #story { left : ' + (wwidth / 3 * 2) + 'px !important; top : ' + wheight / 2 + 'px !important; }' )
.appendTo($body);
$(selected.img).prependTo('#storyinner').parent();
$('<h3>').text(selected.msg.replace(/\(.*/,'')).prependTo('#storyinner');
$body.addClass('storyopen');
} // eo sphereClick()
There's a lot wrong here, but here's a start. It won't solve your problem, but it will help you avoid issues like this.
var passvar = null; is a global variable.
Your loop for (var ii = 0; ... sets that global variable to a new value on every iteration.
Later, you click something and the global variable passvar is never changed.
If you want to use this pattern, you need to set passvar from your click handler so it has the value that was clicked. Since you didn't actually post your click handlers, it's hard to advise more.
But this is also a bad pattern, functions take arguments for a good reason. Since you have to find your clicked item in the click handler anyway, why not pass it directly which does involve a shared global variable at all?
var handleMouseUp = function(event) {
var story = findClickedThing(event);
if (obj) {
showPopup(story.texture, story.caption);
}
}
Which brings me to this:
var titles = ["a","b","c"];
var captions = ["good","better","best"];
var images = ['imagesphere/assets/1.jpg',
'imagesphere/assets/bp/2.png',
'imagesphere/assets/bp/3.png'
];
When you have 3 arrays, all of the same length, each array describing a different property of an object, you are doing it wrong. What you want, is one array of objects instead.
var stories = [
{
title: "a",
caption: "good",
image: "imagesphere/assets/1.jpg"
}, {
title: "b",
caption: "better",
image: "imagesphere/assets/bp/2.jpg"
}, {
title: "c",
caption: "best",
image: "imagesphere/assets/bp/3.jpg"
},
];
console.log(stories[1].caption); // "better"
Now once you find the clicked object, you can just ask it what it's caption is. And you can pass the whole object to the popup maker. And no field is handled differently or passed around in a different manner, because you are not passing around the fields. You are passsing the entire object.

How to move nodes to a desired position?

I want to move a specific node (say i have the node reference), to a desired location (say to the top left corner of the canvas). I tried doing something similar to one in the sample project, where they move nodes while dragging with the mouse. But it doesn't seem to work. I am not seeing the node move as i expected. This is the code i have.
$("#someElement").click(function() {
sys.eachNode(function(node, pt) {
if (node.name === "specificNode") {
// moveToOrigin
var s = arbor.Point(1, 1);
var p = sys.fromScreen(s);
node.fixed = true;
node.p = p;
node.fixed = false;
node.tempMass = 1000;
}
}
});
To move a node to a desired position get the desired position relative to the canvas and set it via particle system's fromScreen(...) function:
var point = point;
var pos = canvas.offset();
var s = arbor.Point(point.x-pos.left, point.x-pos.top);
node.p = particleSystem.fromScreen(s);
You need to set position of node first, then again iterate each loop for nodes.
redraw: function () {
gfx.clear()
particleSystem.eachNode(function (node, pt) {
//var node = particleSystem.getNode("Carrol Wahi")
if (node.data.color == "yellow") {
var pos = $(canvas).offset();
var point = particleSystem.fromScreen(arbor.Point(pos.left + 150, pos.top));
node._fixed = true;
node._p = point;
//console.log("x=" + point.x + ", y=" + point.y);
node.tempMass = .1
}
});
particleSystem.eachEdge(function (edge, pt1, pt2) {
// your code goes here
}
particleSystem.eachNode(function (node, pt) {
//your code goes here
})
}

Categories

Resources