Conflict between Pinterest and Fancybox - javascript

I have a page that has both Fancybox and a Pinterest pin button. Both seem to work as they should, but when I close the Fancybox overlay I see the following JavaScript error:
Uncaught TypeError: Cannot read property 'data-pin-aha' of null
My Pinterest button renders as this:
<span class="PIN_1354830754034_pin_it_button_count" id="PIN_1354830754034_pin_count_0"><i></i>3</span>
Just for fun, my Pinterest button is being loaded asynchronously with this:
(function () {
window.PinIt = window.PinIt || { loaded: false };
if (window.PinIt.loaded) return;
window.PinIt.loaded = true;
function async_load() {
var s = document.createElement("script");
s.type = "text/javascript";
s.async = true;
if (window.location.protocol == "https:")
s.src = "https://assets.pinterest.com/js/pinit.js";
else
s.src = "http://assets.pinterest.com/js/pinit.js";
var x = document.getElementsByTagName("script")[0];
x.parentNode.insertBefore(s, x);
}
if (window.attachEvent)
window.attachEvent("onload", async_load);
else
window.addEventListener("load", async_load, false);
})();
And my Fancybox link:
<span>Watch Our Story</span>
Overall it's a pretty basic setup. Just for kicks I used the normal inline script tag for Pinterest, but got the same error.
Has anyone ever seen this error and know how to fix it?

I had a similar issue with the Pinterest button. It turned out to be a problem with Pinterest's pinit.js script.
I’ve reported the issue to Pinterest (sign in required), and they’re looking at it.
We were using the Pinterest button on a page that had another link on it with a click event assigned. The link's HTML was, roughly speaking, like this:
<span>Select</span>
The click event handler was like this:
$('.youCanClickThis').click(function (e) {
$(this).html('Selected');
});
This click handler was somehow causing an error in pinit.js (Uncaught TypeError: Cannot read property 'data-pin-log' of null).
I unminified https://assets.pinterest.com/js/pinit.js in order to trace the error more easily. It was showing up in this function in the unminified pinit.js:
get: function (b, c) {
var d = null;
return d = typeof b[c] === "string" ? b[c] : b.getAttribute(c)
},
Specifically, typeof b[c]. get() is called from getData(), and the value of b is passed straight through from whatever called getData(). That turned out to be this function:
click: function (b) {
if ((b = a.f.getEl(b || a.w.event)) && b !== a.d.b) {
if (!a.f.getData(b, "log")) b = b.parentNode;
This appears to fire whenever the user clicks on anything on a page that has a Pinterest button. The last bit - b.parentNode - is what caused us problems.
By that point, b has been assigned to the element that the click event originated on. In our case, that was the <span> inside the <a>. However, because our JavaScript replaced the contents of the <a> tag with text, the <span> was no longer part of the document, and thus no longer had a parentNode.
Thus b = b.parentNode caused b’s value to be null.
We worked around this by not removing the <span> from the document on click. However, it would be good if Pinterest could add a check to see if b.parentNode exists, or something.
(I don’t understand the Pinterest script well enough to know what the best fix would be, but it’s built with the assumption that the source of a click event will always have a parentNode, which, as this demonstrates, isn’t a safe assumption).

I'm getting the Uncaught TypeError: Cannot read property 'data-pin-log' of null error on that page.
A hacky way to fix the issue would be to add an afterShow event that adds the data-pin-log attribute to the close button
$(".watch").fancybox({
helpers: {
media: {}
},
afterShow: function(e){
$('.fancybox-close').attr('data-pin-log', false);
}
});
This would also work for the OP's problem by replacing data-pin-log with data-pin-aha

We were having the same issue using jQuery Modal. We solved the problem by adding an onHide handler that hid the modal window, waited a few seconds, and then deleted the modal window. Not the prettiest solution, but it worked.

Fix for this is pushing today; very sorry for the trouble. If you run into difficulties with pinit.js in the future, please let us know here:
https://github.com/pinterest/widgets/

Related

How to write into existing HTML window with JQuery from another window

When I add another window using var w = window.open("", "_blank"); , it shows as URL about:blank and I can write to its body with no problem. but at the end, looking at the sources it only has and there is nothing to work with.
If instead I use existing HTML file,var w = window.open("{some path}/Empy.html", "_blank"); All the $(w.document.body).append(... commands write somewhere else not inside the opened file.
Is there a promise I can use, to start writing to it only after the existing file finished rendering?
this will work in IE to, extended from this answer
function openindex(){
OpenWindow = window.open("http://www.htmlgoodies.com/beyond/javascript/article.php/3471221", "_blank");
myFunction = function(){
alert("hi")
window.document.write("<TITLE>Title Goes Here</TITLE>")
window.document.write("<BODY BGCOLOR=pink>")
window.document.write("<h1>Hello!</h1>")
window.document.write("This text will appear in the window!")
window.document.write("</BODY>")
window.document.write("</HTML>")
window.document.close()
}
OpenWindow[OpenWindow.addEventListener ? 'addEventListener' : 'attachEvent'](
(OpenWindow.attachEvent ? 'on' : '') + 'load', myFunction, false
);
}
in my example i overwrite the entire page since i dont know if it has jQuery nor i tried to target specific element, but that is the way to go.
p.s. the url is just random

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();
}
}
})

