I have three URLs that return different JSON responses (say user mobiles, addresses and emails) being populated from different beans.
url='/mobile.do?username=x&password=y'
url='/email.do?username=x&password=y'
url='/address.do?username=x&password=y'
For the following autocomplete plugin (fcbkcomplete):
<script type="text/javascript">
$(document).ready(function(){
$("#mySelect").fcbkcomplete({
json_url: "?!!",
});
});
</script>
Now I want to use these URLs to populate and add data to a single field rather than three different fields. Hence, somehow I need to mix these URL or something like this.
I was wondering what is the best way for this? Can we set more than one URLs or something?
You could modify the plugin, by changing the function load_feed. This isn't tested, so might need some tweeking.
function load_feed(etext) {
counter = 0;
if (options.json_url_list && maxItems()) {
if (options.cache && json_cache_object.get(etext)) {
addMembers(etext);
bindEvents();
} else {
getBoxTimeout++;
var getBoxTimeoutValue = getBoxTimeout;
setTimeout(function () {
if (getBoxTimeoutValue != getBoxTimeout) return;
var count = 0;
var all_data = [];
var finished = function () {
if (!isactive) return; // prevents opening the selection again after the focus is already off
json_cache_object.set(etext, 1);
bindEvents();
};
for (var i = 0; i < options.json_url_list.length; i++) {
$.getJSON(options.json_url_list[i], {
"tag": xssDisplay(etext)
}, function (data) {
addMembers(etext, data);
count += 1;
if (count === options.json_url_list.length) finished();
});
}
}, options.delay);
}
} else {
addMembers(etext);
bindEvents();
}
}
Related
Overview
So I'm trying to take functionality from one part of Squarespace's Galapagos commerce template and add it to another but it's proving to be more difficult than I thought.
I need the image-swapping capability of the "Quick View" (example - mouse over any image and click Quick View ) to replace the column of full sized zoomable images in the "Product View" (example - you see this once you click on a product).
So I found the code for each section:
Product View
This code simply goes through each image in the array and spits it out with the id jsProductItemImages which allows it to be hovered and zoomed.
<div class="productitem-images" id="jsProductItemImages">
{.repeated section items}
{.image?}
<div class="productitem-image-zoom-wrapper sqs-image-zoom-area"><img data-load="false" class="productitem-image loading" {#|image-meta} /></div>
{.end}
{.video?}
{#|video}
{.end}
{.end}
</div>
Quick View
I'm not 100% on the logic here, but essentially it's grabbing the first image and making it a hover/zoomable primary image then listing the entire array of images beneath it as thumbnails. I read that the # symbol is the equivalent of saying this in javascript, but I don't get why it's being used to spit out only the first image in the array.
<figure class="ProductItem-gallery">
{.section items}
<div class="ProductItem-gallery-slides">
{.repeated section #}
{.image?}
<div class="ProductItem-gallery-slides-item" data-slide-index="{#index}"><img class="ProductItem-gallery-slides-item-image" data-load="false" {#|image-meta} /></div>
{.end}
{.video?}
{#|video}
{.end}
{.end}
</div>
{.end}
<div class="ProductItem-gallery-thumbnails">
{.if items.1}{.repeated section items}<div class="ProductItem-gallery-thumbnails-item"><img class="ProductItem-gallery-thumbnails-item-image" data-load="false" {#|image-meta} /></div>{.end}{.end}
</div>
</figure>
Associated JS
First off, it should be noted that I went through and console logged every function to see what was giving the Quick View it's functionality - to no avail. Which is subsequently why I'm here. So it's easy to see where the zoom function is originating: the Product View in the Galapagos.ProductItem function on line 103 $imageContainer = Y.one('#jsProductItemImages');
But I don't see anything out of the ordinary pop up when I look at the Quick View. I've got to be missing something!
var Galapagos = {};
Y.use('node', function(Y) {
Galapagos.Site = (function(){
console.log("Galapagos.Site");
var $productPage;
function init() {
console.log("Galapagos.Site init()");
$productPage = Y.one('.collection-type-products');
if( $productPage && $productPage.hasClass('view-list') ) Galapagos.ProductList.init();
if( $productPage && $productPage.hasClass('view-item') ) Galapagos.ProductItem.init();
addDesktopTouchscreenClass();
addMediaQueryBreakpointClass();
bindEventListeners();
}
function addDesktopTouchscreenClass() {
console.log("Galapagos.Site addDesktopTouchscreenClass()");
if (Y.one('html').hasClass('touch')) {
var mousemoveDetection = Y.on('mousemove', function(){
Y.one('body').addClass('galapagos-desktop-touchscreen');
mousemoveDetection.detach();
});
}
}
function addMediaQueryBreakpointClass() {
console.log("Galapagos.Site addMediaQueryBreakpointClass()");
if( document.documentElement.clientWidth <= 724 ) {
if (Y.one('.catnav-container')) Y.one('.nav-container').prepend(Y.one('.catnav-list'));
Y.one('html').addClass('tablet-breakpoint-mixin');
} else {
if (Y.one('.catnav-container')) Y.one('.catnav-container').prepend(Y.one('.catnav-list'));
Y.one('html').removeClass('tablet-breakpoint-mixin');
}
}
function bindEventListeners() {
console.log("Galapagos.Site bindEventListeners()");
Y.on('resize', addMediaQueryBreakpointClass);
}
function getDocWidth() {
console.log("Galapagos.Site getDocWidth()");
return Y.one(document).get('docWidth');
}
function getDocHeight() {
console.log("Galapagos.Site getDocHeight()");
return Y.one(document).get('docHeight');
}
return {
init:init,
getDocWidth: getDocWidth,
getDocHeight: getDocHeight
}
}());
Galapagos.TweakListener = (function(){
console.log("Galapagos.TweakListener");
function listen(tweakName, callBack) {
if (Y.Global) {
Y.Global.on('tweak:change', Y.bind(function(f){
if ((f.getName() == tweakName) && (typeof callBack === 'function')) {
callBack(f.getValue());
}
}));
}
}
return {
listen:listen
}
}());
Galapagos.ProductItem = (function(){
console.log("Galapagos.ProductItem");
var cat;
var $imageContainer;
var $images;
var imageZoomInstances = [];
function init() {
console.log("Galapagos.ProductItem init()");
cat = Y.QueryString.parse(location.search.substring(1)).category;
$imageContainer = Y.one('#jsProductItemImages');
$images = $imageContainer.all('img[data-src]');
if ( cat ) setCatCrumb();
loadProductDetailImages();
bindEventListeners();
bindTweakListeners();
buildProductDetailImagesLightbox();
}
function bindEventListeners() {
console.log("Galapagos.ProductItem bindEventListeners()");
Y.on('resize', function(){
loadProductDetailImages();
});
}
function setCatCrumb() {
console.log("Galapagos.ProductItem setCatCrumb()");
var $catCrumb = Y.one('#jsCategoryCrumb');
var $catCrumbLink = $catCrumb.one('a');
var catCrumbHref = $catCrumbLink.getAttribute('href');
//var $mobileCatCrumbLink = Y.one('#jsMobileCategoryCrumb');
$catCrumbLink.set('text', cat).setAttribute('href', catCrumbHref + '?category=' + encodeURIComponent(cat));
//$mobileCatCrumbLink.setAttribute('href', catCrumbHref + '?category=' + encodeURIComponent(cat));
$catCrumb.removeClass('galapagos-display-none');
}
function loadProductDetailImages() {
console.log("Galapagos.ProductItem loadProductDetailImages()");
var imageZoomEnabled = Y.one('.tweak-product-item-image-zoom-enabled');
$images.each(function(image) {
ImageLoader.load(image.removeAttribute('data-load'), { load:true });
if (imageZoomEnabled) {
image.on('load', function() {
instantiateImageZoom(image);
});
}
});
}
function instantiateImageZoom(image) {
console.log("Galapagos.ProductItem instantiateImageZoom()");
imageZoomInstances.push(new Y.Squarespace.ImageZoom({
host: image.get('parentNode'),
behavior: 'hover',
zoom: parseFloat(Y.Squarespace.Template.getTweakValue('tweak-product-item-image-zoom-factor'))
}));
}
function destroyImageZoomInstances() {
console.log("Galapagos.ProductItem destroyImageZoomInstances()");
if (!imageZoomInstances || imageZoomInstances.length < 1) {
return;
}
Y.Array.each(imageZoomInstances, function(zoomInstance){
zoomInstance.destroy(true);
});
}
function buildProductDetailImagesLightbox() {
console.log("Galapagos.ProductItem buildProductDetailImagesLightbox()");
if ($images.size() >= 1 ) {
var lightboxSet = [];
$images.each(function(image) {
lightboxSet.push({
content: image
});
});
// Only show controls for size > 1
var hasControls = $images.size() > 1;
$imageContainer.delegate('click', function(e) {
var lightbox = new Y.Squarespace.Lightbox2({
controls: {
previous: hasControls,
next: hasControls
},
set: lightboxSet,
currentSetIndex: $images.indexOf(e.target)
});
lightbox.render();
}, 'img', this);
}
}
function bindTweakListeners() {
console.log("Galapagos.ProductItem bindTweakListeners()");
if (Y.Global) {
Y.Global.on('tweak:close', function() {
if (Y.one('.collection-type-products.view-item')) {
destroyImageZoomInstances();
if (Y.one('.tweak-product-item-image-zoom-enabled')) {
$images.each(function(image){
instantiateImageZoom(image);
});
}
}
}, this);
}
}
return {
init:init
}
}());
Galapagos.ProductList = (function(){
console.log("Galapagos.ProductList");
var $catNav,
$productGrid,
$productGridOrphans,
$productGridImages,
$orphanProducts,
productCount,
maxGridUnit,
orphanProductCount,
isGridBuilt;
function init() {
console.log("Galapagos.ProductList init()");
$catNav = Y.one('#jsCatNav');
$productGrid = Y.one('#jsProductGrid');
$productGridOrphans = Y.one('#jsProductGridOrphans');
if (!Y.UA.mobile && Y.one('.show-alt-image-on-hover:not(.product-info-style-overlay)')) {
$productGridImages = $productGrid.all('img[data-src]');
} else {
$productGridImages = $productGrid.all('img.productlist-image--main[data-src]');
}
productCount = $productGrid.all('.productlist-item').size();
maxGridUnit = 8;
orphanProductCount;
isGridBuilt = false;
bindEventListeners();
bindTweakListeners();
if($catNav) setActiveCategory();
if(Y.one('body').hasClass('product-grid-style-organic')) {
buildGrid();
} else {
$productGrid.removeClass('loading').removeClass('loading-height');
loadGridImages($productGridImages);
}
}
function bindEventListeners() {
console.log("Galapagos.ProductList bindEventListeners()");
Y.on('resize', function(){
loadGridImages($productGridImages);
});
}
function buildGrid() {
console.log("Galapagos.ProductList buildGrid()");
for (var i = maxGridUnit; i > 0; i--) {
orphanProductCount = productCount % i;
if(productCount <= maxGridUnit || i > 4) {
if(0 === orphanProductCount) {
$productGrid.addClass('item-grid-' + i);
isGridBuilt = true;
break;
}
} else {
if(0 === productCount % 9) { // if productCount is a multiple of 9, use the 9-grid. we use 9-grid only for multiples of 9 because 8-grid looks more interesting.
$productGrid.addClass('item-grid-' + 9);
} else { // otherwise, use the 8-grid and put the remainder into the orphan div
$productGrid.addClass('item-grid-' + maxGridUnit);
$orphanProducts = Y.all('.productlist-item').slice((productCount % maxGridUnit) * -1);
$productGridOrphans
.append($orphanProducts)
.addClass('item-grid-' + productCount % maxGridUnit);
}
isGridBuilt = true;
break;
}
}
if(isGridBuilt) {
$productGrid.removeClass('loading').removeClass('loading-height');
loadGridImages();
}
}
function setActiveCategory() {
console.log("Galapagos.ProductList setActiveCategory()");
var catNavItemCount = $catNav.all('.catnav-item').size();
for (var i = catNavItemCount - 1; i > 0; i--) {
var $item = $catNav.all('.catnav-item').item(i);
var $link = $item.one('.catnav-link');
var category = Y.QueryString.parse(location.search.substring(1)).category;
var href = Y.QueryString.parse($link.getAttribute('href').substring(2)).category;
if(category && href && category === href) {
$item.addClass('active-link');
}
else if(!category) {
$catNav.one('#jsCatNavRoot').addClass('active-link');
}
}
}
function loadGridImages() {
console.log("Galapagos.ProductList loadGridImages()");
$productGridImages.each(function(image) {
ImageLoader.load(image.removeAttribute('data-load'), { load: true });
image.on('load', function(){
if (image.hasClass('productlist-image--main.has-alt-image')) {
image.siblings('.productlist-image--alt').removeClass('galapagos-hidden');
}
});
});
}
function bindTweakListeners() {
console.log("Galapagos.ProductList bindTweakListeners()");
if (Y.Global) {
Y.Global.on(['tweak:beforeopen', 'tweak:close', 'tweak:reset'], function() {
setTimeout(function(){
Galapagos.ProductList.init();
}, 1000);
});
Y.Global.on(['tweak:beforeopen'], function() {
setTimeout(function(){
Galapagos.ProductList.init();
$productGrid.one('.productlist-item').addClass('is-hovered');
}, 1000);
});
Y.Global.on(['tweak:close'], function() {
setTimeout(function(){
Galapagos.ProductList.init();
$productGrid.one('.productlist-item').removeClass('is-hovered');
}, 1000);
});
}
Galapagos.TweakListener.listen('product-grid-style', function(value) {
if('Organic' === value) {
buildGrid();
} else {
$productGrid.append($orphanProducts);
loadGridImages();
}
});
Galapagos.TweakListener.listen('product-info-style', function(value) {
if('Overlay' === value) {
$productGrid.one('.productlist-item').addClass('is-hovered');
} else {
$productGrid.one('.productlist-item').removeClass('is-hovered');
}
});
Galapagos.TweakListener.listen('productImageAspectRatio', function(value) {
loadGridImages();
});
Galapagos.TweakListener.listen('productImageSpacing', function(value) {
loadGridImages();
});
}
return {
init:init
}
}());
Y.on('domready', function() {
Galapagos.Site.init();
});
});
My Attempts
My first few attempts have been dropping the jsProductItemImages div from the Product view and dumping in the entire figure block from the Quick View then updating the associated css. While it pulls in the images (I can see them in the inspector and they take up space on the page) it shows up as being blank.
I also tried only using the thumbnails section from the Quick View and limiting the Product View to only show the first image by using {.section items.0} but then any thumbnail I clicked wouldn't swap out without writing the script for it (obviously) but I didn't want to write something like that when I know it exists in the code already!
Any help would be greatly appreciated!
UPDATE:
After replacing the product view markup with the quick view markup I ran into these errors
Uncaught TypeError: Cannot read property 'all' of null site.js:104
init # site.js:104
init # site.js:17
(anonymous function) # site.js:432
_notify # common-2a739bf…-min.js:1479
notify # common-2a739bf…-min.js:1479
_notify # common-2a739bf…-min.js:1475
_procSubs # common-2a739bf…-min.js:1476
fireSimple # common-2a739bf…-min.js:1476
_fire # common-2a739bf…-min.js:1476
fire # common-2a739bf…-min.js:1489
_load # common-2a739bf…-min.js:1463
f # common-2a739bf…-min.js:1457
Unsure why it's hitting an error with .all because it should be addressing the same array of images in both situations?
There's a few questions buried in the this post but let me answer the Quick View question specifically since that's what you're looking to "fix".
Squarespace uses a modular system of JavaScript/CSS add-ons called "rollups". If you pull the source code you'll see a window object that contains the current configuration of any given page. When visiting a Products page, the system triggers the use of their quick view JS and accommodating CSS file. This is where you'll want to be looking. The JS you're digging into is not relevant to Quick View (I don't believe).
Quick View Rollup JS: http://static.squarespace.com/universal/scripts-compressed/product-quick-view-6a1e5642b473ebbb5944-min.js
Quick View Rollup CSS: http://static.squarespace.com/universal/styles-compressed/product-quick-view-eb4b900ac0155bed2f175aa82e2a7c17-min.css
These rollups are triggered off of JavaScript hooks in the template files. What you'll need to do is experiment with using the Galapagos product template word and word so it has the same classes and data-attributes, and see if that works. It would take far too long to cover all of the details of what you need to do without actually working on the project. I would start here first and see if you can setup your product template to triggers the Quick View JS as is, without customization.
With alot of help from #kalley we have found out that If I comment the following two lines out the LAG is gone!
var $tableContents = $table.find('tbody')
var $html = $('<tbody/>').html(data);
But how do I keep the above but cancel out the LAG ?
MORE INFO:
The code below works but the problem is that the $.GET is causing the browser to hang until the ajax request completes. I need (flow control?) or something that will solve this problem without locking/hanging up the browser until ajax completes the GET request.
The biggest LAG/Lockup/Hang is at $.get("updatetable.php", since the others only return 7 or less (number) values and this one ('updatetable.php') returns alot more (200-300kb). I would like to implement some sort of flow control here or make the script wait like 5 secs before firing the update command for tablesort and before showing the toast message so that ajax has time to GET the $.get("updatetable.php"data I just don't understand why does it lockup the browser as it is getting the data? is it trying to fire the other commands and that's whats causing the LAG?
Here are the STEPS
1.
$.get("getlastupdate.php" Will fire every 10 secs or so to check if the date and time are the same the return data looks like this: 20130812092636 the format is: YYYmmddHHmmss.
2.
if the date and time are not the same as the last GET then $.get("getlastupdate2.php" will trigger and this data will be send back and placed into a toast message and dispalyed to the user $().toastmessage('showNoticeToast', Vinfoo);
3.
before or after the above ($.get("getlastupdate2.php") another GET will fire: $.get('updatetable.php' this will GET the updated table info. and replace the old one with the new info. and then update/resort the table
4.
at the end of it all I want to $.get("ajaxcontrol.php" and this will return a 1 or 2 if the user is logged in then it will be a 2 else it's a 1 and it will destroy the session and log the user out.
<script type="text/javascript" src="tablesorter/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="tablesorter/final/jquery.tablesorter.js"></script>
<script type="text/javascript" src="tablesorter/final/jquery.tablesorter.widgets.js"></script>
<script type="text/javascript" src="tablesorter/final/toastmessage/jquery.toastmessage-min.js"></script>
<script type="text/javascript" src="tablesorter/qtip/jquery.qtip.min.js"></script>
<script type="text/javascript">
var comper;
function checkSession() {
return $.get("ajaxcontrol.php", function (DblIn) {
console.log('checking for session');
if (DblIn == 1) {
window.location = 'loggedout.php';
}
}).then(updateTable);
}
function checkComper() {
var SvInfo;
var onResponse = function (comperNow) {
if (comper === undefined) {
comper = comperNow;
} else if (comper !== comperNow) {
var Vinfoo;
comper = comperNow;
// returning this $.get will make delay done until this is done.
return $.get("getlastupdate2.php", function (primaryAddType) {
Vinfoo = primaryAddType;
$().toastmessage('showNoticeToast', Vinfoo);
}).then(checkSession);
}
};
$.get('getlastupdate.php').then(onResponse).done(function () {
tid = setTimeout(checkComper, 2000);
});
}
function updateTable() {
return $.get('updatetable.php', function (data) {
console.log('update table');
var $table = $("table.tablesorter");
var $tableContents = $table.find('tbody')
var $html = $('<tbody/>').html(data);
$tableContents.replaceWith('<tbody>' + data + '</tbody>')
//$tableContents.replaceWith($html)
$table.trigger("update", [true]);
var currentUrl = document.getElementById("frmcontent").contentWindow.location.href;
var urls = ['indexTOM.php', 'index1.php'],
frame = document.getElementById('frmcontent').contentDocument;
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
if (frame.location.href.indexOf(url) !== -1) {
frame.location.reload()
}
}
$('[title!=""]').qtip({});
});
};
$(function () {
var tid = setTimeout(checkComper, 2000);
$("#append").click(function (e) {
// We will assume this is a user action
e.preventDefault();
updateTable();
});
// call the tablesorter plugin
$("table.tablesorter").tablesorter({
theme: 'blue',
// hidden filter input/selects will resize the columns, so try to minimize the change
widthFixed: true,
// initialize zebra striping and filter widgets
widgets: ["saveSort", "zebra", "filter"],
headers: {
8: {
sorter: false,
filter: false
}
},
widgetOptions: {
filter_childRows: false,
filter_columnFilters: true,
filter_cssFilter: 'tablesorter-filter',
filter_filteredRow: 'filtered',
filter_formatter: null,
filter_functions: null,
filter_hideFilters: false, // true, (see note in the options section above)
filter_ignoreCase: true,
filter_liveSearch: true,
filter_reset: 'button.reset',
filter_searchDelay: 300,
filter_serversideFiltering: false,
filter_startsWith: false,
filter_useParsedData: false
}
});
// External search
$('button.search').click(function () {
var filters = [],
col = $(this).data('filter-column'), // zero-based index
txt = $(this).data('filter-text'); // text to add to filter
filters[col] = txt;
$.tablesorter.setFilters($('table.hasFilters'), filters, true); // new v2.9
return false;
});
});
</script>
Maybe instead of using setInterval, you should consider switching to setTimeout. It will give you more control over when the time repeats:
function checkComper() {
var SvInfo;
var onResponse = function (comperNow) {
if (comper === undefined) {
comper = comperNow;
} else if (comper !== comperNow) {
var Vinfoo;
comper = comperNow;
// returning this $.get will make delay done until this is done.
return $.get("getlastupdate2.php", function (primaryAddType) {
Vinfoo = primaryAddType;
$().toastmessage('showNoticeToast', Vinfoo);
}).then(checkSession);
}
};
$.get('getlastupdate.php').then(onResponse).done(function () {
tid = setTimeout(checkComper, 10000);
});
}
var tid = setTimeout(checkComper, 10000);
Then you can keep it async: true
Here's a fiddle showing it working using echo.jsontest.com and some fudging numbers.
Since the click event callback seems to be where the issue is, try doing this and see if it removes the lag (I removed other comments to make it more brief):
function checkSession() {
return $.get("ajaxcontrol.php", function (DblIn) {
console.log('checking for session');
if (DblIn == 1) {
window.location = 'loggedout.php';
}
}).then(updateTable);
}
function updateTable() {
return $.get('updatetable.php', function (data) {
console.log('update table');
var $tableContents = $table.find('tbody')
//var $html = $('<tbody/>').html(data);
//$tableContents.replaceWith($html);
// replaceWith text seems to be much faster:
// http://jsperf.com/jquery-html-vs-replacewith/4
$tableContents.replaceWith('<tbody'> + data + '</tbody>');
//$table.trigger("update", [true]);
var currentUrl = document.getElementById("frmcontent").contentWindow.location.href;
var urls = ['indexTOM.php', 'index1.php'],
frame = document.getElementById('frmcontent').contentDocument;
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
if (frame.location.href.indexOf(url) !== -1) {
frame.location.reload()
}
}
$('[title!=""]').qtip({});
});
};
$("#append").click(function (e) {
// We will assume this is a user action
e.preventDefault();
updateTable();
});
I commented out $table.trigger("update", [true]) since if you sort the table on the server before you return it, you shouldn't need to run that, which I'm almost certain is where the bottleneck is.
It is really hard untangle the mess you have but if what you want is ajax requests every 10 seconds it make sense to separate this logic from business logic over data from server.
Your code would also really benefit from using promises. Consider this example
$(document).ready(function() {
var myData = { }
, ajaxPromise = null
setInterval(callServer, 1000)
function callServer() {
ajaxPromise = updateCall()
.then(controlCall)
.done(handler)
.error(errorHandler)
}
function updateCall() {
return $.get('updateTable.php', function(data) {
myData.update = data
})
}
function controlCall( ) {
return $.get('ajaxControl.php', function(data) {
myData.control = data
})
}
function handler() {
console.dir(myData)
}
function errorHandler(err) {
console.log(err)
console.dir(myData)
}
})
I use a Greasemonkey script in Firefox to intercept a submit process in order to modify a certain post variable. I save the old submit routine to call it later and overwrite HTMLFormElement.prototype.submit with my interception (modification) function.
The problem I am currently facing is that something drops the post variable post=Submit and calling the (old) submit function after the modification takes me back to the current page.
var intercept_complete = false;
window.addEventListener('submit', function (e) {
e.stopPropagation();
e.preventDefault();
interceptor(e);
}, true);
function interceptor_setup() {
HTMLFormElement.prototype.real_submit = HTMLFormElement.prototype.submit;
HTMLFormElement.prototype.submit = interceptor;
}
function interceptor(e) {
var frm = e ? e.target : this;
if (!interceptor_onsubmit(frm)) {
return false;
}
if (!intercept_complete) {
ModifyAndPost(frm);
return false;
} else {
HTMLFormElement.prototype.real_submit.apply(frm);
return true;
}
}
function interceptor_onsubmit(f) {
return !f.onsubmit || f.onsubmit();
}
function ModifyAndPost(f) {
var attrs = new Array('name', 'type', 'value');
for (var i = 0; i < f.elements.length; i++) {
for (var a = 0; a < attrs.length; a++) {
if (attrs[a] == 'name') {
if (f.elements[i][attrs[a]] == "message") {
var current_message = f.elements[i][attrs[a + 2]];
if (current_message.indexOf("hello") != -1) {
var do_replace = confirm("Detected hello, would you like to replace that with bye?");
if (do_replace) {
f.elements[i][attrs[a + 2]] = current_message.replace("hello", "bye");
}
}
}
}
}
}
PerformSubmit(f);
}
function PerformSubmit(f) {
HTMLFormElement.prototype.real_submit.apply(f);
}
interceptor_setup();
Basically the script works and modifies the post variables successfully but when calling HTMLFormElement.prototype.real_submit.apply(f); to submit the modified form the request is missing the Post=Submit variable and the submit fails.
I tried removing e.stopPropagation() and e.preventDefault() and then it worked sometimes, but still dropped that post variable once in a while.
Would be great if anyone could point me in the right direction on this one. ;)
I am trying to modify the script below to click a button that looks like this on a site:
<button id="checkPrice-02070" onclick="checkPrice(02070,null); return false;" class="orangeDark">
<span>check price</span>
</button>
I am using the code below. So far, the page seems to keep reloading; nothing else happens.
Any advice to someone new?
(function () {
window.addEventListener("load", function (e) {
clickConfirmButton()
}, false);
})();
function clickConfirmButton() {
var buttons = document.getElementsByTagName('button');
var clicked = false;
for (var index = 0; (index < buttons.length); index++) {
if (buttons[index].value == "check price") {
buttons[index].click();
clicked = true;
break;
}
}
if (!clicked) {
setTimeout("window.location.reload()", 300 * 1000);
}
}
A <button>s value is not the visible text. You'd want to search textContent.
However:
If that sample HTML is correct, you'd be better off searching for ids that start with checkPrice. See the code below.
Are you sure you want to reload if the button is not found? If it is added by AJAX this is not the best approach. See this answer.
Don't use setTimeout with a string (to evaluate) argument like that. See the code below.
You do not need to wrap the code in an anonymous function.
Anyway, this should work, given the sample HTML:
window.addEventListener ("load", clickConfirmButton, false);
function clickConfirmButton (zEvent) {
var button = document.querySelector ("button[id^='checkPrice']");
if (button) {
button.click ();
}
else {
setTimeout (function () { location.reload(); }, 300 * 1000);
}
}
To check the button text anyway, use:
function clickConfirmButton (zEvent) {
var buttons = document.querySelectorAll ("button[id^='checkPrice']");
var clicked = false;
for (var index = 0, numBtn = buttons.length; index < numBtn; ++index) {
if (/check price/i.test (buttons[index].textContent) ) {
buttons[index].click();
clicked = true;
break;
}
}
if (!clicked) {
setTimeout (function () { location.reload(); }, 300 * 1000);
}
}
I have some jQuery plugin that changes some elements, i need some event or jQuery plugin that trigger an event when some text input value changed.
I've downloaded jquery.textchange plugin, it is a good plugin but doesn't detect changes via external source.
#MSS -- Alright, this is a kludge but it works:
When I call boxWatcher() I set the value to 3,000 but you'd need to do it much more often, like maybe 100 or 300.
http://jsfiddle.net/N9zBA/8/
var theOldContent = $('#theID').val().trim();
var theNewContent = "";
function boxWatcher(milSecondsBetweenChecks) {
var theLoop = setInterval(function() {
theNewContent = $('#theID').val().trim();
if (theOldContent == theNewContent) {
return; //no change
}
clearInterval(theLoop);//stop looping
handleContentChange();
}, milSecondsBetweenChecks);
};
function handleContentChange() {
alert('content has changed');
//restart boxWatcher
theOldContent = theNewContent;//reset theOldContent
boxWatcher(3000);//3000 is about 3 seconds
}
function buttonClick() {
$('#theID').value = 'asd;lfikjasd;fkj';
}
$(document).ready(function() {
boxWatcher(3000);
})
try to set the old value into a global variable then fire onkeypress event on your text input and compare between old and new values of it. some thing like that
var oldvlaue = $('#myInput').val();
$('#myInput').keyup(function(){
if(oldvlaue!=$('#myInput').val().trim())
{
alert('text has been changed');
}
});
you test this example here
Edit
try to add an EventListner to your text input, I don't know more about it but you can check this Post it may help
Thanks to #Darin because of his/her solution I've marked as the answer, but i have made some small jQuery plugin to achieve the same work named 'txtChgMon'.
(function ($) {
$.fn.txtChgMon = function (func) {
var res = this.each(function () {
txts[0] = { t: this, f: func, oldT: $(this).val(), newT: '' };
});
if (!watchStarted) {
boxWatcher(200);
}
return res;
};
})(jQuery);
var txts = [];
var watchStarted = false;
function boxWatcher(milSecondsBetweenChecks) {
watchStarted = true;
var theLoop = setInterval(function () {
for (var i = 0; i < txts.length; i++) {
txts[i].newT = $(txts[i].t).val();
if (txts[i].newT == txts[i].oldT) {
return; //no change
}
clearInterval(theLoop); //stop looping
txts[i].f(txts[i], txts[i].oldT, txts[i].newT);
txts[i].oldT = $(txts[i].t).val();
boxWatcher(milSecondsBetweenChecks);
return;
}
}, milSecondsBetweenChecks);
}