Markup or Trick? Nested forms - html

There are interesting task: my active record 'Event' entity can contain one 'Attachment' PDF file. On the Create Event page, user can Upload this attachment BEFORE Submits that Event. Attachment uploads to Amazon via Ajax, progress-bar displays etc blablabla.
It should be displayed in_a_way:
= form_for #event do |e|
= e.text_field :name
= form_for #attach, :remote=>true, html=>{:multipart=>true} do |at|
= at.file_field :pdf, :accept=>"pdf", :size=>"1"
= at.submit
= e.submit
Yes, this is just pseudo-code, and I don't mind how it can work, but the main idea is presents: [Submit Attachment] button should be placed inside the Event form.
How I can implement it? Maybe, just make some offset to nested Attachment form so it will be displayed inside Event form, or there are any others solutions?
..........................................................................................................

Solution: override form headers
This is a form for creating new event.
Inside this form, we need ajax file uploading.
There is a solution: mixing single form between two different types of submits: ajax(js) and html:
= form_for #event, html=>{:multipart=>true} do |e|
= e.text_field :name
= file_field_tag "attach[pdf]", :id=>"attach_pdf", :accept => "pdf", :maxlength => "200"
= submit_tag "", :id => "ajax_submit", :style=>"display:none"
= e.submit <!-- id = "new_event_submit" -->
////////////////////////////
// before 'submits' call override functions:
$("#ajax_submit").click(function(){
prepeareFormForAjax();
return true;
});
$("#new_event_submit").click(function(){
prepeareFormForHtml();
return true;
});
//////////////////////////////
// to store original (previous, html) form data
var html_form_action = "";
var html_form_method = "";
///////////////////////////////
/*
* To ajax file upload:
**/
function prepeareFormForAjax() {
$("form").attr("data-remote", "true");
$("form").attr("enctype", "multipart/form-data");
html_form_action = $("form").attr("action"); // save old action
$("form").attr("action", "/attach"); // I need /nors action
//_method field is a hidden form field, maybe you have it too on the page:
if ($('input[name="_method"]').length != 0) {
html_form_method = $('input[name="_method"]').val();
$('input[name="_method"]').val("post");
}
}
function prepeareFormForHtml() {
$("form").removeAttr("data-remote");
$("form").removeAttr("enctype");
if (html_form_action != "") {
$("form").attr("action", html_form_action);
html_form_action = "";
}
if (html_form_method != "") {
$('input[name="_method"]').val(html_form_method);
html_form_method = "";
}
}
///////////////////////
Now, to upload file via AJAX use:
$("#ajax_submit").click();
any questions?

Related

How to deal with if statement when one Form Response has no response in Google Script?