IE10 oninput event repeatedly triggered on redirection

I've been experiencing an odd problem with IE10 when redirecting the page on an 'oninput' event (with no equivalent issue when using Chrome). I've produced the most pared-down version of the code that still exhibits the problem, as follows:
<html>
<head>
<script type="text/javascript">
function onChangeInputText()
{
window.location.href = "oninput_problem.html"; // Back to this page.
}
</script>
</head>
<body>
<input type="text"
oninput="onChangeInputText()"
value="£"
/>
</body>
</html>
On my Windows 7 PC using IE10, this code when browsed to (either by double clicking or via Apache) repeatedly redirects as if the act of initialising the value of the input text box itself is generating an immediate 'oninput' event. However, when I change the initial input text box value from the '£' symbol to a letter 'A', the repeated redirection doesn't occur.
I first noticed this problem as part of a project I'm working on. In that case, the user's input should cause a delayed page refresh, which began repeatedly redirecting when I entered a '£' symbol. As I say, the above code is the most pared-down version I produced in trying to track what was causing the issue.
Does anyone else experience this using IE10? If so, can anyone explain why IE10 is behaving this way?
I've found the following that appears to indicate that this may be a bug in IE10:
social.msdn.microsoft.com: Event oninput triggered on page load
Also, there's a follow-up bug report (within the page linked to above):
connect.microsoft.com: onInput event fires on loading the page when input #value is non-ASCII
EDITED TO ADD: At the bottom of the page pointed to by the second link, there's what would seem to be an unhelpful reply from Microsoft stating that they are unable to reproduce the bug described, so it may be a while before the issue is fixed...
There's anoter bug report which is still open :
http://connect.microsoft.com/IE/feedback/de...
For anyone who might encounter this, you can use this "class" as an alternative to the onInput event.
const getFieldWatcherInstance = (function(watchedElement, onElementValueChange){
let intervalReference = null;
let lastValue = null;
if(!watchedElement instanceof Element) return new Error('watchedElement is not an HTML Element');
if(typeof onElementValueChange !== 'function') return new Error('onElementValueChange is not a function');
return {
toggleFieldWatching : function(){
if(intervalReference){
clearInterval(intervalReference);
intervalReference = null;
}
else{
intervalReference = setInterval(function(){
const currentValue = watchedElement.value;
if(lastValue !== currentValue){
onElementValueChange(currentValue);
lastValue = currentValue;
}
}, 100);
}
}
};
});
Set it up like this:
const myInputChangeWatcher = getFieldWatcherInstance(<**insert real element reference here**>, function(newValue){
console.log('The new value is: ' + newValue);
});
call myInputChangeWatcher.toggleFieldWatching() in the onfocus and onblur events of the input

userscript: I lost some JS?

