Execute different actions depending on search results - php

I have a form with a lot of inputs (text inputs, textareas, checkboxes...) that users can populate with their own presets. At the moment, users can search for their presets, an ajax query is called and I return HTML with a list of found presets. The HTML is (elaboratly) generated in a PHP file that adds an onclick="" with lots of different actions. The users can click the presets and the form gets populated.
An example of generated HTML (that gets put in the page) could be
<a onclick=" $('#AgendaItemName').val('Preset 1'); $('#AgendaItemOpmerking').val(''); $('#AgendaItemLokaalID').val(''); $('#AgendaItemPlaats').val(''); $('#AgendaItemBegeleidendeLeerkrachten').val(''); $('#AgendaItemDoelgroep').val(''); $('#AgendaItemIsPubliek').val('1'); $('#AgendaItemLesFicheAbonnementID').val(''); $('#AgendaItemAgendaItemTypeID').val('2'); $('#AgendaItemAgendaItemPublicatieTypeID').val(''); $('#AgendaItemLeergebiedID').val('1'); $('#AgendaItemLeerdomeinID').val('1'); $('#AgendaItemLessenTaken').val(''); $('#AgendaItemVerloop').val('Test verloop\r\n\r\ntest opslaan vanuit agendaitem'); $('#AgendaItemBeginsituatie').val(''); $('#AgendaItemMateriaal').val(''); $('#AgendaItemEvaluatie').val('Test evaluatie'); $('#AgendaItemEigenLesdoelen').val('Test lesdoelen'); $('#AgendaItemAgendaItemHerhaalModeID').val(''); $('#AgendaItemHerhaalStartDatum').val(''); $('#AgendaItemHerhaalEindDatum').val(''); $('#AgendaItemAgendaItemKleuterModeID').val('0'); UpdateVisibleFields('AgendaItem');$('.HoekVeldInput').val('');$('#AgendaItemAgendaItemBelangstellingsCentrumID').val(''); $('#AgendaItemLesFicheID').val('791'); $('#AgendaItemIsBestaandeFicheAanpassen').attr('disabled', false); loadFieldsets(791, 'LesficheID'); return false; " href="#">Preset 1</a>
You don't actually have to fully read that piece of code, cuz it's... well, not so good. Most of the times it's just setting values, but sometimes, I also need to execute a few functions, depending on preset settings. Now I was thinking about a better way to approach this, but I'm stuck. Is there any way to send these actions along with JSON? Is it possible to do something like
var returndatafromajax = [
{
"html" : "preset",
"actions" : "dothis(); dothat();"
},
{
"html" : "preset 2",
"actions" : "someofthis();"
},
{
"html" : "preset 3",
"actions" : "noneofthat();"
}
]
$('ul').on('click', 'a', function() {
var index = $(this).attr('rel');
somehowexecute(returndatafromajax[index].actions);
});

Yes you can do this in this way
var returndatafromajax = [
{
"html" : "preset",
"actions" : {"1":"dothis","2":"dothat"}
},
{
"html" : "preset 2",
"actions" : {"1":"someofthis"}
},
{
"html" : "preset 3",
"actions" : {"1":"noneofthat"}
}
]
use only function names not the (); with their names.

Related

MongoDB Map Reduce newbie (PHP)

