Discussion Forums  >  Plugins, Customizing, Source Code

Replies: 11    Views: 80

sarahk
Code is Art
Profile
Posts: 159
Reg: Jul 16, 2014
Auckland
10,290
08/21/14 07:04 PM (10 years ago)

Dynamic Content

It might be my newbie-ness showing but I'm not sure how some of the json stuff works. My sample app that I'm working is using David's map example and at the moment I'm using the native driving directions - and getting the map points from a url. If I wanted to point those map points to a separate page I'd need to specify an actual page that exists in my btconfig file. Every map point would need it's own page - no reuse, right? After looking at the json snippet keeper I can see how I can manually edit the btconfig to think that pages exist event though I haven't created them through the site. So... if I'm adding map points on the fly then I'd also need to be adding the pages that they point to on the fly. Do I do that * via the json feed; or * do I put my btconfig on the same server and inject the json for the destination page based on the database. or is there something I've missed? I've just been watching the cubbyhole videos and figured that Niraj can't have been creating a json page for every one of those player profiles, surely?
 
PaddyO
Lost but trying
Profile
Posts: 189
Reg: Sep 11, 2013
Geelong
5,190
like
08/21/14 07:19 PM (10 years ago)
Hi Sarah, I had a similar challenge early on and Chris1 and Smug helped me enormously. In my case it worked a bit like this: - dataURL in the BT config file points to a php script on my server - php script finds stuff in my database according to the specified search parameters - php script also cleverly does the JSON formatting of all the relevant data, INCLUDING setting up the JSON so that it 'preloads' the data that I want it to show after each map pin is tapped, by embedding a second php script call specifically for the additional data that's associated with each map pin. If I understand it correctly, this is what you mean by 'map pins pointing to a separate page', yes? That it's the additional info that you're looking to see after the initial callout bubble pops up? What this all ended up with is two plugins - one (BT_screen_map) that calls and loads the map pins, and the other that displays the 'metadata' associated with each pin, but this is all generated dynamically because the initial php request is based on variable parameters. In my case the second plugin just calls an html file that displays the relevant metadata. If this sounds like what you're looking for I'm more happy to share what I have, though I don't pretend to know even half of how it works either! Cheers Paddy.
 
sarahk
Code is Art
Profile
Posts: 159
Reg: Jul 16, 2014
Auckland
10,290
like
08/21/14 07:40 PM (10 years ago)
Hi Paddy - that sounds perfect. What I'll eventually be doing will be a lot more complex but baby steps, right? I'd love to see the metadata bit - I think thats the missing piece of the puzzle.
 
SmugWimp
Smugger than thou...
Profile
Posts: 6316
Reg: Nov 07, 2012
Tamuning, GU
81,410
like
08/21/14 08:12 PM (10 years ago)
For things to work 'right', you'll need to dip into PHP, a little MySQL, and perhaps a smidgen of javascript. You don't have to be a guru, but you'll need to learn how to edit small bits and keep it working. Check out the post on 'WB AddOns' located here: https://www.buzztouch.com/forum/thread.php?tid=DD7AB5D535F2631073ED32C&fid=06DB0BCB08E6666 Be sure to watch the video; it should help make things a bit easier to understand. The way it works (in a nutshell) is you will 'load up' the database with your locations, and some information about the location. Then, you will 'point' your menu to a php enabled web page that will query the database, and return the information to you in json format. It will populate your menu. When you tap on the menu, the dataURL for 'that' location will again query a php enabled web page to deliver the data pertinent to that menu choice. When you 'tap' on the pin, the dataURL will once again query the database and deliver data pertinent to the choice. The word of the day is 'cascade'. Each 'level' of query delivers data for the next level. Granted, at first it will be a lot to take in. But just inspect it one piece at a time, and if you break it down into managable chunks, it'll make sense a lot sooner than the overwhelming task of trying to digest it all at once. Good luck, and if you have any questions at all, just yell. Cheers! -- Smug
 
sarahk
Code is Art
Profile
Posts: 159
Reg: Jul 16, 2014
Auckland
10,290
like
08/21/14 08:28 PM (10 years ago)
Perfect Smug - I hadn't been able to work out how to pass variables or data between the screens. From what you've written I'm about to get all those answers! Thank you!!!
 
