Set scrollLeft/scrollTop simultaneously does not work in Safari 6 - scroll

When setting the scrollTop and scrollLeft parameters in Safari 6 simultaneously, only one of both gets executed, scrolling the page only over one axis. This happens both using native JavaScript, jQuery and the jquery.scrollTo plugin.
Example using jQuery's .animate():
$('body').animate({
'scrollLeft': 100,
'scrollTop': 100
}, {
'duration': 500,
'easing': 'swing'
});
I've set up a demo page here: http://nabble.nl/demo/safari6scrollto/
All examples work fine in all major browsers as expected, in Safari 6 only example no. 4, 6 and 7 work.
Somehow, when loading the demo page in an IFRAME (see bottom of demo page), everything works just fine.
Is this a bug in Safari? If so, how to work around this issue? If not, what is causing it and how can this be resolved?
Other related reports:
https://github.com/flesler/jquery.scrollTo/issues/9
http://forum.jquery.com/topic/scrolltop-scrollleft-not-working-in-safari-6
http://bugs.jquery.com/ticket/12588

I needed to get the jquery.scrollTo plugin working on OSX Mountain Lion, and since I couldn't find the specifics on what is causing this behaviour, I put together a rather ugly workaround. It uses window.scrollTo(x, y) in the step function of jQuery's .animate(), which gives no problems in Safari 6:
var left;
$(window).animate({
'pageXOffset': 100,
'pageYOffset': 100
}, {
duration: 500,
easing: 'swing',
step: function(now, fx) {
if (fx.prop == 'pageXOffset') {
left = now;
} else if (fx.prop == 'pageYOffset') {
window.scrollTo(left, now);
}
}
});
Please note that the step function is called for every animated property, for every element the animation is applied on (in our case just 1: window). Hence the intermediate variable to store the current X position in the animation.
It uses the pageXOffset and pageYOffset properties of the window object, so I don't know how suitable this workaround is for animating the scrollLeft and scrollTop properties of non-window objects.
Anyway, it works for scrolling the entire document, which was all I wanted, and does so very smooth in Safari 6, too!

Related

Click somewhere on page to close items such as drop-down

Is it possible to click somewhere unspecific on a page?
I have the issue that a drop down becomes top level in the dom and all other elements are not visible anymore for cypress. A user probably simply clicks somewhere in order to close the dropdown. However, I fail with cypress. I can only click on the dropdown-element itself and since there are multiple items in the dropdown I have to even select one (not wanted)
I need something for cypress to click on something unspecific like:
root().click
or
cy.get('body div').click
These 2 are not working not even with force: true.
I had a similar issue and I used coordinates according to the Syntax
.click(x, y, options)
So you should be able to get the body and click on position x = 50, y = 50 or some other position outside the dropdown menu
cy.get('body').click(50, 50, { force: true })
If this does not work, you can try negative coordinates
cy.get('{{dropdown-menu-name}}').click(-50, 0, { force: true})
If this still does not work use .mousemove()
cy.get("{{dropdown-menu-name")
.trigger("mousemove", 50, 50)
.trigger("mousedown", {which : 1})
.trigger("mouseup", {which : 1})
but that seems excessive
{edit} 50 is the number of pixels to move. That is just an example. of course. Pick a number of pixels what works for your project.

PhaserJS: Visual guide for placing sprites when knowing the x and y

Is there some kind of Chrome addon or something for phaser to allow me to find out the x and y coordinates of where I wish to place sprites?
Right now, it's a guessing game. I have to use a number, reload the browser and then go to the point in the game (which might now be the beginning) and see if it's OK. Otherwise, repeat the process.
Is there anything better? A visual debugger or something similar?
I have tried using the standard Google Chrome dev tools, but I can't get access to the sprites inside the HTML canvas or WebGL.
if you don't have any action in the onClick callback, you can use something like this:
var text;
Jumper.Game.prototype = {
create: function() {
this.game.input.onDown.add(this.onTap, this);
},
onTap: function(pointer){
text = "x:"+parseInt(pointer.x)+" y="+parseInt(pointer.y);
},
render:function(){
this.game.debug.text(text || '--', 2, 14, '#00ff00');
}
}
or you can changethis.game.input.onDown.add(this.onTap, this); with this.game.input.addMoveCallback(this.onTap, this) for "live" position.

YUI3 FF retrieving selected option and its background-color property

