Specific property of EmberJS loaded by AJAX and updated in view - ajax

I'm having an issue here when attempting to build an integration to our partners. They're gonna submit an image URL as a GET-variable, which I obviously don't want to print straight up. The submitted image URL is submitted back to our servers with AJAX to be sanitized, returned and then updated.
What I want to do here is when the model loads, I want to display a placeholder image, and when the sanitation check is done by the server, it will return the URL (the same or another placeholder) that is to be set as the template image source.
Now, the problem is that I don't get how to make Ember listen for the update of this event. I'm trying to use observes, but apparently, this isn't available in the route. Here's my current code:
ROUTE
MyApp.PartnerRoute = Ember.Route.extend({
imageUrl: "/img/placeholder.png";
getImageUrl: function(imageUrlToCheck) {
instance = this;
$.ajax({
url: "/ajax/get-image-url",
type: "post",
data: {
"imageUrl": imageUrlToCheck
},
success: function(response) {
if(response.status === 0) {
instance.set("imageUrl", response.data.imageUrl);
}
}
});
},
// Ember update property.
imageUrlDidChange: function() {
this.get("imageUrl");
}.observes("imageUrl"),
model: function(params) {
this.getImageUrl(params.imageUrl);
return {
heading: "Welcome!",
imageUrl: this.imageUrl
}
}
});
VIEW
<script type="text/x-handlebars" data-template-name="partner">
<h1>{{heading}}</h1>
<img {{bind-attr src=imageUrl}} />
</script>
I get the error message:
Uncaught TypeError: Object function () {
this.get("imageUrl");
} has no method 'observes'
I'm not at all sure as of how to make this happen. Am I going about this the wrong way? Any help is appreciated.
Thank you for your time.
Best regards,
dimhoLt
PS. I've extracted the applicable pieces of code from much bigger objects, so if there are any typos, missing commas etc, it's due to the copy-paste and is not applicable to the actual code.
EDIT:
Worth noting is that because of legacy functionality I haven't yet rewritten, I was forced to turn off Ember extended prototypes. This is, I guess, the major cause of the issue.
Since I wrote this, I've also gone over to using a fixed model instead of attempting to work directly with the route.

You need to use a setter
http://emberjs.jsbin.com/OxIDiVU/117/edit
model: function(params) {
var model = {
heading: "Welcome!",
imageUrl: this.imageUrl
};
this.getImageUrl(params.imageUrl).then(function(result){
Em.set(model, 'imageUrl', result.imageUrl);
});
return model;
}

Related

Can I call a jScript function from url or when an image changes?

I'm using the free Securimage package for captcha validation in my signup form.
I'm using jScript / AJAX / PHP to check the code while the user types it, and output "incorrect" or "correct" next to the input box and giving it a red border if it's left empty or incorrect.
The issue here is: if the user first enter the correct key, then for some reason clicks the "select another image" url the key will change but the input box will not change and therefore not be validated and this might confuse the user to think that the right key is entered when it has actually changed and should be re-entered.
The check captcha function is invoked when something is typed in the captcha input box (keyup) or when done typing (blur). The code looks something like this:
$(document).ready(function()
{
var chckcaptcha = function()
{
var captcha = encodeURIComponent($("#captcha").val());
$.ajax(
{
type: "POST",
url: "lib_ajax/somescript.php",
data: "captcha="+ captcha,
success: function(msg_captcha)
{
$("#status_captcha").ajaxComplete(function(event, request, settings)
{
// ... some validation code here
});
}
});
}
$("#captcha").bind('keyup',chckcaptcha)
$("#captcha").blur(chckcaptcha);
});
The image:
<img src="/lib_class/securimage/securimage_show.php" alt="CAPTCHA Image" name="captcha_img" width="100%" height="100" id="captcha_img" />
The refresh url:
refresh image
I need a way to invoke the check captcha function in the jScript when that url is clicked, or when the new image is created. I have absolutely no clue on how to do this.
I have already tried (among many other things) to add this to the jScript:
$("#captcha_img").change(chckcaptcha);
But that didn't help. Any tips to a solution would be much appreciated!
The above answer didn't work but gave me an idea to a solution. This worked for me...
Function:
function refreshImage()
{
// New image
document.getElementById('captcha_img').src =
'/lib_class/securimage/securimage_show.php?' + Math.random();
// New validation
chckcaptcha();
}
Refresh link:
refresh image
You can define the chckcaptcha function and the function that refreshes the image outside the document ready handler, and then call them in succession when the image is refreshed?
refresh image
...
function chckcaptcha()
{
var captcha = encodeURIComponent($("#captcha").val());
$.ajax(
{
type: "POST",
url: "lib_ajax/somescript.php",
data: "captcha="+ captcha,
success: function(msg_captcha)
{
$("#status_captcha").ajaxComplete(function(event, request, settings)
{
// ... some validation code here
});
}
});
}
$(document).ready(function()
{
$("#refresh-link").click(function() {
document.getElementById('captcha_img').src = '/lib_class/securimage/securimage_show.php?' + Math.random();
chckcaptcha();
});
$("#captcha").bind('keyup',chckcaptcha);
$("#captcha").blur(chckcaptcha);
});

