Roku Search Bar

Does anyone have any example code for a search bar?

I’m trying to setup a search bar for my app to filter and search through videos. I don’t see anything on the Roku SDK Dev site.

Is that something I’m going to have to do custom?

Well first off you need to have a server side script that will perform the search itself.. I personally use PHP.

Assuming you do have a script, this is something you can use with the stock keyboard dialog.

sub tvshows()
url = “http://theUrlwithScriptToSearch” + m.top.dialog.text
regex = CreateObject(“roRegex”, " ", “”) 'to replace any blank spaces.
url = regex.ReplaceAll(url, “%20”)
m.readVideoContentTask = createObject(“RoSGNode”, “ContentReader”)
m.readVideoContentTask.observeField(“content”, “showvideolist”)
m.readVideoContentTask.contenturi = url
m.readVideoContentTask.control = “RUN”
end sub

There is a little more to it than that like setting up key events on press or some sort of search button. If you need more let me know.

If your app downloads a master content table with everything in it, then you can search during runtime on the client side using brightscript.

“destruk” wrote:
If your app downloads a master content table with everything in it, then you can search during runtime on the client side using brightscript.
You are right but the Roku is extremely slower in parsing than server side.

So to make sure I understand.

There currently is no functionality that allows me to setup a search bar without doing it custom.

Yes we will be using PHP for the backend part and thank you for the sample code.

You would make a minikeyboard, or a full keyboard, and handle the input to create a working “search bar”.
And I think it depends a lot on your internet connection speed and server power, as far as which is faster. The actual parsing on roku will be the pretty much the same depending on how many results you get, I think I have parsed 5000 entries from json in 3 or 4 seconds on a Roku 4. If you have a cheap shared server which is running at capacity from GoDaddy or another typical cheap provider like rackspace then it just might be faster to have the roku client do the searching itself. It’s your choice which to do of course.

With all due respect 3-4 seconds is extremely slow. With 19,000 items my results return in .2 seconds via server side and php.

Here is a sample of how i do it

1st I have a master file in xml format, no database needed.
I named it “all.xml” and place it in the root folder of my server.

Sample:

<?xml version = "1.0" encoding = "utf-8" standalone = "yes" ?>
  <Content>
    <item url="a_bit_of_fry_and_laurie" title="A Bit of Fry and Laurie" year="1987" hdposterurl="yourPosterUrl"/>
  </Content>

2nd i create a search script that will return the results.
I name it “livesearch.php” and place it in the root folder of my server.
“\n” = end of line and “i” = not case sensitive
I then append the url to a base url that handles the actual video file on click of the results.

Sample:

<?php header("Content-type: text/xml")?>
<?php echo "<?xml version = \"1.0\" encoding = \"utf-8\" standalone = \"yes\" ?>\n" ?>
  <?php echo "<Content>\r\n" ?>
    <?php
      $q=$_GET["q"];
      $xml=file_get_contents("all.xml");
      preg_match_all("/.*title=\".*$q.*\"*\n/i", $xml, $output,PREG_SET_ORDER);
      foreach($output as $file){
      $file= $file[0];
      echo "$file";
      } 
<?php echo "</Content>" ?>

So now if I go to “https://myWebAddress.com/livesearch.php?q=searchTextInput” it gets returned with all results parsed in a Roku xml format.
I also use a function so the results are returned as they type and not by a search button being pressed.

This method also allows all results returned regardless of where the word falls in the search and you dont have to worry about exact matches.

IE … “https://myWebAddress.com/livesearch.php?q=brady” will return “the brady bunch” assuming that is a file.

“norcaljohnny” wrote:
With all due respect 3-4 seconds is extremely slow. With 19,000 items my results return in .2 seconds via server side and php.
And with all due respect it could take 3-4 seconds to download the data from your server to the client app. So… you know, we can argue about which is better for months if you prefer, but really it’s up to the individual channel developer to decide what they want to use. While results might return from your server it still takes the roku devices (low end and roku 4) 5 seconds to parse the results for 19,000 items, so that is still slow. But since3 you can’t make that part faster, well… Maybe chill out, we’re not fighting here, we are discussing different techniques to accomplish a goal dude.

I’m sure this code can be made faster, it’s from about a decade ago.

'Create Searchresults Array
searchresults=[]
'Loop through content list categories
For x=0 To m.masterlist.count()-1
	'Loop through items in each category
	For y=0 To m.masterlist[x].count()-1
		'If search term is 1 character long, then check for matches based on title only
		If Len(FinalSearchTerm)=1
			'search titles that begin with that character and skip other fields
			If LCASE(m.masterlist[x][y].Title.Left(1))=LCASE(FinalSearchTerm)
				'by default if it matches we will add it
				oktoadd=1
				'verify item doesn't already exist in the search results
				For z=0 To searchresults.count()-1
					If searchresults[z].contentID=m.masterlist[x][y].contentID
						oktoadd=0
						Exit For
					End If
				Next
				If oktoadd=1 searchresults.push(m.masterlist[x][y])
			End If
		Else
			If(Instr(1,LCASE(m.masterlist[x][y].Title),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Director),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Actors[0]),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Actors[1]),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Actors[2]),LCASE(FinalSearchTerm))>0)  or (Instr(1,LCASE(m.masterlist[x][y].Description),LCASE(FinalSearchTerm))>0) or (Instr(1,m.masterlist[x][y].ReleaseDate,FinalSearchTerm)>0)
				oktoadd=1
				For z=0 To searchresults.count()-1
					If searchresults[z].contentID=m.masterlist[x][y].contentID
						oktoadd=0
						Exit For
					End If
				Next
				If oktoadd=1 searchresults.push(m.masterlist[x][y])
			End If
		End If
	Next
