Rails 4: Testing out AJAX .click and .load - javascript

Hi I am trying to display text from another html document with AJAX in my rails app. I just wrote this small piece of code because I'm trying to learn AJAX. Can someone please explain to me what's going wrong with this piece of code?
Stepone.htm.erbl
<div class="margin-top">
<div class="container">
<h1> Do you like Math or Science </h1>
<br>
<div class="row">
<div class="col-4">
<button id="math1-1"> Math </button>
</div>
<br>
<div class="col-4">
<button> Science </button>
</div>
</div></div></div>
<br><br><br><br><br><br><br>
<script>
$(document).ready(function(){
$("#math1-1").click(function(){
$("#math1").load("math_1.html");
});
});
</script>
Math_1.html.erb
<div class="margin-top">
<div class="container">
<h1> Do you like Math or Science </h1>
<br>
<div id="math1">
Math_1
</div>
</div></div>

Because you're learning, let me give you some ideas:
Ajax
Ajax (Asynchronous Javascript And XML) is a type of functionality inside JQuery (it's pure XML Header Request / XHR in javascript). It basically sends a "pseudo-request" to an endpoint in your application, receiving & processing the response
The beauty of ajax is its asynchronous nature (working independently of any processes) - meaning you can use it to send a request "out of scope" of the typical application flow:
Typically used to create the appearance of providing the user with the ability to "interact" with the webpage (without it reloading), ajax has become prolific, not least due to JQuery's assimilation of the $.ajax() functionality into a single call
In simple terms - Ajax provides you with the ability to load & process a request on your front-end. This means if you want to use it, you need to be able to firstly have a way to process the result, and then ensure you're able to manage the response (typically by amending your DOM)
--
Structure
Since this is posted in the Rails section, let me give you some ideas on how to correctly get Ajax working with Rails. You need several important elements:
An endpoint
A backend controller action
A way to handle the response
You first need an endpoint. Simply, this is a route which will direct your ajax request to a specific controller action. The route itself is not important (Ajax is literally just a way to send "pseudo" requests to your system). What is important is the action the route will lead you to:
#config/routes.rb
resources :your_controller do
collection do
get :birthdays
end
end
#app/controllers/your_controller.rb
Class YourController < ApplicationController
respond_to :js, :json, :html, only: :birthdays
def birthdays
#birthdays = Model.where(birthday: Date.today)
respond_with #birthdays
end
end
This means that if you want to send an ajax request to the controller, you'll be able to do the following:
#app/assets/javascripts/application.js
$.ajax({
url: "/your_controller/birthdays",
success: function(data) {
$("#your_element").html(data);
}
});
--
Fix
As mentioned by EasyCo, the answer for you is to make sure you have an element to append your new data to. This is relatively simple, but I also want to discuss the importance of keeping your javascript unobtrusive with you
You should always put your javascript into the asset pipeline of Rails (IE /app/assets/javascripts/xxx.js). There are many reasons for this (DRY, Convention over Configuration), but the most important thing is to keep your application modular
Modularity is what gives great applications a natural "flow" and structure, allowing you to use / reuse as many functions as you require throughout the app. It is for this reason why I highly recommend you include any javascript in the respective JS files - as these then act as dependencies for your browser-based pages
So in essence, you'll want the following:
#app/assets/javascripts/application.js
$("#math1-1").on("click", function(){
$("#math1").get("/maths/1");
});
#app/views/maths/index.html.erb
<%= link_to "1", math_path("1") %>
<div id="math_1"> </div>

You need a DOM element with id="math1" in your Stepone.html.erb file.
You're trying to load math_1.html but it can't find an element with ID of math1 in Stepone.html.erm. It therefore doesn't load math_1.html because it has nowhere to append the data.
Change Stepone.html.erb to:
<div class="margin-top">
<div class="container">
<h1> Do you like Math or Science </h1>
<br>
<div class="row">
<div class="col-4">
<button id="math1-1"> Math </button>
</div>
<br>
<div class="col-4">
<button> Science </button>
</div>
</div></div></div>
<br><br><br><br><br><br><br>
<div id="math1"></div> <!-- AJAX will get loaded in this div -->
<script>
$(document).ready(function(){
$("#math1-1").click(function(){
$("#math1").load("math_1.html");
});
});
</script>

Related

What is the standard approach to creating DOM Elements from an Ajax Response

What are some standard approaches to load up a repeating DOM structure from an Ajax JSON object?
This is a plain jQuery application.
Example: I have a complex DOM structure corresponding to a "Question",
<div class="list-group">
<a class="someClass data=toggle="collapse">
<span class="someSpanClass">**QuestionTopLevel**
</span>
<div class="someDivClass">
<div class="someSubDivClass">
**QuestionSubElement1**
</div>
</div>
<div class="someDivClass">
<div class="someSubDivClass">
**QuestionSubElement2**
</div>
</div>
</a>
</div>
In this example my dynamic placeholders (marked with **) are QuestionTopLevel, QuestionSubElement1, QuestionSubElement2.
The Ajax response coming back from the server is of the type
"QuestionTopLevel" : { "QuestionSubElement1", "QuestionSubElement2" }
I can manually try to insert/remove DOM elements in jQuery using $('..').insertAfter(..) but that has some problems:
Too verbose, there are lots of DOM sub-structures in this "repeater"
What if the structure changes?
Is there some standard tool or technique to deal with DOM "repeater" structures from an Ajax JSON response?
I'd recommend a babel/JSX frontend framework, but you could try something like this:
var $new_el = $('<div/>');
then add classes and append whatever html into it that you want...
$new_el.addClass('thisclass')
$new_el.append( $('<span>a nice little bit of html</span>') );
then append or insert it into an element in your DOM (the body in this case)
$('body').append($new_el);

how to create string resource manager system in web application by jquery?

I am in beginning of a web project and I want to read my web site stings such as labels, title of pages, placeholder and ... from a json file. i think this approach may help me to increase my speed in changes and create a multi language web site.
is there any jquery library for doing this? and if ther is not how can i do this work by jquery?
You can make mustache templates and populate them with data using handlebars.js:
http://handlebarsjs.com/
Mustache templates use curly braces as placeholders and handlebars uses the json format to hold the data. It could look something like this (though not a full working example):
HTML:
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
Javascript:
var context = {title: "My New Post", body: "This is my first post!"};
var html = template(context);
Result:
<div class="entry">
<h1>My New Post</h1>
<div class="body">
This is my first post!
</div>
</div>
Here is a working example: https://jsfiddle.net/k4u64exL/
What you're searching for is a Javascript/jQuery Template Engine - there are lot of them (start e.g. with http://www.sitepoint.com/10-javascript-jquery-templates-engines/ ).
If you want to write your own template engine try the following:
1) Fetch JSON-Data with Ajax
2) Fetch Template with Ajax
3) Apply variables from JSON-File to Template File (simple replace)
4) Append the result to the current page.

