Ajax function gives Cannot read property 'length' of undefined - ajax

This function works fine as long im on the same page where the search div imagesearch is.
If im on another site on the website, ill get the error
Cannot read property 'length' of undefined.
The console point put row 27, that's where the if statement start if(q.length..
Cant really find out whats the problem. Any ideas ?
function reloadSearch() {
if (!isLoading) {
var q = $('#imagesearch').val();
if (q.length >= 2) {
isLoading = true;
$.ajax({
type: 'GET',
url: 'core/flickr.php',
data: 'search=' + q,
dataType: 'html',
beforeSend: function () {
$('#imageresult').html(
'<img src="img/loading45.gif" alt="loading..." />');
if (!q[0]) {
$('#imageresult').html(
'');
return false;
}
},
success: function (response) {
$('#imageresult').html(
response);
}
});
// enforce the delay
setTimeout(function () {
isLoading = false;
if (isDirty) {
isDirty = false;
reloadSearch();
}
}, delay);
}
}
};
var delay = 1000;
var isLoading = false;
var isDirty = false;
$(document).ready(function () {
reloadSearch();
$('#imagesearch').keyup(function () {
isDirty = true;
reloadSearch();
});
});

change:
if (q.length >= 2) {
to
if (q !== undefined && q.length >= 2) {
this will stop the can't read value from undefined...If you code in .Net this is similar to the null reference exception.

Related

flickr API does not provide any results

Hi I am trying this Flickr API, where I want to display title + image, for the first 3. But it's not working.
http://jsfiddle.net/28hEb/6/
var tag = "mount";
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=" + tag + "&tagmode=all& format=json&jsoncallback=?", function (data) {
$.each(data.items, function (index, item) {
$("<div>").html(item.title).appendTo("#content");
$("<img/>").attr("src", item.media.m).appendTo("#content");
if (index == 3) {
return false;
}
});
});
You have a syntax error:
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?", {
tags: "mount",
tagmode: "any",
format: "json",
}, function (data) {
var $content = $('#content');
$.each(data.items, function (i, item) {
$("<div>").html(item.title.m).appendTo($content);
$("<img/>").attr("src", item.media.m).appendTo($content);
if (i == 3) {
return false;
}
});
});
Check this fiddle
The } should end before the callback. Hence the issue. Your browser's console should give you a hint of what the error is.

IE not reading GET success after POST

I cannot seem to find out why IE does not read my success on get after the post. I have tried cache: false, with no luck. This works in all other browsers, just not IE.
$.ajaxSetup({ cache: false });
num = $('#num').val();
phone = $('#phone').val();
$.post("post.php?"+$("#MYFORM").serialize(), {
}, function(response){
if(response==1 && codeVal == 1 && telVal == 1)
{
$("#after_submit").html('');
$("#Send").after('<label class="success" id="after_submit">Η αποστολή πραγματοποιήθηκε</label>');
change_captcha();
clear_form();
$.ajax({
type:'get',
cache: false,
url: "http://web.somesite/submit_code.php",
dataType: 'html',
data:{ user: "one", pass: "mtwo", source: "WEB", receipt: num, msisdn: phone},
success: function(data) {
var qsFull = "http://web.somesite.gr/submit_code.php?" + data;
var qs = URI(qsFull).query(true);
TINY.box.show({html:qs.message,animate:false,boxid:'error',top:5});
}
});
}
else
{
$("#after_submit").html('');
$("#Send").after('<label class="error" id="after_submit">Error! in CAPTCHA .</label>');
}
});
OK, I tried adding an error after the success and I see that I get my pop up as I should be, but the value of qs.message is 0. Why would I get error and not success, when it is successful in other browsers.
I found the answer, It has to do with IE not being flexible with cross domains and such, so I added a XDomainRequest like so
if (jQuery.browser.msie && window.XDomainRequest) {
var xdr = new XDomainRequest();
var my_request_data = { user: "M1web", pass: "m!", source: "WEB", receipt: num, msisdn: phone};
my_request_data = $.param(my_request_data);
if (xdr) {
xdr.onerror = function () {
alert('xdr onerror');
};
xdr.ontimeout = function () {
alert('xdr ontimeout');
};
xdr.onprogress = function () {
alert("XDR onprogress");
alert("Got: " + xdr.responseText);
};
xdr.onload = function() {
//alert('onload ' + xdr.responseText);
var qsFull = "http://web.web.gr/submit_code.php?" + xdr.responseText;
var qs = URI(qsFull).query(true);
TINY.box.show({html:qs.message,animate:false,boxid:'error',top:5});
callback(xdr.responseText);
};
xdr.timeout = 5000;
xdr.open("get", "http://web.web.gr/submit_code.php?" + my_request_data);
xdr.send();
} else {
}
}
I unfortunately had to do a crash course in legacy IE behavior, and this post was very helpful. Here are some other links to help those having to deal with these issues:
Microsoft's Documentation of their XDomainRequest object
An internal blog post covering some of XDomainRequest's idiosyncrasies
Here's a function I use as a fallback where necessary:
// This is necessary due to IE<10 having no support for CORS.
function fallbackXDR(callObj) {
if (window.XDomainRequest) {
var xdrObj = new XDomainRequest();
xdrObj.timeout = callObj.timeout;
xdrObj.onload = function() {
handleSuccess(xdrObj.responseText);
};
xdrObj.onerror = function() {
handleError(xdrObj);
};
xdrObj.ontimeout = function() {
callObj.xdrAttempts = callObj.xdrAttempts++ || 1;
if (callObj.xdrAttempts < callObj.maxAttempts) {
fallbackXDR(callObj);
}
};
xdrObj.onprogress = function() {
// Unfortunately this has to be included or it will not work in some cases.
};
// Use something other than $.param() to format the url if not using jQuery.
var callStr = callObj ? '?'+$.param(callObj.urlVars) : '';
xdrObj.open("get", callObj.url+callStr);
xdrObj.send();
} else {
handleError("No XDomainRequest available.", callObj);
}
}//fallbackXDR()