PaddyO
Lost but trying
Profile
Posts: 189
Reg: Sep 11, 2013
Geelong
5,190
like
08/21/14 08:32 PM (10 years ago)
OK, see if this makes sense Sarah. First, here's the relevant bit of my config.txt: {"itemId":"2be83734ea74f184e7c9395", "itemType":"BT_screen_map", "itemNickname":"Mymap", "itemId":"2be83734ea74f184e7c9395", "itemType":"BT_screen_map", "itemNickname":"Mymap", "navBarTitleText":"Near you", "navBarBackgroundColor":"#9EBA21", "navBarStyle":"solid", "showUserLocation":"1", "showUserLocationButton":"1", "defaultMapType":"standard", "showMapTypeButtons":"1", "buttonColor":"#FF9933", "showRefreshButton":"1", "singleLocationDefaultZoom":"8", "dataURL":"http://www.noshplanet.com/pins.php?userlat=[deviceLatitude]&userlong=[deviceLongitude]", "backgroundColor":"clear", "childItems":[ ]} Note the dataURL and the variables userlat and userlong built into the dataURL query. You'll see them in the php below. I've commented it so I can try to understand what's going on so take those with grain of salt because my understanding might not be spot on! The magic (I think) is that in the config.txt, there is no child item specified, but the JSON that this php sends back DOES include a child item (see below), which is defined as 'all the extra JSON that the second dataURL (metamap.php) delivers'. Took me ages to get my head around that, but it's the thing that lets the app access the metadata on the fly, as it is cascading down from whatever the initial retrieved data is, no matter what it is. (Because they both 'know' what the record of interest in the database table is, and one passes that value to the next.) If it was hard-coded into config.txt as a child item there'd be no relational connection between this php query and the config.txt child item. Including it in the php-generated JSON creates that relationship. I think of it as using the php files to transfer/carry across your variable values, rather than trying to make the BT plugins talk to each other, I think. <?php require_once("../app/config.php"); //that has my password etc details in, keep as a separate file for security // many thanks to Smug, Chris1 and Big Paul for getting this happening... Function getPost($var) { $ret = ""; if (isset($_POST[$var])) $ret = $_POST[$var]; else if (isset($_GET[$var])) $ret = $_GET[$var]; else if (isset($_REQUEST[$var])) $ret = $_REQUEST[$var]; return $var; } //userlat and userlong are variables that record where the user is standing (ie their current position when they're holding their phone) - they are defined in the config.txt's dataURL. $userlat = getPost($userlat); $userlong = getPost($userlong); //Removes last char function fnRemoveLastChar($theVal, $theChar){ $theVal = trim($theVal); //now, if the last char is the char parameter... if(substr(strtoupper($theVal), (strlen($theVal) - 1), 1) == strtoupper($theChar)){ return substr($theVal, 0, strlen($theVal) - 1); }else{ return $theVal; } } $db_handle = mysql_connect($server, $user_name, $password); $db_found = mysql_select_db($database, $db_handle); if ($db_found) { //this is some sexy mathematical code that says "search the database fields specified for records that occur within x distance of the current location". So it's really just a radius search. 3959 is some magic number to do with how big the earth is. $SQL = "SELECT *, ( 3959 * acos( cos( radians($userlat) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians($userlong) ) + sin( radians($userlat) ) * sin( radians( latitude ) ) ) ) AS distance FROM location HAVING distance < 20"; //note: in the snippet above, 'latitude' and 'longitude' are the column names in our database's 'location' table, not in-built SQL fairies. //OK, we've connected to the MySQL database and have pulled out the required records. Now we're putting them (well, parts of them as per the $dbfield values below) on the mapscreen (because this php is pulling that data for the map screen plugin, which is what has called this php file). The pins currently show the "title" as the "lid" field, which happens to just be a number. For now. Could be anything depending on the db field specified. Subtitles contain other info (address, city, postal code). $result = mysql_query($SQL); //this $result 'stores' the data we've pulled out in its own little ethereal world somewhere, and we access it later... $outputString = '{"childItems":['; $childItemString = ""; $i=0; while ($db_field = mysql_fetch_assoc($result) ) { // 'while' causes the script to loop through all the retrieved records saved temporarily in $result until it has organised them all... // and now we format the results of the query as JSON so Xcode can understand them.. $i++; $childItemString .= '{"itemid":"location' . $i . '","itemType":"BT_mapLocation","latitude":"' . $db_field["latitude"] . '","longitude":"' . $db_field["longitude"] . '","title":"' . $db_field["lid"] . '","subTitle":"' . $db_field["street"] . ' ' . $db_field["city"] . ' ' . $db_field["postal_code"] . '", "loadScreenObject":{"itemId":"26E5DD65713801C423C182B", "itemType":"BT_screen_htmlDoc", "itemNickname":"metamap.php", "navBarTitleText":"", "navBarRightButtonType": "DetailDisclosure", "navBarRightButtonTapLoadScreenNickname": "Mymap", "navBarRightButtonTapLoadScreenItemId": "2FCE8AD101DBEDB5D5C33F8", "navBarRightButtonTapTransitionType": "slideUp", "navBarBackgroundColor":"#9EBA21", "dataURL":"http://www.noshplanet.com/metamap.php?otherID=' . $db_field["lid"] . '", "forceRefresh": "1"}},'; //that little URL call to metamap.php up there is included because it creates the 'info' icon on each pin's popup dialog box. It's the second dataURL in this cascade (remember, THIS php file is the FIRST dataURL that's been called) and all it does (for now) is show that we can 'carry' the value 'lid' through from the tapped pin to the tapped dialog info icon. The next screen is supplied its data by metamap.php, and that will display a 'lid' value that matches the 'lid' value of the same pin tapped in the first place. Later we'll update that so it presents us with something a bit more meaningful, like info about what colour the milkshakes are, or perhaps something even more intrinsically interesting. :) } $outputString .= fnRemoveLastChar($childItemString, ','); $outputString .= "]}"; echo $outputString; mysql_close($db_handle); } else { echo '{"childItems":[{"itemId":"err1", "title":"Database NOT Found"}]'; } ?> Phew. Does that help? Cheers Paddy.
 
