silentScroll will be undone after page is loaded - javascript

After my jQuery mobile site is loaded, I like to scroll to the position of a div. Works using this code
function changeViewport(){
var errorMsg = $('.dataerror').first();
if(errorMsg != null) {
var newPosition = errorMsg.offset();
$.mobile.silentScroll(newPosition.top);
}
}
I call the function on $(document).ready, but after calling the function and silentScroll to the position it seems the framework autoscroll back to the top of the page... Anyone know how to prevent this behaviour? (I also tried events pageinit, pageshow...)
Do I have to overwrite a function or trigger another event? Any help or suggestion is welcome :)
cheers.

After struggling with this myself, I seem to have found the cause as well as a workaround. It appears that the animation used in changePage is taking precidence over the silent scroll. You can read more about this here. On the same page, the comments also begin to discuss different events, such as pagebeforeshow or pageaftershow - unfortunately these yielded no results for me.
The workaround I have found was to wrap the .silentScroll in a timeout of a half a second. It looks a bit choppy, but it seems to be working for me. Hope this helps.
Try This:
function changeViewport(){
var errorMsg = $('.dataerror').first();
if(errorMsg != null) {
var newPosition = errorMsg.offset();
setTimeout(function(){$.mobile.silentScroll(newPosition.top)}, 500);
}
}

Related

Why does jQuery.remove() remove mousedown listener from other div element?