I'm new to the map reduce concept and even though I'm making some slow progress, I'm finding some issues that I need some help with.
I have a simple collection consisting of an id, city and and destination, something like this:
{ "_id" : "5230e7e00000000000000000", "city" : "Boston", "to" : "Chicago" },
{ "_id" : "523fe7e00000000000000000", "city" : "New York", "to" : "Miami" },
{ "_id" : "5240e1e00000000000000000", "city" : "Boston", "to" : "Miami" },
{ "_id" : "536fe4e00000000000000000", "city" : "Washington D.C.", "to" : "Boston" },
{ "_id" : "53ffe7e00000000000000000", "city" : "New York", "to" : "Boston" },
{ "_id" : "5740e1e00000000000000000", "city" : "Boston", "to" : "Miami" },
...
(Please do note that this data is just made up for example purposes)
I'd like to group by city the destinations including a count:
{ "city" : "Boston", values : [{"Chicago",1}, {"Miami",2}] }
{ "city" : "New York", values : [{"Miami",1}, {"Boston",1}] }
{ "city" : "Washington D.C.", values : [{"Boston", 1}] }
For this I'm starting to playing with this function to map:
function() {
emit(this.city, this.to);
}
which performs the expected grouping. My reduce function is this:
function(key, values) {
var reduced = {"to":[]};
for (var i in values) {
var item = values[i];
reduced.to.push(item);
}
return reduced;
}
which gives somewhat an expected output:
{ "_id" : ObjectId("522f8a9181f01e671a853adb"), "value" : { "to" : [ "Boston", "Miami" ] } }
{ "_id" : ObjectId("522f933a81f01e671a853ade"), "value" : { "to" : [ "Chicago", "Miami", "Miami" ] } }
{ "_id" : ObjectId("5231f0ed81f01e671a853ae0"), "value" : "Boston" }
As you can see, I still haven't counted the repeated cities, but as can be seen above, for some reason the last result in the output doesn't look good. I'd expected it to be
{ "_id" : ObjectId("5231f0ed81f01e671a853ae0"), "value" : { "to" : ["Boston"] } }
Has this anything to do with the fact that there is a single item? Is there any way to obtain this?
Thank you.
I see you are asking about a PHP issue, but you are using javascript to ask, so I’m assuming a javascript answer will help you move things along. As such here is the javascript needed in the shell to run your aggregation. I strong suggest getting your aggregation working in the shell(or some other javascript editor) in general and then translating it into the language of your choice. It is a lot easier to see what is going on and there faster using this method. You can then run:
use admin
db.runCommand( { setParameter: 1, logLevel: 2 } )
to check the bson output of your selected language vs what the shell looks like. This will appear in the terminal if mongo is in the foreground, otherwise you’ll have ot look in the logs.
Summing the routes in the aggregation framework [AF] with Mongo is fairly strait forward. The AF is faster and easier to use then map reduce[MR]. Though in this case they both have similar issues, simply pushing to an array won’t yield a count in and of itself (in MR you either need more logic in your reduce function or to use a finalize function).
With the AF using the example data provided this pipeline is useful:
db.agg1.aggregate([
{$group:{
_id: { city: "$city", to: "$to" },
count: { $sum: 1 }
}},
{$group: {
_id: "$_id.city",
to:{ $push: {to: "$_id.to", count: "$count"}}
}}
]);
The aggregation framework can only operate on known fields, but many pipeline operations so a problem needs to broken down with that as a consideration.
Above, the 1st stage calculates the numbers need, for which there are 3 fixed fields: the source, the destination, and the count.
The second stage has 2 fixed fields, one of which is an array, which is only being pushed to (all the data for the final form is there).
For MR you can do this:
var map = function() {
var key = {source:this.city, dest:this.to};
emit(key, 1);
};
var reduce = function(key, values) {
return Array.sum(values);
};
A separate function will have to pretty it however.
If you have any additional questions please don’t hesitate to ask.
Best,
Charlie

Include a search box that can look through a JSON and return drop down list

