Dynamic Javascript output in templated HTML - javascript

I am trying to build a Javascript class which takes some options and returns builds a form. I would like the submit function to be determined by the options passed to the class. All of the HTML is output as expected, but I don't think the javascript that is being output is being parsed. When the HTML renders I get a syntax error -
"Unexpected token function"
and when I try to submit the form I get a
Reference error - "{functionName} is not defined."
Here is the class so far:
var ClassOptionsForm = function(options) {
this.options = options
this.getSubmissionFunction = function() {
switch (this.options.type) {
case 'standard':
return this.standardSubmit;
break;
case 'extendable':
return this.extendableSubmit;
break;
}
}
this.successHandler = "function (data, form) {\
$(form).find('.result').text('Success!').css('color', 'green');\
}"
this.failureHandler = "function (data, form) { \
$(form).find('.result').text('Something went wrong.').css('color', 'red');\
}"
this.submitFunctionName = this.options.optionName + "Submit";
this.standardSubmit = "function " + this.options.optionName + "Submit(form) {\
google.script.run\
.withSuccessHandler(" + this.successHandler + ")\
.withFailureHandler(" + this.failureHandler + ")\
.withUserObject(form)\
.setUserOption('" + this.options.optionName + "', form)\
}"
this.extendableSubmit = "function(this) {\
// Extendable Form Submit
}"
this.buildForm = function() {
var value = this.options.value;
return '\
<script type="text/javascript">\
' + this.getSubmissionFunction() + '\
</script>\
<h3>' + this.options.formTitle + '</h3>\
<form id="' + this.options.optionName + '" onsubmit="' + this.submitFunctionName + '(this)">\
' + Object.keys(value).reduce(function(list, key) {
return list + '<input name="' + key + '" value="' + value[key] + '"/>';
}, '') + '\
<button type="submit">Save</button>\
</form>\
'
}
}
And here is how form render function is called in the HTML file:
<?!= GoogleAnalytics().optionsForm.buildForm(); ?>
And here is the final HTML output:
<script type="text/javascript">
function UAIDSubmit(form) {
google.script.run
.withSuccessHandler(function (data, form) {
$(form).find('.result').text('Success!').css('color', 'green');
})
.withFailureHandler(function (data, form) {
$(form).find('.result').text('Something went wrong.').css('color', 'red');
})
.withUserObject(form)
.setUserOption('UAID', form)
}
</script>
<h3>UAID</h3>
<form id="UAID" onsubmit="UAIDSubmit(this)">
<input name="id" value="********">
<button type="submit">Save</button>
</form>
I am pretty sure that this has something to do with the way that App Script sanitizes HTML, and I know there are a million ways I could accomplish submitting the form without dynamic JS. I am just trying to keep my code as dry as possible, and also I'm curious. Any workarounds that keep that don't involve doing away with templated JS?

When you try to submit the form it won't work because you can use a form object as parameter in a Google Script function but the form object must be the only parameter in that function. Read here[1]
[1] https://developers.google.com/apps-script/guides/html/reference/run

Related

Javascript error on vote up/down system

