Remove Quotes from json_encoded string value - javascript

I am working on a project to implement jTable into a PHP framwework class.
It is going quite well. Now I am stuck at a problem where I would like to be able to make custom input fieds on the edit dialog.
We are already using the select2 plugin, now I want to implement this on the edit dialogs of jTable. As far as I understood it is possible to add custom fields to the edit dialog like this:
Name: {
title: 'Name',
width: '20%',
input: function (data) {
if (data.record) {
return '<input type="text" name="Name" style="width:200px" value="' + data.record.Name + '" />';
} else {
return '<input type="text" name="Name" style="width:200px" value="enter your name here" />';
}
}
}
Notice the code above is in JavaScript.
Basically what I do is that I build this javascript in php array and via json_encode I send it to the client.
My problem here is that when I do
$column_array['name']['input'] = function (data) {if ....and so on}
I get on the javascript side
input: "function (data) {... so on"
Please notice the double quotes, it is a string and not a function anymore.
What I would need is to remove this 2 double quotes after the input. (well that's my idea so far)
OR if any one got some experience with jTable] and knows a better way to implement custom fields like select2, chosen, jQuery multiselect, elfinder and stuff like that.
I can give tomorrow some code if needed, cause I am not at work anymore today.

Based on this concept:
// Create a function that takes two arguments and returns the sum of those arguments
var fun = new Function("a", "b", "return a + b");
// Call the function
fun(2, 6);
Output: 8
you may change your JSON a bit in to
Name: {
title: 'Name',
width: '20%',
input: { name: "input",
param: "data",
body: "if (data.record) {
return '<input type=\".... "
}
....
then you may define a function and execute it
var d = new Function(Name.input.name, Name.input.param, Name.input.body);
d(otherdata);
this will omit the awful eval(...) stuff. Caveat: it's still not a method of the given object.

Related

Shorthand property name are not supported by current Javascript version in PHPStorm

I have used Jquery getScript and generate html form by Javascript however I got
Shorthand property name are not supported by current Javascript version in PHPStorm but my function work as well.
Concern: Before I used PHP to generate html form within another PHP framework but I think I should not used Server script to do that I should use JS to do that but I don't know how is it going on and is it support all browser or not so please give me some idea of this technique because I not yet understand much more about suing DOM and its performance.
Security Concern: if I used Javascript to generate Html form as below script it will less security or bad performance or not?
Another hand if I keep this code inside of HTMl I will never got this errors types.
$(document).ready(function () {
returnTill('returnTill');
});
function returnTill(returnTill) {
var chief_opt = '';
var teller_opt = '';
$.ajax({
url:'/teller/return_till_data',
method:'get',
dataType:'json',
timeout:4000,
async: false,
success:function (data, status) {
$.each(data, function(ins, vals){
if(ins === 'chief') {
cheifs = data.chief;
for(var key in cheifs){
chief_opt += '<option value="'+vals[key].id+'"> '+vals[key].username+' / '+vals[key].account_no+' </option>';
}
}if(ins === 'teller') { /* Tellers*/
tellers = data.teller;
for(var key in tellers){
teller_opt = '<option value="'+vals[key].id+'"> '+vals[key].username+' / '+vals[key].account_no+' </option>';
}
loadModale({
idSelector: returnTill,
title: 'Return Till',
labels: ['From','To','Amount','Description'],
loadType:'returnTill',
forms: {
input: {
selection: {
from:{chief_opt,class:'form-control', name:'retn_chief', id:'retn_chief'},
to:{teller_opt, class:'form-control', name:'retn_teller', id:'retn_teller'},
},
Amount :{type: 'text', name: 'retn_amount', class: 'form-control', Id: 'retn_amount', placeholder: '', style: '', value:''},
token:{ type: 'hidden', name: '_token', class: 'form-control', Id: 'token', placeholder: '', style: '', value: '{{csrf_token()}}'},
},
textarea : {
description:{class:'form-control', name:'tran_descr', rows:10, id:'tran_descr'}
}
},script: [
'/theme/js/jquery.validate.min.js',
'/theme/js/bootstrap-datepicker/js/bootstrap-datepicker.js',
]
});
}
});
},error: errorCallback,
});
}
Errors:
I perform the following steps in Webstorm to solve the same problem, so it may also work in PHPStorm:
Go to Settings by pressing ALT + CNTRL + S
Click on "Languages and Frameworks"
Click on 'Javascript'
In the "Javascript language version" drop-down, select 'ECMAScript 6'.
Click 'OK'
Now re-open any *.js files you may have previously had open, and notice that the errors are no longer there.
Hope that helps someone.
You can fix it this way:
from:{chief_opt: chief_opt}
So, if you change your code to this:
from:{chief_opt: chief_opt, class:'form-control', name:'retn_chief', id:'retn_chief'},
to:{teller_opt: teller_opt, class:'form-control', name:'retn_teller', id:'retn_teller'},
You shouldn't get anymore the PHPStorm error.
Hope it helped or at least cleared a little bit. ;)
PHP STORM SOLUTION
The error is attributed to the version of your Javascript Setting in PHPSTORM
STEPS
Go to settings(preference on macbook)settings/preference and click
Expand the Languages and Frameworks by clicking it
click language & frameworks
Click Javascript and change the Javascript language version to the current or ECMAScript6 recommended.select ecmascript

