Magento jQuery Ajax search issue - ajax

I am trying to implement a customize Magento Advanced Search, using jQuery and Ajax.
The search works something like this:
1) There are 2/3 options to select size
2) 6 options to narrow down search result
3) A text box to enter keywords etc
There is no submit button, that means, search starts when user clicks on any size and/or Options or enter more than 3 char in search text box, search starts, an ajax request is sent to server.
If user clicks on another option or say type in another character, I use to abort previous search using search_request.abort() and set previous search to null.
When you search for first couple of times, it works fine, search returns result and if no result is found, proper message is displayed.But, after after couple of requests, it starts failing. Like if I click on options in short interval (I mean, search is fired frequently)). Some times, it fails without any reason and sometimes it fails, and when I click on the same option a couple of seconds later, it display the results.
Sometimes, when the search fails or there is no result.
It displays the incomplete message in result area like:
Where as it should look like :
Search when it returns result:
Search when it fails
My question is:
1) do you think it might be failing because too many requests are submitted too frequently? I mean is there something related to Magento settings?
2) What can I do to correct this?
Here is the jQuery code:
<script type="text/javascript">
function search(textfield)
{
j('#slides').html("<img src='<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB); ?>skin/frontend/luckybloke/luckybloke/images/ajax-loader.gif' class='no-results-found' style='width:100px !important; padding-top:10px !important;text-align:center;margin-left: 43%;' />");
var form = j("#form-validate");
var action = form.attr("action");
var fieldAdded = Array();
var searchData = '';
var searchVal = '';
var sizeSelected = '';
var searchArray = new Array();
var searchCtr = 0;
var tmp = new Array();
if(typeof search_request =='object' && search_request!=null){
search_request.abort();
search_request = null;
j('#slides').html("<img src='<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB); ?>skin/frontend/luckybloke/luckybloke/images/ajax-loader.gif' class='no-results-found' style='width:100px !important; padding-top:10px !important;text-align:center;margin-left: 43%;' />");
}
j('.input-search').each(function(index,domEle){
var eleID = "#"+j(domEle).attr("id");
var curEle= j(domEle).attr("name");
fieldAdded.push(curEle.replace('[]',''));
////consloe.log(eleID);
if((j(eleID).val()!='' || !jQuery.inArray(curEle,fieldAdded))&& eleID!='#name'){
if(searchVal==''){
searchVal=searchVal+j(eleID).val();
}
if(searchData==''){
searchData = searchData+""+curEle+"="+j(eleID).val();
}else{
searchData = searchData+"&"+curEle+"="+j(eleID).val();
}
searchArray[searchCtr] = j(eleID).val();
searchCtr++;
}
//add description field to search query
tmp[curEle] = j(eleID).val();
}
});
if(searchVal==''){
}
if(j("#name").val()=='brand, style, keyword'){
var val = '';
}else{
val = j("#name").val();
}
searchData = searchData+"&search_keywords="+val;
//toggleFields(sizeSelected, searchArray);
search_request = j.ajax({
type:'get',
url:action,
data:searchData,
cache: false,
dataType:'html',
success:searchComplete
});
return;
}
function searchComplete(responseText, statusText, xhr, $form)
{
var no_item_msg = 'No product found matching your search criteria.';
if(statusText=='success'){
var isFound = responseText.toString().search(new RegExp(/no items found/i));
//alert(isFound+''+responseText.toString());
if((isFound>0 || responseText.length == 0) && search_request ){
j("div#slides").html("<span class='no-results-found'>"+no_item_msg+"</span>");
// j("div#slides").html("<span class='no-results-found'>"+no_item_msg+"</span>");
/*j("div#lb-product-list").block({message:no_item_msg});
setTimeout('j("div#lb-product-list").unblock()', 2000);*/
}else{
var dataToFill = j("div#lb-product-list");
var isFound = responseText.toString().search(new RegExp(/JUST_ONE/i));
if(isFound>=0){
responseText = responseText.replace(/just_one/i,'');
}else{
j.getScript("<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB); ?>js/carousol.js", function() {});
}
dataToFill.html(j(responseText).children());
search_request = null;
}
//reset the css attribute's position value, as ui blocking seems to be affecting positioning of elements are unblocking
j("div#lb-product-list").css("position",'');
return true;
}
}
</script>

Related

How to show duplicates in a UI when searched in google sheets?