I'm trying to set the background-color of a Select element to the background-color of it's selected Option like so:
YUI().use('selector-css3', 'node', function(Y) {
function set_color( e ) {
this.setStyle('backgroundColor',this.one('option:checked').getStyle('backgroundColor'));
};
Y.on(['available','change'], set_color, '#id_linkcolor');
});
Strangely this works perfectly in Chrome. In FF however it seems to always revert to a specific color. Even more weirdly, this:
this.setStyle('backgroundColor',this.get('options').item(3).getStyle('backgroundColor');
does seem to work. But when I use the selectedIndex to retrieve the selected option it doesn't work anymore.
Check it out here: http://jsfiddle.net/9sy02756/4/
Thanks!
UPDATE
I decided to approach this differently like this:
function set_color( e ) {
this.set('className','');
this.addClass( 'linkcolor_'+this.one('option:checked').get('value') );
};
This way the parent SELECT element just gets assigned the same class as the selected child OPTION and css takes care of the rest. Probably a cleaner solution anyway.
http://jsfiddle.net/9sy02756/6/
In your code, when you do this.one('option:checked').getStyle('backgroundColor'), YUI uses the window.getComputedStyle method.
In Firefox, getting the background color on an <option> returns the hover color, which turns out to be a very nice blue. And it will remains that way until you open the select again.
The only way around this is to store the color during <option>'s mouseenter event, and apply it during change. But mouseenter on <option> are only triggered in firefox, not chrome nor IE.
In the end you will need a mix of both approaches to get it right. So the question is answered, the mystery solved, but the alternative approach you proposed in the edit is way simpler.
YUI().use('node', 'selector-css3', function(Y) {
var lastColor;
function set_color(e) {
this.setStyle('backgroundColor', lastColor || this.one('option:checked').getStyle('backgroundColor'));
};
Y.on(['available', 'change'], set_color, '#id_linkcolor');
// For firefox, store computed color before default select blue is applied
Y.on("mouseover", function(e) {
lastColor = e.target.getStyle('backgroundColor');
}, '#id_linkcolor option');
});
http://jsfiddle.net/fxaeberhard/hy3okdph/

Unable to remove element loaded by AJAX

I am trying to remove an element on AJAX success which was loaded and attached to the document during a previous AJAX call.
My code looks something like this:
$("#jobs-table-body").on("click", ".one-rc-button", function() {
var ctx = $.parseJSON($(this).siblings(".context").html());
$("#one-rc-candidate-id").val(ctx.candidateId);
$("#one-rc-job-id").val(ctx.jobId);
var loader = $("#wrapper").loader();
$.post($("#one-rc-form").attr("action"), $("#one-rc-form").serialize(), function(result) {
loader.remove();
if(result.success) {
// This works and returns 1
alert($("#candidate-row-" + result.rejectedCandidateId).length);
// This doesn't seem to be doing anything
$("#candidate-row-" + result.rejectedCandidateId).remove();
} else {
//$("#one-jc-messages").html(result.error);
}
});
});
The elements .one-rc-button and #candidate-row-<candidateId> were loaded by a previous AJAX call and they are attached to the document as I can very well see them on my page.
Now, on click of the previously generated .one-rc-button, I trigger a second AJAX call (which works fine) and on result.success, I want to delete the #candidate-row-<candidateId> (which is within the previously generated parent element).
The alert works and returns 1. So I know for sure that the selector is fine and it is matching one unique element.
What I don't understand is why it is unable to remove the element from the page.
Observations
I use Firefox 10.0.2 where this problem is reproducible.
On IE 8, it works (element gets removed)
On debugging the script on Firebug, I can verify that I have got a handle to the right eleemnt.
Try using FireBug to set a breakpoint on that line so you can see exactly what it's getting from that selector. Ideally break up the statement first, like this:
var unwantedDiv = $("#candidate-row-" + result.rejectedCandidateId);
unwantedDiv.remove(); // <-- Set a breakpoint on this line
You can then look at the unwantedDiv variable in the watch pane on the right of the firebug debugger and see what it is, what methods it has/has not got etc. I would assume that you are not getting back exactly what you think you are, possibly because of how you attached the div after the previous AJAX call. More information about JavaScript debugging with FireBug here.
Another option is to turn on strict warnings in the firebug console and see if you get any 'undefined method' errors, which don't stop the show on FireFox, but just bounce you out of that function. Do you get an error in IE?
Solved it by a really ugly workaround. I am still not sure what causes this behaviour.
if(result.success) {
var removeThis = $("#candidate-row-" + result.rejectedCandidateId);
removeThis.remove();
removeThis = $("#candidate-row-" + result.rejectedCandidateId);
if(removeThis.length != 0) {
removeThis.remove();
}
}
Now it works on both Firefox and IE.

Jquery UI Slider - Input a Value and Slider Move to Location

I was wondering if anyone has found a solution or example to actually populating the input box of a slider and having it slide to the appropriate position onBlur() .. Currently, as we all know, it just updates this value with the position you are at. So in some regards, I am trying to reverse the functionality of this amazing slider.
One link I found: http://www.webdeveloper.com/forum/archive/index.php/t-177578.html is a bit outdated, but looks like they made an attempt. However, the links to the results do not exist. I am hoping that there may be a solution out there.
I know Filament has re-engineered the slider to handle select (drop down) values, and it works flawlessly.. So the goal would be to do the same, but with an input text box.
Will this do what you want?
$("#slider-text-box").blur(function() {
$("#slider").slider('option', 'value', parseInt($(this).val()));
});
Each option on the slider has a setter as well as a getter, so you can set the value with that, as in the example above. From the documentation:
//getter
var value = $('.selector').slider('option', 'value');
//setter
$('.selector').slider('option', 'value', 37);
UPDATE:
For dual sliders you'll need to use:
$("#amount").blur(function () {
$("#slider-range").slider("values", 0, parseInt($(this).val()));
});
$("#amount2").blur(function () {
$("#slider-range").slider("values", 1, parseInt($(this).val()));
});
You'll need to use Math.min/max to make sure that one value doesn't pass the other, as the setter doesn't seem to prevent this.
You were almost there when you were using the $("#slider-range").slider("values", 0) to get each value. A lot of jQuery has that kind of get/set convention in which the extra parameter is used to set the value.
I've done some work around the jQuery UI slider to make it accept values from a textbox, it may not be exactly what you were after but could help:
http://chowamigo.blogspot.com/2009/10/jquery-ui-slider-that-uses-text-box-for.html
$slider = $("#slider");
$("#amountMin").blur(function () {
$slider.slider("values", 0,Math.min($slider.slider("values", 1),parseInt($(this).val()) ) );
$(this).val(Math.min($slider.slider("values", 1),parseInt($(this).val())));
});
$("#amountMax").blur(function () {
$slider.slider("values",1,Math.max($slider.slider("values", 0),parseInt($(this).val()) ) );
$(this).val(Math.max($slider.slider("values", 0),parseInt($(this).val())));
});
I just used martin's code and updated the id to #slider also added the math.max as he suggested so the sliders won't overlap.

Resources