I do not understand what's going on...
I have a simple userscript, that add couple DIVs, css styles and JS functions in the pages I visit
In particular, I have one DIV that trigger a JS function with a onClick listener - this function is a "toggle" function (display/hide an other DIV):
function togglegm(etat) {
if (etat = 'on') {
document.getElementById('greasemky').style.display = 'block';
document.getElementById('greasemkytoggle').innerHTML = '';
} else if (etat = 'off') {
document.getElementById('greasemky').style.display = 'none';
document.getElementById('greasemkytoggle').innerHTML = '';
}
}
var script2 = d.createElement('script');
script2.appendChild(d.createTextNode(togglegm));
(d.body || d.head || d.documentElement).appendChild(script2);
The DIV "greasemkytoggle" only contains a link with a onClick that trigger "togglegm('on'), and my objective is that when togglegm(on) is executed, the innerHTML of this DIV becomes a trigger for togglegm(off).
Now the weird part... when I click on my DIV greasemkytoggle, the function togglegm(on) is perfectly executed (greasemky is displayed), and the innerHTML is perfectly changed with a link for "togglegm(off)", BUT if I click again, then nothing happens.
I looked at the source code, and discovered that my JS function just disappeared (that's why nothing happened on the last click)! Now, there is an empty function replacing my togglegm():
<script>
scriptHolderArray1
</script>
Do you understand that kind of behaviour...?
I found nothing online for that kind of situation...
GreaseMonkey runs under a much more security conscience set of rules.
Attach the event listeners using the proper DOM3 (addEventListener) method.
It is never a good idea (in user scripts or general scripting) to assign Javascript through innerHTML.
It is never a good idea to use the "javascript:" pseudo-protocol.
The problems are etat = 'on' and etat = 'off'.
If you want to set values, use
etat = 'on'
etat = 'off'
If you want to compare, use:
etat == 'on'
etat == 'off'
Moreover, href="javascript:return(false);" throws an error on Firefox because there is a return outside a function (SyntaxError: return not in function). You should do href="javascript:void(0);", or return false at the end of the onclick event.
Anyway, I don't understand very well what you are doing here:
var script2 = d.createElement('script');
script2.appendChild(d.createTextNode(togglegm));
(d.body || d.head || d.documentElement).appendChild(script2);
You have a function togglegm loaded to browser's memory by a <script> element.
Then, you create a new <script> with that function and append it to the document, in order to load it to browser's memory again (I guess).
Why?

Changing Javascript Focus in onClick event?

Note: A possible solution needs only work in Firefox 3.0, my app doesn't allow access from IE! =)
I have a link that, when clicked, will display a lightbox to the user:
show lightbox
My problem is that when the lightbox is displayed, the focus remains on the link. So if the user presses the up or down keys, they end up scrolling the main document, not the lightbox that is displayed!
I've tried to set the focus to the lightbox element using code like this
function focus_on_lightbox() {
document.getElementById('lightbox_content').focus();
}
This works fine if I type it in the firebug console, but will not work if I include it at the end of the onclick snippet. It appears as though I can't change the focus away from the link from code executed inside the onclick event?
-- Update 1
I've tried something like this before
show lightbox
and I've modified function to add some debugging output, as follows
function focus_on_lightbox() {
console.log('hihi');
console.log(document.activeElement);
document.getElementById('lightbox_content').focus();
console.log(document.activeElement);
}
The output is as follows
hihi
<a onclick="closePopup();lightbox('apartment_detail','11619');focus_on_lightbox();return false;" href="#">
<a onclick="closePopup();lightbox('apartment_detail','11619');focus_on_lightbox();return false;" href="#">
So the focus before I did anything was on the link and after I tried to change the focus it still remained on the link?
Not sure if it matters, but I use ajax to load the lightbox, as follows
new Ajax.Updater(lightbox_content_id, url, {asynchronous:true, evalScripts:true, onLoading:show_lightbox_loading(), onComplete:focus_on_lightbox() });
I tried to set the focus after the ajax complete, but also, no luck.
What am I missing?
I've been trying to make a solution work that was suggested below by trying to set the focus, seeing if I succeeded by checking document.activeElement, if not, wait 100 milliseconds and try again. If I use the following function, it will work
function focus_on_lightbox() {
var seconds_waited = 0
pause(100);
var current_focus = document.activeElement
while (document.getElementById(lightbox_content_id) != current_focus && seconds_waited < 2000)
{
document.getElementById(lightbox_content_id).focus();
console.log(document.activeElement);
pause(100);
current_focus = document.activeElement
seconds_waited += 100;
}
}
However, if I remove the firebug debugging statment console.log, the function stops working!! I have no idea why this would be the case?? Why would outputting a variable to the firebug console affect weather focus is moved to the element or not? Does the console.log statement affect focus? perhaps by bringing the focus to the console debugging window?
I think your problem is calling your focus method after return false. your code should be like that :
<a href="#"
onclick="show_lightbox();focus_on_lightbox();return false;">
show lightbox
</a>
Here is the function that finally worked
function focus_on_lightbox(seconds) {
var seconds_waited
seconds_waited = seconds
document.getElementById(lightbox_content_id).focus();
seconds_waited += 100;
if (document.getElementById(lightbox_content_id) != document.activeElement && seconds_waited < 2000)
setTimeout("focus_on_lightbox(" + seconds_waited + ");", 100);
{
}
}
So why did console.log seem to affect setting the focus? Before I was using this function to pause between attempts of changing the focus.
function pause(milliseconds) {
var dt = new Date();
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}
This causes javascript to constantly be doing something and I think it wasn't giving the document time to render or update or something. The console.log seemed to break this lock and give the page a chance to change its focus.
When I changed approaches to using the timeout to pause between attempts, console.log was no longer needed!
Thanks bmoeskau for pointing me in the right direction.
In my experience, focus issues can sometimes be timing-related (e.g., focus() executes before the element is fully ready to be focused). I'm assuming that the lightbox markup is created dynamically when the show_lightbox function is called? If that's the case you could try adding a slight delay before attempting to focus to see if that's the issue, something like:
setTimeout("focus_on_lightbox();", 10);
Make the element focus itself. On the element's load event, set a timeout of a few ms and then call this.focus();
Else try jQuery.

Categories