PaddyO
Lost but trying
Profile
Posts: 189
Reg: Sep 11, 2013
Geelong
5,190
like
08/21/14 08:35 PM (10 years ago)
What Smug said!! (Cos that's what he told me too and that's where a heap of my stuff up there came from!)
 
Niraj
buzztouch Evangelist
Profile
Posts: 2943
Reg: Jul 11, 2012
Cerritos
37,930
like
08/23/14 09:56 AM (10 years ago)
I do indeed have a different JSON text file for each of the Player Profiles. I decided to keep it simple by only having local files in the app. Thus, I did not want to be reliant on a Server for the Player data. Of course, that makes changes be a bit difficult, since the file for each Player would have to be updated. My last update to the files took only 10-minutes of hand-editing of 47 files. Another way to skin that cat is to use PHP and a Database as Smug advises. Then I would pull down those Player Profiles from the PHP and save it as a JSON text file. That way an update to the Player Profile screen can be done in a single PHP file. Then I would run a Bash script using the curl command to ask for all the Player Profiles and save each one onto the disk as a JSON text file. -- Niraj
 
sarahk
Code is Art
Profile
Posts: 159
Reg: Jul 16, 2014
Auckland
10,290
like
08/24/14 01:59 PM (10 years ago)
I can imagine that would be time consuming. It would be pretty simple to run a script that created all the json files and then you just had to ftp them down and copy into the app. My mind is racing ahead to my next project which will have info being sliced and diced any number of ways but which could be supported by a single json file that then had logic in the app filtering and applying. That would be breaking BT's way of doing things so I think local files that can be refreshed on the fly will be the way to go at the moment.
 
SmugWimp
Smugger than thou...
Profile
Posts: 6316
Reg: Nov 07, 2012
Tamuning, GU
81,410
like
08/24/14 03:43 PM (10 years ago)
Well, one of the projects I have in the works (between projects, that is) is the 'SmugData' plugin, which basically keeps an SQLite database in your app, and you make db queries from within the app. It's pretty slick, and pretty fast. But like you said, the only way it works 'well' is by breaking the BT way of doing things... I'm still trying to figure out a 'nice' way to pull it off, with respect to 'other' plugin interaction. Cheers! -- Smug
 
sarahk
Code is Art
Profile
Posts: 159
Reg: Jul 16, 2014
Auckland
10,290
like
08/24/14 03:49 PM (10 years ago)
My next project will include users being able to schedule things - a bit like Paprika does with recipes, only we'll be doing activities. I haven't even started dabbling with saving user info let alone syncing. Babysteps! So Smug - you have a customer champing at the bit for your plugin!
 
Niraj
buzztouch Evangelist
Profile
Posts: 2943
Reg: Jul 11, 2012
Cerritos
37,930
like
08/24/14 07:32 PM (10 years ago)
Hey Smug -- at the Las Vegas CodeCamp, we did what you are wanting: - Within the iPhone app, we consumed a JSON data source from a remote server running PHP - Parsed that JSON data into an array of dictionaries - Loaded that JSON data into a local SQLite database - Queried the local SQLite database as needed Chris1 had written the iOS database management code to make it easy for interfacing with the SQLite database. I don't see that approach as breaking the "Buzztouch way", as it simply extends a particular set of screens. It'd be interesting to compare-contrast with the more powerful FMdb library for SQLite. -- Niraj
 

Login + Screen Name Required to Post

pointerLogin to participate so you can start earning points. Once you're logged in (and have a screen name entered in your profile), you can subscribe to topics, follow users, and start learning how to make apps like the pros.