Include Javascript made from plugin into html button - javascript

We have a plugin that generates a JavaScript file. We want to run/execute this js file from within a html button, e.g.:
<input type=button value="Open js" onclick="javascript:window.open('http://jira.bltelecoms.net:8080/s/en_UScyxsyn/664/8/1.0.23-beta/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?collectorId=e125274b','_self')" />
We use an third party web application called Jira and Confluence, part of the Atlassian suite. It's issue tracking software and it uses a plugin to create this JavaScript file which pops up a window, similar to a lightbox, in which you can fill in data and send it. By default it makes a trigger on the side of the page, how ever we want to execute this from a standard html button. Is there a way do do this?

You could make a new page which includes the script and open this page on click.
Or how about this:
function loadScript() {
var s = document.createElement('script');
s.src = "http://jira.bltelecoms.net:8080/s/en_UScyxsyn/664/8/1.0.23-beta/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?collectorId=e125274b";
document.body.appendChild(s);
}
onclick="loadScript();"

I know that this is an old topic, but please see the following link:
https://confluence.atlassian.com/display/JIRA/Advanced+Use+of+the+JIRA+Issue+Collector#AdvancedUseoftheJIRAIssueCollector-Addingthecustomtriggerfunctionmanually
This shows how to set custom triggers for JIRA issue collectors. You will need a function to extend the global object ATL_JQ_PAGE_PROPS like below (jquery must be available).
window.ATL_JQ_PAGE_PROPS = $.extend(window.ATL_JQ_PAGE_PROPS, {
// ==== custom trigger function ====
triggerFunction : function( showCollectorDialog ) {
$('#feedback-button').on( 'click', function(e) {
e.preventDefault();
showCollectorDialog();
});
// add any other custom triggers for the issue collector here
}
});
So clicking on a DOM element with id="feedback-button" (or whatever other id you want to give it) will trigger your issue collector script.
Bear in mind the issue collector will need to specify a "Custom" trigger. You can do this by editing it in JIRA.
Hope this helps

Related

Refactoring inline <script> elements when using Turbolinks 5