Backbone collection fetch error with no information

I have a strange problem with the fetch of a backbone collection I am working with. In one particular instance of my code I perform a fetch (exactly how I do it in other areas of the code which all work fine), the fetch never seems to make it to the server and the developer tools shows the request as red with the word (canceled) in the status/text field.
I've walked this through into the backbone sync method and I see the $.ajax being built and everything looks fine. Has anyone run into this problem?
here is my code if it helps, this is a function that calls two .ashx services to first check for a file's existence then to open it. The part that isn't working for me is the "me.collection.fetch().
openDocument: function () {
var me = this,
fileId = me.model.get('id'),
userId = Dashboard.Data.Models.UserModel.get("UserInfo").User_ID,
fileRequest = '/genericHandlers/DownloadFile.ashx?id=' + fileId + '&userId=' + userId,
fileCheck = '/genericHandlers/CheckFileExistance.ashx?id=' + fileId + '&userId=' + userId;
//hide tooltip
me.hideButtonTooltips();
// Check for file existance
$.ajax({
url: fileCheck
})
.done(function (data) {
if (data && data === "true") {
document.location.href = fileRequest;
me.collection.fetch();
} else if (!!data && data === "false") {
"This file is no longer available.".notify('error');
}
})
.fail(function (data) {
"Something went wrong during the File Existance check".notify('error');
"Something went wrong during the File Existance check".log(userId, 'error', 'Docs');
});
},
my collection:
// docsCollection.js - The collection of ALL the documents available to a given user
// Document Collection
Dashboard.Collections.DocsCollection = Backbone.Collection.extend({
model: Dashboard.Models.DocumentUploadModel,
url: function () {
return 'apps/docs/Docs/' + this.userId;
},
initialize: function (options) {
this.userId = options.userId;
this.deferredFetch = this.fetch();
},
comparator: function (model) {
return -(new Date(model.get('expirationDate')));
},
getDaysSinceViewedDocuments: function () {
return this.filter(function (model) {
return model.get('daysSinceViewed') !== null;
});
},
getNewDocuments: function () {
return this.filter(function (model) {
return model.get('isNew');
});
},
getExpiredDocuments: function () {
return this.filter(function (model) {
return model.get('isExpired');
});
}
});
and my model:
Dashboard.Models.DocumentUploadModel = Backbone.Model.extend({
defaults: {
fileArray: [],
name: '',
description: '',
accesses: [],
tags: [],
expirationDate: ''
},
initialize: function () {
this.set({
userId: Dashboard.Data.Models.UserModel.get("UserInfo").User_ID,
expirationDate: (this.isNew()) ? buildExpirationDate() : this.get('expirationDate')
}, { silent: true });
function buildExpirationDate() {
var date = new Date((new Date()).getTime() + 24 * 60 * 60 * 1000 * 7),
dateString = "{0}/{1}/{2}".format(date.getMonth() + 1, date.getDate(), date.getFullYear());
return dateString;
}
},
firstFile: function () {
return this.get('fileArray')[0];
},
validate: function (attributes) {
var errors = [];
if (attributes.name === '' || attributes.name.length === 0)
errors.push({
input: 'input.txtName',
message: "You must enter a name."
});
if (attributes.description === '' || attributes.description.length === 0)
errors.push({
input: 'textarea.taDescription',
message: "You must enter a description."
});
if (errors.length > 0)
return errors;
return;
},
sync: function (method, model, options) {
var formData = new FormData(),
files = model.get("fileArray"),
$progress = $('progress'),
success = options.success,
error = options.error;
// Nothing other than create or update right now
if (method !== "create" && method !== "update")
return;
// Build formData object
formData.append("name", model.get("name"));
formData.append("description", model.get("description"));
formData.append("accesses", model.get("accesses"));
formData.append("tags", model.get("tags"));
formData.append("expirationDate", model.get("expirationDate"));
formData.append("userId", model.get("userId"));
formData.append("isNew", model.isNew());
// if not new then capture id
if (!model.isNew())
formData.append('id', model.id);
for (var i = 0; i < files.length; i++) {
formData.append('file', files[i]);
}
xhr = new XMLHttpRequest();
xhr.open('POST', '/genericHandlers/UploadDocsFile.ashx');
xhr.onload = function () {
if (xhr.status === 200) {
if (success)
success();
} else {
if (error)
error();
}
}
if ($progress.length > 0) {
xhr.upload.onprogress = function (evt) {
var complete;
if (evt.lengthComputable) {
// Do the division but if you cant put 0
complete = (evt.loaded / evt.total * 100 | 0);
$progress[0].value = $progress[0].innerHTML = complete;
}
}
}
xhr.send(formData);
},
upload: function (changedAttrs, options) {
this.save("create", changedAttrs, options);
}
});
You're assigning a value to document.location.href before you try to fetch your collection:
document.location.href = fileRequest;
me.collection.fetch();
Changing document.location.href will change the whole page and in the process, any currently running JavaScript will get shutdown so I wouldn't expect your me.collection.fetch() to ever get executed.

