getting the javascript results in python list - javascript

I use this site to download required info about lat/ lon of districts of India.
http://india.csis.u-tokyo.ac.jp/
Can I get all the districts of a give state using python? For e.g. if I choose State: maharashtra I get the list of districts like Akola, Raigarh in the next drop down list. I need that info as a python list.
I can see that a javascript function is called and it is getting the data from /api/ directory.
function setDistrictList() {
var selected = "";
state = $("#state_list").val();
districts = {};
url = "/api/getDistrictList";
Is it possible that I can get this list of districts programmatically using python?
update:
I have tried this function. But that returns the results and not the Java Script drop down list that I expect.
def __getVillageMarkersFromWeb(self,query, state_code=None, district_code=None):
stateString = '"state":"' + state_code + '"' if state_code is not None else ""
districtString = ',"district":"' + district_code + '"' if district_code is not None else ""
f_param = '{' + stateString + districtString + '}'
params = urllib.urlencode({"q":query,"f":f_param})
url = "http://india.csis.u-tokyo.ac.jp/geocode-cgi/census_ajax_json.cgi"
http = httplib2.Http()
response, markers_xml = http.request(url, "POST", params)
dom = minidom.parseString(markers_xml)
markers = dom.getElementsByTagName("marker")
return markers

You could, using BeautifulSoup.
BeautifulSoup allows you to target elements with particular class/id after you've gotten the markup from a page using Requests/urllib/urllib2.
Then you can loop through your BS object and save each to your list.
If the content on a page is generated with JavaScript, PhantomJS can emulate the JS before the markup is scraped.

Related

JQuery autocomplete text search with results from remote source

I'm trying to implement an input field with an autocomplete feature. I'd be using Google Books API to autocomplete names of books based on the keyword that the user enters in the input text field. I'd be using Django as my framework to implement this feature.
This is what I have been able to do so far:
JS
$( document ).ready(function()
{
$("#id_book_name").on("change paste keyup", function()
{
var app_url = document.location.origin;
var book_name = $('#id_book_name').val();
var url = app_url+'/book-search/';
if(book_name.length > 4)
{
var data = {
'book_name': book_name,
'csrfmiddlewaretoken': document.getElementsByName('csrfmiddlewaretoken')[0].value,
};
console.log(data);
$.post(url, data).done(function(result)
{
for(var book_title of result)
{
console.log(book_title);
}
console.log(result);
}).fail(function(error)
{
console.log(error)
});
return false;
}
});
});
Here, #id_book_name is the id of my input text field. As soon as the length of the keyword entered by the user exceeds 4, I'm sending a POST request to /book-search which is mapped to the following Python function where I hit Google Books API's endpoint and return the book titles in a specific JSON format:
def book_search(request):
book_results = {'titles':[]}
key = 'XXXXXXX'
url = 'https://www.googleapis.com/books/v1/volumes?q=' + request.POST['book_name'] + '&maxResults=5&key=' + key
result = requests.get(url)
json_result = json.loads(result.text)
if 'items' in json_result:
for e in json_result['items']:
if 'industryIdentifiers' in e['volumeInfo']:
isbn = ''
for identifier in e['volumeInfo']['industryIdentifiers']:
isbn = identifier['identifier'] if (identifier['type'] == 'ISBN_10') else isbn
if 'subtitle' in e['volumeInfo']:
book_results['titles'].append(e['volumeInfo']['title'] + ' - '
+ e['volumeInfo']['subtitle'] + ' (' + isbn + ')')
else:
book_results['titles'].append(e['volumeInfo']['title'] + ' (' + isbn + ')')
result = json.dumps(book_results)
return HttpResponse(result)
Sample return format of the above function for keyword 'python':
{"titles": ["Python - A Study of Delphic Myth and Its Origins (0520040910)", "Python Machine Learning (1783555149)", "Learn Python the Hard Way - A Very Simple Introduction to the Terrifyingly Beautiful World of Computers and Code (0133124347)", "Natural Language Processing with Python - Analyzing Text with the Natural Language Toolkit (0596555717)", "Python (0201748843)"]}
Now, what I'm not able to figure out is how to loop through the above JSON format to display the results below my input text field. I know I can use the append() JQuery function to add my book titles inside the <li> tags. However, I'm stuck on how to loop through my response result to individually get each book title using a for loop:
for(var book_title of result)
{
console.log(book_title);
}
I'm new to JQuery, and would really appreciate some guidance on this one. Thanks!
Your requirement is quite simple. One way to achieve this is ..please follow the comments
$(function() {
var myDiv = $("#mydiv"); //Assuming there is a div wrapped
var myUl = $('<ul/>'); //blank unordered list object
//Your result from the query
var result = JSON.parse('{"titles": ["Python - A Study of Delphic Myth and Its Origins (0520040910)", "Python Machine Learning (1783555149)", "Learn Python the Hard Way - A Very Simple Introduction to the Terrifyingly Beautiful World of Computers and Code (0133124347)", "Natural Language Processing with Python - Analyzing Text with the Natural Language Toolkit (0596555717)", "Python (0201748843)"]}');
//Iterate through each object
result.titles.forEach(function(item) {
var li = $('<li/>'); //create an li item object
li.append(item); // append the item/txt to the list item
myUl.append(li); //append the list item to the list
});
myDiv.append(myUl) //Append list to the div
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='mydiv'>
<input id='id_book_name' />
</div>
Let us know
Firstly, there is no reason to return a one-key dictionary. Just return the array. So, your result would look more like:
["Python - A Study of Delphic Myth and Its Origins (0520040910)", "Python Machine Learning (1783555149)", "Learn Python the Hard Way - A Very Simple Introduction to the Terrifyingly Beautiful World of Computers and Code (0133124347)", "Natural Language Processing with Python - Analyzing Text with the Natural Language Toolkit (0596555717)", "Python (0201748843)"]
Then, you pass a fourth parameter to $.post, the datatype of JSON, so it always automatically parses it into a JavaScript array.
$.post(url, data, onSuccess, 'json').fail(onFail);
Then you just have a simple array to append to search results.
Make an array of, say, 5 suggestions, and only fill the top 5 (As more would probably be uneccessary). Then use CSS to hide empty ones (Like #auto-complete :empty { display: none; }). Your onSuccess function could look like (Assuming you have a ol or ul element with the id auto-complete that has 5 li elements):
var autoCompleteBoxes = $('#auto-complete li');
$.post(url, data, function(data) {
for (var i = 0; i < 5; i++) {
autoCompleteBoxes[i].text(data[i] || '');
}
}, 'json').fail(function() {
// Reset auto complete boxes if there was a failure.
for (var i = 0; i < 5; i++) {
autoCompleteBoxes[i].text('');
}
$('#auto-complete').hide();
}

How can I delete specific rows in parse.com?

I have objects in Parse called "Post" and within that, I have columns called "title" and "content". I am trying to ask the user for an input value and save this as "remove". If the user's input value ("remove") matches a "title" value already saved in parse.com, I want to delete the entire row in parse, so that both the "title", "content" and everything else in the row is deleted. The deleting part is not working so I am wondering if my code is actually making it go through all the data saved in parse and find the one that matches the user's input and then delete it.
What am I doing incorrectly and what can I change to make it delete the entire row?
Thank you in advance.
function getPosts(){
var query = new Parse.Query(Post);
query.find({
success: function(results){
for(var i in results){
var title = results[i].get("title");
var content = results[i].get("content");
var remove = $("#post-remove").val();
console.log("Remove: "+remove);
console.log("MAC Address: " +title);
console.log("place: "+content);
if (title == remove)
{
window.alert("The MAC address matches.");
console.log(remove+" matches " + title+ " and is located in " +content);
var Post = Parse.Object.extend("Post");
var query = new Parse.Query(Post);
query.find("objectId", {
success: function(yourObj){
//console.log(yourObj);
//Post.destroy({}); //if title matches remove, delete the Post (title and content) (but it's not deleting it)
Post.remove("title");
Post.remove("content");
}
});
}
}
}
});
}
To clarify and add a bit to #JakeT's acceptable answer:
1) find objects to delete like this:
function postsMatching(title) {
var Post = Parse.Object.extend("Post");
var query = new Parse.Query(Post);
query.equalTo("title", title);
return query.find();
}
2) Delete an array of parse objects like this:
Parse.Object.destroyAll(posts);
3) Put the two ideas together (returning a promise to find then delete) like this:
var title = $("#post-remove").val();
postsMatching(title).then(function(posts) {
console.log("deleting " + JSON.stringify(posts));
Parse.Object.destroyAll(posts);
}, function(error) {
console.log("error " + JSON.stringify(error));
});
First of, you can use the Parse.Query.equalTo(key, value) method to filter for the Post/s you are looking for. That will render a lot of your logic unnecessary.
Additionally, since most parse calls are asynchronous, I would suggest learning about Parse Promises and using those instead of the call backs you're using.
Finally, you don't need a second nested query, since you already have the object you are trying to destroy. You just need to call destroy() on that object, and if you have some extra content you need to take care of deleting (i.e., your 'content' is a pointer to another object that is owned only by the Post you are deleting), you should set up a beforeDestroy() trigger for the Post object in your cloud code that will delete that pointer as well.

Alfresco: Javascript data list creation

I am attempting to execute some Javascript in my Alfresco workflow to create a custom data list type in my site called "Testing". But before I fill in my custom data list type information, I tried simply creating a contact list data list based on examples I found to make sure it works.
Here is my code:
var site = siteService.getSite("Testing");
var dataLists = site.childByNamePath("dataLists");
if (!dataLists) {
var dataLists = site.createNode("dataLists", "cm:folder");
var dataListProps = new Array(1);
dataListProps["st:componentId"] = "dataLists";
dataLists.addAspect("st:siteContainer", dataListProps);
dataLists.save();
logger.log("Created new datalists folder.");'
}
var contactList = dataLists.childByNamePath("contactlist1");
if (!contactList) {
var contactList = dataLists.createNode("contactlist1","dl:dataList");
// tells Share which type of items to create
contactList.properties["dl:dataListItemType"] = "dl:contact";
contactList.save();
var contactListProps = [];
contactListProps["cm:title"] = "My Contacts";
contactListProps["cm:description"] = "A contact list generated by a javascript.";
contactList.addAspect("cm:titled", contactListProps);
logger.log("Created contact datalist.");
}
var contact = contactList.createNode(null, "dl:contact")
contact.properties["dl:contactFirstName"] = "Florian";
contact.properties["dl:contactLastName"] = "Maul";
contact.properties["dl:contactEmail"] = "info#fme.de";
contact.properties["dl:contactCompany"] = "fme AG";
contact.properties["dl:contactJobTitle"] = "Senior Consultant";
contact.properties["dl:contactPhoneMobile"] = "not available";
contact.properties["dl:contactPhoneOffice"] = "not available";
contact.properties["dl:contactNotes"] = "Alfresco Expert";
contact.save();
logger.log("Created new contact: " + contact.nodeRef);
My guess is it's not selecting the right site, but I'm not sure how else to set the site variable to the "Testing" site. Also, I know this code is in the right place in my .bpmn file, because other Javascript in there executes correctly.
What is wrong with my code?
There are 2 javascript object on which you have confusion.One is site and other is node.Site object does not have method called childByNamePath.
Instead of that use below for getting datalist.
var dataLists = site.getContainer("dataLists");
Your code for retrieving site is correct.The only change is for datalist.

Birt: access content of dataset from beforeFactory

Im trying (desperately) to access the content of a dataset by script in the beforeFactory.
The task at hand is to create design elements from a linked library and place them in a certain cell of a grid. Everything works fine except for the "place them in a certain cell of a grid"-part.
The information about which element is to be created and where it is to be placed is available in a dataset (dsDesignInformation), which contains three columns: targetRow, targetColumn, targetContent. targetContent contains a string, which is used to find an element in the library.
For example: There is a grid placed on the body (grdMasterGrid), with two rows and two columns. If the dsDesignInformation would contain a row like (1,1,"testObjectName"), I want to create the element "testObject" from a linked library and place it in the intersection of row 1 and column 1 of my grdMasterGrid.
The code for creating and placing the element:
importPackage(org.eclipse.birt.report.model.api);
var myLibraryHandle = reportContext.getDesignHandle().getLibrary("myLibraryName");
var myElementFactory = reportContext.getDesignHandle().getElementFactory();
// should be the objectname as defined in the dsDesignInformation
var myTargetElementHandle = myLibraryHandle.findElement("testObjectName");
var myCreatedElementHandle = myElementFactory.newElementFrom(myTargetElementHandle , "someUniqueElementName");
var myMasterGridHandle = reportContext.getDesignHandle().findElement("grdMasterGrid");
// should be target coordinates as defined in dsDesignInformation
var myTargetCellHandle= myMasterGridHandle.getCell(1,1);
myTargeCellHandle.getContent().add(myCreatedElementHandle);
This works like a charm when used with hard coded target-information and placed in the beforeFactory of the report design.
I do however need to access the contents of dsDesignInformation and pass them on to the script above. So far (4 days in) I had zero (as in null) success.
I would be glad for any help or ideas on the topic.
Regards,
maggutz
It is possible to do this, but with some severe restrictions.
The main restriction is: You cannot use your DataSource and your DataSet directly.
Instead, you'll have to copy them and work with the copy.
Don't ask my why this is, because I don't know. But I learned it the hard way during hours and days of trying...
The next restriction is: You cannot access report parameter values, unfortunately. This is not a problem if your query works without parameters.
Otherwise, you'll have to find a way to access the parameter value anyhow. Depending on how your report is integrated into the app, you could try writing the value into the appContext before calling BIRT, for example.
Here is a fragment of working code (in the beforeFactory event) to show you how to workaround this limitation:
importPackage( Packages.org.eclipse.birt.report.model.api );
importPackage(Packages.org.eclipse.birt.data.engine.api);
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.data.engine.api.querydefn);
importPackage(Packages.org.eclipse.birt.data.engine.core);
importPackage( Packages.org.eclipse.birt.report.model.api );
var myconfig = reportContext.getReportRunnable().getReportEngine().getConfig();
var de = DataEngine.newDataEngine( myconfig, null );
var dsrc = reportContext.getDesignHandle().findDataSource("lisa");
// This is the existing data source.
var odaDataSource = new OdaDataSourceDesign( "Test Data Source" );
// We create a new DataSource which is only to be used in this event
// Now we copy the relevant properties from the existing DataSource to the new one.
var dbUrl = dsrc.getProperty("odaURL").toString();
var dbUsr = dsrc.getProperty("odaUser").toString();
var dbPwd = dsrc.getProperty("odaPassword").toString();
var dbDrv = dsrc.getProperty("odaDriverClass").toString();
odaDataSource.setExtensionID( "org.eclipse.birt.report.data.oda.jdbc" );
odaDataSource.addPublicProperty( "odaURL", dbUrl );
odaDataSource.addPublicProperty( "odaDriverClass", dbDrv);
odaDataSource.addPublicProperty( "odaUser", dbUsr );
odaDataSource.addPublicProperty( "odaPassword", dbPwd );
// log.info("odaURL=" + dbUrl); // Only if you have a logging framework at hand
// Now create a new DataSet and set its query etc.
// I suppose that it is possible to copy the properties from an existing DataSet instead.
// However, I didn't try that.
var odaDataSet = new OdaDataSetDesign( "Test Data Set" );
odaDataSet.setDataSource( odaDataSource.getName() );
odaDataSet.setExtensionID( "org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet" );
// This is the SQL query (in my application).
// You'll have to modify this as needed.
odaDataSet.setQueryText( " select STEDA.TEDA_ID, STBST.LANGTEXT" +
" from STEDA, STBST" +
" where STEDA.ZUSATZ_1 = 'MATRIX'" +
" and STBST.TBST_ID = STEDA.TEDA_ID");
// Tell the DataEngine about the new objects.
de.defineDataSource( odaDataSource );
de.defineDataSet( odaDataSet );
// Now execute the query:
// This seems overly complicated, but hey: it works.
var queryDefinition = new QueryDefinition( );
queryDefinition.setDataSetName( odaDataSet.getName() );
queryDefinition.setAutoBinding(true);
var pq = de.prepare( queryDefinition );
var qr = pq.execute( null );
rowcount=0;
var elementFactory = reportContext.getDesignHandle().getElementFactory()
var ri = qr.getResultIterator( );
// Our application is using the query to generate a layout structure
// into an (already existing) placeholder element "Layout MATRIX".
var containerGrid = reportContext.getDesignHandle().findElement("Layout MATRIX");
// Iterate through the query results
while ( ri.next( ) )
{
// get the actual values of the query output columns
var tedaId = ri.getString("TEDA_ID");
var langtext = ri.getString("LANGTEXT");
// log.info("langtext: " + langtext);
rowcount++;
// Do something with the current result row.
... myModifyLayout(containerGrid, tedaId, langtext); ...
}
// Cleanup
ri.close( );
qr.close( );
de.shutdown( );
// You may want to save the modified design file while developing.
// That way you can check the mresults in the Report Designer.
if (false) {
reportContext.getDesignHandle().saveAs("c:/temp/modified.rptdesign");
}

Change one URL variable on re-submission

I have a PHP page that displays data using different variables submitted through the URL. For instance:
index.php?rownum=30&colnum=2&qlang=en
I need to give the user the ability to change the sort order.
For that I have added an HTML <select> with two options calling my re_order() function which should basically call the same URL with all parameters intact except the new sort order.
Is there an easy way to perform that or should I use a PHP session to see what parameters have been set before?
That's a task that should be handled by the client.
You can probably do something like this:
location.search = location.search.replace(/([&?]sort)(?:=[^&]*)?(?=&|$)/i, '$1=newvalue');
You can make it a reusable function:
function setUrlParam(searchString, param, value) {
var rx = new RegExp('([&?]' + param + ')(?:=[^&]*)?(?=&|$)', 'i'),
encodedVal = encodeURIComponent(value);
return rx.test(searchString)?
searchString.replace(rx, '$1=' + encodedVal) :
searchString += '&' + param + '=' + encodedVal;
}
location.search = setUrlParam(location.search, 'sort', 'date');

Categories