jquery drag image - javascript

i want to make a draggable image in jquery.
first of all my experience with jquery is 0. having said that let me describe what i want to achieve. i have fixed width/height div. and the image contained inside the div is large in size. so i want the image to be draggable inside that div so that the user can see the entire image.
can someone help. pls be a little elaborate about the procedure considering my jquery fluency.

You can use the following;
$(function() {
$("#draggable").draggable();
});
.container {
margin-top: 50px;
cursor: move;
}
#screen {
overflow: hidden;
width: 200px;
height: 200px;
clear: both;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="container">
<div id="screen">
<img src="https://picsum.photos/200/200" class="drag-image" id="draggable" />
</div>
</div>

You want the jQuery Draggable UI tool. The code for this, as with all jQuery, is very simple:
$(document).ready(function(){
$("#draggable").draggable();
});
Will create a draggable object from a standard html tag (the IMG in your case). And for limiting it's mobility to a specific region, you would look into its containment option.
Update: "What is '#draggable' and 'ready'"?
'#draggable' represents the element that you want to be able to drag. The hash (#) symbol represents an ID. When you add your image tags, may give give it an id like the following:
<img src="myimage.jpg" id="draggable" />
That will make the javascript above make your image draggable, because it has the '#draggable' id that the jQuery is looking for.
'.ready()' is the method that is automagically raised by your browser once the page is finished loading. Developers are encouraged by the jQuery group to place all jQuery code within this method to ensure all of the elements on the page are completely loaded prior to any jQuery code attempts to manipulate them.

to limit to a region for this example, containment is not much of a help.
I have implemented this for vertical only scroll, needs enhancement for horizontal limit:
stop: function(event, ui) {
var helper = ui.helper, pos = ui.position;
var h = -(helper.outerHeight() - $(helper).parent().outerHeight());
if (pos.top >= 0) {
helper.animate({ top: 0 });
} else if (pos.top <= h) {
helper.animate({ top: h });
}
}

$('#dragMe').draggable({ containment: 'body' });
This code will make it posible to drag the div with the ID of dragMe where ever you want inside the body of the document. You can also write a class or id as containment.
$('#dragMe').draggable({ containment: '#container' });
This code will make the div dragMe able to be draggable inside of the id container.
Hope this helps otherwise you should be able to find your answer here http://jqueryui.com/demos/draggable/

Expanding on the answer from PH. this will provide an elastic bounceback whenever the image is dragged to the point the underlying container is exposed:
stop: function(event, ui) {
var helper = ui.helper, pos = ui.position;
var h = -(helper.outerHeight() - $(helper).parent().outerHeight());
var w = -(helper.outerWidth() - $(helper).parent().outerWidth());
if (pos.top <= h) {
helper.animate({ top: h });
} else if (pos.top > 0) {
helper.animate({ top: 0 });
}
if (pos.left <= w) {
helper.animate({ left: w });
} else if (pos.left > 0) {
helper.animate({ left: 0 });
}
}

Related

How to make my animated skills bar responsive

I have an animated skills bar on my website, which fires when the section scrolls into view. Everything is working well so far.
Except when the viewport changes/window resizes the animated bars won't adjust to it and will be too long or to short.
I tried to solve this problem with
$(window).resize(function(){location.reload();
but on mobile viewport it keeps refreshing the page even though I'm just scrolling.
I already searched the net to see if there is a way to just reload the specific jquery function, but couldn't find anything. Or to be honest I didn't quite understood I guess, and couldn't get it working.
Here is what I found: https://css-tricks.com/forums/topic/reload-jquery-functions-on-ipad-orientation-change/
I read there is a way to make the website reload the whole js file. But since I still have other animations on my page, I don't know if this is the best way to do it.
I'm glad if anyone could help me with this. I'm very new to coding and my js/jquery knowledge is still very limited/non-existent.
here is my script for the bar animation
var $meters = $(".meter > span");
var $section = $('#skills .meter');
var $queue = $({});
function loadDaBars() {
$meters.each(function() {
var $el = $(this);
var origWidth = $el.width();
$el.width(0);
$queue.queue(function(next) {
$el.animate({width: origWidth}, 800, next);
});
});
}
$(document).bind('scroll', function(ev) {
var scrollOffset = $(document).scrollTop();
var containerOffset = $section.offset().top - window.innerHeight;
if (scrollOffset > containerOffset) {
loadDaBars();
$(document).unbind('scroll');
}
});
the width for the skillbar is defined via div class and span in %.
Maybe there is a css solution to this?
edit: this is how my html and css code looks like
.meter {
background-color: hsla(54, 73%, 95%, 1);
vertical-align: bottom;
width: 100%;
position: relative;
}
.meter>span {
display: block;
background-color: rgb(241, 233, 166);
position: relative;
overflow: hidden;
}
<div class="col-lg-6 col-md-6 col-sm-6">
<div class="meter">
<span style="width: 50%"></span>
</div>
You remove the style property of the bar once the animation has finished. This way the css rule will apply again:
$el.animate({width: origWidth}, {duration: 800, complete: function (){$el.removeAttr('style')}}, next);
(Assuming the width defined by the css is responsive)

Run Jquery only when an element is in the viewport

I'm trying to perform the Jquery function below when the element becomes visible in the viewport rather than on the page load. What would I need to change to allow that to happen? I'm using an external JS file to perform the Jquery, so keep that in mind.
Here's a piece of the HTML that is associated with the Jquery function -
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title" style="background: #FF704D;">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D;"></div>
<div class="skill-bar-percent">70%</div>
</div>
jQuery(document).ready(function(){
jQuery('.skillbar').each(function(){
jQuery(this).find('.skillbar-bar').animate({
width:jQuery(this).attr('data-percent')
},4000);
});
});
I once came across such problem and what I used is waypoints small library.
all you need is to include this library and do:
var waypoint = new Waypoint({
element: document.getElementById('waypoint'),
handler: function(direction) {
console.log('Element is in viewport');
}
})
Using CSS3 transitions instead of jQuery animations might be more performant and simpler. a cheap and nasty way of pushing it out of screen to demonstarate the effect.
There's a couple of things you'll need to do - firstly if you only want the animation to trigger when it's in the viewport then you'll need to check if anything is in the viewport on scroll. Then only update the bars width when it comes into view. If you want the effect to repeat every time it comes into viewport you'll need to set .skillbar-bar's width back to 0 if it's out of the viewport (just add an else statement to the viewport checking if)
I've added a 1000px margin-top and 400px margin-bottom in my example to .skillbar as a cheap and nasty way of demonstrating the effect
(function($){
$(document).ready(function(){
var $els = $('.skillbar'); // Note this must be moved to within event handler if dynamically adding elements - I've placed it for performance reasons
var $window = $(window);
$window.on('scroll', function(){
$els.each(function(){ // Iterate over all skillbars
var $this = $(this);
if($window.scrollTop() > $this.offset().top - $window.height()){ // Check if it's in viewport
$this.find('.skillbar-bar').css({'width' : $this.attr('data-percent')}); // Update the view with percentage
}
});
});
});
}(jQuery));
.skillbar{
margin-top: 1000px;
margin-bottom: 400px;
position: relative
}
.skillbar-bar{
transition: width 4s;
position: absolute;
height: 20px;
}
.skill-bar-percent{
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Scroll down 1000px :)
<div class="skillbar clearfix " data-percent="70%">
<div class="skillbar-title">
<span>Illustrator</span></div>
<div class="skillbar-bar" style="background: #FF704D; width: 20%"></div>
<div class="skill-bar-percent">70%</div>
</div>
This might work for you.
var el = $('.yourElement'),
offset = el.offset(),
scrollTop = $(window).scrollTop();
//Check for scroll position
if ((scrollTop > offset.top)) {
// Code..
}

JavaScript auto re-size height

I've been trying - and I'm at the point where I just don't know what to try anymore.
I'm trying to make my website's chat fill the entire page with this script
<script>
$(document).ready(function() {
function setHeight() {
windowHeight = $(window).innerHeight();
$('ul').css('min-height', windowHeight);
};
setHeight();
$(window).resize(function() {
setHeight();
});
});
</script>
I'm using this script for my chat's ul tag, and it fits the height so the script works, but I'm trying to figure out how to make it fill about 95% of the page, so I still have room for the content below. (Send message, settings and emotes.)
I have a div tag around the entire chat, but setting that in the script doesn't affect the list of messages.
Any ideas to my struggle?
dont bother with js/jquery, use css, pure css like this :
div {
position: fixed!important;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
<div id="container">
...
</div>
<script>
var container=document.getElementById('container');
var h=document.documentElement.clientHeight;
container.style.height=h+'px';
</script>

Scroll helper for mobile website

I have a very long article page that I want to help mobile users scroll on. For very long lists in mobile apps there's usually a alphabetical index that can help users jump to various places in the list. How do I implement something like that for a webapp?
If it helps my stack is angularjs / jquery / phonegap.
Just use angular's built-in $anchorScroll service.
See the live example in angular's official docs. Here are the important pieces of code:
In your view template:
<div id="scrollArea" ng-controller="ScrollCtrl">
<a ng-click="gotoBottom()">Go to bottom</a>
<a id="bottom"></a> You're at the bottom!
</div>
In your controller:
function ScrollCtrl($scope, $location, $anchorScroll) {
$scope.gotoBottom = function (){
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('bottom');
// call $anchorScroll()
$anchorScroll();
};
}
iOS7 Style List Navigator
If you want something nice on the phone, I just wrote this iOS7 style list navigator. I think the way Apple solved the problem is very straightforward. So we steal it.
It's written considering that you won't probably scroll the body, because in the many designs I've seen for smartphones, scrolling a container allows you to have fixed headers and footers for Android < 4 without getting mad.
A word of warning: this code is really fresh and untested.
SEE DEMO AND CODE
CSS (extract)
#scrolling {
padding-top: 44px;
overflow: scroll;
-webkit-overflow-scroll: touch;
height: 100%;
}
.menu {
position: fixed;
right: 0;
font-size: 12px;
text-align: center;
display: inline-block;
z-index: 2;
top: 58px;
}
.list .divider {
position: -webkit-sticky; /* will stop the label when it reaches the header */
top: 44px;
}
HTML (extract)
<div id="scrolling">
<ul class="menu">
<li>A</li>
<li>B</li>
<li>C</li>
<!-- etc -->
</ul>
<ul class="list">
<li class="divider" id="a">A</li>
<li>Amelia Webster</li>
<li>Andrew WifKinson</li>
<!-- etc -->
Javascript (zepto/jquery)
$(function() {
$(window).on("touchstart touchmove mouseover click", ".menu a", function(e) {
e.preventDefault();
clearInterval(t);
var steps = 25;
var padding = 68;
var target = $( $(this).attr("href") ).next("li");
if ( target.length > 0 ) {
var scroller = $("#scrolling")[0];
var step = parseInt((target[0].offsetTop - padding - scroller.scrollTop)/steps);
var stepno = 0;
setInterval( function() {
if ( stepno++ <= steps ) {
scroller.scrollTop += step;
} else {
clearInterval(t)
}
}, 20);
};
});
});
It performs a basic check of link validity before attempting the scroll. You can change padding to your needs.
Also, you will notice that we are targeting the first element after the required target. This is because Safari seems to go nuts because of the sticky positioning.
This code uses jQuery/Zepto selectors for the sake of brevity and readability. But these libraries are not really needed to achieve the result. With just a little extra digitation you could easily go dependency-free.
http://codepen.io/frapporti/pen/GtaLD
You can use a toggleable sidebar like this one. Resize your browser to the width of the screen of a mobile phone to understand what I mean.
Then create a directive in angularjs to wrap jQuery's animate function to scroll to a specific part in the article. Like this:
angular.module('yourModule', [])
.directive('scrollTo', function() {
return {
restrict : 'EA',
link: function(scope , element, attr){
$('html, body').animate({
scrollTop: $( attr['href'] ).offset().top
}, 300);
}
};
});
where href will be an id of a specific section in the article. Then all you need to do is apply the directive to the links in the sidebar.
...
<li><a href="#section-1" scroll-to>Jump to section 1</a></li>
...
Hope this helps.
This might be what you're looking for http://www.designkode.com/alphascroll-jquery-mobile/
Haven't used it myself, but seems pretty simple to get going with.
I think something like this could work for you: http://codepen.io/aecend/pen/AsnIE. This is just a basic prototype I put together to answer but I could expand on the concept if needed. Basically, it creates a translucent bar on the right side of the screen, finds each of the headings for articles (which would need to be adapted to suit your needs) and places clickable/tappable anchors to jump to individual articles. When you click one, the page scrolls to that article. I have a few ideas to make this actually usable, but here's the proof of concept.
CSS
#scrollhelper {
position: fixed;
top: 0;
right: 0;
height: 100%;
width: 5%;
background-color: rgba(0,0,0,0.2);
overflow: hidden;
}
#scrollhelper .point {
position: absolute;
display: block;
width: 100%;
height: 10px;
margin: 0 auto;
background-color: rgba(0,0,255,0.5);
}
JavaScript
var articles;
function buildScrollHelp() {
var bodyHeight = $("body").height();
var viewHeight = window.innerHeight;
$("#scrollhelper").html("");
articles.each(function() {
var top = $(this).offset().top;
var element = document.createElement("a");
element.className = "point";
element.href = "#" + $(this).attr("id");
element.style.top = ((top / bodyHeight) * viewHeight) + "px";
$(element).on("click", function(e){
e.preventDefault();
$('html, body').animate({
scrollTop: $($(this).attr("href")).offset().top
}, 500);
});
$("#scrollhelper")[0].appendChild(element);
});
}
$(document).ready(function() {
articles = $("body").children("[id]");
$("body").append("<div id=\"scrollhelper\"></div>");
$(window).resize(function(){
buildScrollHelp();
});
buildScrollHelp();
});

Jquery have a parent div have the same width and height of it's child element

I'm having this problem to solve for weeks now and really need help.
I have this system where a user selects a template with 2 types of areas. One for inserting images and one for inserting text.
Each template may come with numerous areas to insert images and each image area is just a div with it's own dimensions [width px - height px] within a limited area of 800px - 650px.
I will call this div to receive images div.img
Inside that div.img theres an input type="file" and throw jquery.form.js plugin I'm able to insert a new image into it.
I will call the inserted image new.img
This new.img comes wrapped in a div div.newImg because I had to have a button to delete the image on top of the image itself.
I'm using jquery ui draggable and resizable so the div.newImg may be resized and dragged inside of div.img.
Here are the different elements: div.img -> div.newImg -> new.img + button delete
HTML
<div class="child" style="z-index: 70; position: absolute; top: 0px; left: 0px; width: 800px; height: 172px; cursor: default; background-color: rgba(254, 202, 64, 0.701961);" alt="reset">
<div class="imgh ui-resizable ui-draggable" alt="reset3" style="height: 100%; width: 204px;">
<img src="###" style="width:inherit; height:inherit; min-width:50px; min-height:50px;" class="img_set">
<div class="close"><i class="icon-remove-sign"></i></div>
</div>
</div>
JQUERY
$('.imgh').resizable({ containment: $(this).closest('.child') });
$('.imgh').draggable({ containment: $(this).closest('.child'), scroll: true, snap: true, snapTolerance: 5 });
This is what I've manage to approach so far but doesn't help me at all
if($('.child').width() > $('.child').height()){
$('.imgh').height('100%');
$('.imgh').width($('.imgh img').width());
}else{
$('.imgh').width('100%');
$('.imgh').height($('.imgh img').height());
}
I've managed to have the img.img_set have the same dimensions as it's parent by having style="width:inherit; height:inherit;".
What I need is a way for the div.imgh to have the same dimensions as it's inner img.img_set. Like a reversed inherit.
UPDATE
This code does what I want but my problem is that everytime I resize it comes back to what I've defined in the initialization:
if($('.child').width() > $('.child').height()){
$('.imgh').height('100%');
$('.imgh').width('auto');
}else{
$('.imgh').width('100%');
$('.imgh').height('auto');
}
if($('.imgh').width() > $('.imgh img').width()){
$('.imgh').width($('.imgh img').width());
}
Is there a way for this to only happen once to each div.imgh?
You could use .bind() to resize it it every time something changes...
$('.imgh').bind('resize', FullWidthHeight); //Note: check the 'resize' event is relevant to imgh
function FullWidthHeight() {
$('.imgh').css('height', img.img_set.height());
$('.imgh').css('width', img.img_set.width());
}

Categories

Resources