I migrated my application to Ruby on Rails 5 (v5.2.2) and I'm trying to use Turbolinks 5 (v5.2.0).
In my application I have view files that include <script> elements and I would like to make them to properly work with Turbolinks (whose documentation states to avoid script elements and use the turbolinks:load event instead). What I have to make?
That is, for example, I have:
# app/views/.../_partial_template.html.erb
<script type="text/javascript">
$(document).ready(function () {
$.ajax({...})
});
// Note: I tried to use $(document).on('turbolinks:load', function() {...});
// and it seems that the JS code runs twice (or more) on every page load.
// I also tried to use <script type="text/javascript" data-turbolinks-eval="false">...</script>
// without success.
</script>
How should I refactor the above code to make it to properly work with Turbolinks?
Bonus:
The Turbolinks documentation says: You can use inline body scripts to set up per-page JavaScript state or bootstrap client-side models. What do they mean with "per-page JavaScript state" and "bootstrap client-side models"?
If your inline scripts are included at the bottom of the <body> (or if they don't immediately manipulate the DOM), then you might be able to remove your code from the $(document).ready… function, and have them work as expected.
Inline scripts are generally discouraged because traditionally they have indicated that the code will only run on the page that it's included on, and that any event listeners will be automatically destroyed when the user navigates away. However, in Turbolinks apps this isn't the case. If you add an event listener in an inline script (and don't remove it), it will continue to listen and run on subsequent page loads. As you found by setting up a turbolinks:load event listener in this way, the handler triggered on subsequent page loads, and on revisiting the first page, the event listener was added again, resulting in duplicate calls.
Regarding setting up "per-page JavaScript state" and "bootstrap client-side models", let's say you have a calendar page that you wish to enhance with some JavaScript. You might have a Calendar JavaScript class which handles this, so you could include the following to bootstrap it with some JSON:
<script>new Calendar(<%= #calendar.to_json %>)</script>
(bearing in mind that any added event listeners set up within the Calender class should probably be destroyed at some point e.g. turbolinks:before-cache).
That demonstrates the idea, but a better approach in this case might be to set up a system that looks for calendar elements and in the DOM then instantiates them. For example:
<div data-component="calendar" data-props="<%= #calendar.to_json %>">…</div>
then in your JavaScript (included in an application bundle):
;(function () {
var calendar
$(document).on('turbolinks:load', function () {
var $el = $('[data-component=calendar]')
if ($el.length) calendar = new Calender($el.data('props'))
})
$(document).on('turbolinks:before-cache', function () {
if (calendar) {
calendar.destroy() // to teardown any event listeners etc
calender = null
}
})
})()
This approach can be generalised and I've walked through one implementation here: https://stackoverflow.com/a/44057187/783009
Hope that helps!

How to make GTM Tags wait for some jQuery to be loaded?

I would like to track if a toast (or any "popup element") gets displayed using Google Analytics Event Tracking via GTM.
Whether or not the toast gets displayed is defined by jQuery code and based on cookie information like so
function ShowToast(Msg){
$('#toast-msg').html(Msg);
$('#toast').animate({ left: '-10px' });
}
called by
<script type="text/javascript">
$(function() {
ShowToast("SOME HTML");
});
</script>
This is what I got in GTM so far using a custom variable
function(){
if(document.querySelector("#toast #toast-msg").length > 0){
return true;
}
}
with a trigger listening for this variable to be true and the usual Universal Analytics Event Tag. The idea is to simply check if the toast-msg is shown or not, which works fine in preview mode.
Now to the problem: The tag is listening to gtm.js (pageview), but the jQuery code from the toast might load only after gtm.js is ready. Hence, sometimes the toast is not yet displayed when the tracking code is ready to fire and the event is not recorded.
Is there a way to use GTM and Javascript / JQuery to make sure all JQuery is loaded before GTM variables/triggers/tags are resolved? Or a completly different approach?
Make Sure you have the dataLayer initialized in the <head> of your document by including this line of code: <script>window.dataLayer = window.dataLayer || [];</script>
Add this code to your jQuery toasts (or whatever else you want to track) dataLayer.push({'event': 'event_name'});
Create a Custom Event trigger in GTM with the event_name you chose above.
Create a GA Tag of type event with the above trigger
One method is to push an event to dataLayer when the popup is loaded.
the other method is you can fire your code and gtm.dom or gtm.load(when the page is completely loaded)
Check the related article for more details http://marketlytics.com/analytics-faq/control-gtm-tags-to-wait
While using the dataLayer works, as suggested by others, I also found that my code works using two alterations:
Change errenous code: document.querySelector("#toast #toast-msg").innerHTML.length > 0 I forgot the innerHTML attribute
In order to ensure that jQuery has loaded I changed the trigger type to gtm.dom, which triggered the event reliably thus far.

Fire a Javascript function after submitting a Gravity Form

I have a multi-page form where the url remains the same when moving between pages.
I am trying to change some HTML after the submit button has been clicked.
I can run this in the console and the result is as I want it.
How can I get this run after submit?
I've tried window.onload and document.onload functions but they are not working. I've also tried an onclick function but it seems moving to the next page stops this working?
var confirm = document.getElementById('gform_confirmation_message_14');
if(confirm) {
document.getElementsByClassName("entry-title")[0].innerHTML = "PAYE Worker";
}
Thanks
Perhaps the gform_page_loaded event? From the documentation it:
Fires on multi-page forms when changing pages (i.e. going to the next or previous page).
$(document).on('gform_page_loaded', function(event, form_id, current_page) {
// do stuff
});
There are a bunch of javascript events available, and if not this one, maybe another serves your purpose, e.g. gform_post_render.
I removed the Javascript completely and created a confirmation in Gravity Forms that redirects to a new page upon submission.
Created a title for this new page "PAYE worker"
Problem solved

Google Analytics does not track link click events

I am currently using analytics.js (the newer version of GA) and I am trying to track all types of events from my website, including when a user clicks on an anchor tag pointing to an external URL.
I am currently using this setup:
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-KEY-HERE', { 'alwaysSendReferrer': true, 'allowAnchor': true });
and I send the events when hitting a link like this:
$(document).on("click", ".anchor-class", function (event) {
label = //get data from anchor element here ...
ga('send', 'event', 'Link Clicked', 'Click Details', label);;
return;
}
});
and this does not send anything to GA (even though the event handler is calling the ga(send...) method).
How ever, if I use this exact technique for but with event.preventDefault(); at the beginning of the function, the event is sent and it appears in GA dashboard.
Is there some setting that I missed in order to make this work properly?
Use the hitCallback function:
$(document).on('click','a', function(event){
event.preventDefault();
var label = $(this).attr('href');
ga('send', 'event', 'Link Clicked', 'Click Details', label, {
'hitCallback': function(){
window.location.href = label;
}
});
});
As pointed out by Blexy, the correct way to do this is to use a hit callback. However, you also need to take into account that users may block Google Analytics using some privacy protection tool such as Ghostery, in which case the hit callback will never be executed. The following article explains how to implement this correctly:
http://veithen.github.io/2015/01/24/outbound-link-tracking.html
We currently had this issue and ported our analytics code off of the website and into GTM. Another issue is that we have hundreds of sites that cannot have the new code released to them to deprecate the on-page analytics, but we already had GTM on them.
We were able to find the jQuery events that were bound to the click event and write code in GTM that removes the jQuery event on those clicked buttons via the exact event handler. Then we were able to apply standard GTM click triggers and tags so we didn't get double eventing.
Assuming you can easily remove the code from the page the following should work great using GTM.
This will fire an event off to analytics when a user clicks a given element and it will make any navigation wait until the corresponding tags have finished firing first before letting the page navigate away.
GTM Implementation
This is the quick and standard way now with the newer GTM.
Pre-Setup
Variables
You will need access to the Click Element Built-In variable. You can enable this under Variables --> Configure --> Click Element.
Also enable the Page Path or Page URL Built-In variable. This is later used to help you determine which pages to run the trigger on.
It looks like you're trying to get some text off of the clicked element for the event. If so you should create a Custom JavaScript variable. This just gets the inner text of the element, but you could also get an attribute or whatever other data you're looking for at this step.
Name: Click Element - Inner Text
Variable Type: Custom JavaScript
Custom JavaScript: function() { return {{Click Element}}.innerText; }
Triggers
Create a new trigger
Trigger Type: Click - Just Links
Wait for Tags: Enable this, this is the magic you're looking for.
Max wait time: set this to what you feel is appropriate and if you can live with the possibility that you may loose some analytics for a better user experience. Imagine what the wait time may be for a 3G user on a mobile device. Is 5000ms enough, not enough, maybe 10000ms. The user probably understands their connection is bad.
Enable this trigger when all of these conditions are true:
NOTE: you should only run this on pages that you need to run it on. Google isn't very clear if there is a performance loss and their "Learn More" says nothing about it.
If you need this to run on all pages though, configure it like so:
Page Path matches RegEx .*
Otherwise you should write something like:
Page Path matches RegEx ^/path/my-page$ specific page
Page Path matches RegEx ^/path/my-page/.*
NOTE: I'm not sure if those regex are correct, I'm not sure if you'll get a path with a proceeding or appended forward slash / or if you need anchors - normally it's best to be explicit on anchors so you don't get any funny business.
This trigger fires on: Some Link Clicks
Fire this trigger when an Event occurs and all of these conditions are true. Choose one below that fits your needs and change it how you need it.
Click Element matches CSS selector a
or maybe something more specific?
Click Element matches CSS selector .container .calls-to-action a
maybe only on external links? Assuming all internal links are relevant pathing.
Click Element matches CSS selector a[href^="http"]
Tags
Create a new tag
Tag Type: Event
Category: Link Clicked
Action: Click Details
Label: {{Click Element - Inner Text}}
Google Analytics Settings: best to use these for reusability and consistency rather than manually setting them up.
Firing Triggers: The Link Clicking Trigger you created above.

Multiple jQuery document.read event handlers running in wrong order

I recently added a feature to our ASP.NET MVC web application. There's a page that is displayed when the user clicks on an item in a table. The page uses AJAX to display a partial view in a single div in the page's HTML. The partial view uses the Telerik Kendo UI to define and display dialogs and DropDownList controls. This is complicated in that the JavaScript imports are all on the View for the page, while the PartialView just builds the HTML to be displayed in the div.
The JavaScript I wrote on the page includes a jQuery document.ready event handler:
$(document).ready(
function () {
if ( $('#details-map').val() != '' )
$('#details-map').remove();
var urlTail = '?t=' + (new Date().getTime());
// Make the AJAX call and load the result into the details box.
$('#detailsbox').load('<%= Url.Action("Details") %>' + '/' + '<%: Model.Id %>' + urlTail, displayDetails);
}
)
This works fine when I run the application on my localhost. The problem appears when I deploy the page to our development server. In this case, there's an additional document.ready event handler that's emitted to very end of the page by the Telerik Kendo / ASP.net MVC extensions:
<script type="text/javascript">
//<![CDATA[
jQuery(document).ready(function(){
if(!jQuery.telerik) jQuery.telerik = {};
jQuery.telerik.cultureInfo=...;
});
//]]>
</script>
On this page, the $(document).ready event handler I wrote runs before the Telerik handler, and my code clearly depends on the Telerik handler running first. When mine runs first, I get a JavaScript error that says "jQuery.telerik.load is not a function'.
Since this does not happen on my localhost, how do I make sure that the second document ready event handler is run first?
Edit:
After more research, I've found that the problem is that the two scripts mentioned in my answer, which are supposed to be written to the page via the following line in the Master Page used by my page:
<%= Html.Telerik().ScriptRegistrar().Globalization(true).jQuery(false).DefaultGroup(group => group.Combined(false).Compress(false)) %>
Are not being loaded. In other words, the above line does nothing. It works on another page that uses the same Master Page, though. I've placed a breakpoint on the line and it is executing. Does anyone have any ideas?
You're either going to have to make it show up after the second one on the page OR do something I hate to suggest:
$(document).ready(function() {
function init {
/* all your code that needs to be run after telerik is loaded */
}
if ( $.telerik ) {
init();
} else {
setTimeout(function check4telerik() {
if ( $.telerik ) {
return init();
}
setTimeout(check4telerik, 0);
}, 0);
}
});
So, if $.telerik is loaded, it runs, otherwise it polls until it's set, and when it is set, it runs the code. It's not pretty, but if you don't have more control, it's probably your only option, unless $.telerik emits some kind of event that you can hook into.
After spending a few hours working on this, I finally got it to work. The problem turned out to be that two JavaScript files that are used by the Telerik DropdownList control and Window control were not being loaded.
In spelunking through the JavaScript on the page, I came across this script that was generated by Telerik:
if(!jQuery.telerik){
jQuery.ajax({
url:"/Scripts/2011.3.1306/telerik.common.min.js",
dataType:"script",
cache:false,
success:function(){
jQuery.telerik.load(["/Scripts/2011.3.1306/jquery-1.6.4.min.js","/Scripts/2011.3.1306/telerik.common.min.js","/Scripts/2011.3.1306/telerik.list.min.js"],function(){ ... });
}});}else{
jQuery.telerik.load(["/Scripts/2011.3.1306/jquery-1.6.4.min.js","/Scripts/2011.3.1306/telerik.common.min.js","/Scripts/2011.3.1306/telerik.list.min.js"],function(){ ... });
}
This script was emitted by a call to Html.Telerik.DropdownListFor() in my partial view. I'm guessing that the code to include for the two JavaScript files mentioned in the code, telerik.common.min.js and telerik.list.min.js, was not emitted since the call was on a partial view. Or I was supposed to include them all along & didn't know it (I'm very new to these controls). Oddly, everything worked when I ran it locally, so I don't get it.
In any case, I added two <script> tags to my View to include these files and everything started working. That is, I added the following tags to my page:
<script type="text/javascript" src="../../Scripts/2011.3.1306/telerik.common.min.js"></script>
<script type="text/javascript" src="../../Scripts/2011.3.1306/telerik.list.min.js"></script>
Live and learn.

Categories

Resources