This is my second topics
so i am trying to insert array data with input tag.
I am make the tag input with an jquery
<input type="button" class="btn btn-primary" onclick="steps(); return false;" value="Add steps">
function steps() {
var idf = document.getElementById("idf").value;
var stre;
stre="<p id='srow" + idf + "'><input type='text' class='haha{{ $errors->has('steps') ? ' is-invalid' : '' }}' name='steps[]' id='steps' /> <a href='#' style=\"color:#3399FD;\" onclick='hapusElemen(\"#srow" + idf + "\"); return false;'>Hapus</a></p>";
$("#divHobi").append(stre);
idf = (idf-1) + 2;
document.getElementById("idf").value = idf;
}
function hapusElemen(idf) {
$(idf).remove();
}
also this result after input data with dd()
array:3 [0 => "banget"
1 => "asd"
2 => "wwww"
]
at this case i am trying to input that array to database and that work
this is the code
$hitung = $req->steps;
$hitung2 = count($hitung);
dd($hitung);
for ($i=0; $i < $hitung2; $i++) {
$user = new TestCase;
$user->id_test_case = $req->id_test_case;
$user->id_document = $req->id_document;
$user->test_scenario = $req->test_scenario;
$user->post_condition = $req->post_condition;
$user->pre_condition = $req->pre_condition;
$user->expected_result = $req->expected_result;
$user->steps = $req->steps[$i];
$user->actual_result = $req->actual_result;
$user->status = $req->status;
$user->save();
}
but the result is be like
and then the expected result that i hope is be like
so is that possible to make it? without the loop?
You're creating a new TestCase in every loop; so of course you're going to end up with 3 rows in your table. Get rid of the loop and use implode() to set steps as a string:
$user = new TestCase;
$user->id_test_case = $req->id_test_case;
$user->id_document = $req->id_document;
$user->test_scenario = $req->test_scenario;
$user->post_condition = $req->post_condition;
$user->pre_condition = $req->pre_condition;
$user->expected_result = $req->expected_result;
$user->steps = implode(",", $req->steps);
$user->actual_result = $req->actual_result;
$user->status = $req->status;
$user->save();
Now saving an array into a database as a CSV value isn't necessarily the best approach, so be aware that you may run into limitations based on that decision. Consider using a pivot approach (users, steps, users_steps) or similar.
Related
WARNING: I'm not a programmer by trade.
Ok. Got the disclaimer out of the way. So this might not be the best way to do this but here is the scenario. I have a dropdown that gets populated via a Google Sheet. The user chooses a selection from the list but this dropdown does not have all of the possible values it could have. There will likely be a time when the user needs a new value added. While I could manually update the spreadsheet as new values are requested that introduces an element of human availability to get this done and I'm not always available.
What I would prefer is a self-serve model. I want to supply the user with a text field where they can enter the new value and submit it to the Google Sheet. Then I would like the dropdown to be updated with the new value for the user to choose.
Now, I realize that I could just submit the value in the new field to the Google Sheet but that will require building a condition to see whether it is the dropdown or text field that has a value in it. I'd also need some type of error handling in case both the dropdown and text field have values. That seems like a bigger headache to program then my ask.
I'm not sure what code you would need to see to help make this work but here is what I think might help.
doGet function
function doGet(e){
var ss = SpreadsheetApp.openById(ssId)
var ws = ss.getSheetByName("External");
var range = ws.getRange("A2:D2");
var valuesArray = [];
for (var i = 1; i <= range.getLastColumn(); i++){
var lastRowInColumn = range.getCell(1, i).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var list = ws.getRange(2,i,lastRowInColumn-1,1).getValues();
valuesArray.push(list);
}
var userEmail = Session.getActiveUser().getEmail();
var sourceListArray = valuesArray[2].map(function(r){ return '<option>' + r[0] + '</option>'; }).join('');
var productListArray = valuesArray[3].map(function(r){ return '<option>' + r[0] + '</option>'; }).join('');
var tmp = HtmlService.createTemplateFromFile("config");
tmp.productList = productListArray;
return tmp.evaluate();
}
Add to Google Sheet
function userClicked(tagInfo){
var ss = SpreadsheetApp.openById(ssId)
var ws = ss.getSheetByName("Data");
ws.appendRow([tagInfo.email, tagInfo.source, tagInfo.product, new Date()]);
}
Add record
function addRecord(){
var tagInfo = {};
tagInfo.product = document.getElementById("product").value;
google.script.run.userClicked(tagInfo);
var myApp = document.getElementById("source");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
var myApp = document.getElementById("brand");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
var myApp = document.getElementById("product");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
}
How dropdowns are populated in the HTML.
<div class="input-field col s3">
<select id="product" onchange="buildURL()">
<option disabled selected value="">Choose a product</option>
<?!= productList; ?>
</select>
<label>Product</label>
</div>
Need to see anything else? I think it might be relatively easy to add the new value to the column but the tricky part seems to be the update of only that one dropdown and not the entire app. To me it seems like I want to trigger the doGet() function again but only for that specific dropdown. Thoughts?
UPDATE: current code to add new value to dropdown
function addProduct() {
let newProd = document.getElementById("newProduct").value;
google.script.run.withSuccessHandler(updateProductDropdown).addNewProduct(newProd);
document.getElementById("newProduct").value = "";
}
function updateProductDropdown(newProd){
var newOption = document.createElement('option');
newOption.value = newProd;
newOption.text = newProd;
document.getElementById('product').add(newOption);
}
UPDATE2: App Scripts function to add new value to column in spreadsheet
function addNewProduct(newProd){
var columnLetterToGet, columnNumberToGet, direction, lastRow, lastRowInThisColWithData, rng, rowToSet, startOfSearch, valuesToSet;
var ss = SpreadsheetApp.openById(ssId);
var ws = ss.getSheetByName("List Source - External");
lastRow = ws.getLastRow();
//Logger.log('lastRow: ' + lastRow)
columnNumberToGet = 9;//Edit this and enter the column number
columnLetterToGet = "I";//Edit this and enter the column letter to get
startOfSearch = columnLetterToGet + (lastRow).toString();//Edit and replace with column letter to get
//Logger.log('startOfSearch: ' + startOfSearch)
rng = ws.getRange(startOfSearch);
direction = rng.getNextDataCell(SpreadsheetApp.Direction.UP);//This starts
//the search at the bottom of the sheet and goes up until it finds the
//first cell with a value in it
//Logger.log('Last Cell: ' + direction.getA1Notation())
lastRowInThisColWithData = direction.getRow();
//Logger.log('lastRowInThisColWithData: ' + lastRowInThisColWithData)
rowToSet = lastRowInThisColWithData + 1;
valuesToSet = [newProd];
ws.getRange(rowToSet, 9).setValues([valuesToSet]);
return newProd;
}
SOLUTION to Update Materialize Dropdown
function updateProductDropdown(newProd){
newProdOption = document.getElementById('product');
newProdOption.innerHTML += '<option>' + newProd + '</option>';
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
}
You can specify a client side callback function if you use google.script.run withSuccessHandler(callback) where your callback could update the list only and not the whole site.
Example:
google.script.run.withSuccessHandler(updateDropdownWidget).updateDropdownList(text_from_input)
Where updateDrownList(text_from_input) is a function in your Apps Script that adds text to the sheet using SpreadsheetApp for example, and returns the "text" to the callback function: updateDropdownWidget(text) which adds a new list item to the HTML drop-down list in your front end.
index.html:
<form>
<label for="newOption">New option for the dropdown:</label>
<input type="text" id="nopt" name="newOption">
<input type="button" value="Submit"
onclick="google.script.run.withSuccessHandler(updateDropdownWidget)
.updateDropdownList(document.getElementById('nopt').value)">
</form>
<label for="cars">Choose a car:</label>
<select name="cars" id="cars">
<?!= values; ?>
</select>
<script>
function updateDropdownWidget(text){
var option = document.createElement('option');
option.value = text;
option.text = text;
document.getElementById('cars').add(option);
}
</script>
Code.gs:
function doGet(e){
var ss = SpreadsheetApp.getActiveSheet();
var lastRow = ss.getDataRange().getLastRow();
var values = ss.getRange(1,1,lastRow,1).getValues();
var valuesArray = [];
for (var i = 0; i < values.length; i++){
valuesArray.push('<option value="'+values[i]+'">' +values[i]+ '</option>');
}
var tmp = HtmlService.createTemplateFromFile("index");
tmp.values = valuesArray;
return tmp.evaluate();
}
function updateDropdownList(text_from_input){
// Log the user input to the console
console.log(text_from_input);
// Write it to the sheet below the rest of the options
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getDataRange().getLastRow();
sheet.getRange(lastRow+1,1).setValue(text_from_input);
// Return the value to the callback
return text_from_input;
}
Here's an example:
In my Stack Over Flow spreadsheet I four buttons which can be used to run any function in 3 script files and every time I load the sidebar it reads the functions in those script files and returns them to each of the select boxes next to each button so that I test functions that I write for SO with a single click and I can select any function for any button. Here's the Javascript:
$(function(){//JQuery readystate function
google.script.run
.withSuccessHandler(function(vA){
let idA=["func1","func2","func3","func4"];
idA.forEach(function(id){
updateSelect(vA,id);
});
})
.getProjectFunctionNames();
})
Here is GS:
function getProjectFunctionNames() {
const vfilesA=["ag1","ag2","ag3"];
const scriptId="script id";
const url = "https://script.googleapis.com/v1/projects/" + scriptId + "/content?fields=files(functionSet%2Cname)";
const options = {"method":"get","headers": {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}};
const res = UrlFetchApp.fetch(url, options);
let html=res.getContentText();
//SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), "Project Functions");
let data=JSON.parse(res.getContentText());
let funcList=[];
let files=data.files;
files.forEach(function(Obj){
if(vfilesA.indexOf(Obj.name)!=-1) {
if(Obj.functionSet.values) {
Obj.functionSet.values.forEach(function(fObj){
funcList.push(fObj.name);
});
}
}
});
//SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(funcList.join(', ')), "Project Functions");
return funcList;//returns to withSuccessHandler
}
Image:
Animation:
i used this code but some thing wrong.
i show only last three number show using php in javascript.
var number = "678342345"
function substr() {
var numbersub = <?php
$rest = substr(number, -3);
echo $rest;
?>
document.getElementById("nember").innerHTML = numbersub;
};
<button class="buttonsa" onclick="substr()">Show Number</button>
<br>
<div id="nember"></div>
var number = "678342345";
Thats a variable in javascript (on the client). You can't access it in PHP (on the backend). But you could just do the same you did in php in js:
var numbersub = number.substr(-3);
Or you have to move number to the backend.
If you want to show the the last three number only:
let number = "678342345"
document.getElementById("mybutton").addEventListener('click', function() {
let str = number.toString();
document.getElementById("number").innerHTML = str.substr(str.length-3);;
})
<button class="buttonsa" id="mybutton">Show Number</button><br>
<div id="number"></div>
If you want to show the number without the last three digits:
let number = "678342345"
document.getElementById("mybutton").addEventListener('click', function() {
let str = number.toString();
document.getElementById("number").innerHTML = str.substr(0, str.length-3);;
})
<button class="buttonsa" id="mybutton">Show Number</button><br>
<div id="number"></div>
Good luck.
I have this code that loops through a HTML structure and builds an array based on its data attributes. I want to execute a conditional statement within a foreach loop and want to check if my count variable is within the array. I looked at inArray() but I'm not sure it works with associative arrays?
Here is the HTML
<div class="dfp" data-adposition="<?php echo $dfpPos; ?>" data-dfpcode='<?php echo $dfpCode; ?>'>
</div>
<div class="dfp" data-adposition="<?php echo $dfpHalfPos; ?>" data-dfpcode='<?php echo $dfpHalfCode; ?>'>
</div>
Here is the JS that builds the array.
var dfpObj = { "adverts" : [] };
$(".dfp").each(function(){ // PROCESS DFPS
var code = $(this).data("dfpcode");
var position = $(this).data("adposition");
var dfp = {
"code": code,
"position": position
}
dfpObj.adverts.push(dfp);
});
And my IF statement.
if($.inArray(count, dfpObj.adverts) !== -1) {
var dfp = $('.dfp[data-adposition=' + count + ']');
var dfpcode = $(dfp).data("dfpcode");
var dfppos = $(dfp).data("adposition");
myfunction(dfpcode, dfppos);
}
// count is within a foreach loop so at the end of the loop is $count++
You can use the following.
$.grep(dfpObj.adverts, function(obj) { return obj.code == "122"; })
This will give you that object or else gives you empty array.
How can I modify this script to capture the 'alt' attribute for the images a user selects in a slideshow?
This code displays a series of 20 pairs of images and asks users to select their preferences. Each time the user clicks one of the 'Select' buttons, the 'manipulateDOM()' function advances to the next set of items in the the text and image arrays. However, since it's not set up as a typical form field, I'm having difficulty figuring out how to capture the value of each selection so that it can be submitted to the database with the rest of the form values.
I tried creating a function with the click() method to (at the very least) capture the src value, but I can't get the syntax right so that it can run in conjunction with the 'manipulateDOM()' function. I'd also much rather capture the 'alt' attribute, but I couldn't figure out how to do that.
Function I was experimenting with:
$(document).ready(function () {
$("#buttons").click(function () {
var imgvalue = $("#imgtrendy").attr("src");
$("#picval").text(imgvalue);
document.write(imgvalue + ', ');
});
});
Existing Code:
Javascript - manipulateDOM() and manipulateDOM1() functions
var NumberOfImages = 3 - 1; //-1 because array members starts from 0
var trendy = new Array(NumberOfImages);
trendy[0] = "files/set1/A1.jpg";
trendy[1] = "files/set1/B1.jpg";
trendy[2] = "files/set1/C1.jpg";
var imgNumber = 1; //array key of current image
var NumberOfImages = 3 - 1;
var classic = new Array(NumberOfImages);
classic[0] = "files/set1/A2.png";
classic[1] = "files/set1/B2.jpg";
classic[2] = "files/set1/C2.jpg";
var classicNumber = 1;
var text = 3 - 1;
var text = new Array;
text[0] = "Which would you be more likely to wear?"
text[1] = "Which look is more you?"
text[2] = "Which would you rather wear?"
var textNumber = 1;
function manipulateDOM() {
changeObjects();
NextImage();
}
function changeObjects() {
document.getElementById("question").innerHTML = text[textNumber];
}
function NextImage() {
if (imgNumber < NumberOfImages) //Stop moving forward when we are out of images
{
imgNumber++;
document.images["taste"].src = trendy[imgNumber];
document.images["taste1"].src = classic[imgNumber];
textNumber++;
document.getElementById["question"].innerHTML = text[textNumber];
document.getElementById["selectButton"].innerHTML = text[textNumber];
}
}
function manipulateDOM1() {
changeObjects();
NextImage1();
}
function NextImage1() {
if (imgNumber < NumberOfImages)
{
imgNumber++;
document.images["taste"].src = trendy[imgNumber];
document.images["taste1"].src = classic[imgNumber];
textNumber++;
document.getElementById["question"].innerHTML = text[textNumber];
document.getElementById["selectButton"].innerHTML = text[textNumber];
}
}
HTML
<form id="taste" name="taste" method="post" action="taste-exec.php" >
<h2 id="question"> Which would you be more likely to wear?</h2>
<table><tr>
<td><img id="imgtrendy" src="files/set1/A1.jpg" name="taste" value="trendy[1]" /></td>
<td><img id="imgclassic" src="files/set1/A2.png" name="taste1" value="classic[1]" /></td></tr>
<tr id="buttons">
<td><img id="trendyButton" alt"Select" src="files/Select.jpg" onclick="javascript:manipulateDOM()"></td>
<td ><img id="classicButton" alt"Select" src="files/Select.jpg" onclick="javascript:manipulateDOM1()"></td>
</tr><tr>
<td id="picval"></td>
<td><input name="answer" id="answer" type="text" /></td>
</tr></table>
</form>
You get the alt attribute using also the attr method and alt as parameter, just like you are already doing with src. You could try:
function changeObjects() {
document.getElementById("question").innerHTML = text[textNumber];
var imgvalue = $("#imgtrendy").attr("alt");
$("#picval").text(imgvalue);
}
Edit: Example of keeping data in one single array
//to save it
var alt = $("#imgtrendy").attr("alt");
var fileName= 'someValue';//populate accordingly
var myArray[index] = alt + '|' + fileName;
//to retrieve it
var bothValues = myArray[index].split('|'); //gives you an array
alt = bothValues[0] //contains alt at index 0
fileName = bothValues[1] //contains fileName at index 1
My current URL is: http://something.com/mobiles.php?brand=samsung
Now when a user clicks on a minimum price filter (say 300), I want my URL to become
http://something.com/mobiles.php?brand=samsung&priceMin=300
In other words, I am looking for a javascript function which will add a specified parameter in the current URL and then re-direct the webpage to the new URL.
Note: If no parameters are set then the function should add ? instead of &
i.e. if the current URL is http://something.com/mobiles.php then page should be re-directed to http://something.com/mobiles.php?priceMin=300
instead of http://something.com/mobiles.php&priceMin=300
try something like this, it should consider also cases when you already have that param in url:
function addOrUpdateUrlParam(name, value)
{
var href = window.location.href;
var regex = new RegExp("[&\\?]" + name + "=");
if(regex.test(href))
{
regex = new RegExp("([&\\?])" + name + "=\\d+");
window.location.href = href.replace(regex, "$1" + name + "=" + value);
}
else
{
if(href.indexOf("?") > -1)
window.location.href = href + "&" + name + "=" + value;
else
window.location.href = href + "?" + name + "=" + value;
}
}
then you invoke it like in your case:
addOrUpdateUrlParam('priceMin', 300);
Actually this is totally trivial, because the javascript location object already deals with this. Just encapsulate this one-liner into a function to re-use it with links etc:
<script>
function addParam(v) {
window.location.search += '&' + v;
}
</script>
add priceMin=300
There is no need to check for ? as this is already the search part and you only need to add the param.
If you don't want to even make use of a function you can write as so:
add priceMin=300
Keep in mind that this does exactly what you've asked for: To add that specific parameter. It can already be part of the search part because you can have the same parameter more than once in an URI. You might want to normalize that within your application, but that's another field. I would centralize URL-normalization into a function of it's own.
Edit:
In discussion about the accepted answer above it became clear, that the following conditions should be met to get a working function:
if the parameter already exists, it should be changed.
if the parameter already exists multiple times, only the changed copy should survive.
if the parameter already exists, but have no value, the value should be set.
As search already provides the search string, the only thing left to achieve is to parse that query-info part into the name and value pairs, change or add the missing name and value and then add it back to search:
<script>
function setParam(name, value) {
var l = window.location;
/* build params */
var params = {};
var x = /(?:\??)([^=&?]+)=?([^&?]*)/g;
var s = l.search;
for(var r = x.exec(s); r; r = x.exec(s))
{
r[1] = decodeURIComponent(r[1]);
if (!r[2]) r[2] = '%%';
params[r[1]] = r[2];
}
/* set param */
params[name] = encodeURIComponent(value);
/* build search */
var search = [];
for(var i in params)
{
var p = encodeURIComponent(i);
var v = params[i];
if (v != '%%') p += '=' + v;
search.push(p);
}
search = search.join('&');
/* execute search */
l.search = search;
}
</script>
add priceMin=300
This at least is a bit more robust as it can deal with URLs like these:
test.html?a?b&c&test=foo&priceMin=300
Or even:
test.html?a?b&c&test=foo&pri%63eMin=300
Additionally, the added name and value are always properly encoded. Where this might fail is if a parameter name results in an illegal property js label.
if(location.search === "") {
location.href = location.href + "?priceMin=300";
} else {
location.href = location.href + "&priceMin=300";
}
In case location.search === "", then there is no ? part.
So add ?newpart so that it becomes .php?newpart.
Otherwise there is a ? part already.
So add &newpart so that it becomes .php?existingpart&newpart.
Thanks to hakre, you can also simply set it like:
location.search += "&newpart";
It will automatically add ? if necessary (if not apparent, it will make it ?&newpart this way, but that should not matter).
I rewrite the correct answer in PHP:
function addOrUpdateUrlParam($name, $value){
$href = $_SERVER['REQUEST_URI'];
$regex = '/[&\\?]' . $name . "=/";
if(preg_match($regex, $href)){
$regex = '([&\\?])'.$name.'=\\d+';
$link = preg_replace($regex, "$1" . $name . "=" . $value, $href);
}else{
if(strpos($href, '?')!=false){
$link = $href . "&" . $name . "=" . $value;
}else{
$link = $href . "?" . $name . "=" . $value;
}
}
return $link;
}
I hope that help's someone...
There is an more elegant solution available, no need to write your own function.
This will add/update and take care of any ? or & you might need.
var params = new URLSearchParams(window.location.search);
params.set("name", "value");
window.location.search = params.toString();
var applyMinPrice = function(minPrice) {
var existingParams = (location.href.indexOf('?') !== -1),
separator = existingParams ? '&' : '?',
newParams = separator + 'priceMin=' + minPrice;
location.href += newParams;
}
If you're having the user fill out a textfield with a minimum price, why not let the form submit as a GET-request with a blank action? IIRC, that should do just what you want, without any javascript.
<FORM action="" method="get">
<P>
<LABEL for="brand">Brand: </LABEL>
<INPUT type="text" id="brand"><BR>
<LABEL for="priceMin">Minimum Price: </LABEL>
<INPUT type="text" id="priceMin"><BR>
</P>
use var urlString = window.location to get the url
check if the url already contains a '?' with urlString.indexOf('?'), -1 means it doesnt exist.
set window.location to redirect
this is like 101 of javascript. try some search engines!
<html>
<body>
..
..
..
<?php
$priceMinValue= addslashes ( $_GET['priceMin']);
if (!empty($priceMin)) {
$link = "currentpage.php?priceMin=". $priceMinValue;
die("<script>location.href = '".$link. "'</script>");
}
?>
</body>
</html>