I've been trying to add event listeners as a part of a plugin. The idea is really simple, the goal is to do a slider plugin that handles 2 dimensions (horizontally and vertically)
So I have something like this
<div class="tab-container bg-dark-blue" start-tab="Home">
<div class="tab-page" x-index="1" y-index="1" id="Home">
<h1>x=1, y=1</h1>
</div>
<div class="tab-page" x-index="1" y-index="2">
<h1>x=1, y=2</h1>
</div>
<div class="tab-page" x-index="2" y-index="1">
<h1>x=2, y=1</h1>
</div>
<div class="tab-page" x-index="2" y-index="2">
<h1>x=2, y=2</h1>
</div>
</div>
Where tab-page divs are absolutely positioned with 100% width and height, and tab-container is relatively positioned with 100% width and height of the browser.
var __MyMethods = {
width : 0
height : 0,
container : null,
// other stuff
setup : function(tab_container) {
// setup __MyPlugin.container = tab_container
// setup width, height of the container
},
/*
* Movement functions
*
*/
move : function(direction)
{
if( direction == 'left' )
{
__MyMethods.x--;
__MyMethods.translate( 'left', __MyMethods.width );
//
}
if( direction == 'right' )
{
__MyMethods.x++;
__MyMethods.translate( 'left', (-1)*__MyMethods.width );
//
}
if( direction == 'up' )
{
__MyMethods.y--;
__MyMethods.translate( 'top', __MyMethods.height );
}
if( direction == 'down' )
{
//
__MyMethods.y++;
__MyMethods.translate( 'top', (-1)*__MyMethods.height );
//
}
},
translate : function(property, offset)
{
// For each .tab-page in we animate the CSS property
$(__MyMethods.container).children(".tab-page").each( function() {
var animation = {};
var x = parseInt( $(this).css(property).replace('px','') ) + offset;
animation[property] = x.toString() + 'px';
$(this).animate(
animation,
{
'duration' : 0,
'queue' : false,
}
);
});
},
};
$.fn.MyPlugin = function()
{
__MyMethods.setup(this);
$(".btn").click( function(event)
{
__MyMethods.move( $(this).attr("move") );
console.log(this);
});
return this;
};
So I put
<button class="btn" move="up"></button>
<button class="btn" move="down"></button>
<button class="btn" move="left"></button>
<button class="btn" move="right"></button>
Somewhere in the HTML and it works fine for up, left, right... but if you click the move="down" button it works only the first time.
I don't know why is that hapening, the event never fires again if you click that button, I tried doing console.log(this) inside the click event function, but it doesn't show anything after the down button is clicked...
Any idea of what can be happening?
Thank you very much for any help you can give me
Edit: Here is a demo
Regards
In you jsfiddle the down button seems to stay behind the tab-page s. Giving z-index to menu and tab-page elements solves the problem.
In your css file:
Add
z-index: 10;
to .menu
Add
z-index: 1;
to .tab-page
css
Related
I have a grid panel in ExtJS with scroll bars. I am trying to detect when the user has scrolled all the way down(so that they can not move bar anymore). So far I have this, which detects when scroll occurs but provides no information(?) about where the scroll bar is.
//bufferedGrid is a grid panel
this.randomGrid.getView().on('scroll', this.onRandomGridScroll, this);
.
.
.
onRandomGridScroll : function(e, t)
{
console.log(e);
console.log(t);
}
Any pointers would be appreciated.
You can access the current scroll bar position(actually, the top of the scroll bar) and the maximum scroll position as follows(works in Firefox but not Chrome):
onBufferedGridScroll : function(e, t)
{
var max = this.bufferedGrid.getView().el.dom.scrollTopMax;
var current = this.bufferedGrid.getView().el.dom.scrollTop;
if( current == max )
alert('You have reached the bottom of the scroll !');
}
Add event on init
After grid is rendered add a mouseup event and a wheel down event.
'container #gridId':{
afterrender: this.addScrollEventListener
}
addScrollEventListener: function(comp){
comp.getTargetEl().on('mouseup', function(e, t) {
var height = comp.getTargetEl().getHeight();
if (height + t.scrollTop >= t.scrollHeight) {
}
});
comp.getTargetEl().on('wheeldown', function(e, t) {
var height = comp.getTargetEl().getHeight();
if (height + t.scrollTop >= t.scrollHeight) {
}
});
}
I'm using this code to create a ladda button:
CSS:
<link href="./assets/global/plugins/ladda/ladda-themeless.min.css" rel="stylesheet" type="text/css">
CODE:
<button type="button" id="test" class="btn green mt-ladda-btn ladda-button" data-style="expand-left"> <span class="ladda-label"> <i class="fa fa-key"></i> Nuova Password</span> </button>
JS:
<script src="./assets/global/plugins/ladda/spin.min.js" type="text/javascript"></script>
<script src="./assets/global/plugins/ladda/ladda.min.js" type="text/javascript"></script>
<script>
Ladda.bind( 'input[type=button]' );
$(function() {
$('#test').click(function(e){
var l = Ladda.create( document.querySelector( '#test' ) );
// Start loading
l.start();
// Will display a progress bar for 50% of the button width
l.setProgress( 0.5 );
});
});
</script>
This way the code work but progress is not correct:
but when use this code js:
Ladda.bind( '#test', {
callback: function( instance ) {
var progress = 0;
var interval = setInterval( function() {
progress = Math.min( progress + Math.random() * 0.1, 1 );
instance.setProgress( 0.5 );
if( progress === 1 ) {
instance.stop();
clearInterval( interval );
}
}, 200 );
}
});
the result is correct:
Why this? I need to use the first code because on click i have some function and i set the progress manualy based on function position.
It is possible to fix? I have metronic license and Material Theme, but u think the problem is plugin not theme.
To understand what's going on in the first example you have to look in the Ladda button code source and at line 154 there is the setProgress function:
/**
* Sets the width of the visual progress bar inside of
* this Ladda button
*
* #param {Number} progress in the range of 0-1
*/
setProgress: function( progress ) {
// Cap it
progress = Math.max( Math.min( progress, 1 ), 0 );
var progressElement = button.querySelector( '.ladda-progress' );
// Remove the progress bar if we're at 0 progress
if( progress === 0 && progressElement && progressElement.parentNode ) {
progressElement.parentNode.removeChild( progressElement );
}
else {
if( !progressElement ) {
progressElement = document.createElement( 'div' );
progressElement.className = 'ladda-progress';
button.appendChild( progressElement );
}
progressElement.style.width = ( ( progress || 0 ) * button.offsetWidth ) + 'px';
}
}
The ladda button in you example has data-style="expand-left" setted.
When setProgress in the else section it calculate the .ladda-progress' width doing:
progressElement.style.width = ( ( progress || 0 ) * button.offsetWidth ) + 'px';
Now, when it gets button.offsetWidth there isn't inside the expand-left rules yet.
When expand-left is applied at .ladda-button element, it change width dimension because expand-left is adding padding-left to it.
.ladda-button[data-style="expand-left"][data-loading] {
padding-left: 56px;
}
E.g. .ladda-button has an offsetWidth of 100px.
When you click it the offsetwidth will change from 100px to 156px because of the expand-left css rule above.
But when setProgress is called button.offsetwidth it will get the 100px offsetWidth because the animation transitions is not happened yet. So when you call l.setProgress(0.5) you will see .ladda-progress width setted to 50px instead of the correct 78px.
A quick fix can be this (jsBin). Please note that is an ugly hard-coded solution. A better solution it could be the following.
When Ladda instantiate the button it could check the data-style attribute and get (for example from an associative array where the keys are only the width-oriented effect name and the value will be the measure) the offeset that will be applied to the .ladda-button element.
EDIT
Thanks, but if change progress to 1 the problem not is solved
jsbin.com/jonupadono/1/edit?html,output – user3477026
I see. The problem start from this css rule:
.ladda-button, .ladda-button .ladda-spinner, .ladda-button .ladda-label {
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0s !important;
}
So, when button.offsetWidth is called inside setProgress it gets a lesser offsetWidth because the css animation has not finished yet, it takes 300ms to finish.
Solution
Using percentage instead of pixels to calculate the .ladda-progress' width jsBin
Hello everyone I explain my problem,
I created a master container 500px wide and 100px high (with overflow hidden) ...
inside a container 2 of various boxes, always 500px 100px, ill' insert a number of boxes 100px X 100px, plus two control buttons to move the container to the right or left of 100px.
The boxes are visible 5, for example, if there are 8 I would like to click the button 'right' container 2 would shift 100px but when they get to the last block (in this example is 8) button to go to right must disable.
Conversely, if we start the button to the left to Go must be disabled until the right has done at least one move.
Also as you can see at the click when I move the elements contained in the box it disappear during movement and this thing is no good, various box must move but always remain visible.
On JSfiddle I created a demo, I can not create the right conditions, you have a solution? thanks
enter link description here
$( "#right" ).click(function() {
$( "#block" ).animate({ "left": "+=105px" }, "slow" );
});
$( "#left" ).click(function(){
$( "#block" ).animate({ "left": "-=105px" }, "slow" );
});
.cont{
width:530px;
height:100px;
position:absolute;
background:#000;
overflow:hidden;
}
.box-cont{
width:auto;
height:100px;
position:absolute;
background:yellow;
}
.box{
width:100px;
height:100px;
position:relative;
float:left;
margin-left:5px;
background:#F00;
text-align:center;
font-size:32px;
}
.btn{
position:absolute;
left:0px;
top:120px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="cont">
<div class="box-cont" id="block">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box">8</div>
</div>
</div>
<div class="btn">
<button id="left">«</button>
<button id="right">»</button>
</div>
You could use something like this:
<script>
var totalBlocks = $('#block div.box').length;
var blockViews = Math.round($('#block').width() / $('#block div.box').width());
var currentPosition = 0;
$( "#right" ).click(function() {
if(currentPosition > 0)
{
$( "#block" ).animate({ "left": "+=105px" }, "slow" );
currentPosition--;
}
});
$( "#left" ).click(function(){
if(blockViews + (currentPosition+1) <= totalBlocks)
{
$( "#block" ).animate({ "left": "-=105px" }, "slow" );
currentPosition++;
}
});
</script>
Take a look at this, does this help? you can drag and move the elements themselves, and put left and right thresholds on them. I was trying to mimic google gmail swipe
http://jsfiddle.net/williamhowley/o9uvo50y/
$('ul#main > li')
.on('movestart', function (e) {
console.log("move start");
// var $li = $(e.target).closest('.swipable'); // this would be normal live integration
var $li = $(e.target);
if ($li.attr("data-hasplaceholder") !== "true") { // if it does not have a placeholder, add one.
createBackgroundSpacer($li);
$li.attr("data-hasplaceholder", true); // signify that a placeholder has been created for this element already.
}
// If the movestart heads off in a upwards or downwards
// direction, prevent it so that the browser scrolls normally.
if ((e.distX > e.distY && e.distX < -e.distY) ||
(e.distX < e.distY && e.distX > -e.distY)) {
e.preventDefault();
return;
}
// To allow the slide to keep step with the finger,
// temporarily disable transitions.
wrap.addClass('notransition'); // add this to the container wrapper.
})
.on('move', function (e) {
// event definitions
// startX : 184, where from left the mouse curser started.
// deltaX: ?
// distX: how far the mouse has moved, if negative moving left. Still need to account for double movement, currently can only handle one movement.
console.log("move");
console.log(e);
var maxLeft = $('.rightContent').width();
var marginLeftNum = Number($(this).css('margin-left').replace(/[^-\d\.]/g, ''));
if (marginLeftNum <= -maxLeft && e.deltaX < 0) { // Case when user is at outermost left threshold, and trying to move farther left.
$(this).css({ 'margin-left': -maxLeft });
}
else if (marginLeftNum == -maxLeft && e.deltaX > 0) { // When user is at threshold, and trying to move back right.
$(this).css({ 'margin-left': marginLeftNum + e.deltaX });
}
else if (e.target.offsetLeft>=0 && e.deltaX>0) { // If the offset is 0 or more, and the user is scrolling right (which is a positive delta, than limit the element. )
$(this).css({ 'margin-left': 0 });
}
// Must have a Negative offset, and e.deltaX is Negative so it is moving left.
else if (e.deltaX < 0) { // Case when element is at 0, and mouse movement is going left.
$(this).css({ 'margin-left': marginLeftNum + e.deltaX });
}
else { // Moving Right when not on 0
$(this).css({ 'margin-left': marginLeftNum + e.deltaX });
}
})
.on('swipeleft', function (e) {
console.log("swipeleft");
})
.on('activate', function (e) {
// not seeing this activate go off, i think this is custom function we can add on if swipe left hits a threshold or something.
console.log("activate");
})
.on('moveend', function (e) {
console.log("move end");
wrap.removeClass('notransition');
});
I'm trying to create a programme page, this page consists of columns that you can expand by clicking on a button. When you get to a certain point on the programme a menu will appear and stay on top of the page. However, when you expand one of the columns, a problem will occur where the Y position isn't returned correctly. This makes the menu jump to the top of the page too early.
My Jquery knowledge is limited so I hope someone can help me with this. I've tried looking for an answer but unfortunately no results yet.
HTML:
<body>
<div id="column1">Expand this div and scroll down to see the problem</div>
<div id="fixed-row"></div>
<div id="column2"></div>
</body>
CSS:
#column1{height:250px; width:200px; background-color:#545454; cursor:pointer; margin-bottom:5px; color:#fff;}
#column2{height:1000px; width:200px; background-color:#cecece;}
#fixed-row{height:50px; width:200px; background-color:#ff00ff; margin-bottom:5px;}
.fixed{position:fixed; top:0;}
JQuery:
$(document).ready(function () {
$('#column1').click(function() {
if ($('div#column1').height() > 251) {
($('div#column1').animate({height: '250px', navigation: true}))
} else {
($('div#column1').animate({height: '500px', navigation: true}));
}
});
var top = $('#fixed-row').offset().top;
$(window).scroll(function () {
//Y position of scroll
var y = $(window).scrollTop();
//Whether below form
if (y >= top) {
//If so, add class fixed
$('#fixed-row').addClass('fixed');
}else {
//Otherwise remove class fixed
$('#fixed-row').removeClass('fixed');
}
});
});
I also created a JSfiddle to illustrate the problem
Many thanks in advance
Basically, you calculate top value before the animation, and do not update it afterwards. You need to update it when the animation is done.
Try something like this:
$(document).ready(function () {
var top = $('#fixed-row').offset().top;
$('#column1').click(function() {
if ($('div#column1').height() > 251) {
($('div#column1').animate({height: '250px', navigation: true},function() { top = $('#fixed-row').offset().top; }));
} else {
($('div#column1').animate({height: '500px', navigation: true},function() { top = $('#fixed-row').offset().top; }));
}
});
just change as below it works
$(window).scroll(function () {
var top = $('#column1').height();
//Y position of scroll
var y = $(window).scrollTop();
//Whether below form
if (y >= top) {
//If so, add class fixed
$('#fixed-row').addClass('fixed');
}else {
//Otherwise remove class fixed
$('#fixed-row').removeClass('fixed');
} });
http://jsfiddle.net/jb36m/4/
<script language="javascript">
$(document).ready(function($) {
var methods = {
init: function(options) {
this.children(':first').stop();
this.marquee('play');
},
play: function() {
var marquee = this,
pixelsPerSecond = 100,
firstChild = this.children(':first'),
totalHeight = 0,
difference,
duration;
// Find the total height of the children by adding each child's height:
this.children().each(function(index, element) {
totalHeight += $(element).innerHeight();
});
// The distance the divs have to travel to reach -1 * totalHeight:
difference = totalHeight + parseInt(firstChild.css('margin-top'), 10);
// The duration of the animation needed to get the correct speed:
duration = (difference/pixelsPerSecond) * 1000;
// Animate the first child's margin-top to -1 * totalHeight:
firstChild.animate(
{ 'margin-top': -1 * totalHeight },
duration,
'linear',
function() {
// Move the first child back down (below the container):
firstChild.css('margin-top', marquee.innerHeight());
// Restart whole process... :)
marquee.marquee('play');
}
);
},
pause: function() {
this.children(':first').stop();
}
};
$.fn.marquee = function(method) {
// Method calling logic
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.marquee');
}
};
})(jQuery);
var marquee = $('#marquee');
marquee.marquee();
marquee.hover(function() {
marquee.marquee('pause');
}, function() {
marquee.marquee('play');
});
</script>
<style type="text/css">
#marquee {
margin:inherit;
width:auto;
height:inherit
}
</style>
I would like to create a scroller using jquery but I fail. The above code is the marquee I use to scroll up my items. And I am using it as below,
<html>
<body>
<div class="content">
<div id="marquee">
<ul>
<li>...</li>
....
</ul>
</div>
</div></body>
</html>
But it doesn't scroll at all, is there something incorrect in the code I am using you can find for me ?
Not sure if margin-top should work for this at all.
Try using position:relative for holder block(marquee) and position:absolute for content (ul). And update top instead of margin top. But in this case you may need to specify height and overflow:hidden for marquee div. Another options is to set height and oveflow:hidden for marquee, but leave position default. And scroll content using scrollTop or with some similar jquery functions.