Backbone model save triggers error callback on Chrome/FF

Noob question here:
I'm using ASP.NET MVC 3 and I'm trying to save an entity through Backbone. Here's what I have:
I defined my Backbone model (Program) as such:
var Program = Backbone.Model.extend({
defaults: function () {
return { name: "" };
},
initialize: function (attrs) {
this.set('name', attrs.name);
},
urlRoot: '/program/add'
});
Then I hook up the model save on the click event of a button:
$('.add-program').click(function () {
var programName = $('.program-name').val();
var program = new Program({ name: programName });
program.save(null, {
success: function (model, response) {
alert('success');
},
error: function (model, response) {
alert('error');
}
});
});
It works on IE (surprisingly!) - ProgramController.Add(string name) gets called fine and I get a success response. But I'm having issues on Chrome and FF - They both trigger the error callback with the slight difference that on Chrome my Controller Action doesn't even get hit at all (it does on FF though). The funny thing is that my action breakpoint does get hit on FF, with the appropriate param value, but still get the error callback.
I'm not sure what's going on here. I tried debugging through Firebug/Chromebug and don't see much on the error callback params (the errorStatus is just ... well... "error"!). I also tried looking at the Network tab and Fiddler and I don't see anything that rings a bell (maybe I'm not looking at the right place). I also tried doing a straight jquery ajax call to the controller and still get the same weird behavior.
Just in case, here's the MVC action (although I don't think the issue is here):
[HttpPost]
public JsonResult Add(string name)
{
var stubbedResponse = new {id = Guid.NewGuid()};
return Json(stubbedResponse);
}
Any ideas what could be causing this?
A Fiddle http://jsfiddle.net/Uj5Ae/2 with your client code seems to be OK. Something with your server response? Or Backbone and Underscore versions not matching?
Or maybe the return false at the end of the click handler, if the event propagation is not handled elsewhere.
Spoiler : that was the event propagation :)

How to use AJAX as an alternative to iframe

