I have a website built in Wordpress which is using the "BWL Knowledge Base Manager" plugin which provides an AJAX search bar.
Our SEO Manager has provided us with the following tracking script which needs to be triggered when someone enters a search string into the search bar:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'search'
'Dlv-Search': 'ger', //recorded under “s”
});
</script>
(Where, obviously, 'ger' is to be replaced with whatever the user has entered into the search field).
It turns out that I have very little idea of how to implement this. Can anyone point me in the right direction here?
This code looks more intimidating than it is. You should be able to add it straight to your search bar, perhaps on the keydown or onchange events. It may be cleaner if you wrap it in a function though.
<script>
function SO_64130617_search( el, e ){
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'search'
'Dlv-Search': el.value,
});
}
</script>
Then just add that function to your input on whatever event you want to handle it on:
<input type="search" id="your-search" onchange="SO_64130617_search(this,event);" />
Edit:
Since you're unable to modify the HTML of the input, you should be able to bind an event handler to it instead. Check out this snippet:
var search = document.querySelector('#s');
if( search != null ){
search.addEventListener('change', function(e){
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'search',
'Dlv-Search': this.value,
});
console.log( window.dataLayer );
});
}
<input id="s" />
Run the snippet, and the change event will log the dataLayer variable as soon as you tab away or click. The change (onchange) events require you to leave the field. You may need to use keydown or keyup or something, but that can create a LOT of function calls, at which point you'd need to look at using a typing timeout or something.
Ah hah! So it appears that the plugin is somehow generating the search input field after the DOM is initially loaded. So this appears to have done the trick:
I have created the function (Thanks Xhynk for the suggestion):
function SO_64130617_search( el, e ){
console.log(el.value);
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'search',
'Dlv-Search': el.value,
});
}
And then I have added the following to my child-theme's footer.php file:
jQuery("#s").ready(function(){
console.log("I showed up");
jQuery("#s").change(function(){
SO_64130617_search(this,event);
});
});
So now it is waiting and checking to see when "#s" is actually ready before trying to do anything with it.
Related
Ok, I've looked at a lot of examples that don't really appear different from mine. I simply want to do something (right now, just an alert), when a checkbox changes (is clicked, or whatever). My code:
$(document).ready(
function () {
$('input:checkbox').bind('change', function() {
var id = $(this).attr("id").substring(5);
var skill = $("#skill" + id).val();
alert("you processed skill number " + skill);
})
}) ; // end doc ready
One thing that MAY be different from others is that I'm dynamically creating these checkboxes with another script included like this (without the "script" tags here):
<pre>src="jscript/skills_boxes.js" type="text/javascript" </pre> <br>
Currently that is ABOVE my 'problem' but I've had it below and my stuff still doesn't work. Is there some sort of timing issue here? I'd appreciate any help. Thanks.
Use jquery on function.
$(document).ready(
function () {
$('body').on('change', 'input:checkbox', function() {
var id = $(this).attr("id").substring(5);
var skill = $("#skill" + id).val();
alert("you processed skill number " + skill);
})
}) ; // end doc ready
I have a page that is built around a wrapper with some very defined logic. There is a Save button on the bottom of the wrapped form that looks like this:
<form>
... my page goes here...
<input id="submitBtnSaveId" type="button" onclick="submitPage('save', 'auto', event)" value="Save">
</form>
This cannot change...
Now, I'm writing some javascript into the page that gets loaded in "...my page goes here...". The code loads great and runs as expected. It does some work around the form elements and I've even injected some on-page validation. This is where I'm stuck. I'm trying to "intercept" the onclick and stop the page from calling "submitPage()" if the validation fails. I'm using prototype.js, so I've tried all variations and combinations like this:
document.observe("dom:loaded", function() {
Element.observe('submitBtnSaveId', 'click', function (e) {
console.log('Noticed a submit taking place... please make it stop!');
//validateForm(e);
Event.stop(e);
e.stopPropagation();
e.cancelBubble = true;
console.log(e);
alert('Stop the default submit!');
return false;
}, false);
});
Nothing stops the "submitPage()" from being called! The observe actually works and triggers the console message and shows the alert for a second. Then the "submitPage()" kicks in and everything goes bye-bye. I've removed the onclick attached to the button in Firebug, and my validation and alert all work as intended, so it leads me to think that the propagation isn't really being stopped for the onclick?
What am I missing?
So based on the fact that you can't change the HTML - here's an idea.
leave your current javascript as is to catch the click event - but add this to the dom:loaded event
$('submitBtnSaveId').writeAttribute('onclick',null);
this will remove the onclick attribute so hopefully the event wont be called
so your javascript will look like this
document.observe("dom:loaded", function() {
$('submitBtnSaveId').writeAttribute('onclick',null);
Element.observe('submitBtnSaveId', 'click', function (e) {
console.log('Noticed a submit taking place... please make it stop!');
//validateForm(e);
Event.stop(e);
e.stopPropagation();
e.cancelBubble = true;
console.log(e);
alert('Stop the default submit!');
return false;
submitPage('save', 'auto', e);
//run submitPage() if all is good
}, false);
});
I took the idea presented by Geek Num 88 and extended it to fully meet my need. I didn't know about the ability to overwrite the attribute, which was great! The problem continued to be that I needed to run submitPage() if all is good, and that method's parameters and call could be different per page. That ended up being trickier than just a simple call on success. Here's my final code:
document.observe("dom:loaded", function() {
var allButtons = $$('input[type=button]');
allButtons.each(function (oneButton) {
if (oneButton.value === 'Save') {
var originalSubmit = oneButton.readAttribute('onclick');
var originalMethod = getMethodName(originalSubmit);
var originalParameters = getMethodParameters(originalSubmit);
oneButton.writeAttribute('onclick', null);
Element.observe(oneButton, 'click', function (e) {
if (validateForm(e)) {
return window[originalMethod].apply(this, originalParameters || []);
}
}, false);
}
});
});
function getMethodName(theMethod) {
return theMethod.substring(0, theMethod.indexOf('('))
}
function getMethodParameters(theMethod) {
var parameterCommaDelimited = theMethod.substring(theMethod.indexOf('(') + 1, theMethod.indexOf(')'));
var parameterArray = parameterCommaDelimited.split(",");
var finalParamArray = [];
parameterArray.forEach(function(oneParam) {
finalParamArray.push(oneParam.trim().replace("'","", 'g'));
});
return finalParamArray;
}
I have made a jQuery thing; with will load content without refreshing the page. The code for that is:
$(document).ready(function(){
// initial
$('#content').load('content/index.php');
// handle menu clicks
$('#navBar ul li ').click(function(){
var page = $(this).children('a').attr('href');
$('#content').load('content/'+ page +'.php');
return false;
});
});
Now I want to have a sort of history thing in that, the code for that is:
(function(){
// Bind an event to window.onhashchange that, when the hash changes, gets the
// hash and adds the class "selected" to any matching nav link.
$(window).hashchange( function(){
var hash = location.hash;
// Set the page title based on the hash.
document.title = 'The hash is ' + ( hash.replace( /^#/, '' ) || 'blank' ) + '.';
// Iterate over all nav links, setting the "selected" class as-appropriate.
$('#nav a').each(function(){
var that = $(this);
that[ that.attr( 'href' ) === hash ? 'addClass' : 'removeClass' ]( 'selected' );
});
})
// Since the event is only triggered when the hash changes, we need to trigger
// the event now, to handle the hash the page may have loaded with.
$(window).hashchange();
});
Found on: http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
My Question is: how can i make the second code working with the first?
Since you haven't gotten an answer yet I will write it. You need the plugin jQuery hashchange for the code to run.
https://github.com/cowboy/jquery-hashchange
To implement a cache you could do something like
$('#content').load('content/index.php');
//create a cache object
var cache = {};
// handle menu clicks
$('#navBar ul li ').click(function(){
var page = $(this).children('a').attr('href');
//check if the page was already requested
if(cache[page] === undefined){
//if not fetch the page from the server
$.get('content/'+ page +'.php', function(data){
$('#content').html(data);
//save data in cache
cache[page] = data;
}else{
//use data from cache
$('#content').html(cache[page]);
}
return false;
});
Use History JS. It works for HTML5 pushState and also falls back to HTML 4 hashtags. Also works for keeping the state model when the page is refreshed.
I don't think this is a Drupal-specific question, but more of a general jquery/ajax issue:
Basically, I'm trying to use javascript to add up form fields and display the result in a "subtotal" field within the same form. Everything is working fine until i click the option to add another field (via ajax), which then changes my "subtotal" field to zero, and won't work again until I remove the field.
Here is the function that adds up the fields:
function calculateInvoiceFields(){
var total = 0;
var rate = 0;
var quantity = 0;
var i = 0;
var $ = jQuery;
$("#field-aminvoice-data-values tr").each(function(){
// quantity field number
quantity = $("#edit-field-aminvoice-data-und-"+i+"-field-aminvoice-quantity-und-0-value").val();
// rate field as number
rate = $("#edit-field-aminvoice-data-und-"+i+"-field-aminvoice-rate-und-0-value").val();
if(!isNaN(quantity) && !isNaN(rate)){
total += quantity*rate;
}
i++;
});
return total;
}
And here are the functions that get fired for .ready and .live:
jQuery(document).ready(function(){
var $ = jQuery;
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
jQuery(function(){
var $ = jQuery;
$(".form-text").live('change', function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
});
Any ideas would be a big help. Thanks in advance!
I recommend using 'on' for any binding statement. and 'off' for unbinding.
The reason it doesn't work after an AJAX call, is because you need to be watching for that element to be added to the DOM, and an event attached to it after it gets loaded. If you load a new element in, and there is nothing watching for it, it won't add the event watch to that new DOM element.
As below:
function calculateInvoiceFields(){
/*..*/
return total;
}
$(document).ready(function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
$("body").on('change', ".form-text", function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
});
usually it stops working when an error has been thrown. did you check out your javascript console (firefox firebug, or built in for chrome) for any indication of an error?
hey guys,
I have an input field that looks for matched characters on a page. This page simply lists anchor links. So when typing I constantly load() (using the jquery load() method) this page with all the links and I check for a matched set of characters. If a matched link is found it's displayed to the user. However all those links should have e.preventDefault() on them.
It simply won't work. #found is the container that shows the matched elements. All links that are clicked should have preventDefault() on them.
edit:
/*Animated scroll for anchorlinks*/
var anchor = '',
pageOffset = '',
viewOffset = 30,
scrollPos = '';
$(function() {
$("a[href*='#']").each(function() {
$(this).addClass('anchorLink');
$(this).bind('click', function(e) {
e.preventDefault();
//console.log('test');
anchor = $(this).attr('href').split('#')[1];
pageOffset = $("#"+anchor).offset();
scrollPos = pageOffset.top - viewOffset;
$('html, body').animate({scrollTop:scrollPos}, '500');
})
});
});
Well, I'm looking for all href's that contain a #. So I know those elements are anchors that jump to other elements. I don't want my page to jump, but rather scroll smoothly to this element with this specific #id.
This works fine when I use bind('click', ... for normal page-elements that have been loaded when the page is opened. It doesn't work for anchors that have been loaded via ajax! If I change the bind to live nothing does change for the ajax loaded elements - they still don't work. However normal anchors that have always been on the page are not triggering the function as well. So nothing works with live()!
When you say "it won't work" do you mean that your function is not been called or that you can not cancel out of the function? As far as I know you can not cancel out live events. With jQuery 1.4 you can use return false to cancel out live event propagation. Calling e.preventDefault() won't work.
Edit: right so this code should in principal work. What it still won't do is, it won't add the 'anchorLink' class to your new anchors. However if the clicks work then let me know and I will give you the right code to add the class too!
var anchor = '',
pageOffset = '',
viewOffset = 30,
scrollPos = '';
$(function() {
$("a[href*='#']").each(function() {
$(this).addClass('anchorLink');
});
$("a").live('click', function(e) {
if ($(this).attr("href").indexOf("#") > -1) {
e.preventDefault();
//console.log('test');
anchor = $(this).attr('href').split('#')[1];
pageOffset = $("#" + anchor).offset();
scrollPos = pageOffset.top - viewOffset;
$('html, body').animate({ scrollTop: scrollPos }, '500');
//nikhil: e.preventDefault() might not work, try return false here
}
});
});