I'm using a JSON file to populate some drop down menus for various conversions. The converter has grown somewhat and I'd like to have the option of including a search bar.
So a user can search for Milliampere instead of navigating to the 'Current' category within "Electricity" etc etc. I'd just like to make it a bit easier for them.
My JSON only has two fields, the name and value of the drop down, example below.
The value is a string in the fashion that I understand so that Milliampere is milliAmpere and various others all using camel case. I don't think it would be suitable to run the search on this field as the values may differ from the name.
The name field in this instance is Milliampere(mA) so I need for the search to be able to look at part of the string and not do a full match ignoring case as the liklihood is the search string would be milliamp or milliampere or even milliamperes.
From there the next step is either to populate the drop downs whilst on that page or to return a list of possible options if there are many.
Is this possible at all and if so can you please guide me in the right direction?
Many thanks!
"current":[
{
"value" : "ampere",
"name" : "Ampere(A)"
},
{
"value" : "kiloAmpere",
"name" : "Kiloampere(kA)"
}]
You can use this JS lib - DefiantJS (defiantjs.com), which extends the global object JSON with a new method: "search". With this method, you can search a JSON structure with XPath expressions, like this:
var data = {
"current": [
{ "value": "ampere", "name": "Ampere(A)" },
{ "value": "kiloAmpere", "name": "Kiloampere(kA)" },
{ "value": "milliAmpere", "name": "milliAmpere" },
{ "value": "Milliampere", "name": "Milliampere" }
]
},
res = JSON.search( data, '//name[contains(translate(., "MA", "ma"), "millia")]/..' );
console.log( res[0].name );
console.log( res[1].name );
The "translate" method in the expression extends the search to include uppercase and lowercase versions of the letters "ma". If you want to cover all the alphabetic letter, then add all of them.
Here is a working fiddle;
http://jsfiddle.net/hbi99/6ssS9/

MongoDB Query to find out all the array elements of a collection