I'm trying to put together a snappy webapp, utilizing JS, Prototype and AJAX for all my requests once the GUI has loaded. The app is simple: A set of links and a container element to display whatever the links point to, just like an iframe. Here's an approximate HTML snippet:
<a class="ajax" href="/somearticle.html">An article</a>
<a class="ajax" href="/anotherarticle.html">Another article</a>
<a class="ajax" href="/someform.html">Some form</a>
<div id="ajax-container"></div>
The JS that accompanies the above (sorry it's a bit lengthy) looks like this:
document.observe('dom:loaded', function(event) {
ajaxifyLinks(document.documentElement);
ajaxifyForms(document.documentElement);
});
function ajaxifyLinks(container) {
container.select('a.ajax').each(function(link) {
link.observe('click', function(event) {
event.stop();
new Ajax.Updater($('ajax-container'), link.href, {
method: 'get',
onSuccess: function(transport) {
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
function ajaxifyForms(container) {
console.debug('Notice me');
container.select('form.ajax').each(function(form) {
form.observe('submit', function(event) {
event.stop();
form.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
// Make sure new ajax-able elements are ajaxified
ajaxifyLinks(container);
ajaxifyForms(container);
}
});
});
});
}
When clicking a link, the response is displayed in the container. I'm not using an iframe for the container here, because I want whatever elements are on the page to be able to communicate with each other through JS at some point. Now, there is one big problem and one curious phenomenon:
Problem: If a form is returned and displayed in the container, the JS above tries to apply the same behavior to the form, so that whatever response is received after submitting is displayed in the container. This fails, as the submit event is never caught. Why? Note that all returned form elements have the class="ajax" attribute.
Phenomenon: Notice the console.debug() statement in ajaxifyForms(). I expect it to output to the console once after page load and then every time the container is updated with a form. The truth is that the number of outputs to the console seems to double for each time you click a link pointing to a form. Why?
I found another way to achieve what I wanted. In fact, the code for doing so is smaller and is less error prone. Instead of trying to make sure each link and form element on the page is observed at any given time, I utilize event bubbling and listen only to the document itself. Examining each event that bubbles up to it, I can determine whether it is subject for an AJAX request or not. Here's the new JS:
document.observe('submit', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
event.target.request({
onSuccess: function(transport) {
$('ajax-container').update(transport.responseText);
}
});
}
});
document.observe('click', function(event) {
if (event.target.hasClassName('ajax')) {
event.stop();
new Ajax.Updater($('ajax-container'), event.target.href, {
method: 'get'
});
}
});
Works like a charm :)

Spring MVC: Auto-save functionality (jQuery, Ajax...)

I'd like to implement a "auto-save" functionality on my page. I don't really know how to start though. I got one object (with a list of tasks). I'd like to submit the form every 20 seconds, so the users won't lose their data. It doesn't have to be exactly like that. After every submit the submit-button should be disabled as long as there are no changes.
I'm using Spring MVC. I did some research but I'm not an expert in jQuery, Spring... So it's all pretty complicated for me. A tip, or a working example would help me a lot.
It's a pretty complex form (a timesheet). There are +/- 50 textboxes on one page (minimum, depends on the number of tasks available)
Thanks.
I don't know what spring mvc is, but in ASP.NET MVC I would do the following:
I assume all your data is in a form, you give the form an ID, then post it:
$(function () {
var timer = 0;
$(this).mousemove(function(e){
timer = 0;
});
$(this).keypress(function() {
timer = 0;
});
window.setInterval(function () {
timer++;
if (timer == 20) {
$('#form').submit(function() {
});
}
}, 1000);
});
Checks for mousemove, keypress, if this isnt done in 20 seconds then it saves the form.
Edit: What you could also do maybe is, after every textbox they fill in, post the data: as followed:
http://api.jquery.com/change/
$('.textbox').change(function() {
$.ajax({
url: '/Save/Textbox',
data: 'TextBoxId=' + $(this).id + '&TextValue=' + $(this).value
});
});
In this example, you make a controller called Save, action called Textbox, you give the textbox the ID of data that it has to save, and on change (after un focussing the textbox), it posts the textbox id, and the value of the box.
then in the controller you retrieve it:
public void SaveText(string TextBoxId, string TextValue) {
// SAVE
}
Below Js script will help you to make ajax call when ever form field changes.
<script>
$(document).ready($('.form-control').change(function() {
$.ajax({
type : "post",
url : "http://localhost:8521/SpringExamples/autosave/save.htm",
cache : false,
data : $('#employeeForm').serialize(),
success : function(response) {
var obj = JSON.parse(response);
$("#alert").text(JSON.stringify(obj));
$("#alert").addClass("alert-success");
},
error : function() {
alert('Error while request..');
}
});
}));
</script>

Prototype Ajax.PeriodicalUpdater inserts empty string when server unreachable

I'm using the following to grab some updated HTML and insert it into a div with id "content"
var updater = new Ajax.PeriodicalUpdater('content', '/Doc?'+d.getTime(),
{
method: 'post',
frequency: 5,
});
The problem is that when the server is shut down (it's running inside of an app that is modifying and server up the data), the updater then simply clears out the content div.
Is there a way to make it so that when PeriodicalUpdater times out, gets a 404, etc. it just leaves the content unchanged? I would rather that the last available data just stay there, not be erased.
For completeness, this is my entire code:
<html>
<head>
<title></title>
<script type="text/javascript" src="/Prototype"></script>
<script type="text/javascript">
var css;
var css_data;
function load_content()
{
var d = new Date();
css = document.createElement('style');
css.setAttribute('type', 'text/css');
if(css.styleSheet) { css.styleSheet.cssText = '';} //Because IE is evil
else { css_data = document.createTextNode(''); css.appendChild(css_data); } //And everyone else is cool
document.getElementsByTagName("head")[0].appendChild(css);
var updater = new Ajax.PeriodicalUpdater({success: 'content'}, '/%doc_path%?'+d.getTime(),
{
method: 'post',
frequency: 5,
onSuccess: function(transport) {
new Ajax.Request('/%css_path%?'+d.getTime(), {
method: 'post',
onSuccess: function(transport) {
if(css.styleSheet) { css.styleSheet.cssText = transport.responseText}
else {
var new_css_data = document.createTextNode(transport.responseText);
css.replaceChild(new_css_data, css_data);
css_data = new_css_data;
}
}
});
new Ajax.Request('/%title_path%?'+d.getTime(), {
method: 'post',
onSuccess: function(transport) {
document.title = transport.responseText;
}
});
}
});
}
</script>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
load_content();
</script>
</body>
</html>
As you can see, I tried Triptych's solution...but still no go. It updates with blank data when the request fails still. Since I've got the whole thing here now, can anyone see any mistakes I'm making.
Note: Ignore the strings like %doc_path%... those are just control strings I use so that they can later be replaces programmatically with the proper path for each document...all stuff that's done on the server and really doesn't matter for this.
#Vinze
According to the documentation, onFailure is "Invoked when a request completes and its status code exists but is not in the 2xy family. This is skipped if a code-specific callback is defined, and happens before onComplete."
But if the server was stopped, wouldn't it just time out and there be no status code at all? Maybe I'm understanding that wrong...
Pass an object (not a string) as the first parameter to PeriodicalUpdater. The value keyed as 'success' will only be called on successful AJAX calls.
new Ajax.PeriodicalUpdater({success: 'content'}, '/Doc?'+d.getTime(),
{
method: 'post',
frequency: 5,
});
More on Ajax.Updater (from which PeriodicalUpdater inherits)
you can add a onFailure option in the option list as the Ajax.PeriodicalUpdater inherits the properties of Ajax.Request (http://www.prototypejs.org/api/ajax/request)
In the opposite you may be more interested in the use of "onComplete" or any of the "Request life-cycle" in the link below
How about doing it all by yourself?
Start with a function that will call the update:
function requestMoreInfo(){
new Ajax.Request('url',
{
method:'get',
parameters: "someget=here",
onSuccess: handleTheReturn
});
}
Then create a function that will handle the answer from the server:
function handleTheReturn(reply){
var newMessages = eval('(' + reply.responseText + ')');
//update your element or whatever
}
And then run it every 20(or whatever) seconds with:
new PeriodicalExecuter(requestMoreInfo, 20);
Then just add a first requestMoreInfo to your onload function and your good to go... now to solve your problem, just validate the newMessages var in the handleTheReturn function and you can do anything you want(make the server send a JSON object to know is ok, or some other codes maybe, or search for the specific errors you want to avoid!
More details on this.
Ajax.PeriodicalUpdater does not inherit from Ajax.Updater, as explained on http://www.prototypejs.org/api/ajax/periodicalupdater:
Ajax.PeriodicalUpdater is not a specialization of Ajax.Updater, despite its name.
It does forward the optional parameters to Ajax.Updater (itself a class that inherits from Ajax.Request), which does seem to imply that it is equivalent to instantiating an Ajax.Request and passing callbacks to it.
I have tested and can confirm that adding a onFailure function does not work in this case. Nor does adding onException.
Both could have been expected to work, since they are passed to the Ajax.Updater object instantiated by the Ajax.PeriodicalUpdater. However, after some debugging, it appears that Ajax.Updater never considers an unavailable server as an exception or a failure. That is, the container for success is always updated (well, emptied, in this case), even when defined as {success : 'content', failure : 'failureContent'}.
Also, according to my tests, Ajax.Updater (and Ajax.PeriodicalUpdater) calls neither onSuccess() nor onComplete() when the server does not respond.
In fact, the only callback I managed to get is on0, as follows:
new Ajax.PeriodicalUpdater('content', 'url', {
frequency: 5,
on0: function(requester, exception) {
alert("ERROR 0");
}
});
It appears that 0 is the error code for Ajax.Request (the parent class for Ajax.Updater) when the server is not reachable.
The bad news, however, is that on0() is called before the content is updated/emptied, meaning that it is impossible to replace that content with a custom one.
As far as I can tell, in the case of the server being unreachable, no optional callback at all is called after the content is updated.
This is true both for Ajax.PeriodicalUpdater and Ajax.Updater. Meaning that the only way I see to get the wanted behavior is to use Ajax.Request directly.

Resources