Group results in autocompleted dropdown [Meteor]

I try to do a dropdown list in my app. First of all I use a Meteor, so that's specific kind of app ofc :)
Second thing is that I use sebdah/meteor-autocompletion package, because I want my results to be sorted in specific way and limited.
The last thing I need is to group my results.
For example: If I have 2 products named "blah" I want to get only 1 "blag" in my dropdown "autocompletion" list.
Some code:
HTML:
<template name="InvoicesEditInsertInsertForm">
<input id="descriptionautocomplete" type="text" name="description" value="" class="form-control" autofocus="autofocus" placeholder="New Item...">
</template>
JS:
Template.InvoicesEditInsertInsertForm.rendered = function() {
AutoCompletion.init("input#descriptionautocomplete");
};
Template.InvoicesEditInsertInsertForm.events({
'keyup input#descriptionautocomplete': function () {
AutoCompletion.autocomplete({
element: 'input#descriptionautocomplete', // DOM identifier for the element
collection: InvoicesItem, // MeteorJS collection object
field: 'description', // Document field name to search for
limit: 5, // Max number of elements to show
sort: { modifiedAt: -1 },
}); // Sort object to filter results with
},
});
I need to use function that could group my "description" here.
I tried to do it in helper and I get it on my screen, but to be honest I don't know how to put that into my dropdown :(
try: function() {
var item= InvoicesItem.find({},{sort:{modifiedAt:-1}}).fetch();
var descriptions={};
_.each(item,function(row){
var description = row.description;
if(descriptions[description]==null)
descriptions[description]={description:description};
});
return _.values(descriptions);
},
I don't think you can do what you want with that package. If you have a look at the current limitations of the package documentation, you can see other potential solutions to your problem.
You can do addtional filtering as follows:
filter: { 'gender': 'female' }});
but I don't think this will allow you to demand only unique options.
The code you wrote above for try won't do anything. Autocomplete doesn't take a field called try.

creating a dynamic form that builds a multi dimensional array

I am a php developer that is new to angular and javascript in general but finding it really powerful and fast for creating interactive UIs
I want to create a form for a user to create an object called a program, a program has some basic info like title and description and it can have many weeks. I want their to be an 'add week' button that when pressed displays a group of form fields related to weeks, if pushed again it shows another group of form fields to fill in the second weeks information.
edit1: specifically, how I am adding the objects to scope.program with the addWeeks method.
secondly when I console.log the $scope.program it just looks very messy a lot of arrays within objects within objects. it just dosnt look like a clean array of data but maybe thats just because I am not used to javascript and or json? Each week is going to have up to 7 days obviously and each day can have numerous events so it just seems to me like it is going to be quite messy but maybe I should just have faith :p
finally how the addProgram method is creating the json object to be sent to the server
when the form is submitted it should post a json object that looks something like this
program {
title: 'name of programme',
desc: 'description of programme',
weeks: [
{
item1: 'foo',
item2: 'more foo'
},
{
item1: 'foo2',
item2: 'more foo 2'
}
]
]
}
here is a codepen of what I am doing right now but I am not sure it is the best or even an ok way to do it, particularly how I am appending the arrays/objects in teh addWeek method.
there are going to be many more layers to the form and the object it is posting(days, sessions, excersises etc) so I want to get the basics of doing this right before adding all of that.
html
<div ng-app="trainercompare">
<div ng-controller="programsController">
<input type="text" placeholder="Program Title" ng-model="program.title"></br>
<input type="text" placeholder="Program Focus" ng-model="program.focus"></br>
<input type="text" placeholder="Program Description" ng-model="program.desc"></br>
<button ng-click="addWeek()"> add week</button>
<div ng-repeat="week in program.weeks">
<input type="text" placeholder="Name the week" ng-model="week.name">
<input type="text" placeholder="Describe It" ng-model="week.desc">
{{ week.name }}</br>
{{ week.desc }}</br>
</div>
<button ng-click="addProgram()"> add program</button>
</div>
</div>
app.js
var myModule = angular.module("trainercompare", ['ui.bootstrap']);
function programsController($scope, $http) {
$scope.program = {
weeks: [{
}]
};
$scope.addWeek = function() {
$scope.program.weeks.push(
{
}
);
};
function isDefined(x) {
var undefined;
return x !== undefined;
}
$scope.addProgram = function() {
var program = {
title: $scope.program.title,
focus: $scope.program.focus,
desc: $scope.program.desc,
weeks: []
};
angular.forEach($scope.program.weeks, function(week, index){
var weekinfo = {
name: week.name,
desc: week.desc
};
program.weeks.push(weekinfo);
});
$http.post('/programs', program).success(function(data, status) {
if(isDefined(data.errors)) {
console.log(data.errors);
}
if(isDefined(data.success)) {
console.log(data.success);
}
});
};
}
Looks to me like you've got a good grasp on it. The addWeek code looks correct. The extra data you see when you console.log your model is some of Angular's internal stuff to track bindings. When you post that to your server it should be cleaned up by Angular.
Angular has a JSON function that removes all of the hash values and other 'angular' things from your JSON. That's why they start with a $ so it knows to remove them.
This happens automatically when you use $http, it's in the documentation here:
If the data property of the request configuration object contains an object, serialize it into JSON format.
Since Angular will clean up the hashes and things, you don't need to "rebuild" the model when you're posting it... just set data to $scope.program and remove 70% of the code in $scope.addProgram.
To learn more specifically how Angular cleans up the JSON, look at this answer: Quick Way to "Un-Angularize" a JS Object