Next

I did a bit more digging and this is 30% faster for a local search, so thanks, I learned something.

'Create Searchresults Array
searchresults=[]

'create associative array for faster searchingg
clist={}

'Loop through content list categories
For x=0 To m.masterlist.count()-1
   'Loop through items in each category
   For y=0 To m.masterlist[x].count()-1
      'If search term is 1 character long, then check for matches based on title only
      If Len(FinalSearchTerm)=1
         'search titles that begin with that character and skip other fields
         If LCASE(m.masterlist[x][y].Title.Left(1))=LCASE(FinalSearchTerm)
	    If clist.doesexist(m.masterlist[x][y].contentID)=FALSE
		searchresults.push(m.masterlist[x][y])
		clist.AddReplace(m.masterlist[x][y].contentID,0)
	    End If
         End If
      Else
         If(Instr(1,LCASE(m.masterlist[x][y].Title),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Director),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Actors[0]),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Actors[1]),LCASE(FinalSearchTerm))>0) or (Instr(1,LCASE(m.masterlist[x][y].Actors[2]),LCASE(FinalSearchTerm))>0)  or (Instr(1,LCASE(m.masterlist[x][y].Description),LCASE(FinalSearchTerm))>0) or (Instr(1,m.masterlist[x][y].ReleaseDate,FinalSearchTerm)>0)
	    If clist.doesexist(m.masterlist[x][y].contentID)=FALSE
		searchresults.push(m.masterlist[x][y])
		clist.AddReplace(m.masterlist[x][y].contentID,0)
	    End If
         End If
      End If
   Next
Next

“destruk” wrote:

“norcaljohnny” wrote:
With all due respect 3-4 seconds is extremely slow. With 19,000 items my results return in .2 seconds via server side and php.
And with all due respect it could take 3-4 seconds to download the data from your server to the client app. So… you know, we can argue about which is better for months if you prefer, but really it’s up to the individual channel developer to decide what they want to use. While results might return from your server it still takes the roku devices (low end and roku 4) 5 seconds to parse the results for 19,000 items, so that is still slow. But since3 you can’t make that part faster, well… Maybe chill out, we’re not fighting here, we are discussing different techniques to accomplish a goal dude.
Please know I am not trying to argue anything out with you. I know you are extremely helpful in the forums and have learned from your past posts a dozen times at least.
So please believe me when I say with all due respect, as its from the heart. I just wanted to present something different.
As far as the downloading the master list to the client, it never does. It only returns the results based on the user input. So even if the master list may be 7 megs it never poses a problem because the search happens server side and the returned results are about 10k if that. And that is what makes it so fast.
Again Im just bouncing things around to see if there are methods outside the roku sdk that we can benefit from. Cheers

Both methods can be even quicker if you limit the results with paging - only sending 20-50 items from the server or doing the search in 50 item chunks and adding a “select for more” to grab the next page of results. In my own experience, the master full content list could be transferred one time when the app loads after the user logs in. We were doing that for smaller channels with fewer than 500 items and that allowed us to use low-power servers to handle hundreds of users per hour and was sufficient. I realize your user base is most likely higher, and you have a lot more content than we have dealt with here, and I do agree if money was available for more powerful servers and connectivity, us handing off the harder tasks to the server would be a better idea for scalability.

For the actual search bar itself. When I select the button to search a Poster Node needs to be created with a minikeyboard attached to it. How would I go about doing that?

I would create a group, add a rectangle, and within that add the minikeyboard, set the group to visible and set focus to the minikeyboard. https://sdkdocs.roku.com/display/sdkdoc/MiniKeyboard

You’ll also need a button involved to accept the input and hide/get rid of the search box.

“lylyahiko” wrote:
For the actual search bar itself. When I select the button to search a Poster Node needs to be created with a minikeyboard attached to it. How would I go about doing that?
The search bar/screen I use resembles apple tv 4 search screen. I can share the complete code with you or if you wish I can write a code using the minikeyboard to it…

“norcaljohnny” wrote:
Here is a sample of how i do it

1st I have a master file in xml format, no database needed.
I named it “all.xml” and place it in the root folder of my server.

Sample:


  

2nd i create a search script that will return the results.
I name it “livesearch.php” and place it in the root folder of my server.
“\n” = end of line and “i” = not case sensitive
I then append the url to a base url that handles the actual video file on click of the results.

Sample:


\n" ?>
  \r\n" ?>
           $q=$_GET["q"];
      $xml=file_get_contents("all.xml");
      preg_match_all("/.*title=\".*$q.*\"*\n/i", $xml, $output,PREG_SET_ORDER);
      foreach($output as $file){
      $file= $file[0];
      echo "$file";
      } 
" ?>

So now if I go to “https://myWebAddress.com/livesearch.php?q=searchTextInput” it gets returned with all results parsed in a Roku xml format.
I also use a function so the results are returned as they type and not by a search button being pressed.

This method also allows all results returned regardless of where the word falls in the search and you dont have to worry about exact matches.

IE … “https://myWebAddress.com/livesearch.php?q=brady” will return “the brady bunch” assuming that is a file.
Interesting. I didn’t know it was possible to use php. I am versed in PHP. However, ban new to scenegraph/brightscript. I see clearly how to get this to show on a PHP web page. But how would I integrate this with Scenegraph/brightscript?
Thanks