Watir Random Popup

High all, I'm testing this e-commerce and I get this random popup (it's a div)that gets in the way of my scripts, given its random appereance I can't relly predict when it's going to show, otherwise I can easily interact with it, as it is a simple div, whenever I see it. It's there a way that can I catch this popup and do as I please whenever it dares to show? Thanks in advance
<div class="fsrFloatingMid"><div class="fsrInvite">
<div class="fsrDialogs">
<div style="margin-left: 0px;" class="fsrDialog ">
<div class="fsrLogos">
<img src="/_ui/desktop/common/foresee/sitelogo.gif" alt="" class="fsrSiteLogo">
<img src="/_ui/desktop/common/foresee/fsrlogo.gif" alt="Foresee" class="fsrCorpLogo">
</div>
<h1 class="fsrHeading">We'd welcome your feedback!</h1>
<p class="fsrBlurb">Some bullshit text</p>
<p class="fsrSubBlurb">The survey is designed to measure your entire experience, please look for it at the <u>conclusion</u> of your visit.</p>
<p class="fsrAttribution">This survey is conducted by an independent company, on behalf of the site you are visiting.</p>
<div style="" class="fsrB">
<div class="fsrAcceptButtonContainer">
Yes, I'll give feedback<span class="hidden-accessible"> (this will launch a new window)</span>
</div>
<div class="fsrDeclineButtonContainer">No, thanks
</div>
</div>
<div class="fsrFooter">
<img src="/_ui/desktop/common/foresee/truste.png" alt="TRUSTe verified" class="fsrTruste">
</div>
</div>
</div>
×<span class="hidden-accessible">Click to close.</span>
If this pop-up appears randomly then I think using the "protection proxy" design pattern would help most. The purpose of it is to execute a particular piece of code, in our example this:
if browser.div(class: 'fsrDialogs').exists?
browser.a(class: 'fsrCloseBtn').click
end
BEFORE any method on the "subject" ("subject" is the object we wrap inside the Proxy class, in our case it's the browser) is called. The Proxy design pattern is pretty straightforward to implement in Ruby, here's how we'd do it in your particular case:
class WatirProxy
attr_reader :subject
def initialize(browser)
#subject = browser
end
def method_missing(method, *args)
puts "I am executing the code below before calling #{method} with args #{args}"
if subject.div(class: 'fsrDialogs').exists?
subject.a(class: 'fsrCloseBtn').click
end
subject.send(method, *args)
end
end
You can remove the puts below method_missing in production, however, I'd recommend you keep it for now if you're not 100% clear on how the code below works.
Let's try playing with it:
browser = WatirProxy.new(Watir::Browser.new(:chrome)) # you can use ANY method on browser, although it's wrapped in a proxy
browser.goto 'https://google.com'
puts browser.text_field(name: 'q').exists?
Ruby should output:
I am executing the code below before calling goto with args ["https://google.com"]
I am executing the code below before calling text_field with args [{:name=>"q"}]
true # May change if google search box 'name' attribute changed to something other than 'q' in the future
In your specific case, this pop-up is raising errors because the browser didn't expect it, now we make sure there's a check BEFORE ANY method on browser is called. A great book for reading about the Proxy design pattern (and some other useful ones in Ruby) is Design Patterns in Ruby by Russ Olsen.
#browser.link(class: "fsrCloseBtn").click if #browser.h1(class: "hsrHeading").visible?
Something like this should be enough. Obviously, sub whatever you name your WebDriver instance for #browser. This clicks the close link if the dialog is visible and skips this step if the dialog is not there. My syntax might be a little wrong, so double check that. I'm used to wrapping all this in page-object, which would look like:
page_class.close_dialog if page_class.dialog_header_element.visible?
Had same issue with Foresee survey, I got around it by adding
while browser.text.include?("We'd welcome your feedback!") == false do
browser.refresh
sleep 1
end
browser.link(:class => /declineButton/).click
end
to the first step after going to the page. It's not the best option but it deals with the Foresee because once you close the window you get a fsr cookie that prevents the survey from popping up again during that browser session. The "sleep 1" was added so chrome would slow down and look for the Foresee survey. Hope it helps.

Render cherrypy's template with id/hash

How would I render a page and go to a specific id?
Right now I have a following function with this code:
#cherrypy.expose
#require
def page():
tmpl = lookup.get_template('page.html')
return tmpl.render()
However, now the page.html does have several subpages, which I can access through URL like mydomain.com/page#someid.
Is there a way to render a template to go directly to the id?
I think that you are mixing the ideas, the # part of the URL is the client duty to focus in the specific element id. Nevertheless, I suppose that you want to do that to dynamically embed chunks of a particular part of the page trough javascript, I can think on two possibilities:
One, compose the full page template with the different ids from different sub-templates, this is easy if you are using a template module, like mako, and make a cherrypy handler to return the indivudual parts, this is of course supposing that you are in control of the content of the page and the ids are not dynamic (generated from a db or something) and the main site is a bunch of includes.
#cherrypy.expose
def page_part(section):
tpl_name = 'page_%s.html' % section
# validate that the template exists, then:
tmpl = lookup.get_template(tpl_name)
return tmpl.render()
Mako templates:
page.html:
<html>
<body>
<div id="main">
This is the main content of the site!
</div>
<h4>Sections</h4>
<div id="section_1">
<%include file="page_section1.html" />
</div>
<div id="section_2">
<%include file="page_section2.html" />
</div>
</body>
</html>
page_section1.html:
<p> Content of section 1</p>
page_section2.html:
<p> Content of section 2</p>
Or two, use jQuery selectors or something similar to request the page once and make the sub-selects in the returned html.
$.get('/page.html',
function(data){
$('#this_page_id').html($('#sect_in_other_page', $(data)).html());
});

Should I use template or return full code in jquery AJAX?

I am currently working on a project that lets users post comments with jquery and ajax. So far it is using Json and retunring several items, username, comment text, user photo url, comment ID number and stuff like that, I then need to use some sort of template to make all this data go into the correct div's before adding it all to the screen.
I am new to using javascript so this is a hard task for me. I am now considering the easy route.
Just have my PHP backend script return the whole block of code, div's and everything in place but I am wondering is this a bad idea? More importantly is it a bad idea with json?
Here is an example of a block of code that needs to be added to the screen when a comment is posted
<li class="admin" id="comment-1371">
<div class="photocolumn">
<!-- START Photo block -->
<div class="imageSub" style="width: 100px;">
<img class="male" src="http://cache2.mycrib.net/images/image_group34/0/39/T_653807517aff2b1f5662d865b40d87d527c8eb.jpg" alt="Something" width="100"/>
<div class="blackbg"></div>
<div class="label">JasonDavis</div>
</div>
<!-- END Photo block -->
</div><!-- END photocolumn -->
<div class="commenttext">
<p>02/12/3009</p>
<p>sample text for comment area!</p>
</div>
<!-- END COMMENTTEXT -->
</li>
I would say it depends on the situation/application. For instance I would use json and templating for a flight/hotel etc result screen. Why return 50k's worth of the same markup when a 4k json object will do and will allow for rapid clientside sort/filter. If you dont need quick clientside filtering/sorting then responding with dom fragments is ok. Horses for courses.
I don't see a problem with returning HTML via AJAX. A bonus of this is that you can generate most of the HTML in a view in PHP and still keep things fairly clean.
Tokenizing your data into an object is nice for re-use but can be overkill for a one-off.
Go the easy route, I can see no reasons of going with JSON array.

Categories