How can I remove AutoNumeric formatting before submitting form?

I'm using the jQuery plugin AutoNumeric but when I submit a form, I can't remove the formatting on the fields before POST.
I tried to use $('input').autonumeric('destroy') (and other methods) but it leaves the formatting on the text fields.
How can I POST the unformatted data to the server? How can I remove the formatting? Is there an attribute for it in the initial config, or somewhere else?
I don't want to send the serialized form data to the server (with AJAX). I want to submit the form with the unformatted data like a normal HTML action.
I wrote a better, somewhat more general hack for this in jQuery
$('form').submit(function(){
var form = $(this);
$('input').each(function(i){
var self = $(this);
try{
var v = self.autoNumeric('get');
self.autoNumeric('destroy');
self.val(v);
}catch(err){
console.log("Not an autonumeric field: " + self.attr("name"));
}
});
return true;
});
This code cleans form w/ error handling on not autoNumeric values.
With newer versions you can use the option:
unformatOnSubmit: true
Inside data callback you must call getString method like below:
$("#form").autosave({
callbacks: {
data: function (options, $inputs, formData) {
return $("#form").autoNumeric("getString");
},
trigger: {
method: "interval",
options: {
interval: 300000
}
},
save: {
method: "ajax",
options: {
type: "POST",
url: '/Action',
success: function (data) {
}
}
}
}
});
Use the get method.
'get' | returns un-formatted object via ".val()" or
".text()" | $(selector).autoNumeric('get');
<script type="text/javascript">
function clean(form) {
form["my_field"].value = "15";
}
</script>
<form method="post" action="submit.php" onsubmit="clean(this)">
<input type="text" name="my_field">
</form>
This will always submit "15". Now get creative :)
Mirrored raw value:
<form method="post" action="submit.php">
<input type="text" name="my_field_formatted" id="my_field_formatted">
<input type="hidden" name="my_field" id="my_field_raw">
</form>
<script type="text/javascript">
$("#my_field_formatted").change(function () {
$("#my_field").val($("#my_field_formatted").autoNumeric("get"));
});
</script>
The in submit.php ignore the value for my_field_formatted and use my_field instead.
You can always use php str_replace function
str_repalce(',','',$stringYouWantToFix);
it will remove all commas. you can cast the value to integer if necessary.
$("input.classname").autoNumeric('init',{your_options});
$('form').submit(function(){
var form=$(this);
$('form').find('input.classname').each(function(){
var self=$(this);
var v = self.autoNumeric('get');
// self.autoNumeric('destroy');
self.val(v);
});
});
classname is your input class that will init as autoNumeric
Sorry for bad English ^_^
There is another solution for integration which doesn't interfere with your client-side validation nor causes the flash of unformatted text before submission:
var input = $(selector);
var proxy = document.createElement('input');
proxy.type = 'text';
input.parent().prepend(proxy);
proxy = $(proxy);
proxy.autoNumeric('init', options);
proxy.autoNumeric('set', input.val())''
proxy.change(function () {
input.val(proxy.autoNumeric('get'));
});
You could use the getArray method (http://www.decorplanit.com/plugin/#getArrayAnchor).
$.post("myScript.php", $('#mainFormData').autoNumeric('getArray'));
I came up with this, seems like the cleanest way.
I know it's a pretty old thread but it's the first Google match, so i'll leave it here for future
$('form').on('submit', function(){
$('.curr').each(function(){
$(this).autoNumeric('update', {aSign: '', aDec: '.', aSep: ''});;
});
});
Solution for AJAX Use Case
I believe this is better answer among all of those mentioned above, as the person who wrote the question is doing AJAX. So
kindly upvote it, so that people find it easily. For non-ajax form submission, answer given by #jpaoletti is the right one.
// Get a reference to any one of the AutoNumeric element on the form to be submitted
var element = AutoNumeric.getAutoNumericElement('#modifyQuantity');
// Unformat ALL elements belonging to the form that includes above element
// Note: Do not perform following in AJAX beforeSend event, it will not work
element.formUnformat();
$.ajax({
url: "<url>",
data : {
ids : ids,
orderType : $('#modifyOrderType').val(),
// Directly use val() for all AutoNumeric fields (they will be unformatted now)
quantity : $('#modifyQuantity').val(),
price : $('#modifyPrice').val(),
triggerPrice : $('#modifyTriggerPrice').val()
}
})
.always(function( ) {
// When AJAX is finished, re-apply formatting
element.formReformat();
});
autoNumeric("getArray") no longer works.
unformatOnSubmit: true does not seem to work when form is submitted with Ajax using serializeArray().
Instead use formArrayFormatted to get the equivalent serialised data of form.serializeArray()
Just get any AutoNumeric initialised element from the form and call the method. It will serialise the entire form including non-autonumeric inputs.
$.ajax({
type: "POST",
url: url,
data: AutoNumeric.getAutoNumericElement("#anyElement").formArrayFormatted(),
)};

knockout js remove does not work

I'm trying to get my head around observables in knockout js!
However, I'm facing a problem implementing the remove function on an observable array.
My js is as follow:
$(function () {
var data = [{ name: "name1" }, { name: "name2" }, { name: "name3"}];
var viewModel = {
namesList: ko.observableArray(data),
nameToAdd: ko.observable("name4"),
myCustomAddItem: function () {
this.namesList.push({ name: this.nameToAdd() });
},
myCustomRemove: function () {
console.log("before + " + this.nameToAdd());
this.namesList.remove(this.nameToAdd());
console.log("after + " + this.nameToAdd());
}
};
ko.applyBindings(viewModel);
});
and my html is:
Name To add/remove <input type="text" data-bind="value: nameToAdd, valueUpdate: 'afterkeydown'"/>
<ul data-bind="template: {name: 'listTemp1', foreach :namesList}">
</ul>
<p>
<button data-bind="click: myCustomAddItem">Add Item</button>
<button data-bind="click: myCustomRemove">Remove Item</button>
<script id="listTemp1" type="text/html">
<li data-bind="text:name"> </li>
</script>
</p>
my myCustomAddItem works fine, but not the myCustomRemove. I also have put a console.log before and after the this.namesList.remove(this.nameToAdd()); to see if anything's wrong there, but I cannot see any error in there. When I click the "Remove Item" button, firebug console shows the logs but the item's not removed from the list.
Any help appreciated
The parameter to remove should be a function which returns true or false on whether to remove something.
It works quite similarly to the filter function.
In your case, something like this should work:
myCustomRemove: function () {
console.log("before + " + this.nameToAdd());
var nameToAdd = this.nameToAdd();
this.namesList.remove(function(item) {
//'item' will be one of the items in the array,
//thus we compare the name property of it to the value we want to remove
return item.name == nameToAdd;
});
console.log("after + " + this.nameToAdd());
}
[this should be a comment on Jani answer, but I can't still comment on others post, sorry]
Just a small clarification: technically you can call remove() passing the element to remove, see section "remove and removeAll" on http://knockoutjs.com/documentation/observableArrays.html.
the problem with your code is that the elements in 'data' array are objects (containing a property called 'name'), and you are asking to remove from the array the string "name4" (or whatever 'nameToAdd' contains).
You can be tempted to create a new object to pass to remove, like this:
// old code
//this.namesList.remove(this.nameToAdd());
this.namesList.remove({ name: this.nameToAdd() });
but this still fails, because the way javascript object equality works (see, for example: How to determine equality for two JavaScript objects?).
So, in the end you need to use the function anyway.
In this simple example, you can also convert the 'namesList' array to a simple array of strings, and bind "$data" in the template. see http://jsfiddle.net/saurus/usKwA/.
In a more complex scenario, maybe you can't avoid using objects.
[observableArray].remove(function(item) { return item.[whatever] == [somevalue] ; } );

Categories