I apologize in advance as I am fairly good with PHP, but when it comes to javascript and jquery, I really am a bit clueless. I have the following code, which I edited from the example found here https://gist.github.com/boucher/1750375, and wanted to combine the credit card exp month and year field into one. The issue is splitting them back apart to use with the stripe example code where it creates a token. Obviously the example on github works perfectly but when I attempt to edit, the script doesn't act like anything is wrong but doesn't submit to stripe and retreive the token as before.
$(document).ready(function() {
$("#payment-form").submit(function(event) {
// disable the submit button to prevent repeated clicks
$('.submit-button').attr("disabled", "disabled");
var expgroup = document.getElementById('date-exp').val;
var expArray = expgroup.split( '/' );
var expmm = ( expArray[ 0 ] );
var expyy = ( expArray[ 1 ] );
// createToken returns immediately - the supplied callback submits the form if there are no errors
Stripe.createToken({
number: $('.cc').val(),
cvc: $('.card-cvc').val(),
exp_month: expmm,
exp_year: expyy
}, stripeResponseHandler);
return false; // submit from callback
});
});
This won't work.
var expgroup = document.getElementById('date-exp').val;
use this instead:
var expgroup = $("#date-exp").val()
Also "cc" is id and not a class.
You need to use:
$("#cc").val()
and not:
$(".cc").val()
document.getElementById('date-exp').val
Is a mixture of jQuery and DOM idiom. It should either be:
document.getElementById('date-exp').value
or:
$('#date-exp').val()
Also consider checking that / is actually in the value (ie that expArray.length===2).
Stripe's jquery.payment library has this function built into it already:
https://github.com/stripe/jquery.payment#paymentcardexpiryvalstring-and-fnpaymentcardexpiryval
Here's some sample code.
# form fields on HTML.ERB page
<%= form_tag url do %>
<%= text_field_tag :expiry, nil, name: nil, placeholder: "MM / YYYY", size: 9, id: "stripe-card-expiry" %>
<%= hidden_field_tag :exp_month, nil, name: nil, id: "stripe-card-exp-month", data: { stripe: "exp-month" } %>
<%= hidden_field_tag :exp_year, nil, name: nil, id: "stripe-card-exp-year", data: { stripe: "exp-year" } %>
...other fields and submit...
<% end %>
# Split single expiration field into month/year
expiration = $("#stripe-card-expiry").payment("cardExpiryVal") # => {month: "value", year: "value"}
$("#stripe-card-exp-month").val(expiration.month || 0)
$("#stripe-card-exp-year").val(expiration.year || 0)
# Submit to Stripe.com and get token
Stripe.card.createToken($("#form-id"), handleStripeResponse)
Depending on which version of Stripe.js you are using, if you use the "data-stripe..." items Stripe.js will automatically grab the values from the hidden fields.
Related
I have a form for multiple pupils, with checkboxes next to each pupil to collect their IDs. I'm trying to have two buttons that each lead to different forms, and I've tried submitted params with the button click but to no avail:
simple_form_for - multiple submit buttons with different params
Is there any way to write some JS that adds a parameter to the params before submitting the form? My form is as follows:
<%= simple_form_for :pupils, url: edit_multiple_school_group_pupils_path(school, group) do |f| %>
...
...
<%= f.button :submit, 'Change Levels', name: 'editing', value: 'levels' %>
<%= f.button :submit, 'Move to A Class', name: 'editing', value: 'classes' %>
<% end %>
Each of the buttons have their own ID in the raw HTML so I'm hoping theres a way to pluck that before the form gets submitted and add it to the params.
I'm extremely green with JS so wouldn't even know where to start. Thanks in advance.
I'm not 100% sure what is needed for the rails portion, but it sounds like you want to serialize your form.
This is fairly easily accomplished. Here is an example of what a serialize to JSON function might look like
function toJSONString( form ) {
var obj = {};
var elements = form.querySelectorAll( selectors );
for( var i = 0; i < elements.length; ++i ) {
var element = elements[i];
var name = element.name;
var value = element.value;
if( name ) {
obj[ name ] = value;
}
}
return JSON.stringify( obj );
}
The selectors can be pretty much whatever you want within your form. Inputs, textareas, buttons etc.
Hope this helps!
My app has a live search implemented and it works properly. The problem that I have is that now I have a table with a lot of columns and I want to search through all elements. I want to have only one text input and a drop down that will select the column that I want to search in.
Searchable module
module Searchable
extend ActiveSupport::Concern
module ClassMethods
def search_for(present_column,record)
record.present? ? where(present_column+' LIKE ?', record+"%") : all
end
end
end
People controller
class PeopleController < ApplicationController
def index
#people = Person.page(params[:page]).per(5).search_for(params[:object_columns], params[:search])
end
The search engine
<%= form_tag do %>
<% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
<%= select_tag :object_columns, options_for_select(valid_column_names) %>
<%= text_field_tag :search, '', autocomplete: :off %>
<% end %>
The live search js
$(function () {
$("input#search").keyup(function () {
$.get($("#object_columns option:selected").text(), $("#object_columns").serialize(), null, "script");
$.get($("#search").attr("action"), $("#search").serialize(), null, "script");
});
});
The input text is returned as expected, but nothing comes from the object_columns. When I type the word "n", for example, my server terminal returns this message:
Started GET "/people?&search=n&_=1463081307356" for 127.0.0.1 at 2016-05-12 16:28:34 -0300
Processing by PeopleController#index as JS
Parameters: {"search"=>"n", "_"=>"1463081307356"}
EDIT:
I had an idea later on and made some changes. I gave the form an ID and used it to do the request, now I can have both information (column names and the search record) at the same time. The only problem now is with the path, it is returning an URI error.
The search engine
<%= form_tag people_path, class: "form_id" do %>
<% valid_column_names = target.column_names.reject{|r| r == "created_at" || r == "updated_at" || r == "slug"} %>
<%= select_tag :object_columns, options_for_select(valid_column_names) %>
<%= text_field_tag :search, '', autocomplete: :off %>
<% end %>
The live search
$(function () {
$("input#search").keyup(function () {
$.get($(".form_id"), $(".form_id").serialize(), null, "script");null, "script");
});
});
In your search_for method, the return value is always all. You really want the return value to be the result of the ternary operator directly above it. Remove the last all and you should be good to go.
module ClassMethods
def search_for(present_column,record)
record.present? ? where(present_column+' LIKE ?', record+"%") : all
# all <== this should be removed
end
end
In your javascript, you'll need a few changes:
$(function () {
function search() {
$.get("/search", { column_name: $("select#column_name").val(), search: $("#search").val() }, null, "script");
};
$("select#column_name").change(search);
$("input#search").keyup(search);
});
The actual Ajax call has been changed to:
remove the undefined "action" attribute on the search input field
explicitly reference the URL to send the request
create hash parameters for the ajax call
remove the unnecessary calls to serialize()
This also installs a handler on the change event of the column selection, hence the refactoring of the Ajax call to a separate function.
I'm trying to obtain the selected date from a date_select:
<%= form_for(#newevent) do |f| %>
<%= f.date_select :day, { id: "date-select"} %>
<button id="check-button" type="button">Check</button>
<% end %>
using JQuery/Javascript:
$(document).on('click', "#check-button", function(){
var selectedDate = $("#date-select").val();
alert(selectedDate);
var checkList = []; //creates array to store customer ids
$("#check-list li input").each(function(){ //for each listed colleague...
if( $(this).is(":checked")){ //if check-box is ticked
checkList.push($(this).val()); //add id to list
}
});
$.ajax({
url: '/events/check',
data: {checkList: checkList , selected_date: selectedDate },
method: "POST"
}
);
});
for reference here is where :day is defined in my migration file:
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.timestamps
t.references :calendar, foreign_key: true
...
t.date :day
...
end
However, on alert the returned value is "undefined". Why is this happening? I would like it to return the a value in the form YYYY-MM-DD. Apologies if this is obvious, but I am new to programming and can't seem to fix this one myself
Date_select, according to the rails api "Returns a set of select tags (one for year, month, and day)". Your javascript is going to have to deal with three separate selects and construct a date from them. Look at your generated HTML to get the id's.
On the page that contains my order form, in the <head>, I have:
= jquery_include_tag Rails.application.config.jquery_version
= javascript_include_tag "https://js.stripe.com/v2/"
:javascript
$(function(){
Stripe.setPublishableKey('pk_test_NEgBLhQ1dJGvlE8SDFEXqRQ4');
});
(function() {
var stripeResponseHandler;
$("#new_order").submit(function(event) {
var form;
form = $(this);
form.find("#submit_order").prop("disabled", true);
Stripe.createToken(form, stripeResponseHandler);
return false;
});
stripeResponseHandler = function(status, response) {
var form, token;
form = $("#new_order");
if (response.error) {
form.find(".payment-errors").text(response.error.message);
form.find("#submit_order").prop("disabled", false);
} else {
token = response.id;
form.append($("<input type=\"hidden\" name=\"stripeToken\">").val(token));
form.get(0).submit();
}
};
}).call(this);
The key you see listed above is labelled "Test Publishable Key" at https://manage.stripe.com/account/apikeys.
The form on that page includes:
= simple_form_for #order, :html => {:id => "new_order"} do |f|
= f.error_notification
= text_field_tag :number, nil, :name => nil, "data-stripe" => "number"
= text_field_tag :cvc, nil, :name => nil, "data-stripe" => "cvc"
= text_field_tag :expiry_month, nil, "data-stripe" => "exp-month"
= text_field_tag :expiry_year, "data-stripe" => "exp-year"
= f.button :submit, :as => :button, :id => 'submit_order'
(With all the labels/placeholders/etc and non-Stripe fields stripped out.)
At present I am running this in development mode on localhost without any SSL.
When I complete an order with valid or invalid credit card data and click Create Order, my Rails app logs an order but the Javascript does not seem to communicate with the Stripe server. I see no errors -- or any Javascript activity at all as far as I can tell -- in Chrome's Javascript console. And I see no charges -- successful or otherwise -- at https://manage.stripe.com/test/events.
I know my way around Rails but am a Javascript novice. How can I diagnose what's going on here? And what might be the cause?
(function() {
This should maybe be
$(function() {
(and you can ditch the .call(this) stuff)
It's executing immediately in the <head>, which probably means $("#new_order") isn't finding the form — the browser hasn't even rendered it, or possibly even received the HTML for it off the network, yet — so the selector matches zero items, and the event binding is a no-op.
Alternatively, if you put the code just before your </body>, that'd do the trick, too.
(Also, putting the Stripe.setPublishableKey() in a $(function() { … }) block is not useful.)
I have this form that renders a partial for selecting a person's task.
new.html.slim:
= form_for(#person) do |f|
= f.text_field :name
= f.fields_for :assignment do |a|
= a.collection_select :project_id, Project.order(:name), :id, :name
div id="task_list"
= render 'shared/_task_select', a: a
= f.submit 'Save'
shared/_task_select.html.slim:
= a.collection_select :task_id, #tasks, :id, :name
Changing the project triggers a javascript that runs a "create_tasklist"-method in the PersonsController.
new.js:
$(document).ready(function() {
$('#person_assignment_attributes_project_id').change(function() {
var selection = $('#person_assignment_attributes_project_id').val();
$.ajax({
url: "/create_tasklist",
data: {
project_id : selection
},
dataType: "script"
});
});
});
The "create_tasklist"-method triggers a javascript that updates the partial:
create_tasklist.js.erb:
$("#task_list").html("<%= escape_javascript(render 'shared/task_list', a: a) %>");
Now this raises the error:
undefined local variable or method `a' for #<#<Class:0x42cd770>:0x4213ef0>
The same form works well when editing existing persons - until changing the project. Thus, FormBuilder "a" loses its definition through the javascript actions. I have to use a partial here because I want to do more stuff with it in a later stage. Any ideas how to get that variable to keep its defintion?
Edit 1:
I already tried adding this below the third line of new.html.slim:
javascript:
var a = "#{a}";
and then adding: a: a in the "data" declaration of new.js.
Edit 2:
With this the FormBuilder seems to pass through until the "create_tasklist"-method, but I do not know how to access it properly there. If I declare ´#a = params[:a]´ in the "create_tasklist"-method and then use (in create_tasklist.js.erb):
$("#task_list").html("<%= escape_javascript(render 'shared/task_list', a: #a) %>");
I recieve the error:
undefined method `collection_select' for "#<ActionView::Helpers::FormBuilder:0x4760400>":String
So the FormBuilder has become a string but a least it "got through" somehow. How can I leave it intact and is a more efficent way to achieve this?