I'm trying to create a script that sends an email when someone submits a google form. The form includes an optional file upload that the script will then attach to the email as a pdf.
The issue I'm facing is how to ignore the process that creates the attachment if the response is empty.
Sample code below
function getIdFrom(url) {
var id = '';
var parts = url.split(
/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/
);
if (url.indexOf('?id=') >= 0) {
id = parts[6].split('=')[1].replace('&usp', '');
return id;
} else {
id = parts[5].split('/');
var sortArr = id.sort(function (a, b) {
return b.length - a.length;
});
id = sortArr[0];
return id; //returns google doc id.
}
}
function onFormSubmit(response) {
var link = response.namedValues['Upload file'];
if (typeof link !== "undefined" && link.length > 0) { // I think it's here that's the issue
var uploadFileId = getIdFrom(link[0]);
var uploadFile = DriveApp.getFileById(uploadFileId);
var uploadFileType = (function () {
if (uploadFile.getMimeType().includes('image')) {
return uploadFile.getMimeType();
} else {
return 'application/pdf';
}
};
var attachArr = [uploadFile.getAs(uploadFileType)];
}
// etc etc send email.
}
Works fine if the user submits a form with an uploaded file.
However if the form is submitted without entering anything in the "Upload File" question, I'm getting a "TypeError: Cannot read property 'split' of undefined" at the getIdFrom(url) function I assume because it's still trying to pass link through getIdFrom() even though it shouldn't because it's undefined.
Weirdly it works perfectly fine when I use the two test inputs I have, one of which 'Upload File' exists but is empty and the other it doesn't exist at all.
I'm not sure what I'm missing here.
Also I have no doubt it's a messy way to do things but I'm getting there.
response.namedValues['Upload file'] is an object
even if it's empty it will have at least the length of >0
Workaround
Modify your if statement to
if (link[0].length > 0) {
...
}

JSON callback function to show an album cover

I am working on a task to learn how to use JSON. I am trying to link to spotify's API via a search, get an artists albums and show them on the webpage. I am a beginner and do not know what I am missing in the data / callback function to create the correct html to show on my page. If anyone has time to point me in the right direction, it would be appreciated.
$(document).ready(function() {
// Creating the AJAX Request
//
$('#search').submit(function(event) {
// Stop the form from submitting
event.preventDefault();
// Get The value from the form
var SpotifyURL = "https://api.spotify.com/v1/searchjsoncallback=?";
var artist = $('#search').val();
var artistOptions = {
"type" : "album",
"q" : "artisit"
};
function displayAlbums(data) {
var albumHTML = '<ul>';
$.each(data.items,function(i, album) {
albumHTML += '<li class="albumInformation">';
albumHTML += '<></li>';
}); // end each
albumHTML += '</ul>';
$('#albums').html( albumHTML);
}
$.getJSON(SpotifyURL, artistOptions, displayAlbums );// end getJSON
}); // end submit function
}); // Closing Ready function

How to handle tvOS MenuBarTemplate selection?

I have a basic MenuBarTemplate set up and displaying.
How do I react to a user's Menu selection and load an appropriate content template?
In the menuItem tag include a template attribute pointing to the template to load and a presentation attribute set to menuBarItemPresenter.
<menuItem template="${this.BASEURL}templates/Explore.xml.js"
presentation="menuBarItemPresenter">
<title>Explore</title>
</menuItem>
You can then use the menu bar's MenuBarDocument feature to associate a document to each menu bar item.
menuBarItemPresenter: function(xml, ele) {
var feature = ele.parentNode.getFeature("MenuBarDocument");
if (feature) {
var currentDoc = feature.getDocument(ele);
if (!currentDoc) {
feature.setDocument(xml, ele);
}
}
This assumes you're using a Presenter.js file like the one in Apple's "TVML Catalog" sample. The load function specified there is what calls the function specified in the menuItem's presentation attribute.
I suppose that TVML and TVJS is similar with HTML and Javascript. When we want to add some interaction into the user interface, we should addEventListener to DOM.
In Apple's "TVML Catalog", Presenter.js is a nice example, but it is abstract, and it could be used in different Present actions.
When I develop my app, I had wrote this demo for handling menuBar selection.
Module : loadTemplate.js
var loadTemplate = function ( baseURL , templateData ){
if( !baseURL ){
throw("baseURL is required");
}
this.BASEURL = baseURL;
this.tpData = templateData;
}
loadTemplate.prototype.loadResource = function ( resource , callback ){
var self = this;
evaluateScripts([resource], function(success) {
if (success) {
var resource = Template.call(self);
callback.call(self, resource);
} else {
var title = "Resource Loader Error",
description = `There was an error attempting to load the resource '${resource}'. \n\n Please try again later.`,
alert = createAlert(title, description);
Presenter.removeLoadingIndicator();
navigationDocument.presentModal(alert);
}
});
}
module.exports = loadTemplate;
Module nav.js ( use menuBarTemplate ) :
import loadTemplate from '../helpers/loadTemplates.js'
let nav = function ( baseURL ){
var loader = new loadTemplate(
baseURL ,
{
"explore" : "EXPLORE",
"subscribe" : "SUBSCRIBE",
"profile" : "PROFILE",
"settings" : "SETTINGS"
}//need to use i18n here
);
loader.loadResource(`${baseURL}templates/main.xml.js`, function (resource){
var parser = new DOMParser();
var navDoc = parser.parseFromString(resource, "application/xml");
navDoc.addEventListener("select" , function ( event ){
console.log( event );
var ele = event.target,
templateURL = ele.getAttribute("template");
if (templateURL) {
loader.loadResource(templateURL,
function(resource) {
if (resource) {
let newParser = new DOMParser();
var doc = newParser.parseFromString( resource , "application/xml" );
var menuBarItemPresenter = function ( xml , ele ){
var feature = ele.parentNode.getFeature("MenuBarDocument");
if( feature ){
var currentDoc = feature.getDocument( ele );
if( !currentDoc ){
feature.setDocument( xml , ele );
}
}
};
menuBarItemPresenter( doc , ele );
}
}
);
}
});
navigationDocument.pushDocument(navDoc);
});//load from teamplate.
}
module.exports = nav;
My code is not the best practice, but as you can see, you just need to addEventListener like you are writing a web application. Then you can handle menuBarTemplate selection easily, even after XHR loading.
Avoid too many callbacks, you should rebuild your code again and again. :-)

generate check-boxes based on drop-down selection?

In my project, I have a one-to-many relation (a Client has many contacts), Now, I am listing the clients in a Drop-down menu, What i want is, To have the Selected Client's Contacts rendered dynamically as check-boxes.
Here is (the part) of my _form.html.haml, and the jQuery part that sends the Ajax request:
%h4 This meeting is made for :
= f.input :client_id, collection:(Client.all)
%br
%hr
%h4 Assign Contacts:
//HERE WHERE I REALLY WANT THE CHECKBOXES TO BE REDNERED DYNAMICALLY.
= check_box_tag "contact_ids[]", c.id, #meeting.contacts.include?(c)
= c.first_name
%br
:javascript
$(document).ready(function (){
$('#meeting_client_id').change(function(){
var state = $('#meeting_client_id :selected').val();
if(state !== "")
{
$.getJSON('/clients/client_contacts/' + state, function(data){
console.log(data);
})
}
return false;
})
});
and here is my Clients_controller action, that handles the request:
def client_contacts
client = (params[:id])
cou = Contact.where(client_id: client)
#msg = { "success" => "true", "message" => "hello", "count" => cou}
respond_to do |format|
format.html
format.json { render json: #msg }
end
end
Now, in the console, I can see that the request is returning the count, and objects.
and hence I am really new to JS/jQuery , and fairly new to Rails, I really don't know how to take it from here.
Any tips/Articles/links/Helps or advice, is really appreciated.
If the only part you're missing is the creation of checkboxes, you can try something like this;
var output = $("some selector for an element containing the checkboxes");
$('#meeting_client_id').change(function(){
var state = this.value;
if(state !== "") {
$.getJSON("/clients/client_contacts/" + state).done(function(data) {
output.empty(); // clear the container
// assuming data is an array of strings, modify as needed
$.each(data, function () {
// for each array item in the result, create a checkbox
$('<input type="checkbox" value="'+this+'">'+this+'</option>')
.appendTo(output); // append it to the container
});
});
}
});
The important parts I used here is:
$.each() for looping through arrays: http://api.jquery.com/jQuery.each/
$("<html>") syntax for creating a new element: http://api.jquery.com/jQuery/#jQuery2
.appendTo() for attaching to the DOM: http://api.jquery.com/appendTo/
Here is a demo where i'm just using a custom function to fake the ajax call.
http://jsfiddle.net/kK622/1/
try this:
$.getJSON('/clients/client_contacts/' + state, function(data){
console.log(data);
data.each(function(){
var id = data.id;
var name = data.firstName;
//add to new div with id myDiv
$('#myDiv').append('<input name='+ id +' type="checkbox" /> ' + name + '<br />');)
});
});

Couldn't make ASPJAX working

I want to make a demo on how to combine ASP and AJAX. I have found snippets from http://www.aspjax.com and implemented it in my project. However, the text that should be displayed cannot be output properly.
Here's the code. Basically the same as the one in the original:
In index.asp
<script language="javascript" type="text/javascript">
/** XHConn - Simple XMLHTTP Interface - bfults#gmail.com - 2005-04-08 **
** Code licensed under Creative Commons Attribution-ShareAlike License **
** http://creativecommons.org/licenses/by-sa/2.0/ **/
function XHConn()
{
var xmlhttp, bComplete = false;
try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
catch (e) { try { xmlhttp = new XMLHttpRequest(); }
catch (e) { xmlhttp = false; }}}
if (!xmlhttp) return null;
this.connect = function(sURL, sMethod, sVars, fnDone)
{
if (!xmlhttp) return false;
bComplete = false;
sMethod = sMethod.toUpperCase();
try {
if (sMethod == "GET")
{
xmlhttp.open(sMethod, sURL+"?"+sVars, true);
sVars = "";
}
else
{
xmlhttp.open(sMethod, sURL, true);
xmlhttp.setRequestHeader("Method", "POST "+sURL+" HTTP/1.1");
xmlhttp.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
}
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4 && !bComplete)
{
bComplete = true;
fnDone(xmlhttp);
}};
xmlhttp.send(sVars);
}
catch(z) { return false; }
return true;
};
return this;
}
// doAJAXCall : Generic AJAX Handler, used with XHConn
// Author : Bryce Christensen (www.esonica.com)
// PageURL : the server side page we are calling
// ReqType : either POST or GET, typically POST
// PostStr : parameter passed in a query string format 'param1=foo&param2=bar'
// FunctionName : the JS function that will handle the response
var doAJAXCall = function (PageURL, ReqType, PostStr, FunctionName) {
// create the new object for doing the XMLHTTP Request
var myConn = new XHConn();
// check if the browser supports it
if (myConn) {
// XMLHTTPRequest is supported by the browser, continue with the request
myConn.connect('' + PageURL + '', '' + ReqType + '', '' + PostStr + '', FunctionName);
}
else {
// Not support by this browser, alert the user
alert("XMLHTTP not available. Try a newer/better browser, this application will not work!");
}
}
// launched from button click
var getMessage = function () {
// build up the post string when passing variables to the server side page
var PostStr = "";
// use the generic function to make the request
doAJAXCall('ajaxtest.asp', 'POST', '', showMessageResponse);
}
// The function for handling the response from the server
var showMessageResponse = function (oXML) {
// get the response text, into a variable
var response = oXML.responseText;
// update the Div to show the result from the server
document.getElementById("responseDiv").innerHTML = response;
};
</script>
<body>
<button onclick="javascript:getMessage();">Get Message From Server</button>
<div id="responseDiv">Original Text</div>
</body>
So, the code tells it to replace the Original Text in the div with the one in ajaxtest.asp
In ajaxtest.asp
<%# Language=VBScript %>
Response.Write "The Server time is " & Now()
The problem is when I click the button Get Message From Server, the stuff in ajaxtest.asp is rendered as plain text, but not in ASP. How to fix this? Is it because of the extension used is wrong?
EDIT: by plain text I mean exactly as Response.Write "The Server time is " & Now()
You probably want the contents of your ASP page to be:
<%# Language=VBScript %>
The Server time is <%=Now()%>