I had the following code for expanding textarea, i have no problem to expand the textarea base on text length,however, i need to execute a function when it expand. I don't know which term I should use to do that. Something like, if(this textarea expand){ alert('ok'); appreciate.
$.fn.TextAreaExpander = function(minHeight, maxHeight) {
var hCheck = !($.browser.msie || $.browser.opera);
// resize a textarea
function ResizeTextarea(e) {
// event or initialize element?
e = e.target || e;
// find content length and box width
var vlen = e.value.length, ewidth = e.offsetWidth;
if (vlen != e.valLength || ewidth != e.boxWidth) {
if (hCheck && (vlen < e.valLength || ewidth != e.boxWidth)) e.style.height = "0";
var h = Math.max(e.expandMin, Math.min(e.scrollHeight, e.expandMax));
e.style.overflow = (e.scrollHeight > h ? "auto" : "hidden");
e.style.height = h + "px";
e.valLength = vlen;
e.boxWidth = ewidth;
}
return true;
};
// initialize
this.each(function() {
// is a textarea?
if (this.nodeName.toLowerCase() != "textarea") return;
// set height restrictions
var p = this.className.match(/expand(\d+)\-*(\d+)*/i);
this.expandMin = minHeight || (p ? parseInt('0'+p[1], 10) : 0);
this.expandMax = maxHeight || (p ? parseInt('0'+p[2], 10) : 99999);
// initial resize
ResizeTextarea(this);
// zero vertical padding and add events
if (!this.Initialized) {
this.Initialized = true;
$(this).css("padding-top", 0).css("padding-bottom", 0);
$(this).bind("keyup", ResizeTextarea).bind("focus", ResizeTextarea);
}
});
return this;
};
jQuery("textarea[class*=expand9-999]").TextAreaExpander();//initialize the text expand
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="expand9-999">good</textarea>
You need to save the height and check the current height with the previously saved height.
FYI - You need to include jQuery Migrate library for $.browser.msie to work. Reference.
Working Code Snippet:
$.fn.TextAreaExpander = function(minHeight, maxHeight) {
var hCheck = !($.browser.msie || $.browser.opera);
var prevHeight;
// resize a textarea
function ResizeTextarea(e) {
// event or initialize element?
e = e.target || e;
// find content length and box width
var vlen = e.value.length, ewidth = e.offsetWidth;
if (vlen != e.valLength || ewidth != e.boxWidth) {
if (hCheck && (vlen < e.valLength || ewidth != e.boxWidth)) e.style.height = "0";
var h = Math.max(e.expandMin, Math.min(e.scrollHeight, e.expandMax));
e.style.overflow = (e.scrollHeight > h ? "auto" : "hidden");
e.style.height = h + "px"; // this is where you are actually resizing
if(e.style.height !== prevHeight) // throw the alert only if the height is not same as the previous one
alert("resized");
e.valLength = vlen;
e.boxWidth = ewidth;
prevHeight = e.style.height; // save the height
}
return true;
};
// initialize
this.each(function() {
// is a textarea?
if (this.nodeName.toLowerCase() != "textarea") return;
// set height restrictions
var p = this.className.match(/expand(\d+)\-*(\d+)*/i);
this.expandMin = minHeight || (p ? parseInt('0'+p[1], 10) : 0);
this.expandMax = maxHeight || (p ? parseInt('0'+p[2], 10) : 99999);
// initial resize
ResizeTextarea(this);
// zero vertical padding and add events
if (!this.Initialized) {
this.Initialized = true;
$(this).css("padding-top", 0).css("padding-bottom", 0);
$(this).bind("keyup", ResizeTextarea).bind("focus", ResizeTextarea);
}
});
return this;
};
jQuery("textarea[class*=expand9-999]").TextAreaExpander();//initialize the text expand
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.js"></script>
<textarea class="expand9-999">good</textarea>
<p>Check your console.</p>
Try following will help you.
$(document).ready(function () {
var $textareas = jQuery('textarea');
// set init (default) state
$textareas.data('x', $textareas.outerWidth());
$textareas.data('y', $textareas.outerHeight());
$textareas.mouseup(function () {
var $this = $(this);
if ($this.outerWidth() != $this.data('x') || $this.outerHeight() != $this.data('y')) {
alert("ok");
}
// set new height/width
});
});
textareaResize($(".expand9-999"));
$.fn.TextAreaExpander = function(minHeight, maxHeight) {
var hCheck = !($.browser.msie || $.browser.opera);
// resize a textarea
function ResizeTextarea(e) {
// event or initialize element?
e = e.target || e;
// find content length and box width
var vlen = e.value.length, ewidth = e.offsetWidth;
if (vlen != e.valLength || ewidth != e.boxWidth) {
if (hCheck && (vlen < e.valLength || ewidth != e.boxWidth)) e.style.height = "0";
var h = Math.max(e.expandMin, Math.min(e.scrollHeight, e.expandMax));
e.style.overflow = (e.scrollHeight > h ? "auto" : "hidden");
e.style.height = h + "px";
e.valLength = vlen;
e.boxWidth = ewidth;
}
return true;
};
// initialize
this.each(function() {
// is a textarea?
if (this.nodeName.toLowerCase() != "textarea") return;
// set height restrictions
var p = this.className.match(/expand(\d+)\-*(\d+)*/i);
this.expandMin = minHeight || (p ? parseInt('0'+p[1], 10) : 0);
this.expandMax = maxHeight || (p ? parseInt('0'+p[2], 10) : 99999);
// initial resize
ResizeTextarea(this);
// zero vertical padding and add events
if (!this.Initialized) {
this.Initialized = true;
$(this).css("padding-top", 0).css("padding-bottom", 0);
$(this).bind("keyup", ResizeTextarea).bind("focus", ResizeTextarea);
}
});
return this;
};
jQuery("textarea[class*=expand9-999]").TextAreaExpander();//initialize the text expand
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="expand9-999">good</textarea>
Related
I need your help because I've been on a project for hours and can't make any headway. An "animated" counter is to be installed on our website. This shows, for example, the monthly cost savings. The following code works great so far.
<script>
/* <![CDATA[ */
var ersparnis = 4600;
var inv = setInterval(function() {
if(ersparnis < 4800)
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
else
clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
+ <span id="counter_ersparnis"></span> €
</h2>
But now I want the Javascript to start only when the user scrolls to the relevant point. I have now tried to do this with a jQuery code from the Internet, but without success!
<script>
/* <![CDATA[ */
jQuery.fn.isOnScreen = function()
{
var win = jQuery(window);
var viewport = {
top : win.scrollTop(),
left : win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
jQuery(window).scroll(function()
{
if(jQuery('#element').isOnScreen())
{
var ersparnis = 4600;
var inv = setInterval(function() {
if(ersparnis < 4800)
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
else
clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
+ <span id="counter_ersparnis"></span> €
</h2>
} }
By the way, the whole thing should be implemented on a Jimdo site, so I also added the database with the following code in the head area.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" type="text/javascript"></script>
You might hear it already, I'm not really familiar with CSS / HTML and Javascript. So it would be great if someone could offer me a plug and play solution. I usually get it rewritten, but not tinkered together (because I want three of these counters next to each other.
Try This im not a big proponent of jquery so its plain JavaScript.
const targetElement = document.querySelector('#element');
let isCounting = false;
var inv;
document.addEventListener('scroll', function(e) {
const bounding = targetElement.getBoundingClientRect();
if (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
) {
if(!isCounting ){
var ersparnis = 4600;
inv = setInterval(function() {
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
}, 500 / 100);
isCounting = true;
}
}else{
isCounting = false;
clearInterval(inv);
}
});
To make the code a bit cleaner and reuseable you could do this.
const targetElement = document.querySelector('#element');
let isCounting = false;
let inv;
const isVisible = function (elem) {
var bounding = elem.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
function startCounter(){
var ersparnis = 4600;
inv = setInterval(function() {
document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
}, 500 / 100);
isCounting = true;
}
function stopCounter(){
clearInterval(inv);
isCounting = false;
}
document.addEventListener('scroll', function(e) {
const visible = isVisible( targetElement );
if( visible && !isCounting ){
startCounter();
}else if( !visible && isCounting ){
stopCounter();
}
});
You can use Intersection Observer API to observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport:
let options = {
root: null, //--> viewport if it is null
rootMargin: '0px',
threshold: 1.0
}
const callback = function(entries, observer) {
entries.forEach(entry => {
let ersparnis = 4600;
const inv = setInterval(function() {
if (ersparnis < 4800)
entry.target.innerHTML = ++ersparnis;
else
clearInterval(inv);
}, 500 / 100);
});
};
let observer = new IntersectionObserver(callback, options);
const target = document.querySelector('#counter_ersparnis');
observer.observe(target);
I was trying to do a full page scroll while using anchor links throughout the page but sometimes it won't scroll up anymore or the links stop working or go to the wrong places. It gets pushed down leaving strange white space after I scroll around an press on the links.
Link to code:
https://codepen.io/serelath/pen/NEzyxL
I appreciate it if anyone can look into this for me.
(function() {
"use strict";
/*[pan and well CSS scrolls]*/
var pnls = document.querySelectorAll('.panel').length,
scdir, hold = false;
function _scrollY(obj) {
var slength, plength, pan, step = 100,
vh = window.innerHeight / 100,
vmin = Math.min(window.innerHeight, window.innerWidth) / 100;
if ((this !== undefined && this.id === 'well') || (obj !== undefined && obj.id === 'well')) {
pan = this || obj;
plength = parseInt(pan.offsetHeight / vh);
}
if (pan === undefined) {
return;
}
plength = plength || parseInt(pan.offsetHeight / vmin);
slength = parseInt(pan.style.transform.replace('translateY(', ''));
if (scdir === 'up' && Math.abs(slength) < (plength - plength / pnls)) {
slength = slength - step;
} else if (scdir === 'down' && slength < 0) {
slength = slength + step;
} else if (scdir === 'top') {
slength = 0;
}
if (hold === false) {
hold = true;
pan.style.transform = 'translateY(' + slength + 'vh)';
setTimeout(function() {
hold = false;
}, 500);
}
console.log(scdir + ':' + slength + ':' + plength + ':' + (plength - plength / pnls));
}
/*[swipe detection on touchscreen devices]*/
function _swipe(obj) {
var swdir,
sX,
sY,
dX,
dY,
threshold = 100,
/*[min distance traveled to be considered swipe]*/
slack = 50,
/*[max distance allowed at the same time in perpendicular direction]*/
alT = 300,
/*[max time allowed to travel that distance]*/
elT, /*[elapsed time]*/
stT; /*[start time]*/
obj.addEventListener('touchstart', function(e) {
var tchs = e.changedTouches[0];
swdir = 'none';
sX = tchs.pageX;
sY = tchs.pageY;
stT = new Date().getTime();
//e.preventDefault();
}, false);
obj.addEventListener('touchmove', function(e) {
e.preventDefault(); /*[prevent scrolling when inside DIV]*/
}, false);
obj.addEventListener('touchend', function(e) {
var tchs = e.changedTouches[0];
dX = tchs.pageX - sX;
dY = tchs.pageY - sY;
elT = new Date().getTime() - stT;
if (elT <= alT) {
if (Math.abs(dX) >= threshold && Math.abs(dY) <= slack) {
swdir = (dX < 0) ? 'left' : 'right';
} else if (Math.abs(dY) >= threshold && Math.abs(dX) <= slack) {
swdir = (dY < 0) ? 'up' : 'down';
}
if (obj.id === 'well') {
if (swdir === 'up') {
scdir = swdir;
_scrollY(obj);
} else if (swdir === 'down' && obj.style.transform !== 'translateY(0)') {
scdir = swdir;
_scrollY(obj);
}
e.stopPropagation();
}
}
}, false);
}
/*[assignments]*/
var well = document.getElementById('well');
well.style.transform = 'translateY(0)';
well.addEventListener('wheel', function(e) {
if (e.deltaY < 0) {
scdir = 'down';
}
if (e.deltaY > 0) {
scdir = 'up';
}
e.stopPropagation();
});
well.addEventListener('wheel', _scrollY);
_swipe(well);
var tops = document.querySelectorAll('.top');
for (var i = 0; i < tops.length; i++) {
tops[i].addEventListener('click', function() {
scdir = 'top';
_scrollY(well);
});
}
})();
I'm finishing my site on fabric.js and i've caught very annoying bug.
I have made a handler for right mouse click, that open context menu.
It works fine on most times, but for Safari and sometimves for chrome, it opens context menu for just a moment and closes it right instead.
For some reason after contextmenu listener mouse.up event fires only in Safari.
I need to prevent mouse.up after contextmenu somehow.
Here is the code.
var activeObject = canvas.getActiveObject();
var activeGroup = canvas.getActiveGroup();
var objectInGroup = false;
var relativeX = e.clientX;
var relativeY = e.clientY;
var offset = jQuery(this).offset();
var clickPoint = new fabric.Point(e.offsetX, e.offsetY);
//debugger;
var pointer = canvas.getPointer(e.originalEvent);
var objects = canvas.getObjects();
for (var i = objects.length - 1; i >= 0; i--) {
if (objects[i].containsInGroupPoint(clickPoint) || objects[i].containsPoint(clickPoint)) {
console.log(i);
if (activeGroup)
{
for (var y = 0, len = activeGroup._objects.length; y < len; y++) {
if (activeGroup._objects[y]==objects[i])
{
objectInGroup = true;
}
}
}
if (activeObject!=objects[i] && !objectInGroup)
{
canvas.deactivateAll();
canvas.setActiveObject(objects[i]);
}
break;
}
}
if (i < 0) {
}
activeObject = canvas.getActiveObject();
//console.log(activeObject);
if(activeObject == null && activeGroup == null){
var obj = canvas.getObject();
}
console.log(obj);
console.log(e.pageX + " - " + e.pageY);
console.log(offset.left + " - " + offset.top);
if(jQuery("#prozrachnost").is(':visible')){
jQuery("#prozrachnost").hide();
jQuery(".rect_books").hide();
jQuery(".cap_palitra").hide();
}else{
jQuery("#prozrachnost").css({
'position':'absolute', 'top' : relativeY, 'left' : relativeX, 'width' : '171px', 'height' : 'auto', 'z-index': 1
});
jQuery("#prozrachnost").show();
var ch = jQuery('#prozrachnost').find('.button_menu_top').height();
var cw = jQuery('#prozrachnost').find('.button_menu_top').width();
jQuery('#prozrachnost').find('.button_menu_bottom').css({height:ch});
jQuery('#prozrachnost').find('.button_menu_center').css({
left : ((cw / 2) - (jQuery('#prozrachnost').find('.button_menu_center').width() / 2)) + 'px'
});
var type = '';
jQuery('#prozrachnost .button_menu_top').hide();
jQuery('#prozrachnost .button_menu_bottom a').hide();
if(activeObject){
if(activeObject.get('myType') == 'text' || activeObject.get('myType') == 'image'){
jQuery('#prozrachnost .button_menu_top').show();
jQuery('#prozrachnost .button_menu_bottom a.del').show();
jQuery('#prozrachnost .button_menu_bottom a.palitra').show();
}
if(activeObject.get('myType') == 'rect' || activeObject.get('myType') == 'captionborder'){
jQuery('#prozrachnost .button_menu_bottom a.books').show();
jQuery('#prozrachnost .button_menu_bottom a.del').show();
jQuery('#prozrachnost .button_menu_bottom a.palitra').show();
}
type = activeObject.get('myType');
}else if (activeGroup){
if(activeGroup._objects[0].get('myType') == 'text' || activeGroup._objects[0].get('myType') == 'image'){
jQuery('#prozrachnost .button_menu_top').show();
jQuery('#prozrachnost .button_menu_bottom a.del').show();
jQuery('#prozrachnost .button_menu_bottom a.palitra').show();
}
if(activeGroup._objects[0].get('myType') == 'rect' || activeGroup._objects[0].get('myType') == 'captionborder'){
jQuery('#prozrachnost .button_menu_bottom a.books').show();
jQuery('#prozrachnost .button_menu_bottom a.del').show();
jQuery('#prozrachnost .button_menu_bottom a.palitra').show();
}
type = activeGroup._objects[0].get('myType');
}
console.log(activeGroup);
jQuery("#prozrachnost a.button_link").click(function(e){
e.preventDefault();
var activeObject = canvas.getActiveObject();
var activeGroup = canvas.getActiveGroup();
var btn = jQuery(this);
var type = '';
if(activeObject) { type = activeObject.get('myType'); }
else if (activeGroup) { type = activeGroup._objects[0].get('myType'); }
if(btn.hasClass('books')){
if(type == 'rect'){ jQuery("#RECTBACK").click(); }
if(type == 'captionborder'){ jQuery("#CAPBACK").click(); }
}
if(btn.hasClass('palitra')){
if(type == 'rect'){
jQuery(".cap_palitra").hide();
jQuery(".ttext_color").hide();
jQuery(".rect_books").show();
}
if(type == 'captionborder'){
jQuery(".rect_books").hide();
jQuery(".ttext_color").hide();
jQuery(".cap_palitra").show();
}
if(type == 'text'){
jQuery(".rect_books").hide();
jQuery(".cap_palitra").hide();
jQuery(".ttext_color").show();
}
}
if(btn.hasClass('del')){
if(type === 'text') { jQuery("#ITDEL").trigger('click'); }
if (type === 'image'){ jQuery("#ITDEL").trigger('click'); }
if(type === 'rect'){ jQuery("#RCBDEL").trigger('click'); }
if (type === 'captionborder'){ jQuery("#RCBDEL").trigger('click'); }
}
});
}
e.preventDefault();
});
// undo and redo buttons
jQuery('#undo').click(function() { replay(w.undo, w.redo, '#redo', this); });
jQuery('#redo').click(function() { replay(w.redo, w.undo, '#undo', this); });
// undo and redo buttons 2
jQuery('#undo1').click(function() { replay(w.undo, w.redo, '#redo1', this); });
jQuery('#redo1').click(function() { replay(w.redo, w.undo, '#undo1', this); });
//disable rotation/scling on selected group
canvas.observe('selection:created', function (e){
if (e.target.type === 'group') {
e.target.hasControls = false;
}
});
canvas.on('mouse:up',function(option){
if(jQuery("#prozrachnost").is(':visible')){
jQuery("#prozrachnost").hide();
jQuery(".rect_books").hide();
jQuery(".cap_palitra").hide();
}
//console.log('up');
if(option.target){
if (option.target == window.change_item) {window.change_item=option.target;}
}
if(option.target){ methods.active(option.target.get('myType'),option); }
});
Would someone give me a clue on this please.
Here is the link http://motivashka-board.ru/konstruktor.html
And this is how context menu looks
Thanks in advance.
Resolved the problem myself.
I've moved disabling code from mouse.up to mouse.down.
if(jQuery("#prozrachnost").is(':visible')){
jQuery("#prozrachnost").hide();
jQuery(".rect_books").hide();
jQuery(".cap_palitra").hide();
}
That did the trick.
I've used a script for a while, which allows me to drag and drop divs up and down:
<div id="root">
<div style="position: relative;">
<input type="text" name="stuff1" value="TEST1" />
</div>
<div style="position: relative;">
<input type="text" name="stuff1" value="TEST2" />
</div>
<div style="position: relative;">
<input type="text" name="stuff1" value="TEST3" />
</div>
</div>
<script language="javascript">
var Drag = {
obj : null,
init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) {
o.onmousedown = Drag.start;
o.hmode = bSwapHorzRef ? false : true ;
o.vmode = bSwapVertRef ? false : true ;
o.root = oRoot && oRoot != null ? oRoot : o ;
if (o.hmode && isNaN(parseInt(o.root.style.left ))) o.root.style.left = "0px";
if (o.vmode && isNaN(parseInt(o.root.style.top ))) o.root.style.top = "0px";
if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right = "0px";
if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
o.minX = typeof minX != 'undefined' ? minX : null;
o.minY = typeof minY != 'undefined' ? minY : null;
o.maxX = typeof maxX != 'undefined' ? maxX : null;
o.maxY = typeof maxY != 'undefined' ? maxY : null;
o.xMapper = fXMapper ? fXMapper : null;
o.yMapper = fYMapper ? fYMapper : null;
o.root.onDragStart = new Function();
o.root.onDragEnd = new Function();
o.root.onDrag = new Function();
},
start : function(e) {
var o = Drag.obj = this;
e = Drag.fixE(e);
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
o.root.onDragStart(x, y);
o.lastMouseX = e.clientX;
o.lastMouseY = e.clientY;
if (o.hmode) {
if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
} else {
if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
}
if (o.vmode) {
if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
} else {
if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
}
document.onmousemove = Drag.drag;
document.onmouseup = Drag.end;
return false;
},
drag : function(e) {
e = Drag.fixE(e);
var o = Drag.obj;
var ey = e.clientY;
var ex = e.clientX;
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
var nx, ny;
if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);
nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
if (o.xMapper) nx = o.xMapper(y)
else if (o.yMapper) ny = o.yMapper(x)
Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
Drag.obj.lastMouseX = ex;
Drag.obj.lastMouseY = ey;
Drag.obj.root.onDrag(nx, ny, Drag.obj.root);
return false;
},
end : function() {
document.onmousemove = null;
document.onmouseup = null;
Drag.obj.root.onDragEnd( parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]),
parseInt(Drag.obj.root.style[Drag.obj.vmode
? "top" : "bottom"]), Drag.obj.root);
Drag.obj = null;
},
fixE : function(e) {
if (typeof e == 'undefined') e = window.event;
if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
return e;
}
};
function recalcOffsets () {
var offsets = new Array();
var elems = root.getElementsByTagName("div");
for (var i = 0; i < elems.length; i++) {
Drag.init(elems[i], null, 0, 0, null, null);
elems[i].onDrag = function(x,y,myElem) {
y = myElem.offsetTop;
recalcOffsets();
var pos = whereAmI(myElem);
var elems = root.getElementsByTagName("div");
if (pos != elems.length-1 && y > offsets[pos + 1]) {
root.removeChild(myElem);
root.insertBefore(myElem, elems[pos+1]);
myElem.style["top"] = "0px";
}
if (pos != 0 && y < offsets[pos - 1]) {
root.removeChild(myElem);
root.insertBefore(myElem, elems[pos-1]);
myElem.style["top"] = "0px";
}
};
elems[i].onDragEnd = function(x,y,myElem) {
myElem.style["top"] = "0px";
}
}
var elems = root.getElementsByTagName("div");
for (var i = 0; i < elems.length; i++) {
offsets[i] = elems[i].offsetTop;
}
}
function whereAmI(elem) {
var elems = root.getElementsByTagName("div");
for (var i = 0; i < elems.length; i++) {
if (elems[i] == elem) { return i }
}
}
recalcOffsets()
</script>
Unfortunately, I don't remember where I got this code from (if you happen to recognize it, please do tell and I will add the link).
My problem now is that I want to have forms inside these divs, which the user should be able to edit. Unfortunately, users are unable to do anything with the forms, a side effect I'm sure comes from the fact that the script has to check whether the user is clicking inside the div or not. How can I make the forms editable? Is it even possible with this setup? If it's not possible, I'm fine with having buttons for each div ("up" and "down"), which move the div up and down onclick. I just need to be able to move a div up or down the hierarchy when the user wants it to. How can I accomplish this? What's the best solution?
The problem is the mousedown is being cancalled. You need to check to see what the user is clicking on
Something like this should do it.
start : function(e) {
if( ["input","select","textarea","button"].indexOf(e.target.nodeName.toLowerCase())!=-1) {
return true;
}
/* rest of the code */
You probably have to do something similar for end.
I'm using http://nick-jonas.github.io/threesixtyjs/ that code to animate a click-and-drag image sequence, but I would like to have it stop on the first and last frame, instead of continuing in a loop. I've taken a look at it but the script is way over my head, and I'm not sure how to do it most effectively.
here is the HTML, followed by the javascript. any help would be much appreciated, thank you!
<html>
<head>
<title>ThreeSixty</title>
<link rel="stylesheet" type="text/css" media="screen and (max-device-width:800px)" href="css/mobile.css">
<link rel="stylesheet" type="text/css" media="screen and (min-device-width:801px)" href="css/css.css">
</head>
<body>
<div id="container">
<h1>HELLO SHIR</h1>
<h2>I'm Sean Connery</h2>
<div class="threesixty-wrapper">
<div class="threesixty" data-path="img/src1/edison{index}.jpg" data-count="50">
</div>
</div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script src="js/jquery.threesixty.js"></script>
<script>
$(document).ready(function(){
var $threeSixty = $('.threesixty');
$threeSixty.threeSixty({
dragDirection: 'horizontal',
useKeys: true,
draggable: true
});
$('.next').click(function(){
$threeSixty.nextFrame();
});
$('.prev').click(function(){
$threeSixty.prevFrame();
});
$threeSixty.on('down', function(){
$('.ui, h1, h2, .label, .examples').stop().animate({opacity:0}, 300);
});
$threeSixty.on('up', function(){
$('.ui, h1, h2, .label, .examples').stop().animate({opacity:1}, 500);
});
});
</script>
</div>
</body>
</html>
/*!
* ThreeSixty: A jQuery plugin for generating a draggable 360 preview from an image sequence.
* Version: 0.1.2
* Original author: #nick-jonas
* Website: http://www.workofjonas.com
* Licensed under the MIT license
*/
;(function ( $, window, document, undefined ) {
var scope,
pluginName = 'threeSixty',
defaults = {
dragDirection: 'horizontal',
useKeys: false,
draggable: true
},
dragDirections = ['horizontal', 'vertical'],
options = {},
$el = {},
data = [],
total = 0,
loaded = 0;
/**
* Constructor
* #param {jQuery Object} element main jQuery object
* #param {Object} customOptions options to override defaults
*/
function ThreeSixty( element, customOptions ) {
scope = this;
this.element = element;
options = options = $.extend( {}, defaults, customOptions) ;
this._defaults = defaults;
this._name = pluginName;
// make sure string input for drag direction is valid
if($.inArray(options.dragDirection, dragDirections) < 0){
options.dragDirection = defaults.dragDirection;
}
this.init();
}
// PUBLIC API -----------------------------------------------------
$.fn.destroy = ThreeSixty.prototype.destroy = function(){
if(options.useKeys === true) $(document).unbind('keydown', this.onKeyDown);
$(this).removeData();
$el.html('');
};
$.fn.nextFrame = ThreeSixty.prototype.nextFrame = function(){
$(this).each(function(i){
var $this = $(this),
val = $this.data('lastVal') || 0,
thisTotal = $this.data('count');
val = val + 1;
$this.data('lastVal', val);
if(val >= thisTotal) val = val % (thisTotal - 1);
else if(val <= -thisTotal) val = val % (thisTotal - 1);
if(val > 0) val = thisTotal - val;
val = Math.abs(val);
$this.find('.threesixty-frame').css({display: 'none'});
$this.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'});
});
};
$.fn.prevFrame = ThreeSixty.prototype.prevFrame = function(){
$(this).each(function(i){
var $this = $(this),
val = $this.data('lastVal') || 0,
thisTotal = $this.data('count');
val = val - 1;
$this.data('lastVal', val);
if(val >= thisTotal) val = val % (thisTotal - 1);
else if(val <= -thisTotal) val = val % (thisTotal - 1);
if(val > 0) val = thisTotal - val;
val = Math.abs(val);
$this.find('.threesixty-frame').css({display: 'none'});
$this.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'});
});
};
// PRIVATE METHODS -------------------------------------------------
/**
* Initializiation, called once from constructor
* #return null
*/
ThreeSixty.prototype.init = function () {
var $this = $(this.element);
// setup main container
$el = $this;
// store data attributes for each 360
$this.each(function(){
var $this = $(this),
path = $this.data('path'),
count = $this.data('count');
data.push({'path': path, 'count': count, 'loaded': 0, '$el': $this});
total += count;
});
_disableTextSelectAndDragIE8();
this.initLoad();
};
/**
* Start loading all images
* #return null
*/
ThreeSixty.prototype.initLoad = function() {
var i = 0, len = data.length, url, j;
$el.addClass('preloading');
for(i; i < len; i++){
j = 0;
for(j; j < data[i].count; j++){
url = data[i].path.replace('{index}', j);
$('<img/>').data('index', i).attr('src', url).load(this.onLoadComplete);
}
}
};
ThreeSixty.prototype.onLoadComplete = function(e) {
var index = $(e.currentTarget).data('index'),
thisObj = data[index];
thisObj.loaded++;
if(thisObj.loaded === thisObj.count){
scope.onLoadAllComplete(index);
}
};
ThreeSixty.prototype.onLoadAllComplete = function(objIndex) {
var $this = data[objIndex].$el,
html = '',
l = data[objIndex].count,
pathTemplate = data[objIndex].path,
i = 0;
// remove preloader
$this.html('');
$this.removeClass('preloading');
// add 360 images
for(i; i < l; i++){
var display = (i === 0) ? 'block' : 'none';
html += '<img class="threesixty-frame" style="display:' + display + ';" data-index="' + i + '" src="' + pathTemplate.replace('{index}', i) + '"/>';
}
$this.html(html);
this.attachHandlers(objIndex);
};
var startY = 0,
thisTotal = 0,
$downElem = null,
lastY = 0,
lastX = 0,
lastVal = 0,
isMouseDown = false;
ThreeSixty.prototype.attachHandlers = function(objIndex) {
var that = this;
var $this = data[objIndex].$el;
// add draggable events
if(options.draggable){
// if touch events supported, use
if(typeof document.ontouchstart !== 'undefined' &&
typeof document.ontouchmove !== 'undefined' &&
typeof document.ontouchend !== 'undefined' &&
typeof document.ontouchcancel !== 'undefined'){
var elem = $this.get()[0];
elem.addEventListener('touchstart', that.onTouchStart);
elem.addEventListener('touchmove', that.onTouchMove);
elem.addEventListener('touchend', that.onTouchEnd);
elem.addEventListener('touchcancel', that.onTouchEnd);
}
}
// mouse down
$this.mousedown(function(e){
e.preventDefault();
thisTotal = $(this).data('count');
$downElem = $(this);
startY = e.screenY;
lastVal = $downElem.data('lastVal') || 0;
lastX = $downElem.data('lastX') || 0;
lastY = $downElem.data('lastY') || 0;
isMouseDown = true;
$downElem.trigger('down');
});
// arrow keys
if(options.useKeys === true){
$(document).bind('keydown', that.onKeyDown);
}
// mouse up
$(document, 'html', 'body').mouseup(that.onMouseUp);
$(document).blur(that.onMouseUp);
$('body').mousemove(function(e){
that.onMove(e.screenX, e.screenY);
});
};
ThreeSixty.prototype.onTouchStart = function(e) {
var touch = e.touches[0];
e.preventDefault();
$downElem = $(e.target).parent();
thisTotal = $downElem.data('count');
startX = touch.pageX;
startY = touch.pageY;
lastVal = $downElem.data('lastVal') || 0;
lastX = $downElem.data('lastX') || 0;
lastY = $downElem.data('lastY') || 0;
isMouseDown = true;
$downElem.trigger('down');
};
ThreeSixty.prototype.onTouchMove = function(e) {
e.preventDefault();
var touch = e.touches[0];
scope.onMove(touch.pageX, touch.pageY);
};
ThreeSixty.prototype.onTouchEnd = function(e) {
};
ThreeSixty.prototype.onMove = function(screenX, screenY){
if(isMouseDown){
var x = screenX,
y = screenY,
val = 0;
$downElem.trigger('move');
if(options.dragDirection === 'vertical'){
if(y > lastY){
val = lastVal - 1;
}else{
val = lastVal + 1;
}
}else{
if(x > lastX){
val = lastVal - 1;
}else if(x === lastX){
return;
}else{
val = lastVal + 1;
}
}
lastVal = val;
lastY = y;
lastX = x;
$downElem.data('lastY', lastY);
$downElem.data('lastX', lastX);
$downElem.data('lastVal', lastVal);
if(val >= thisTotal) val = val % (thisTotal - 1);
else if(val <= -thisTotal) val = val % (thisTotal - 1);
if(val > 0) val = thisTotal - val;
val = Math.abs(val);
$downElem.find('.threesixty-frame').css({display: 'none'});
$downElem.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'});
}
};
ThreeSixty.prototype.onKeyDown = function(e) {
switch(e.keyCode){
case 37: // left
$el.prevFrame();
break;
case 39: // right
$el.nextFrame();
break;
}
};
ThreeSixty.prototype.onMouseUp = function(e) {
isMouseDown = false;
$downElem.trigger('up');
};
/**
* Disables text selection and dragging on IE8 and below.
*/
var _disableTextSelectAndDragIE8 = function() {
// Disable text selection.
document.body.onselectstart = function() {
return false;
};
// Disable dragging.
document.body.ondragstart = function() {
return false;
};
};
/**
* A really lightweight plugin wrapper around the constructor,
preventing against multiple instantiations
* #param {Object} options
* #return {jQuery Object}
*/
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName,
new ThreeSixty( this, options ));
}
});
};
})( jQuery, window, document );
This should help yoyu on your way
The code you'll need to look at is in $.fn.prevFrame and $.fn.nextFrame:
if(val >= thisTotal) val = val % (thisTotal - 1);
else if(val <= -thisTotal) val = val % (thisTotal - 1);
These loop the variable val with the modulus sign. You should be able to stop this by setting them to thisTotal like so:
if(val >= thisTotal) val = thisTotal - 1;
else if(val <= -thisTotal) val = thisTotal - 1;
Good luck.