I got a Button on HTML form (let's call it Form_A) which when clicked, opens a new window (let's call it Form_B).
When user fill in some information in Form_B form and hit submit (or just a button), I need to send some processed information back to 'Form_A' and close 'Form_B.'
How can I accomplish it?
This is best illustrated with an example. In the code of Form_A:
<div id="target"></div> <button onclick="window.open('form_b.html'); return false">Open Form B</button>
function receive_data (value)
{
$("#target").text(value);
}
In the code of Form_B:
<input type="button" onclick="window.opener.receive_data('hello'); window.close();">
You can do it using localStorage, like:
<!--FormB-->
<input type="submit" onclick="processInfo();" />
and in your javascript code:
function processInfo(){
//process your information then
//let's day you have 2 variables as a result of your process
var info1 = "My Information 1";
var info2 = "My Information 2";
localStorage.setItem("info1", info1);
localStorage.setItem("info2", info2);
}
then in your code on the next page get your variables whenever you wanted like:
function getInfo1(){
return localStorage.getItem("info1");
}
function getInfo2(){
return localStorage.getItem("info2");
}
and the other solution for ancient browsers is using window.opener, you can use it in your close function like this:
<!--FormB-->
<input type="button" onclick="closeWindow();" />
javascript code:
function closeWindow(){
//process your information then
//let's day you have 2 variables as a result of your process
var info1 = "My Information 1";
var info2 = "My Information 2";
window.opener._info1 = info1;
window.opener._info2 = info2;
window.close();
}
then you can get them in the main page like:
function getInfo1(){
return window._info1;
}
function getInfo2(){
return window._info2;
}
BTW, we usually use _ when we want to simulate private variable, whereas they are not really private.
Related
Ok, so I have a text field in which I type a string and I have a button next to it.
<div class="sidebar-search">
<div class="input-group custom-search-form">
<<label for="riot-summoner-input">Search a Summoner</label><br>
<input type="text" id="riot-summoner-input" class="form-control" placeholder="Type summoner name..." style="margin-bottom: 20px">
<button type="button" id="valid-summoner">Search</button>
</div>
</div>
By Clicking on this button, the following script gets executed
let res = {{ summoner.summonerLevel }}
$(document).ready(function() {
// Get value on button click and pass it back to controller
$("#valid-summoner").click(function () {
const summoner_input = $("#riot-summoner-input").val();
console.log(summoner_input)
let url = `/coach/?summonerName=${summoner_input}`
history.replaceState(summoner_input, 'Coach Index', url);
console.log(url)
function loadXMLDoc()
{
document.getElementById("display-summonerLevel").innerHTML = `Summoner Level: <h2>${res}</h2>`
}
loadXMLDoc();
});
});
Now as far as I can understand this will change my page url to include the value inserted in the text field and will send it back to my controller without refreshing the page, which it does.
Now in my Controller I'm using that value to do some logic with it
/**
* #Route("/", name="app_coach_index", methods={"GET"})
*/
public function index(CoachRepository $coachRepository, riotApi $callRiot, Request $request): ?Response
{
$value = $request->request->get('summoner_input');
if($value != null){
$this->debug_to_console($value . "Hi");
return $this->render('coach/index.html.twig', [
'coaches' => $coachRepository->findAll(), 'summoner'=> $this->showSummoner("$value")
]);}
else{
$this->debug_to_console($value);
return $this->render('coach/index.html.twig', [
'coaches' => $coachRepository->findAll()
]);
}
}
Now it's interesting to note that I'm doing this in the index function.
Here's the function I'm calling within the index function which is actually the one that gets the value from the script
/**
* #Route("/?summonerName={summoner_input}", name="show_summoner", methods={"GET"})
*/
public function showSummoner($summoner_input)
{
$call = new ApiClient(ApiClient::REGION_EUW, 'API-KEY-HERE');
return $call->getSummonerApi()->getSummonerBySummonerName($summoner_input)->getResult();
}
Now that I'm seeing this I can see that the issue is I'm getting the value in the showSummoner() function but trying to use it in the index function. Which is why I'm not getting a value when I print it to console and the variable is undefined.
Honestly I can't think of any logic I can do to overcome this issue.
EDIT!!!!!!!
Okay, so I know where the problem is arising, the issue is when I'm calling showSummoner($value) within index function. I'm using $value = $request->query->get('summoner_input');
I thought I was getting that value in the index function when in fact I'm getting it in the showSummoner() function. You can tell by the annotations
For index I don't have a parameter in its url, whereas in showSummoner() I have a parameter in the annotations as such.
/**
* #Route("/?summonerName={summoner_input}", name="show_summoner", methods={"GET"})
*/
This is indeed the fact because I'm using that url in the script as such
let url = `/coach/?summonerName=${summoner_input}`
The reason for this is I can't use the parameter in the index url because then I would have to provide the parameter in all the other places I'm using index in even when I don't have a parameter meaning I didn't search for anything.
I hope this gives more clarification
You're trying to get a value from $_GET global, not $_POST.
You can replace :
$value = $request->request->get('summoner_input');
by:
$value = $request->query->get('summoner_input');
You are trying to access the GET parameter using the wrong name ('summoner_input').
$value = $request->request->get('summoner_input');
When you are setting it as summonerName here:
let url = `/coach/?summonerName=${summoner_input}`
You will also want to pass a default value to check for, as the second parameter.
Try this:
$value = $request->request->get('summonerName', false);
if(false !== $value){
/* the parameter is in the url */
}
So I am building a mailmerge tool, and it works fine.
Testing the trigger with a hard coded input works fine:
function test(){
sendEmails("TEST MAILMERGE FROM DRAFT")
}
It also works fine if I prompt an input box (relevant section of the code shown).
function sendEmails(subjectLine,sheet=SpreadsheetApp.getActiveSheet()) {
if (!subjectLine) {
subjectLine = Browser.inputBox(
"Mail Merge",
"Type or copy/paste the subject line of the Gmail " +
"draft message you would like to use:",
Browser.Buttons.OK_CANCEL
);
if (subjectLine === "cancel" || subjectLine == "") {
// if no subject line finish up
return;
}
}
However, trying to be smarty pants and have the menu dynamically populated with Subject lines like this:
function onOpen() {
// get the UI for the Spreadsheet
const ui = SpreadsheetApp.getUi();
// add the menu
const menu = ui.createMenu("TEST");
// get the drafts from Gmail
let drafts = GmailApp.getDraftMessages();
// for each draft, create a new menu item
drafts.forEach((draft) => {
// add the drafts to be triggered using the following: addItem(caption: string, functionName: string)
menu
.addItem(
draft.getSubject().toString(),
'sendEmails("' + draft.getSubject().toString() + '")'
)
.addToUi();
});
}
However, this doesn't work. It comes up with the following error:
Error Script function not found: sendEmails(TEST MAILMERGE FROM DRAFT)
Which to me looks like it should work. As the testing trigger that is hardcoded above works.
Am I being daft here? As far as I can see, this should work? But it's not.
When / if I get it working, I will put a check in to account for 'trash' drafts that don't have a subject. Just trying to get it to actually work for now though.
Menu.addItem(caption, functionName)
Parameters:
caption: The label for the menu item, with only the first word capitalized.
functionName: The name of the function to invoke when the user selects the item. You can use functions from included libraries, such as Library.libFunction1.
Menu.addItem() expects a function name without arguments. It doesn't allow to pass arguments in the function.
Workaround:
Based on my understanding, your goal is to have a different menu item that could send emails on each draft messages available in your email account.
You might want to consider using Custom dialogs or Custom sidebars where in you can select your draft message subject that you want to pass as argument when you call your sendEmails() function. You can refer to the sample code as reference.
Sample Code:
(Code.gs)
function onOpen() {
// get the UI for the Spreadsheet
const ui = SpreadsheetApp.getUi();
// add the menu
const menu = ui.createMenu("TEST")
.addItem('Send Email', 'selectDraft')
.addToUi();
}
function selectDraft() {
var html = HtmlService.createHtmlOutputFromFile('draft');
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showModalDialog(html, 'Select Draft Message');
}
function getDraftSubject(){
// get the drafts from Gmail
let drafts = GmailApp.getDraftMessages();
var subjects = [];
// for each draft, create a new menu item
drafts.forEach((draft) => {
subjects.push(draft.getSubject().toString());
});
Logger.log(subjects);
return subjects;
}
function sendEmails(subjectLine,sheet=SpreadsheetApp.getActiveSheet()) {
Logger.log(subjectLine);
}
(draft.html)
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h2>Select Draft Subject</h2>
<form id="myForm" onsubmit="handleFormSubmit()">
<div class="form-group">
<label for="subject">Draft Subject</label>
<select class="form-control form-control-sm" id="subject" name="subject" required>
<option value="" selected>Choose...</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<script>
google.script.run.withSuccessHandler(function(subj) {
let select = document.getElementById("subject");
subj.forEach(function(e, i) {
let option = document.createElement("option");
option.value = e;
option.text = e;
select.appendChild(option);
});
}).getDraftSubject();
function handleFormSubmit() {
var value = document.getElementById("subject").value;
google.script.run.sendEmails(value);
document.getElementById("myForm").reset();
}
</script>
</body>
What it does?
Create a custom menu that will show a dialog box based on the draft.html
In draft.html, We used google.script.run.withSuccessHandler(function) to call getDraftSubject() in our server side (apps script) which returned an array of draft message subjects. We then update the form's select class and add options based on each draft message subjects obtained.
When the form was submitted, it will call handleFormSubmit(), we get the selected draft message subject and pass that value using google.script.run.myFunction(...) (any server-side function).
google.script.run.sendEmails(value);
Output:
I'm quite new here so if I do something wrong let me know, ok?
I'm quite new in web development as well.
I'm having a problem here with a post method in ASP.NET.
Please, don't mind the name of the buttons and methods, ok? I'm Brazilian and their names are all in portuguese.
I have a submit button that calls a ng-click (Angularjs) method called AdicionarCliente().
View
<div>
<input type="submit" class="btn btn-info" value="Salvar" ng-click="AdicionarCliente()"/>
</div>
JavaScript
myApp.controller('AdicionarClientesController', function ($scope, $http) {
$scope.NomeCliente = "";
$scope.Telefone1Cliente = "";
$scope.AdicionarCliente = function () {
var promisse = $http.post("/app/AdicionarCliente/", { NomeCliente: $scope.NomeCliente, Telefone1Cliente: $scope.Telefone1Cliente })
promisse.then(function () {
window.location.href = "CadastroPet";
return false;
});
};
It works well until this part. All the times that I hit the submit button, it comes here and enter the function in the variable "promisse".
Now - the problem is here:
Controller
[HttpPost]
public JsonResult AdicionarCliente(string NomeCliente, string Telefone1Cliente)
{
var db = new RexsoftEntities();
db.CLIENTES.Add(new CLIENTES() { NOME = NomeCliente,
TELEFONE1 = Telefone1Cliente});
db.SaveChanges();
var Clientes = db.CLIENTES.ToList();
return Json(Clientes, JsonRequestBehavior.AllowGet);
}
The first time that I hit the submit button, the code here goes until the db.CLIENTES.Add part of the code - then it doesn't run the DB.SAVECHANGES() nor the rest of the code here. The second time it works like a charm. The problems just happen on the first submit hit.
As the return of the controller doesn't happens properly, the final part of the Javascript code does not run as well. This part:
window.location.href = "CadastroPet";
return false;
Can anyone help me?
(All the view is inside this div
<div ng-controller="AdicionarClientesController">
)
UPDATE
I removed the TYPE of the submit button and put the simple button type. It seems to be working now. How can I submit my form then?
First,as per EF best practice, try to wrap the db operation in using() { } block. Thus your controller lokks like
[HttpPost]
public JsonResult AdicionarCliente(string NomeCliente, string Telefone1Cliente)
{
var Clientes = new CLIENTES();
using(var db = new RexsoftEntities())
{
var _Clientes = new CLIENTES()
{
NOME = NomeCliente,
TELEFONE1 = Telefone1Cliente
};
db.CLIENTES.Add(_Clientes);
db.SaveChanges();
Clientes = db.CLIENTES.ToList();
}
return Json(Clientes, JsonRequestBehavior.AllowGet);
}
Secondly, in javascript side, you are using angularjs. window.location.href will not work in angular(see this and this). You have to use $window service (source: using angularjs $window service) or $location service (source: using angularjs $location service). Also avoid using return false;.
In your case the below will work.
promisse.then(function () {
$location.path('/CadastroPet');
});
I removed the TYPE of the submit button and put the simple button type. It seems to be working now.
I created another way to validate my form using the same js script that I mentioned. If the criterias wasn't met, i would return a message and a return false statement.
Im having a unusually hard time with this. If I have form that looks like this
HTML
<form id='logForm' method='post' action='seatingProcess.php'>
<span class='close' style='display:none' id='255' desk='9-4' deskval='2-3' changeType='REMOVE'></span>
<span class='close' style='display:none' id='255' desk='7-4' deskval='5-3' changeType='ADD'></span>
<span class='close' style='display:none' id='255' desk='8-4' deskval='8-3' changeType='CHANGE'></span>
<div class='btn btn-primary' type='submit' id='submit'>Submit</div>
</form>
What I want to happen is, when i click the button to submit the form, I want to have an array of the different elements in the span created so it can be sent via AJAX to process in PHP. How do you recommend I do this?
Also, this information will be dynamically created in this form based on user action. They will all be span's but will contain more or less the same attributes with a value attached to them. The idea is for php to receive the arrays and depending on what the attribute "changeType" says, it will generate the SQL script to perform that action. I may need help with this as well.
All I have for javascript. I dont have anything about making the array, thats what I need help with.The HTML above is an example output, but ill post one of the functions that generates the information. :
Javascript
function remDeskId(){
userObject = $dropObject.find('div.dragTest');
userObjectChange = 'REMOVESEAT';
userObjectID = userObject.attr('data-info');
userObjectDeskID = userObject.attr('data-id');
userObjectDeskIDVal = 0;
$('form#logForm').append("<span class='close' style='display:none' id='"+userObjectID+"' desk='"+userObjectDeskID+"' deskval='"+userObjectDeskIDVal+"' changeType='"+userObjectChange+"'></span>");
userObject.attr({"data-id":""}); //remove desk number for new user location
userObject.appendTo('#userPool');
}
$('#submit').click(function(){
// get the form data
// there are many ways to get this data using jQuery (you can use the class or id also)
//var formData = {
// };
// process the form
$.ajax({
type : 'POST', // define the type of HTTP verb we want to use (POST for our form)
url : 'seatingProcess.php', // the url where we want to POST
data : $('#logForm').serialize(), // our data object
})
// using the done promise callback
.done(function(data) {
// log data to the console so we can see
console.log(data);
// here we will handle errors and validation messages
});
// stop the form from submitting the normal way and refreshing the page
event.preventDefault();
});
Thanks in advance
You can iterate through the spans and create an array.
var spans = $('#logForm span');
var data = [];
$.each(spans, function(i, item){
var newItem = {};
newItem.id = $(item).attr('id');
newItem.desk = $(item).attr('desk');
newItem.deskval = $(item).attr('deskval');
newItem.changeType = $(item).attr('changeType');
data.push(newItem);
});
I have a customized Django wizard_form.html which shows the user 3 different images on three different pages of my survey.
I am trying to use the below script to update 3 hidden form fields on 3 different pages with the contents of value="{{display_image}}" as a way of storing the filename of the images shown to the user in the Database
This works fine for the first page/image e.g.
<input id="id_9-slider_one_image" name="9-slider_one_image" type="hidden" value="P1D1.jpg"/>
But I cant seem to get it working on the second or third
<input id="id_10-slider_two_image" name="10-slider_two_image" type="hidden" />
Can anyone tell me what I am doing wrong?
My Code
{% if wizard.steps.current in steps %}
<div class="image_rating">
<img src="{% static "survey/images/pathone/" %}{{display_image}}"
value="{{display_image}}" onload="updateInput1(this); updateInput2(this); updateInput3(this);"/>
</div>
<script type="text/javascript">
function updateInput1(ish) {
var valueAttribute = ish.getAttribute("value");
document.getElementById("id_9-slider_one_image").setAttribute(
"value", valueAttribute);
}
function updateInput2(ish) {
var valueAttribute = ish.getAttribute("value");
document.getElementById("id_10-slider_two_image").setAttribute(
"value", valueAttribute);
}
function updateInput3(ish) {
var valueAttribute = ish.getAttribute("value");
document.getElementById("id_11-slider_three_image").setAttribute(
"value", valueAttribute);
}
</script>
Any helps is as always, much appreciated, Thanks.
First, you need to assign the value of the input id to a variable, say element_id
element_id = "id-slider_one_image"
If you can't name them all the same, just give this the actual element ID (e.g.: id_9-slider_one_image).
Then, you need to change the function arguments to also take the element id
function updateInput(ish, elementId) {
var valueAttribute = ish.getAttribute("value");
document.getElementById(elementId).setAttribute(
"value", valueAttribute);
}
Then, your onload attribute needs to pass the element_id string in addition to the element reference:
onload="updateInput(this, '{{element_id}}');"
simply create a function which calls all 3 update functions with try catch
function Update(sender){
try{
updateInput1(sender); }
catch(e){
try{
updateInput2(sender); }
catch(e){
updateInput3(sender);}}
}
and use onload='Update(this)'