I've trying to adopt script for voting up and down with ajax and jquery from one tutorial. The problem (I think) is that in the tutorial the script is used with jquery-2.1.1 but I use jquery-1.10.1
This is the HTML part
<div id="links-'.$row["image_id"].'">
<input type="hidden" id="votes-'.$row["image_id"].'" value="'.$row["votes"].'">
<input type="hidden" id="vote_rank_status-'.$row["image_id"].'" value="'.$vote_rank.'">
<div class="btn-votes">
<input type="button" title="Up" class="up" onClick="addVote('.$row['image_id'].',"1")"'.$up.' />
<div class="label-votes">'.$row["votes"].'</div>
<input type="button" title="Down" class="down" onClick="addVote('.$row['image_id'].',"-1")"'.$down.'/>
</div>
</div>
Here is the script.js which should pass clicked button to add_vote.php
function addVote(image_id,vote_rank) {
$.ajax({
url: "add_vote.php",
data:'image_id='+image_id+'&vote_rank='+vote_rank,
type: "POST",
beforeSend: function() {
$('#links-' + image_id + ' .pull-right').html("<img src='LoaderIcon.gif' />");
},
success: function(vote_rank_status){
var votes = parseInt($('#votes-' + image_id).val());
var vote_rank_status; // = parseInt($('#vote_rank_status-' + id).val());
switch(vote_rank) {
case "1":
votes = votes + 1;
// vote_rank_status = vote_rank_status + 1;
break;
case "-1":
votes = votes-1;
//vote_rank_status = vote_rank_status - 1;
break;
}
$('#votes-' + image_id).val(votes);
$('#vote_rank_status-' + image_id).val(vote_rank_status);
var up, down;
if (vote_rank_status == 1) {
up = "disabled";
down = "enabled";
}
if (vote_rank_status == -1) {
up = "enabled";
down = "disabled";
}
var vote_button_html = '<input type="button" title="Up" id="up" onClick="addVote(' + image_id + ',\'1\')" ' + up + ' /><div class="label-votes">' + votes + '</div><input type="button" title="Down" id="down" onClick="addVote(' + image_id + ',\'-1\')" ' + down + ' />';
$('#links-' + image_id + ' .pull-right').html(vote_button_html);
}
});
}
When I click vote up or down nothing happen on the page. Didn't add new vote and didn't insert into database.
This is what I see in console of firefox when I click on button
SyntaxError: expected expression, got end of script
and this but I'm not sure if is relevant to this script. Showing that the error is in file jquery-1.10.1.min.js
Empty string passed to getElementById().
Your onclick functions appear to have syntax errors.
onClick="addVote('.$row['image_id'].',"1")"
As you can see, you are using double quotes (around the number 1) inside double quotes. Try:
onClick="addVote('.$row['image_id'].',\"1\")"

javascript searching a json object

I'm trying to search a value in json
<input type="text" id="test" size="21" maxlength="120">
<button onclick="Zoek()" class="btn btn-info btn-block">
tijdelijke zoek knop
</button>
I'm using this to input a value and the button to call the search function
function Zoek() {
var qeustion = document.getElementById("test").value;
document.getElementById("accordion").innerHTML == "";
var text = '{ "FAQ" : [' +
'{ "vraag":"John" , "antwoord":"Doe" },' +
'{ "vraag":"Anna" , "antwoord":"Smith" },' +
'{ "vraag":"Peter" , "antwoord":"Jones" } ]}';
obj = JSON.parse(text);
for (i = 0; i < text.length; i++) {
if (obj.FAQ[i].vraag == qeustion) //(obj.FAQ[i].getString("vraag").contains(question))
{
document.getElementById("accordion").innerHTML += "<div class='panel panel-default'><div class='panel-heading' role='tab' id='heading" + i + "'><h4 class='panel-title'><a data-toggle='collapse' data-parent='#accordion' href='#" + i + "' aria-expanded='false' aria-controls='" + i + "''>" + obj.FAQ[i].vraag + " </a></h4></div><div id='" + i + "' class='panel-collapse collapse in' role='tabpanel' aria-labelledby='heading" + i + "'><div class='panel-body'> " + obj.FAQ[i].antwoord + "</div></div></div> WOWOWOWOWOWOWOWOWWOWOWOOW";
} else {
document.getElementById("accordion").innerHTML = "No results found"
}
}
}
and this is my search function
so lets say i enter John it goes straigt to the else and doesnt do the if statement even though i am pretty sure it kind of is right
could anyone give me some pointers on searching in a json object? is there a other way to do this?
Please see jsfiddle attached demonstrating what you are looking for and will show you what you need to do - https://jsfiddle.net/vuenume2/1/
It is essential to have a break statement in your loop.
Without the break statement your true value for success simply gets overwritten with false on the next iteration, except for the last possible credentials, for which there is no "next" iteration.
if (obj.FAQ[i].vraag == qeustion)
{
<!-- do stuff -->
break;
} else {
<!-- do other stuff -->
}
Also, if you haven't done so you need to add a div with an id accordion to your html
<div id="accordion"></div>
Use filter function. You parsed in obj that string into json so You could do:
var target = obj.FAQ.filter(function(element){ return element.vraag == qeustion})[0];
if(target == undefined) {
// there is no that object logic
} else {
// there is that object logic
}