I am developing a tracking system for candidates
Attached a search button.
But I want a UI to pop up which will show the duplicates if present.
And when one of the duplicates is clicked, it will fill the required details in the form
I have made this.
But the results are the first row which matches the search text in B4
function Search()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("Form");
var dataS = ss.getSheetByName("Data");
var str = formS.getRange("B4").getValue();
var values = dataS.getDataRange().getValues();
var valuesFound = false;
for (var i = 0; i < values.length; i++)
{
var rowValue = values[i];
if (rowValue[0] == str) {
formS.getRange("B7").setValue(rowValue[0]) ;
formS.getRange("B9").setValue(rowValue[1]) ;
formS.getRange("B11").setValue(rowValue[2]) ;
formS.getRange("B13").setValue(rowValue[3]) ;
formS.getRange("E7").setValue(rowValue[4]) ;
formS.getRange("E9").setValue(rowValue[5]) ;
formS.getRange("E11").setValue(rowValue[6]) ;
formS.getRange("E13").setValue(rowValue[7]) ;
return;
}
}
if(valuesFound==false){
var ui = SpreadsheetApp.getUi();
ui.alert("No record found!");
}
}
Description
You could get all the first name matches and show them in a dialog, numbered so its easier to pick. Once the user picks the name you can fill out the form.
To use a dropdown and pick a name, that would require a custom dialog. Doable but more complex.
This script is executed from a menu item.
Data
Script
function search() {
try {
let spread = SpreadsheetApp.getActiveSpreadsheet();
let dataS = spread.getSheetByName("Data");
let str = "John";
let values = dataS.getDataRange().getValues();
let rowValue = values.filter( row => row[0] === str );
let ui = SpreadsheetApp.getUi();
let prompt = "";
rowValue.forEach( (row,i) => prompt = prompt.concat((i+1).toString(),": ",row[0], " ",row[1],"\n"));
if( rowValue.length === 0 ) {
ui.alert("Name not found ["+str+"]");
return;
}
else if( rowValue.length > 1 ) {
let response = ui.prompt("Pick a name",prompt,ui.ButtonSet.OK_CANCEL);
if( response.getSelectedButton() == ui.Button.OK ) {
str = response.getResponseText();
str = parseInt(str)-1;
rowValue = rowValue[str];
}
}
else {
rowValue = rowValue[0];
}
ui.alert(rowValue.toString());
// Now you can fill out your form with rowValue
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
Reference
Array.filter()
Array.forEach()
SpreadsheetApp Ui prompt
Description
So I decided to show how a custom dialog can be used to display a list of names to pick from. First a Ui dialog is displayed to use a filter name. If no name is specified all names will be listed.
Using HTMLService a custom dialog is build using the the pushed variable option for an HTM Template.
Once a name is picked from the list google.script.run is used to return the name to the server and the form can be built from there.
Code.gs
function onOpen(e) {
var menu = SpreadsheetApp.getUi().createMenu("My Menu");
menu.addItem("Test","showTest");
menu.addToUi();
}
function showTest() {
try {
let ui = SpreadsheetApp.getUi();
let response = ui.prompt("What name do you want to search for",ui.ButtonSet.OK_CANCEL);
if( response.getSelectedButton() == ui.Button.OK ) {
var name = response.getResponseText();
if( name === "" ) name = "__All";
}
let spread = SpreadsheetApp.getActiveSpreadsheet();
let dataS = spread.getSheetByName("Data");
let data = dataS.getRange(1,1,dataS.getLastRow(),2).getValues(); // Get range A1:B
if( name !== "__All" ) {
data = data.filter( row => row[0] === name );
}
if( data.length === 0 ) {
ui.alert("No names mathcing ["+name+"] found");
return;
}
let html = HtmlService.createTemplateFromFile('HTML_Test');
html.data = data;
html = html.evaluate();
SpreadsheetApp.getUi().showModalDialog(html,"Show Test");
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
function pickName(name) {
try {
let spread = SpreadsheetApp.getActiveSpreadsheet();
let dataS = spread.getSheetByName("Data");
dataS.getRange(1,5).setValue(name);
// Build your form here
}
catch(err) {
console.log(err);
}
}
HTML_Test.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<select id="selectName">
<? for (let i = 0; i < data.length; i++) { ?>
<option><?= data[i][0]+" "+data[i][1] ?></option>
<? } ?>
</select>
<input type="button" onclick="buttonOnClick()" value="Submit">
<script>
function buttonOnClick() {
let name = document.getElementById("selectName").value;
google.script.run.pickName(name);
google.script.host.close();
}
</script>
</body>
</html>
Reference
HTMLService
HTML Template
google.script.run
google.script.host

Footable fine filtering

I have this code to have a select field filter through a Footable. It works but it's straining more results than needed. Example: "Article in National Journal" option is filtering rows with both "Article in National Journal" and "Article in International Journal". How can I make it more precise? Thank you.
jQuery(function () {
jQuery('#projectos').footable().bind('footable_filtering', function (e) {
var selected = jQuery('.filter-status').find(':selected').text();
if (selected && selected.length > 0) {
e.filter += (e.filter && e.filter.length > 0) ? ' ' + selected : selected;
e.clear = !e.filter;
}
});
jQuery('.clear-filter').click(function (e) {
e.preventDefault();
jQuery('.filter-status').val('');
jQuery('#projectos').trigger('footable_clear_filter');
});
jQuery('.filter-status').change(function (e) {
e.preventDefault();
jQuery('#projectos').trigger('footable_filter', {filter: jQuery('#filter').val()});
});
});
When Footable filters, it uses the entire text from the whole row and it uses indexof() to test. You can see this in footable.filter.js in the filterFunction function.
I had to do 3 things to solve the problem.
Replace window.footable.options.filter.filterFunction with my own function
Do a per column match instead of the whole row. Depending on the HTML in your row, the spaces between the columns could be lost causing the first word of a column to concatenate with the last word of the previous column.
Use a regex match instead of indexof(). This allows you to match a whole word. As an example, if you us indexof() for "be" in "Don't be evil, because that's not good" will return 6 and 15 even though 15 is the beginning of a completely different word.
Here's the function: (I'm sure there are loads of improvements. Feel free to edit...)
window.footable.options.filter.filterFunction = function(index) {
var $t = $(this),
$table = $t.parents('table:first'),
filter = $table.data('current-filter').toUpperCase(),
columns = $t.find('td');
var regEx = new RegExp("\\b" + filter + "\\b");
var result = false;
for (i = 0; i < columns.length; i++) {
var text = $(columns[i]).text();
result = regEx.test(text.toUpperCase());
if (result === true)
break;
if (!$table.data('filter-text-only')) {
text = $(columns[i]).data("value");
if (text)
result = regEx.test(text.toString().toUpperCase());
}
if (result === true)
break;
}
return result;
};
You can find a plunk here: http://plnkr.co/edit/P2DWDtyHP3xmoUIcvgDe

NicEdit link creation doesn't work in IE 8 and FireFox if text wasn't selected

I have a problem with nicEdit link creation tool in IE and Firefox.
In general, I think the problem is related to the execCommand in IE and FireFox. It seems document doesn't get updated after execCommand executes.
This is an example of my problem with nicEdit create link command.
if(!this.ln) {
var tmp = 'javascript:nicTemp();';
this.ne.nicCommand("createlink",tmp);
this.ln = this.findElm('A','href',tmp);
// set the link text to the title or the url if there is no text selected
alert(this.ln);
if (this.ln.innerHTML == tmp) {
this.ln.innerHTML = this.inputs['title'].value || url;
};
}
The code above is called when no text is selected, Chrome returns 'javascript:nicTemp()' for the alert(this.ln), while IE 8 and Firefox return 'undefined', so the next line after the alert encounters an error in IE and Firefox.
it seems findElem can't find the newly created link by nicCommand which in turn calls execCommand
I had similar problems when I try to find and modify tags created with execCommand, it seems the dom isn't updated to include them.
Am I right? How can I solve this problem? how can I force the document to be updated ....
please help
my trick for nicEdit, in the situation when no text is selected, is to paste the title given via the Add Link form into the document and select it, then the rest code works as it works when a text is selected.
I used the function pasteHtmlAtCaret described in the following link to paste the title
Insert html at caret in a contenteditable div
this.removePane();
var url = this.inputs.href.value;
var selected = getSelected();
var B= 'javascript:nicTemp()';
if (selected == '')
{
var B = url;
pasteHtmlAtCaret(this.inputs['title'].value || url,true);
}
if(!this.ln){
this.inputs.title.value;this.ne.nicCommand("createlink",B);
this.ln=this.findElm("A","href",B)
}
the getSelected is also a simple function as below
function getSelected()
{
if (document.selection)
return document.selection.createRange().text;
else
return window.getSelection();
}
Ahmad, just use this variation of the "submit" function to avoid the "insert/edit" problem with the link, it worked for me:
submit : function(e) {
var url = this.inputs['href'].value;
if(url == "http://" || url == "") {
alert("Introduce una URL valida para crear el Link.");
return false;
}
this.removePane();
if(!this.ln) {
//**************** YOUR CHANGE WITH A BIT OF VARIATION **************
var selected = this.getSelected();
var tmp = 'javascript:void(0)';
if (selected == '') {
tmp = url;
this.pasteHtmlAtCaret(this.inputs['title'].value || tmp, true);
}
//**************** END OF YOUR CHANGE WITH A BIT OF VARIATION **************
this.ne.nicCommand("createlink",tmp);
this.ln = this.findElm('A','href',tmp);
// set the link text to the title or the url if there is no text selected
if (this.ln.innerHTML == tmp) {
this.ln.innerHTML = this.inputs['title'].value || url;
};
}
if(this.ln) {
var oldTitle = this.ln.title;
this.ln.setAttributes({
href: this.inputs['href'].value,
title: this.inputs['title'].value,
target: '_blank'
});
// set the link text to the title or the url if the old text was the old title
if (this.ln.innerHTML == oldTitle) {
this.ln.innerHTML = this.inputs['title'].value || this.inputs['href'].value;
};
}
}
this.removePane();
var url = this.inputs['href'].value;
var selected = getSelected();
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
var tmp = "";
if(isChrome == true){
tmp=url;
}
else{tmp='javascript:nicTemp()'}
if (selected == '' && isChrome == false)
{
pasteHtmlAtCaret(this.inputs['title'].value || url,true);
}
if (!this.ln) {
//var tmp = this.inputs['title'].value == "" ? this.inputs['href'].value : this.inputs['title'].value;
this.ne.nicCommand("createlink", tmp);
this.ln = this.findElm('A', 'href', tmp);
}
function getSelected()
{
if (document.selection)
return document.selection.createRange().text;
else
return window.getSelection();
}
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
//create a link format
el.innerHTML = ''+ html +'';
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}

How to pass a input value into a function using GAS

I will try and keep this brief. I am attempting to make a google web app in google spreadsheet that will allow me to enter a values for min and max.
I have been able to create the GUI and add it to the panel. But I can't seem to pass the integer being entered into another function. I've tried everything, I'm relatively new to creating Google Script so I'm sorry if this comes across as a bit of a noobish problem.
Here is all the code so far :
function onOpen() {
var ss = SpreadsheetApp.getActive();
var menuEntries = [];
menuEntries.push({name: "Open Dialog", functionName: "showDialog"});
ss.addMenu("Min/Max", menuEntries);
}
//creating a panel to add the min and max of low to high for scoring
function showDialog() {
max = 10;
var app = UiApp.createApplication();
app.setTitle("My Applicaition");
var panel = app.createVerticalPanel();
var textBox = app.createTextBox();
var label = app.createLabel("Set the min value for 'Low'");
//had to create a hidden element with id="min" for a global value that can be updated
var min = app.createHidden().setValue('0').setName('min').setId('min');
textBox.setName('myTextBox').setId('myTextBox');
var button = app.createButton('Submit');
panel.add(label);
panel.add(textBox);
panel.add(min);
panel.add(button);
//click handler for setting the value of min to the new value
var clickHandler = app.createServerClickHandler("responedToSubmit");
button.addClickHandler(clickHandler);
clickHandler.addCallbackElement(panel);
app.add(panel);
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
function responedToSubmit(e) {
var app = UiApp.getActiveApplication();
var textBoxValue = e.parameter.myTextBox;
Logger.log(e.parameter.min);
if (typeof textBoxValue != "number") {
var num = parseInt(textBoxValue);
app.getElementById('min').setValue(num);
Logger.log("textBoxValue is = "+textBoxValue+"\n min value is = "+e.parameter.min);
} else {
throw "value needs to be set as number";
}
return app.close();
}
This is where I believe things aren't going according to plan :
function responedToSubmit(e) {
var app = UiApp.getActiveApplication();
var textBoxValue = e.parameter.myTextBox;
Logger.log(e.parameter.min);
if (typeof textBoxValue != "number") {
var num = parseInt(textBoxValue);
app.getElementById('min').setValue(num);
Logger.log("textBoxValue is = "+textBoxValue+"\n min value is = "+e.parameter.min);
} else {
throw "value needs to be set as number";
}
return app.close();
}
I find that each time I test the .setValue() will not update the value of 'min' and I cannot see why. Can you please help?
You need to add textBox element to callBack elements list of your clickHandler.
Try this:
//click handler for setting the value of min to the new value
var clickHandler = app.createServerClickHandler("responedToSubmit");
clickHandler.addCallbackElement(panel);
clickHandler.addCallbackElement(textBox);
button.addClickHandler(clickHandler);
app.add(panel);

What exactly am I sending through the parameters?

When doing a XMLHttpRequest and using POST as the form method, what exactly am I sending? I know it should be like send(parameters), parameters = "variable1=Hello", for example. But what if I want to do this:
parameters = "variable1=" + encodeURIComponent(document.getElementById("variable1").value);
variable1 being the id of the HTML form input.
Can I do it like this or do I need to assign the encodeURIComponent value to a javascript variable and send that variable:
var variable2;
parameters = "variable2=" + encodeURIComponent(document.getElementById("variable1").value);
You're suppose to send the object and it's value, but, is it an object from the HTML form, a javascript object or a php object? The problem is I already tried it and I still can't get the encoded input in my database, all I get is the raw input from the user.
BTW, I know it's a pretty dull question, but I feel the need to understand exactly what I'm doing if I want to come up with a solution.
g
function createObject()
{
var request_type;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer")
{
request_type = new ActiveXObject("Microsoft.XMLHTTP");
}
else
{
request_type = new XMLHttpRequest();
}
return request_type;
}
var http = createObject();
//INSERT
function insert()
{
var Faculty2 = encodeURIComponent(document.getElementById("Faculty").value);
var Major2 = encodeURIComponent(document.getElementById("Major").value);
var Professor2 = encodeURIComponent(document.getElementById("Professor").value);
var Lastname2 = encodeURIComponent(document.getElementById("Lastname").value);
var Course2 = encodeURIComponent(document.getElementById("Course").value);
var Comments2 = encodeURIComponent(document.getElementById("Comments").value);
var Grade2 = encodeURIComponent(document.getElementById("Grade").value);
var Redflag2 = encodeURIComponent(document.getElementById("Redflag").value);
var Owner2 = encodeURIComponent(document.getElementById("Owner").value);
//Location and parameters of data about to be sent are defined
//Required: verify that all fields are not empty. Use encode URI() to solve some issues about character encoding.
var params = "Faculty=" + Faculty2 + "&Major=" + Major2 + "&Professor=" + Professor2 + "&Lastname=" + Lastname2 + "&Course=" + Course2 + "&Comments=" + Comments2 + "&Grade=" + Grade2 + "&Redflag=" + Redflag2 + "&Owner=" + Owner2;
var url = "prehp/insert.php";
http.open("POST", url, true);
//Technical information about the data
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
//Now, we send the data
http.onreadystatechange = function()
{
if(http.readyState == 4)
{ var answer = http.responseText;
document.getElementById('insert_response').innerHTML = "Ready!" + answer;
}
else
{document.getElementById('insert_response').innerHTML = "Error";
}}
http.send(params);
}
PHP code:
$insertAccounts_sql = "INSERT INTO Information (Faculty, Major, Professor, Lastname, Course, Comments, Grade, Redflag, Owner)
VALUES('$_POST[Faculty]','$_POST[Major]','$_POST[Professor]','$_POST[Lastname]','$_POST[Course]','$_POST[Comments]','$_POST[Grade]','$_POST[Redflag]','$_POST[Owner]')";
$dbq = mysql_query($insertAccounts_sql, $dbc);
if($dbq)
{
print "1 record added: Works very well!";
}
else
if(!$dbq)
{
die('Error: ' . mysql_error());
}
$dbk = mysql_close($dbc);
if($dbk)
{
print "Database closed!";
}
else
if(!$dbk)
{
print "Database not closed!";
}
I did that but the value that the database got was the raw input and not the encoded input. I'm running out of ideas, don't know what else to try. Could it be the settings of the database, can the database be decoding the input before storing it? That seems far-fetched to me, but I've been looking at this from all angles and still can't come up with a fresh answer.
PS: Sorry for posting my comments on the answer area, first timer here.
when creating query strings, it has really nothing to do with objects or anything like that. All you want to be sending is key/value pairs. how you construct that is up to you, but it often neater and more manageable to assign your values to variables first. i.e.
var myVar1Value = encodeURIComponent(document.getElementById('variable1').value);
var myVar2Value = encodeURIComponent(document.getElementById('variable2').value);
var url = "http://www.mydomain.com?" + "var1=" + myVar1Value + "&var2=" + myVar2Value;
It's called a query string, so it's just a string. what you do with it on the server side is what makes the 'magic' happen.
edit: If you're having problems with values, then you should print them to console to verify you are getting what you expect.

Resources