I'm working on a HTML5 friendly drag and drop system and I've encountered another mystery that seems to make no sense...
The system is working in Edge - it's when I'm emulating IE8 that I encounter this latest problem.
I have a set of '.draggable' divs that get the following listener attached:
$(document).ready(function() {
$('#reset-button').click(resetDraggables);
if (!dragAndDropSupported()) {
var $draggables = $('.draggable');
$draggables.each( function (index) {
$(this).mousedown( jQueryStartDrag );
});
}
}
The draggables can be sent back to their original locations by hitting a 'reset' button. That all works fine.
The problem is - any divs that get sent back to their origins are no longer draggable. Even if I re-attach the listener in the reset function, it does not fire. Once again, this issue is only happening when I'm emulating IE8 and I don't remove the listener anywhere in my code.
function resetDraggables() {
if ( !$('#reset-button').hasClass('inactive') ) {
var $dropTargets = $('.drop-target');
$dropTargets.each(function (index) {
var draggableId = $(this).attr('data-contains');
var $originDraggable = $('#' + draggableId);
if ($originDraggable.attr('id')!=undefined) {
var $droppedDraggable = $(this).find('.draggable');
$droppedDraggable.remove();
$originDraggable.removeClass('inactive').addClass('draggable').attr('draggable', 'true').css('filter', 'alpha(opacity=100)').hide().fadeIn('fast');
$('#' + draggableId).mousedown( jQueryStartDrag );
$(this).removeClass('occupied').attr('data-contains', '');
$('#reset-button').addClass('inactive');
}
});
}
}
I've realised it's the $droppedDraggable.remove() line that's causing the problem. I'm not sure why a line to remove ONE object would remove the listener from another. The $droppedDraggable object was cloned from the other; Is that causing the issue?
Any ideas what might be going on?
OK, so I replaced the jQuery remove() lines with...
var droppedDraggable = document.getElementById('dropped-' + draggableId);
droppedDraggable.outerHTML = "";
...and that has done the trick. I'm guessing there must have been some hidden association made between the objects when one was cloned from the other and remove()ing one removed the mousedown listener from the other.
If anyone has a better theory, feel free to let me know, but this seems to have solved the problem.
Edit
I've just realised the above fixed the problem in IE8, but not in 9. Great! If anyone has any pointers on how NOT to include a bunch of browser-specific work arounds in my code, I'd be very keen to hear them. Thanks.

Firing a manual click event on an button in ember.js doesn't give the required result

TL;DR: Trying to fire a manual javascript click event on the chat button of twitch, won't send the message. Don't understand why the event doesn't do the same as a normal click and don't know how to make it work.
So I am trying to make a custom bot for twitch.tv, only reading his info from the HTML directly. I've got it perfectly working up to the point at where it can recognize commands and put text in the textbox. Now the problem I have is, as soon as I try to fire a manual click event on the "chat" button, it just doesn't seem to work. My guess is it has something to do with ember.js, and I frankly don't know anything about that. Anyway, here is the part of the code that doesn't work. EDIT: this works if I enter it as single in the console, doesn't work in context of the rest of my code though.
$('.send-chat-button').click();
What happens here is that I acquire a piece of html that contains the chat submit button, which is this:
<button class="button primary float-right send-chat-button" data-bindattr-3945="3945">
<span>
Chat
</span>
</button>
When I try to manually fire a click event on this, nothing happens. However, when I fire a manual click event on buttonContain.children[0] and buttonContain.children1 (which are, respectively, the settings and list of viewers buttons), it does work. They look like this:
<a data-ember-action="3943" class="button glyph-only float-left" title="Chat Settings"></a>
I'm guessing the difference is in the data-ember-action and the data-bindattr-*, but I don't know how to make it work. Anyone here knows why the click() event doesn't work and directly clicking does?
EDIT: If you have any questions about my question, feel free to ask.
EDIT2: I experimented a little more, and I can remove all HTML attributes from the button, and clicking on it will still work. I have no idea what is going on :(.
EDIT3: Okay, so it seems it only stops working when i remove the
Span within the button
Still no idea what is going on. (Yes, have also tried to fire the click event on the span)
EDIT4: As requested, here is all the code from my side. Note that I'm trying to click a button from twitch itself, of which ember side I do not own any code. This code is used by pasting it in the console on a twitch.tv stream and then starting it by calling initiateMessageProcessing. I'm sorry for the lot of hardcoded values, those are twitch' fields that I need. For now I'm just looking for a proof of concept.
var frequency = 5000;
var myInterval = 0;
var lastMessageId = 0;
function initiateMessageProcessing() {
if (myInterval > 0) {
clearInterval(myInterval);
}
myInterval = setInterval("checkMessages()", frequency);
}
function checkMessages() {
var chat = document.getElementsByClassName("chat-lines")[0];
processMessages(extractUnprocessedMessages(chat.children));
lastMessageId = parseInt(chat.lastElementChild.getAttribute("id").substring(5, 10));
}
function extractUnprocessedMessages(chat) {
var unprocessedMessages = [];
var chatId = 0;
for ( i = 0; i < chat.length; i++) {
chatId = parseInt(chat[i].getAttribute("id").substring(5, 10));
if (chatId > lastMessageId) {
unprocessedMessages.push(chat[i]);
}
}
return unprocessedMessages;
}
function processMessages(unprocessedMessages) {
var messageElement;
for ( i = 0; i < unprocessedMessages.length; i++) {
messageElement = unprocessedMessages[i].children[0].getElementsByClassName("message")[0];
if (messageElement != undefined && messageElement != null) {
if (messageElement.innerHTML.search("!test") !== -1) {
sendMessage('Hello world!');
}
}
}
}
function sendMessage(message) {
fillTextArea(message);
var button = $('.send-chat-button').get(0);
var event = new MouseEvent('click', {
bubbles : true
});
button.dispatchEvent(event);
}
function fillTextArea(message){
var textArea;
var chatInterface = document.getElementsByClassName("chat-interface")[0];
var textAreaContain = chatInterface.children[0];
textArea = textAreaContain.children[0].children[0];
textArea.value = message;
}
EDIT5: Eventlistener screenshot:
EDIT6: Edited source code to use $('.send-chat-button').click();
I have tried this, does not work in the current code, it does work if I manually fire this single command in the console when there is text in the chat. But sadly does not work in my code.
EDIT7: used Ember.run, still doesn't work.
EDIT8: used dispatchmouseevent, still doesn't work in context of code
It seems that the target site attaches event listeners without help of JQuery. If it is so, you cannot trigger it using jquery .click() method.
You can try directly mocking the browser event like this:
var button = $('.send-chat-button').get(0);
var event = new MouseEvent('click', {bubbles: true});
button.dispatchEvent(event);
This code will not work in IE8 and lower, but I guess it is not your case.
I know this post is quite old but I had been looking for an answer on this for a while and nothing really worked, after trying out A LOT of stuff I found it works when you focus the chatbox first then focus the button then triggering the click event!!! uuuhm yeah...
$('.chat_text_input').focus();
$('.send-chat-button').focus().trigger('click');
I have no idea why this works (and why it doesn't in any other way), but leaving any of the focusses out makes it fail or bug out.
Programmatically clicking a DOM element to make some action done is somewhat a wrong approach.
You should have define a method myAction() which will be called in two ways. First, from your ember action triggerMyAction() and second, after listening to a custom event, "myEvent".
Instead of $('.send-chat-button').click(); you will code $('something').trigger("myEvent") then.
Something like:
Em.Controller.extend({
myAction:function(){
//do your stuff
},
onMyEvent:function(){
$('something').on('myEvent',this.myAction);
}.on('didInsertElement'),
actions:{
triggerMyAction:function(){
this.myAction();
}
}
})

addEventListener to div element

I am trying to fire a script when the contents of a div are altered, specifically when a div receives the next set of results from a js loaded paginator.
I have this:
<script script type="text/javascript" language="javascript">
document.addEventListener("DOMCharacterDataModified", ssdOnloadEvents, false);
function ssdOnloadEvents (evt) {
var jsInitChecktimer = setInterval (checkForJS_Finish, 111);
function checkForJS_Finish () {
if ( document.querySelector ("#tester")
) {
clearInterval (jsInitChecktimer);
//do the actual work
var reqs = document.getElementById('requests');
var reqVal = reqs.get('value');
var buttons = $$('.clicker');
Array.each(buttons, function(va, index){
alert(va.get('value'));
});
}
}
}
</script>
This works well when the doc loads (as the results take a few seconds to arrive) but I need to narrow this down to the actual div contents, so other changes on the page do not fire the events.
I have tried:
var textNode = document.getElementById("sitepage_content_content");
textNode.addEventListener("DOMCharacterDataModified", function(evt) {
alert("Text changed");
}, false);
But the above does not return anything.
Can what I am trying to do be done in this way? If yes where am I going wrong?
Using Social Engine (Zend) framework with MooTools.
I did this in the end with a little cheat :-(
There is a google map loading on the page that sets markers to match the location of the results. So I added my events to the end this code namely: function setMarker() {}.
I will not mark this as the correct answer as it is not really an answer to my question, but rather a solution to my problem, which is localised to the Social engine framework.
I will add a Social engine tag to my original question in the hope it may help someone else in the future.
Thanks guys.

Flickering mousenter mouseleave with delay, button list

I have made a list(<p>) with buttons. When I move my mouse over them it's a 1,2 sec delay before my textbox are marked with yellow to show where I can write. When I move my mouse away they turn normal(white).
My problem is when I quickly hover my mouse over the buttons back and forth a lot of the textboxes gets marked.
I had hoped the 1,2 sec delay would have worked then but it doesn't. But it works if I move my mouse slowly in and out of the button.
Here is a fiddle to it: http://jsfiddle.net/Pota/Fj6E6/
Here is my JavaScript code
$(function () {
$("p.pRespRoleId").mouseenter(function () {
var timeOut = 1200;
$this = $(this);
$this.data("delay", setTimeout(function () {
mouseInRespRoleId();
}, timeOut)
);
})
.mouseleave(function () {
$this = $(this);
if ($this.next(mouseOutRespRoleId()).is(":visible")) {
clearTimeout($this.data("delay"));
mouseOutRespRoleId();
}
else {
$this.next("p.pRespRoleId").show();
}
});
});
and
function mouseInRespRole()
{
var txtInRespRole = document.getElementById("<%=txtRespRoleName.ClientID %>");
txtInRespRole.style.background = "#FFFF00";
if (document.getElementById('txtRespRoleName').value == '')
{
document.getElementById('txtRespRoleName').innerHTML = txtInRespRole;
return false;
}
}
function mouseOutRespRole()
{
var txtOutRespRole = document.getElementById("<%=txtRespRoleName.ClientID %>");
txtOutRespRole.style.background = "white";
if (document.getElementById('txtRespRoleName').value == '')
{
document.getElementById('txtRespRoleName').innerHTML = txtOutRespRole;
return true;
}
}
Your jsFiddle is surely confusing to me (I am not sure what you are trying to achieve - there is a tangible possibility that you are overcomplicating things). I hope I got your requirement right...
Anyway, I believe your logic was right, but there were some flaws in the implementation. So, here is a modified (and partially corrected) version of your jsFiddle, which does what (I believe) you were trying to achieve.
Your use of '$this.next(mouseOutRespRoleId()).is(":visible")' was sure the most confusing, so I removed it completely. (In case it was fulfilling some other, not obvious purpose, you'll have to provide a more detailed description.)
The main problem was that $this.next(mouseOutRespRoleId()).is(":visible") was never evaluating to true, thus never clearing the timer that called mouseInRespRoleId().
EDIT:
I updated my jsFiddle illustration so that it takes care of IE9's strange behaviour (a.k.a. bug (?)). It should work without flickering now.
Short explanation of the problem:
Aparantly, in IE9 the mouse-events generation has some "timing issues", so that when entering (mouseOver) and leaving (mouseOut) a component multiple times rapidly, sometimes the mouse-events order gets messed up. E.g.:
The following event sequence (i.e. actual events):
mouseOver -> mouseOut -> mouseOver
May produce the following (obviously wrong) javascript-event sequence (i.e. events triggered by JS-engine in IE9):
mouseOver -> mouseOver(!) -> mouseOut(!)
So, I added an extra clearTimeout($this.data("delay")) in the "mouseentered" handler-function, in order to clear any pending scheduled executions of "mouseInRespRoleId".
It does not work perfectly on IE9 (and probably previous versions of IE - not tested), but it is as good as it can get (afaik).
(NOTE: It still works as intended on other (non-buggy) browsers.)

iscroll scrollToElement not updating currPage variable

UPDATE:
I was able to get my scroller working as desired but I feel like I have hacked around the actual issue and would love it if anyone has a more solid answer, I've updated and noted in the snippets below the new jQuery I'm using.
I'm using iScroll-4 (http://cubiq.org/iscroll-4) for an iPad/Android web app, everything's working perfectly with the swipes and scrolling but I have a table of contents at the beginning of the app that allows users to jump to specific areas of the scroller --
I'm using the iScroll function scrollToElement(element, duration) in order to jump to the different areas. Also using scrollToPage(page, duration) to allow the user to manually navigate forward and backward one page at a time.
While watching the console logs the currPageX variable updates when I navigate with the scrollToPage function and when I swipe, but when using the scrollToElement the currPageX variable does not update.
Therefore if I jump to an element and then navigate forward with scrollToPage('next', 0) it will go backwards and navigate me to the next page after the table of contents.
I have tried using the scroll.refresh() function after scrollToElement, before, putting the function inside a timeout, etc. and I can't figure out why the currPageX is not updating.
Here's a snippet of the jQuery code that I'm using the two different functions:
// TO NAVIGATE FORWARD AND BACKWARDS
$('span.control').on('click', function() {
var slideDir = $(this).attr('data-dir');
if (slideDir == 'prev') {
var tehPg = tehScroll.currPageX-1;
} else if (slideDir == 'next') {
var tehPg = tehScroll.currPageX+1;
}
tehScroll.scrollToPage(tehPg, 0);
return false;
});
// TO JUMP FROM CONTENTS
$('li[data-page="toc"] span').on('click', function() {
var toPage = $(this).attr('data-page');
tehScroll.scrollToElement('li[data-page="'+toPage+'"]', 800);
// ADDED THE FOLLOWING LINE TO MANUALLY SET currPageX after scrolling!
tehScroll.currPageX = $('#slides li[data-page="'+toPage+'"]').index();
return false;
});
Did you consider using jquery-mobile-iscrollview widget plug-in? - there is a function scrollToPage(pageX, pageY, time), works well for me...
best
M

Categories