Textarea value remain the same after submitting a form

My previous problem has been fixed, now I need to ask how to keep a textarea from resetting its input after a form is submitted. Here is the jsFiddle: http://jsfiddle.net/rz4pnumy/
Should I change the form in the HTML?
<form id="form1" method="GET">
(the form does not go into a php file or anything else, i'm using it to submit the textarea input and use the variables I made using jQuery to make a paragraph on the same page)
or something in the JS?
$(document).ready( function () {
$('#form1').on('submit', function (event) {
// If the form validation returns false, block the form from submitting by
// preventing the event's default behaviour from executing.
if (!validate()) {
event.preventDefault();
}
if(validate()) {
var adjective1 = $('#adjective1').val();
var adjective2 = $('#adjective2').val();
var pluralnoun = $('#plural-noun').val();
var verb1 = $('#verb1').val();
var edibleobject = $('#edible-object').val();
var monster1 = $('#monster1').val();
var adjective3 = $('#adjective3').val();
var monster2 = $('#monster2').val();
var verb2 = $('#verb2').val();
$('body').append(
'<div id="para">' +
'<p>Rain was still lashing the windows, which were now ' + adjective1 +', but inside all looked bright and cheerful. ' +
'The firelight glowed over the countless ' + adjective2 + '' + pluralnoun + ' where people sat ' + verb1 + ', talking, ' +
'doing homework or, in the case of Fred and George Weasley, trying to find out what would happen if you fed a ' + edibleobject +' to a ' + monster1 + '.' +
'Fred had "rescued" the ' + adjective3 + ', fire-dwelling ' + monster2 + ' from a Care of Magical Creatures class and it was now ' + verb2 + ' gently ' +
'on a table surrounded by a knot of curious people. </p>' +
'</div>'
);
}
});
function validate() {
var success = true;
$('.input').each(function(i, item) {
if ($(item).val() === "")
{
console.log("Missing textarea input");
success = false;
$(item).attr("style","border:1px solid red;");
//note it will overwrite your element style in all Input class
}
else
{
$(item).removeAttr('style')
// to remove border
}
});
return success;
}
});
The contents get emptied after pressing submit and I only see the completed paragraph for a split second.
You need to prevent the default event handler from executing whether validate passes or not, so you need to remove the if statement around the event.preventDefault() call. The preventDefault is the function that is keeping the from from submitting and re-loading your page.
Also, your Fiddle was not set to jQuery (it was set to no-library) so that may have also been causing you issues during your testing.
Edited for example of what I'm talking about:
$('#form1').on('submit', function (event) {
// block the form from submitting by
// preventing the event's default behaviour from executing.
event.preventDefault();
if(validate()) {
var adjective1 = $('#adjective1').val();
var adjective2 = $('#adjective2').val();
var pluralnoun = $('#plural-noun').val();
... etc ...
I would use php and set a variable to the GET value of the textarea and set the value of the textarea to that variable

JQuery "Attribute Starts With" Selector Undefined

I have a modal dialog (Bootstrap) that has a list-group with custom list-group-items inside of it (populated by loop using append after adding data from my server).
Inside each list-group-item, I have a Checkbox that will be used to "select" the result. As I populate the items, I hook up the JQuery click event to the respective Checkbox:
// Add to search results
$('#search-results').append(
'<a id="centroid-list-item-' + featureAttrs['ObjectID'] + '" href="\\#"' + 'class="list-group-item" style="outline: 0">' +
'<table style="background: transparent">' +
'<tr>' +
'<td>' +
'<input id="centroid-checkbox-' + featureAttrs['ObjectID'] + '" type="checkbox" value=""> ' +
'</td>' +
'<td>' +
'<h4 class="list-group-item-heading">' +
featureAttrs['UNIQUEID'] +
'</h4>' +
'<p id="centroid-item-text-' + featureAttrs['ObjectID'] + '"' + 'class="list-group-item-text">' +
featureAttrs['NAME'] +
'</p>' +
'</td>' +
'</tr>' +
'</table>' +
'</a>'
);
// When the DOM is ready, add event
$(document).ready(function () {
$('#centroid-checkbox-' + featureAttrs['ObjectID']).click(function (event) {
var objectId = $(this).attr('id').replace(/^\D+/g, '');
console.log(objectId + " was clicked");
if ($(this).is(':checked')) {
// Enable the 'Set Target' button
$('#btn-set-target').removeAttr('disabled');
// Disable all other choices
$('[id^="centroid-checkbox-"]').each(function (event) {
console.log("Picked up values for checkboxes");
if ($(this).attr('id') != ('centroid-checkbox-' + objectId)) {
$(this).attr('disabled', true);
}
});
}
else {
$('#btn-set-target').attr('disabled', 'disabled');
// Enable all text boxes
$('[id^="centroid-checkbox-"]').each(function () {
if (this.attr('id') !== ('centroid-checkbox-' + objectId)) {
this.removeAttr('disabled');
}
});
}
});
});
The problem I am having is that when I call $('[id^="centroid-checkbox-"]') it is returning undefined. However, at the time is gets called, there are about 30 "centroid-checkbox-XXXXX" checkboxes. What am I doing wrong here?
The $ function never returns undefined.
But this in the callback you pass to each is an element, not a jQuery object.
Which means you must use this.id instead of this.attr('id') and $(this).removeAttr('disabled') instead of this.removeAttr('disabled') (and you probably want this.disabled=false or $(this).prop('disabled', false)).
objectId never gets defined because you need to quote enclose the regular expression you're using for replace():
var objectId = $(this).attr('id').replace(/^\D+/g, '');
should be:
var objectId = $(this).attr('id').replace('/^\D+/g', '');
DEMO: http://jsfiddle.net/4fUvn/8/

javascript insert text in specific place in text area

I write a form that inserts some xml tags into textarea. I use this function:
(function ($) {
addCustomTag = function (name, param, value) {
var code = "<" + name + " " + param + "=\"" + value + "\">\n</" + name + ">";
document.getElementById("codeArea").value += code;
};
})(jQuery);
How can I make that some other function will insert subtags into tags that were created before?
XML code will never be used on server. All I need is to insert tex in specific line which is depends on what was on this line before not cutting it. Something like this:
addCustomSubtag = function(name,param,value,parent) {
document.getElementById("codeArea").selectionStart = document.getElementById("codeArea").value - parent.length;
var code = "<" + name + " " + param + "=\"" + value + "\">\n</" + name + ">";
document.getElementById("codeArea").value += code;
};
Javascript isn't necessary. It also can be written on jQuery.
Thanks.
You can any of these jQuery functions
http://api.jquery.com/append/
http://api.jquery.com/appendTo/
http://api.jquery.com/prepend/
Update:
Actually we can use jQuery DOM manipulation methods to manipulate XML also.
var xml = "<main/>";
alert(xml); // <main/>
var $xml = $(xml).append($("<sub1/>"));
alert($xml.html()); // <sub1></sub1>
$xml.find("sub1").append($("<sub2/>"));
alert($xml.html()); // <sub1><sub2></sub2></sub1>
alert($xml.get(0).outerHTML); // <main><sub1><sub2></sub2></sub1></main>

Categories

Resources