fancybox: show partial view

I have the following js code:
function getSelectedPlace(form) {
var places = 1
$(form).find(":input").each(function () {
if ($(this).attr("name") === "Signed_Order_B64") {
$.ajax({
type: 'POST',
url: '/MyController/MyAction',
data: "id=" + places,
success: function (response) {
if (response.Result) {
ret = response.Message;
result = true;
$("input[type=hidden][name=email]").val(response.Email);
$("input[type=hidden][name=appendix]").val(response.Appendix);
} else {
// show fancybox
result = false;
}
},
error: function () {
result = false;
},
async: false
});
$(this).val(ret);
}
});
if (!result) {
$(submitButton).attr("value", btnText);
setStateFotBuyButton(false);
}
return result;
}
I have if statement in success block. I want show partial view in the fancybox in else block. How can I do this? Thanks
Not totally sure what you mean with "partial view" but you could do
} else {
$.fancybox(response,{
// fancybox options here
}); // fancybox
}
You could use the content switch which allows you to set the content of the fancybox to any html:
$.fancybox({
content: response
});

Adding new row to SlickGrid

I have a slickgrid using the dataview. From what I can tell, the grid's add new row event isn't called until after the first new row field's editor is complete. The field I was editing is a custom editor that uses a input box with autocomplete and save the selected item "value" to the grid source data. The problem is the new "item" source isn't created until the grid add new row event is fired. I know there is a way around this and just want to know what is the best way to solve for this.
Thanks.
//Add new row event
grid.onAddNewRow.subscribe(function (e, args) {
var item = args.item;
addnewid = addnewid - 1;
item.inventorytransferdetailid = addnewid;
$.extend(item, args.item);
dataView.addItem(item);
});
// Custom editor
function Suggest2(args) {
var $input;
var defaultValue;
var scope = this;
this.init = function () {
$input = $("<INPUT type=text class='editor-text' />")
$input.width = args.column.width;
$input.appendTo(args.container);
$input.focus();
$input.bind("keydown.nav", function (e) {
if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
e.stopImmediatePropagation();
}
else if ($input.val().length > 0) {
$.ajax({
type: "GET",
url: "http://localhost:11111/GetProducts/" + $input.val(),
dataType: "json",
data: "{}",
contentType: "application/json; charset=utf-8",
success: function (data) {
$input.autocomplete({
source: data,
select: function (event, ui) {
var v = ui.item.value;
var l = ui.item.label;
//Set "display" field with label
args.item[args.column.field] = l;
this.value = l;
//Set "hidden" id field with value
args.item["productid"] = v;
return false;
}
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
}
})
};
this.destroy = function () {
$input.remove();
};
this.focus = function () {
$input.focus();
};
this.getValue = function () {
return $input.val();
};
this.setValue = function (val) {
$input.val(val);
};
this.loadValue = function (item) {
defaultValue = item[args.column.field] || "";
$input.val(defaultValue);
$input[0].defaultValue = defaultValue;
$input.select();
};
this.serializeValue = function () {
return $input.val();
};
this.applyValue = function (item, state) {
//item[args.column.field] = state;
};
this.isValueChanged = function () {
return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
};
this.validate = function () {
if (args.column.validator) {
var validationResults = args.column.validator($input.val());
if (!validationResults.valid) {
return validationResults;
}
}
return {
valid: true,
msg: null
};
};
this.init();
}
You can try below code.
function add_new_row(){
item = {
"id": (Math.round(Math.random()*-10000))
};
data_view.insertItem(0, item);
}
Then, bind with button.
<button onclick="add_new_row()">Add Row</button>

Resources