Related
I need to get vertex from an object (box) in an AFRAME or i need to calculate intersection between raycaster and the face of an entity.
Someone can help me? Thank you all!ç
EDIT: I added code below.
AFRAME.registerComponent("intersection-handler", {
schema: {
fps: { type: 'number', default: 15 }
},
init: function() {
this.bindMethods();
},
tick: function(){
if(new Date().getTime()-this.lastTick<(1000/this.data.fps))return;
if(this.isIntersecting){
let distance = this.calculateDistance(this.el.object3D.position, this.hittedElem.object3D.position);
this.el.emit('intersection-detected-' + this.el.id, distance );
}else{
this.el.emit('intersection-cleared-' + this.el.id);
}
this.lastTick = new Date().getTime();
},
bindMethods(){ // You could do all of this directly in your init() method, but I like to separate it.
this.onIntersection = this.onIntersection.bind(this);
this.onIntersectionClear = this.onIntersectionClear.bind(this);
},
play: function() {
this.registerEventListeners(); // It's a good practice in general to enable your event listeners here.
},
pause: function() {
this.deregisterEventListeners(); // Similarly a good practice to remove them here so that they don't stay bound while the scene isn't actually 'running'
},
registerEventListeners() {
this.el.addEventListener('raycaster-intersection', this.onIntersection);
this.el.addEventListener('raycaster-intersection-cleared', this.onIntersectionClear);
},
deregisterEventListeners() {
this.el.removeEventListener('raycaster-intersection', this.onIntersection);
this.el.removeEventListener('raycaster-intersection-cleared', this.onIntersectionClear);
},
onIntersection: function(e) {
console.log(this.el.components.raycaster.getIntersection(e.detail.els[0]))
this.isIntersecting = true;
if(e.detail.intersections[0].object){
this.hittedElem = e.detail.intersections[0].object.el;
}
},
onIntersectionClear: function(e) {
this.isIntersecting = false;
},
calculateDistance: function(myElposition, hittedElposition) {
// distance = sqrt((x2 - x1)^2 + (y2 - y1)^2) - rolloff
let rolloffFactor = 0.5;
let d = Math.sqrt(Math.pow((hittedElposition.x - myElposition.x), 2) + Math.pow((hittedElposition.y - myElposition.y), 2)) - rolloffFactor;
return d;
}
});
I can't use the raycaster-intersected event, i'm managing intersections on raycaster side not in the other entities.
no need for the vertex coordinates. The raycasters intersection.point contains a Vector3 with the intersection position.
On the other hand if you get your camera (raycasters origin) position, you get another Vector3.
From the three.js docs, you can get the distance between them with a simple a.distanceTo(b).
Fiddle here.
Any ideas how to make switchable characters I have a html game it's finished but I want to implement a way to switch my main character.
Simple coding using Phaser framework
upload function() {
this.game.load.sprite ("bird" assets/bird.png);
this.game.load.sprite ("bird2" assets/bird2.png);
this.game.load.sprite ("bird3" assets/bird3.png);
},
create function() {
this.game.add.sprite (0, 0 "bird" );
},
I want to be able to switch my playable character the "bird" with the "bird2" or "bird3" through a selection button if a player selects a switch character button for the playable character to switch to that. I'm pretty sure this is something simple but I'm still pretty new with coding.
I want a button where I press then I can switch the character
(Button 1) switches to bird2
"if button 1 is selected button two and current bird are disabled"-only bird2 is visible
(Button 2) switches to bird3
"if button 2 is selected button one and current bird are disabled"-only bird3 is visible
Edit This is My current code and states
var MainState = {
//load the game assets before the game starts
preload: function () {
this.load.image('background', 'assets/spring2.png');
this.load.spritesheet('bird', 'assets/bird.png',52 ,28, 7);
this.load.spritesheet('bird2', 'assets/bird2.png',52 ,28, 7);
this.load.spritesheet('bird3', 'assets/bird3.png',52 ,28, 7);
this.load.image('pipe', 'assets/pipe4.png');
},
//executed after everything is loaded
create: function () {
this.background = game.add.tileSprite(0, game.height-736,game.width, 736, 'background');
this.background.autoScroll(-20,0);
/////Bird///////////////////////////////////////////////////
this.bird = this.game.add.sprite(100, 200, 'bird');
this.bird.animations.add('fly');
this.bird.animations.play('fly', 50, true);
game.physics.startSystem(Phaser.Physics.ARCADE);
game.physics.arcade.enable(this.bird);
this.bird.body.gravity.y = 1000;
var spaceKey = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
this.bird.body.collideWorldBounds=true;
this.bird.body.immovable= true;
game.input.onDown.add(this.jump, this); //////touch screen jump
spaceKey.onDown.add(this.jump, this);
///////////////////////////////////////////////////////Pipes
this.pipes = game.add.group();
//timer
this.timer = game.time.events.loop(1600, this.addRowOfPipes, this); /////////////timer for pipes
///Bird anchor
this.bird.anchor.setTo(-0.2, 0.5)
},
// this is execated multiple times per second
update: function () {
if (this.bird.y < 0 || this.bird.y > 480)
game.state.start("StateOver");
///Collision
game.physics.arcade.overlap(
this.bird, this.pipes, this.restartGame, null, this);
///Bird Angle
if (this.bird.angle < 30)
this.bird.angle += 1;
///////////////music stop w top+bottom collision
if (this.bird.y < 0 || this.bird.y > 479)
music.stop();
},
jump: function () {
//this is for so the bird wount fly once dead
if (this.bird.alive == false)
return;
// Add a vertical velocity to the bird
this.bird.body.velocity.y = -350;
// Jump Animation
var animation = game.add.tween(this.bird);
// Change the angle of the bird to -20° in 100 milliseconds
animation.to({angle: -20}, 100);
// And start the animation
animation.start();
game.add.tween(this.bird).to({angle: -20}, 100).start();
},
restartGame: function () {
// Start the 'main' state, which restarts the game
game.state.start(game.state.StateOver); /////////////////////changed from current #########
///Hit pipe Null
game.physics.arcade.overlap(
this.bird, this.pipes, this.hitPipe, null, this);
},
addRowOfPipes: function() {
var hole = Math.floor(Math.random() * 5) + 1; ///Math.floor(Math.random() * 5) + 1;
for (var i = 0; i < 10 ; i++) ///// (var i = 0; i < 8; i++)
if (i != hole && i != hole + 1) ///// if (i != hole && i != hole + 1)
this.addOnePipe(440, i * 50 ); ///// 640 starting point of pipe 240 point of down ////this.addOnePipe(480, i * 60 + 10);
},
addOnePipe: function(x, y) {
var pipe = game.add.sprite(x, y, 'pipe');
this.pipes.add(pipe);
game.physics.arcade.enable(pipe);
pipe.body.velocity.x = -200;
pipe.checkWorldBounds = true;
pipe.outOfBoundsKill = true;
},
hitPipe: function() {
// If the bird has already hit a pipe, do nothing
// It means the bird is already falling off the screen
if (this.bird.alive == false)
return;
else {
game.state.start("StateOver");
}
// Set the alive property of the bird to false
this.bird.alive = false;
// Prevent new pipes from appearing
game.time.events.remove(this.timer);
// Go through all the pipes, and stop their movement
this.pipes.forEach(function(p){
p.body.velocity.x = 0;
}, this);
},
};
character.js
var characters={
preload:function()
{
game.load.spritesheet('button', 'assets/button.png', 215, 53, 8);
game.load.image("background", "assets/characterbackground.png");
game.load.image("pajaro", "assets/storeicon.png");
game.load.image("logo", "assets/extra/storef.png");
this.load.spritesheet('bird', 'assets/bird.png',52 ,28, 7);
this.load.spritesheet('bird2', 'assets/bird2.png',52 ,28, 7);
this.load.spritesheet('bird3', 'assets/bird3.png',52 ,28, 7);
game.load.spritesheet("button2", 'assets/button2.png', 100, 10, 10);
},
create:function()
{
bird = game.add.image(140, 150, 'pajaro');
logo = game.add.image (20, 350, 'logo');
this.background = game.add.tileSprite(0, game.height-736,game.width, 736, 'background');
this.background.autoScroll(-100,0);
this.btnMainMenu=game.add.button(130,500,'button',this.mainMenu,this,4,5,4);
this.btnbird=game.add.button(180,600,"button2",this.changebird2,this,0,1,0);
},
mainMenu:function()
{
game.state.start("stateTitle");
},
update:function()
{
// bird.x +=1;
},
changebird2: function(){
},
};
Instead of creating three sprites that you either hide or show, I might recommend just changing what texture is loaded when the sprite is created/added.
To do this you'll need to store a reference to the playable character, which you probably already have.
// On the game itself, add a reference.
this.bird = null;
// In your preload, load the different images.
this.load.image('bird', 'assets/bird.png');
this.load.image('bird2', 'assets/bird2.png');
this.load.image('bird3', 'assets/bird3.png');
// When creating, default to one.
this.bird = this.game.add.sprite(0, 0, 'bird');
// In your function where they select a new skin, you can load in a different texture.
this.bird.loadTexture('bird3');
Alternatively, you could store the key that should be used on the game.
// On the game itself, track which key to use.
this.birdSkin = 'bird';
// You'll still have to load your possible textures.
this.load.image('bird', 'assets/bird.png');
this.load.image('bird2', 'assets/bird2.png');
this.load.image('bird3', 'assets/bird3.png');
// Now when creating just use the variable.
this.bird.loadTexture(this.birdSkin);
The Phaser init() will allow 0 or more parameters to be passed in (see the end of Phaser Tutorial: understanding Phaser states), which is where you could populate this.birdSkin.
I would look at what states you're using to determine what's best for you. If you have one state for the game and another for selecting which image/texture is used, than the second option might be better.
Update for Character State
Given your comments and what I saw in your code, I created a short example that you could tweak for your use.
There's a JSFiddle available, but the code is also included below.
var mainState = {
preload: function() {
// Load the three sprites that they can choose between.
this.load.crossOrigin = 'anonymous';
this.load.image('ball', 'https://raw.githubusercontent.com/photonstorm/phaser-examples/master/examples/assets/sprites/orb-blue.png');
this.load.image('ball2', 'https://raw.githubusercontent.com/photonstorm/phaser-examples/master/examples/assets/sprites/orb-green.png');
this.load.image('ball3', 'https://raw.githubusercontent.com/photonstorm/phaser-examples/master/examples/assets/sprites/orb-red.png');
},
create: function() {
this.ball = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY, this.game.global.skin);
this.ball.anchor.setTo(0.5);
// Let the ball be acted upon. This will allow the player to change the sprite used.
this.ball.inputEnabled = true;
this.ball.events.onInputDown.add(this.changeCharacter, this);
},
update: function() {
},
changeCharacter: function() {
game.state.start('character');
}
};
var characterState = {
preload: function() {
},
create: function() {
// For this, add our three possible ball skins.
this.ball1 = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY / 2, 'ball');
this.ball1.anchor.setTo(0.5);
this.ball1.inputEnabled = true;
this.ball2 = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY, 'ball2');
this.ball2.anchor.setTo(0.5);
this.ball2.inputEnabled = true;
this.ball3 = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY * 1.5, 'ball3');
this.ball3.anchor.setTo(0.5);
this.ball3.inputEnabled = true;
// Use the selected ball's sprite in our main game.
this.ball1.events.onInputDown.add(this.selectBall, this);
this.ball2.events.onInputDown.add(this.selectBall, this);
this.ball3.events.onInputDown.add(this.selectBall, this);
},
update: function() {
},
selectBall: function(sprite, pointer) {
// Grab the key of the sprite and save it to our global variable.
this.game.global.skin = sprite.key;
this.game.state.start('main');
}
};
var game = new Phaser.Game(200, 200);
// Create a global object that we can add custom variables to.
game.global = {
skin: 'ball'
};
game.state.add('main', mainState);
game.state.add('character', characterState);
game.state.start('main');
This actually simplifies things a bit, in that it just uses a global variable (I've been using TypeScript the last handful of months, so there's probably a better way to declare this).
I have a jsfiddle here using jquery 1.8.3 and scrollTo to scoll to an element #en on an XY axis
https://jsfiddle.net/80kxdsxe/
var $scrollTo = $.scrollTo = function(target, duration, settings) {
return $(window).scrollTo(target, duration, settings);
};
$scrollTo.defaults = {
axis:'xy',
duration: 0,
limit:true
};
The jsfiddle that i need to work is using pure js but it only scrolls to the element #en on either the X or Y axis and i need it to scroll using XY
https://jsfiddle.net/43s8wpd7/
/* Note: In order to be subjected to chaining and animation options, scroll's tweening is routed through Velocity as if it were a standard CSS property animation. */
if (action === "scroll") {
/* The scroll action uniquely takes an optional "offset" option -- specified in pixels -- that offsets the targeted scroll position. */
var scrollDirection = (/^x$/i.test(opts.axis) ? "Left" : "Top"),
scrollOffset = parseFloat(opts.offset) || 0,
scrollPositionCurrent,
scrollPositionCurrentAlternate,
scrollPositionEnd;
if (opts.container) {
if (Type.isWrapped(opts.container) || Type.isNode(opts.container)) {
opts.container = opts.container[0] || opts.container;
scrollPositionCurrent = opts.container["scroll" + scrollDirection];
scrollPositionEnd = (scrollPositionCurrent + $(element).position()[scrollDirection.toLowerCase()]) + scrollOffset; /* GET */
} else {
opts.container = null;
}
} else {
scrollPositionCurrent = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + scrollDirection]];
scrollPositionCurrentAlternate = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + (scrollDirection === "Left" ? "Top" : "Left")]]; /* GET */
scrollPositionEnd = $(element).offset()[scrollDirection.toLowerCase()] + scrollOffset; /* GET */
}
/* Since there's only one format that scroll's associated tweensContainer can take, we create it manually. */
tweensContainer = {
scroll: {
rootPropertyValue: false,
startValue: scrollPositionCurrent,
currentValue: scrollPositionCurrent,
endValue: scrollPositionEnd,
unitType: "",
easing: opts.easing,
scrollData: {
container: opts.container,
direction: scrollDirection,
alternateValue: scrollPositionCurrentAlternate
}
},
element: element
};
if (Velocity.debug) console.log("tweensContainer (scroll): ", tweensContainer.scroll, element);
Can anyone help me fix the second NON-jquery fiddle to allow the scroll to be on the XY axis?
Thanks.
I am using this jquery splitter plugin located here: http://methvin.com/splitter/
It is working fine with the version of jquery I am using until I enable the resizeToWidth property then it is giving me the error: too much recursion.
Here is a link to a demo I created on jsfiddle: http://jsfiddle.net/S97rv/4/
Iv looked at the plugin code but im not a javascript expert and don't want to mess with it to much.
Can anybody see a solution to this error?
Here is the plugin code but probably better just looking at the jsfiddle link:
;(function($){
$.fn.splitter = function(args){
args = args || {};
return this.each(function() {
var zombie; // left-behind splitbar for outline resizes
function startSplitMouse(evt) {
if ( opts.outline )
zombie = zombie || bar.clone(false).insertAfter(A);
panes.css("-webkit-user-select", "none"); // Safari selects A/B text on a move
bar.addClass(opts.activeClass);
A._posSplit = A[0][opts.pxSplit] - evt[opts.eventPos];
$(document)
.bind("mousemove", doSplitMouse)
.bind("mouseup", endSplitMouse);
}
function doSplitMouse(evt) {
var newPos = A._posSplit+evt[opts.eventPos];
if ( opts.outline ) {
newPos = Math.max(0, Math.min(newPos, splitter._DA - bar._DA));
bar.css(opts.origin, newPos);
} else
resplit(newPos);
}
function endSplitMouse(evt) {
bar.removeClass(opts.activeClass);
var newPos = A._posSplit+evt[opts.eventPos];
if ( opts.outline ) {
zombie.remove(); zombie = null;
resplit(newPos);
}
panes.css("-webkit-user-select", "text"); // let Safari select text again
$(document)
.unbind("mousemove", doSplitMouse)
.unbind("mouseup", endSplitMouse);
}
function resplit(newPos) {
// Constrain new splitbar position to fit pane size limits
newPos = Math.max(A._min, splitter._DA - B._max,
Math.min(newPos, A._max, splitter._DA - bar._DA - B._min));
// Resize/position the two panes
bar._DA = bar[0][opts.pxSplit]; // bar size may change during dock
bar.css(opts.origin, newPos).css(opts.fixed, splitter._DF);
A.css(opts.origin, 0).css(opts.split, newPos).css(opts.fixed, splitter._DF);
B.css(opts.origin, newPos+bar._DA)
.css(opts.split, splitter._DA-bar._DA-newPos).css(opts.fixed, splitter._DF);
// IE fires resize for us; all others pay cash
if ( !$.browser.msie )
panes.trigger("resize");
}
function dimSum(jq, dims) {
// Opera returns -1 for missing min/max width, turn into 0
var sum = 0;
for ( var i=1; i < arguments.length; i++ )
sum += Math.max(parseInt(jq.css(arguments[i])) || 0, 0);
return sum;
}
// Determine settings based on incoming opts, element classes, and defaults
var vh = (args.splitHorizontal? 'h' : args.splitVertical? 'v' : args.type) || 'v';
var opts = $.extend({
activeClass: 'active', // class name for active splitter
pxPerKey: 8, // splitter px moved per keypress
tabIndex: 0, // tab order indicator
accessKey: '' // accessKey for splitbar
},{
v: { // Vertical splitters:
keyLeft: 39, keyRight: 37, cursor: "e-resize",
splitbarClass: "vsplitbar", outlineClass: "voutline",
type: 'v', eventPos: "pageX", origin: "left",
split: "width", pxSplit: "offsetWidth", side1: "Left", side2: "Right",
fixed: "height", pxFixed: "offsetHeight", side3: "Top", side4: "Bottom"
},
h: { // Horizontal splitters:
keyTop: 40, keyBottom: 38, cursor: "n-resize",
splitbarClass: "hsplitbar", outlineClass: "houtline",
type: 'h', eventPos: "pageY", origin: "top",
split: "height", pxSplit: "offsetHeight", side1: "Top", side2: "Bottom",
fixed: "width", pxFixed: "offsetWidth", side3: "Left", side4: "Right"
}
}[vh], args);
// Create jQuery object closures for splitter and both panes
var splitter = $(this).css({position: "relative"});
var panes = $(">*", splitter[0]).css({
position: "absolute", // positioned inside splitter container
"z-index": "1", // splitbar is positioned above
"-moz-outline-style": "none" // don't show dotted outline
});
var A = $(panes[0]); // left or top
var B = $(panes[1]); // right or bottom
// Focuser element, provides keyboard support; title is shown by Opera accessKeys
var focuser = $('')
.attr({accessKey: opts.accessKey, tabIndex: opts.tabIndex, title: opts.splitbarClass})
.bind($.browser.opera?"click":"focus", function(){ this.focus(); bar.addClass(opts.activeClass) })
.bind("keydown", function(e){
var key = e.which || e.keyCode;
var dir = key==opts["key"+opts.side1]? 1 : key==opts["key"+opts.side2]? -1 : 0;
if ( dir )
resplit(A[0][opts.pxSplit]+dir*opts.pxPerKey, false);
})
.bind("blur", function(){ bar.removeClass(opts.activeClass) });
// Splitbar element, can be already in the doc or we create one
var bar = $(panes[2] || '<div></div>')
.insertAfter(A).css("z-index", "100").append(focuser)
.attr({"class": opts.splitbarClass, unselectable: "on"})
.css({position: "absolute", "user-select": "none", "-webkit-user-select": "none",
"-khtml-user-select": "none", "-moz-user-select": "none"})
.bind("mousedown", startSplitMouse);
// Use our cursor unless the style specifies a non-default cursor
if ( /^(auto|default|)$/.test(bar.css("cursor")) )
bar.css("cursor", opts.cursor);
// Cache several dimensions for speed, rather than re-querying constantly
bar._DA = bar[0][opts.pxSplit];
splitter._PBF = $.boxModel? dimSum(splitter, "border"+opts.side3+"Width", "border"+opts.side4+"Width") : 0;
splitter._PBA = $.boxModel? dimSum(splitter, "border"+opts.side1+"Width", "border"+opts.side2+"Width") : 0;
A._pane = opts.side1;
B._pane = opts.side2;
$.each([A,B], function(){
this._min = opts["min"+this._pane] || dimSum(this, "min-"+opts.split);
this._max = opts["max"+this._pane] || dimSum(this, "max-"+opts.split) || 9999;
this._init = opts["size"+this._pane]===true ?
parseInt($.curCSS(this[0],opts.split)) : opts["size"+this._pane];
});
// Determine initial position, get from cookie if specified
var initPos = A._init;
if ( !isNaN(B._init) ) // recalc initial B size as an offset from the top or left side
initPos = splitter[0][opts.pxSplit] - splitter._PBA - B._init - bar._DA;
if ( opts.cookie ) {
if ( !$.cookie )
alert('jQuery.splitter(): jQuery cookie plugin required');
var ckpos = parseInt($.cookie(opts.cookie));
if ( !isNaN(ckpos) )
initPos = ckpos;
$(window).bind("unload", function(){
var state = String(bar.css(opts.origin)); // current location of splitbar
$.cookie(opts.cookie, state, {expires: opts.cookieExpires || 365,
path: opts.cookiePath || document.location.pathname});
});
}
if ( isNaN(initPos) ) // King Solomon's algorithm
initPos = Math.round((splitter[0][opts.pxSplit] - splitter._PBA - bar._DA)/2);
// Resize event propagation and splitter sizing
if ( opts.anchorToWindow ) {
// Account for margin or border on the splitter container and enforce min height
splitter._hadjust = dimSum(splitter, "borderTopWidth", "borderBottomWidth", "marginBottom");
splitter._hmin = Math.max(dimSum(splitter, "minHeight"), 20);
$(window).bind("resize", function(){
var top = splitter.offset().top;
var wh = $(window).height();
splitter.css("height", Math.max(wh-top-splitter._hadjust, splitter._hmin)+"px");
if ( !$.browser.msie ) splitter.trigger("resize");
}).trigger("resize");
}
else if ( opts.resizeToWidth && !$.browser.msie )
$(window).bind("resize", function(){
splitter.trigger("resize");
});
// Resize event handler; triggered immediately to set initial position
splitter.bind("resize", function(e, size){
// Custom events bubble in jQuery 1.3; don't get into a Yo Dawg
if ( e.target != this ) return;
// Determine new width/height of splitter container
splitter._DF = splitter[0][opts.pxFixed] - splitter._PBF;
splitter._DA = splitter[0][opts.pxSplit] - splitter._PBA;
// Bail if splitter isn't visible or content isn't there yet
if ( splitter._DF <= 0 || splitter._DA <= 0 ) return;
// Re-divvy the adjustable dimension; maintain size of the preferred pane
resplit(!isNaN(size)? size : (!(opts.sizeRight||opts.sizeBottom)? A[0][opts.pxSplit] :
splitter._DA-B[0][opts.pxSplit]-bar._DA));
}).trigger("resize" , [initPos]);
});
};
})(jQuery);
The plugin you are using is based on a old jQuery version. For some reason, an infinite recursion was introduced by jQuery 1.6, probably due to event bubbling. It seems like a resize event triggered on a specific DOM element follow the event propagation path, all the way to document.
In the resize event handler, you can add a test to prevent recursion:
$(window).bind("resize", function (e) {
if (e.target === window) { splitter.trigger('resize'); }
});
That works, at least in Chrome and Firefox.
Using jQuery Migrate plugin will allow you to use jQuery 1.9 and even 2.0; but relying on browser specific behavior is generally a bad practice. You may have a look at this splitter.js fork, which already fixes your infinite recursion issue, using the same test as above.
I have this script which enable scrollbar within <div>
I want to add functionality to scroll even using "Mouse Scroll-Wheel"
Here is code :
var TINY={};
function T$(id){return document.getElementById(id)}
function T$$$(){return document.all?1:0}
TINY.scroller=function(){
return{
init:function(a,c,b,s,d){
a=T$(a); a.c=c; a.s=s; c=T$(c); b=T$(b); s=T$(s); a.n=d||0;
b.style.display='block'; a.style.overflow='hidden';
var h=a.offsetHeight, t=c.offsetHeight;
if(t<h){
b.style.display='none'
}else{
a.m=h-t; a.d=t/h; s.style.height=(h*(h/t))+'px'; s.style.top=b.style.top=0;
s.onmousedown=function(event){TINY.scroller.st(event,a.id); return false};
s.onselectstart=function(){return false}
}
a.l=b.offsetHeight-s.offsetHeight
},
st:function(e,f){
var a=T$(f), s=T$(a.s); a.bcs=TINY.cursor.top(e); a.bct=parseInt(s.style.top);
if(a.mv){this.sp(f)}
a.mv=function(event){TINY.scroller.mv(event,f)};
a.sp=function(){TINY.scroller.sp(f)};
if(T$$$()){
document.attachEvent('onmousemove',a.mv); document.attachEvent('onmouseup',a.sp)
}else{
document.addEventListener('mousemove',a.mv,1); document.addEventListener('mouseup',a.sp,1)
}
if(a.d){s.className+=' '+a.n}
},
mv:function(e,f){
var a=T$(f), m=TINY.cursor.top(e)-a.bcs+a.bct, s=T$(a.s), c=T$(a.c);
if(m>=0&&m<a.l){
s.style.top=m+'px'; c.style.top=(m*-1*a.d)+'px'
}else if(m<0){
s.style.top=0; c.style.top=0
}else if(m>a.l){
s.style.top=a.l+'px'; c.style.top=a.m+'px'
}
},
sp:function(f){
var a=T$(f), s=T$(a.s); if(a.d){s.className=s.className.replace(' '+a.n,'')}
if(T$$$()){
document.detachEvent('onmousemove',a.mv); document.detachEvent('onmouseup',a.sp)
}else{
document.removeEventListener('mousemove',a.mv,1); document.removeEventListener('mouseup',a.sp,1)
}
a.mv=0;
}
}
}();
TINY.cursor=function(){
return{
top:function(e){
return T$$$()?window.event.clientY+document.documentElement.scrollTop+document.body.scrollTop:e.clientY+window.scrollY
}
}
}();
How to add this ability to current code ?
Thanks.
EDIT : Issue Solved
Use this code:
http://adomas.org/javascript-mouse-wheel/
TINY.scroller=function(){
return{
init:function(a,c,b,s,d){
a=T$(a); a.c=c; a.s=s; c=T$(c); b=T$(b); s=T$(s); a.n=d||0;
b.style.display='block'; a.style.overflow='hidden';
var h=a.offsetHeight, t=c.offsetHeight;
if(t<h){
b.style.display='none'
}else{
a.m=h-t; a.d=t/h; s.style.height=(h*(h/t))+'px'; s.style.top=b.style.top=0;
s.onmousedown=function(event){TINY.scroller.st(event,a.id); return false};
s.onselectstart=function(){return false}
}
if (window.addEventListener) a.addEventListener('DOMMouseScroll', function(event){TINY.scroller.wheel(event,a.id); return false}, false);
/** IE/Opera. */
a.onmousewheel = a.onmousewheel = function(event){TINY.scroller.wheel(event,a.id); return false};
a.l=b.offsetHeight-s.offsetHeight
},
/** Event handler for mouse wheel event.
*/
wheel: function (event,f){
var delta = 0;
if (!event) /* For IE. */
event = window.event;
if (event.wheelDelta) { /* IE/Opera. */
delta = event.wheelDelta/120;
} else if (event.detail) { /** Mozilla case. */
/** In Mozilla, sign of delta is different than in IE.
* Also, delta is multiple of 3.
*/
delta = -event.detail/3;
}
/** If delta is nonzero, handle it.
* Basically, delta is now positive if wheel was scrolled up,
* and negative, if wheel was scrolled down.
*/
if (delta) {
console.log(delta);
var a=T$(f), s=T$(a.s), c=T$(a.c); a.bcs=TINY.cursor.top(event); a.bct=parseInt(s.style.top);
var m = a.bct - delta;
if(m>=0&&m<a.l){
s.style.top=m+'px'; c.style.top=(m*-1*a.d)+'px'
}else if(m<0){
s.style.top=0; c.style.top=0
}else if(m>a.l){
s.style.top=a.l+'px'; c.style.top=a.m+'px'
}
}
/** Prevent default actions caused by mouse wheel.
* That might be ugly, but we handle scrolls somehow
* anyway, so don't bother here..
*/
if (event.preventDefault)
event.preventDefault();
event.returnValue = false;
},
st:function(e,f){
var a=T$(f), s=T$(a.s), c=T$(a.c); a.bcs=TINY.cursor.top(e); a.bct=parseInt(s.style.top);
if(a.mv){this.sp(f)}
a.mv=function(event){TINY.scroller.mv(event,f)};
a.sp=function(){TINY.scroller.sp(f)};
if(T$$$()){
document.attachEvent('onmousemove',a.mv); document.attachEvent('onmouseup',a.sp)
}else{
document.addEventListener('mousemove',a.mv,1); document.addEventListener('mouseup',a.sp,1)
}
if(a.d){s.className+=' '+a.n}
},
mv:function(e,f){
var a=T$(f), m=TINY.cursor.top(e)-a.bcs+a.bct, s=T$(a.s), c=T$(a.c);
if(m>=0&&m<a.l){
s.style.top=m+'px'; c.style.top=(m*-1*a.d)+'px'
}else if(m<0){
s.style.top=0; c.style.top=0
}else if(m>a.l){
s.style.top=a.l+'px'; c.style.top=a.m+'px'
}
},
sp:function(f){
var a=T$(f), s=T$(a.s); if(a.d){s.className=s.className.replace(' '+a.n,'')}
if(T$$$()){
document.detachEvent('onmousemove',a.mv); document.detachEvent('onmouseup',a.sp)
}else{
document.removeEventListener('mousemove',a.mv,1); document.removeEventListener('mouseup',a.sp,1)
}
a.mv=0;
}
}
}();
Or, just create a hidden scrollbar on the left, under your scrollbar!