I have a pretty big MongoDB document that holds all kinds of data. I need to identify the fields that are of type array in a collection so I can remove them from the displayed fields in the grid that I will populate.
My method now consists of retrieving all the field names in the collection with
This was taken from the response posted here MongoDB Get names of all keys in collection
mr = db.runCommand({
"mapreduce" : "Product",
"map" : function() {
for (var key in this) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "things" + "_keys"
})
db[mr.result].distinct("_id")
And running for each of the fields a query like this one
db.Product.find( { $where : "Array.isArray(this.Orders)" } ).count()
If there's anything retrieved the field is considered an array.
I don't like that I need to run n+2 queries ( n being the number of different fields in my collection ) and I wouldn't like to hardcode the fields in the model. It would defeat the whole purpose of using MongoDB.
Is there a better method of doing this ?
I made a couple of slight modifications to the code you provided above:
mr = db.runCommand({
"mapreduce" : "Product",
"map" : function() {
for (var key in this) {
if (Array.isArray(this[key])) {
emit(key, 1);
} else {
emit(key, 0);
}
}
},
"reduce" : function(key, stuff) { return Array.sum(stuff); },
"out": "Product" + "_keys"
})
Now, the mapper will emit a 1 for keys that contain arrays, and a 0 for any that do not. The reducer will sum these up, so that when you check your end result:
db[mr.result].find()
You will see your field names with the number of documents in which they contain Array values (and a 0 for any that are never arrays).
So this should give you which fields contain Array types with just the map-reduce job.
--
Just to see it with some data:
db.Product.insert({"a":[1,2,3], "c":[1,2]})
db.Product.insert({"a":1, "b":2})
db.Product.insert({"a":1, "c":[2,3]})
(now run the "mr =" code above)
db[mr.result].find()
{ "_id" : "_id", "value" : 0 }
{ "_id" : "a", "value" : 1 }
{ "_id" : "b", "value" : 0 }
{ "_id" : "c", "value" : 2 }

passing string in "textfield" to another part in code

I have one question about passing strings from one Ext.formPanel textfield to another part of the code. The thing is that I have two "textfield" in the formPanel and I want the words I enter there as part of the "url" I have in the code. Probably you may ask, why does this guy want that?? this is because the "url" I'm using has a PHP script that generates features stored in a postgis db table as GeoJSON.
This the code:
[CODE]
// define the data source
var protocol = new OpenLayers.Protocol.HTTP({
url: "http://localhost/postgis_geojson.php?geotable=boreholes_point_wgs84&geomfield=geom&parameters=" + "column" + ilike '%"string"%',
format: new OpenLayers.Format.GeoJSON({
ignoreExtraDims: true,
'internalProjection': new OpenLayers.Projection("EPSG:900913"),
'externalProjection': new OpenLayers.Projection("EPSG:4326")
})
});
formPanel = new GeoExt.form.FormPanel({
title: "Place Name Search",
height: 150,
region: "north",
protocol: protocol,
items: [{
xtype: "textfield",
id: "column",
emptyText: "Choose table column",
fieldLabel: "Choose table column",
width: 200,
allowBlank: false
}, {
xtype: "textfield",
id: "string",
emptyText: "Search inside table",
fieldLabel: "Enter a word to search",
width: 200,
allowBlank: false
}],
listeners: {
actioncomplete: function(form, action) {
features = action.response.features;
store.loadData(features);
vm=map.getLayersByName("Results");
if(vm.length===0){
vecLayer = new OpenLayers.Layer.Vector("Results");
map.addLayer(vecLayer);
store.bind(vecLayer);
select.bind(vecLayer);
}
}
},
buttons: [{text: 'search',
handler: function(){
formPanel.search();
}
}],
keys: [{ key: [Ext.EventObject.ENTER],
handler: function() {
formPanel.search();
}
}]
});
[/CODE]
These are the cases I already tested:
url: http://localhost/postgis_geojson.php?geotable=boreholes_point_wgs84&geomfield=geom: this generates the whole table "boreholes_point_wgs84" as GeoJSON.
url: http://localhost/postgis_geojson.php?geotable=boreholes_point_wgs84&geomfield=geom&parameters=station ilike '%llena%': this generates only one feature, the feature that has "llena" in the "station" column. So, in this way I can find the feature through the search form.
What I was thinking is if I can pass these two strings I enter in "textfield" and modify the "url" in the way that it can catch these two words and form, for example, the second case I put above. I was playing with this:
url: http://localhost/postgis_geojson.php?geotable=boreholes_point_wgs84&geomfield=geom&parameters=" + "column" + ilike '%"string"%', so using the "id" I specified below each xtype, but it doesn't work.
I appreciate any support on this, thanks in advance,
Best regards,
Gery
The correct way to this is a simple form submission. The text input values will be sent to the server in a form post. Server side should parse the submitted values and do what's necessary. This isn't any different from the use of plain HTML and any server side frameworks.
Alternatively you can force your form to submit using HTTP GET method instead of POST and then your input values will be part of your URL. In ExtJS you use 'method' config. See API docs: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.form.Basic-cfg-method
EDIT: if you are not at all interested in actually 'submitting' the form you can get your field values like this: form.findField('myField').value
I'm pretty sure that this solution will help to understand how to solve this problem, I solved myself.

Textarea list via jquery .ajax to php

I have a textarea that I want to submit via ajax. When I try to output the value, I only get [object Object]
Jquery (ajax)
$("#insertAddresses").click(function() {
$.ajax({
type: "POST",
url: "insertAddr.php",
data: 'addresses=' +
}).done(function(list) {
//getList(); // run query to get addresses and populate list
});
});
PHP (i've tried)
$_POST['addresses'];
or
$addresses = explode("\n", $_POST['addresses']);
Regardless of anything i've tried, always returns
[object Object]
Help?!
Your serverscript is returning a json object, which is correctly recognized by JavaScript as an object. You can do a whole lot of things with that object, but you can't just put it on your website, as it is not html or text.
Here is a short description of json: http://en.wikipedia.org/wiki/JSON
I don't know how your data is structured, so i can't tell you how you can access your data. But in a json like this (example from wikipedia):
{
"firstName": "John",
"lastName" : "Smith",
"age" : 25,
"address" :
{
"streetAddress": "21 2nd Street",
"city" : "New York",
"state" : "NY",
"postalCode" : "10021"
},
"phoneNumber":
[
{
"type" : "home",
"number": "212 555-1234"
},
{
"type" : "fax",
"number": "646 555-4567"
}
]
}
You could, ie., excess the firstName simply with:
data.firstName
An voila, there is your excpected data.
You're data should be an object:
data: { adresses: "value" }
Just a little tip: the shorthand ajax-call for what you're doing in jQuery is $.post(.... and then you can lose the "type". Does exactly the same, but I think it's just a little neater.

Categories