Hiding contents of a js array in the view

Hi.

I am using the LocalAutocompleter and therefore the autocompleter object
needs to include an inlined javascript array that includes all the
possible results. I generate the array in the controller and pass it to
the view. The problem is that the whole array is included in the html
and users can see it if they look at the html source. I want to hide
this information from the user for 2 reasons: 1) it makes the html
source huge and 2) more important I want to only let users access it
through the autocomplete functionality. I don’t want them to see all the
options.

Any help is appreciated!

Here is the relevant code:

Controller

rubyarray includes 2500 text entries

rubyarray = array.inspect # ‘inspect’ makes array ‘javascript-like’

View

var jsarray = new Array();
jsarray = <%= @rubyarray %> <-- here is where the array contents get
exposed

new Autocompleter.Local(..., ..., jsarray , {...} );

bump. still interested in an answer if anyone has one!

hi,
try json if it fits your need
in my autocompleter I used it.
regards
gaurav

These are all excellent suggestions! I really like the encryption idea
which could be simple enough to do and I’ll also check out ujs4rails
which if it does just what you suggest could be perfect.
thanks for taking the time for the reply! very appreciated.

On 12/26/06, Gustav P. [email protected] wrote:

Autocompleter handles that variable (I’ve never used Autocompleter.Local
in a regular Autocompleter would have taken to respond (if I’m correct)
some_array = #populate some_array
end

encoded_array = [‘bc’, ‘cb’]

telling it to? I don’t know how they do it) other than the html source
of the page.

I can’t think of any other ways at the moment, but maybe someone else in
here has faced a similar problem?

Cheery-o
Gustav P.

Unobtrusive JavaScript is simply for PrototypeHelper calls, it’s not
going
to magically move all Javascript out of the HTML. With this plugin, any
call
to remote_form_for, etc gets an entry in ujs.js (something liek that)
which
registers the associated DOM elements with AJAX calls, leaving your HTML
clean of JS with a bonus of being sure that your site works when
javascript
is turned off.

As for hiding information from people, you don’t put it in Javascript.
It
doesn’t matter how hard you try, if you want something hidden, keep it
on
the server because JavaScript and HTML sources are impossible to “hide”.
Seeing as you want autocomplete, you’re going at it entirely wrong.
Autocomplete should be AJAX calls back to the server as the contents of
the
text-field change for the reason you mentioned earlier: the list of
possible
choices can be HUGE.

Besides, Rails already includes everything you need for autocomplete:
http://api.rubyonrails.com/classes/ActionController/Macros/AutoComplete/ClassMethods.html

Jason

Hi

The problem is that the whole array is included in the html
and users can see it if they look at the html source. I want to hide
this information from the user for 2 reasons:

  1. it makes the html source huge
    One way would be to simply define jsarray as a global variable in the
    head of your HTML file on first page load. Then populate it with a
    second ajax call after the page loads. I don’t know how the
    Autocompleter handles that variable (I’ve never used Autocompleter.Local
    before), it looks as though updating jsarray after the page loads (with
    the Autocompleter already initialized) won’t do much. If this is the
    case, you could try setting the Autocompleter with the same rjs you’re
    using to set jsarray.

Sadly, this approach will mean that you will have to spend two requests
per page load (the first being the actual page load, and the second an
ajax call to populate the array) If this is an in-house project or will
otherwise be receiving relatively little traffic this shouldn’t be much
of a problem. Also, this ajax call will take as long as typing something
in a regular Autocompleter would have taken to respond (if I’m correct)
so its not exactly blasphemous…

This could be done with something like the following

#view
<%=javascript_tag(“var jsarray = new Array();”)%>
<%=javascript_tag(remote_function(:url => {…}))%>

#controller
def foo
some_array = #populate some_array

render(:update) do |page|
   page.assign('jsarray', some_array.inspect)
   #cool use of inspect btw,
   #rails has 'array_or_string_for_javascript',
   #but inspect is pretty cool

    page << "new Autocompleter.Local(..., ..., jsarray , {...} ); "

#the line from your view
end
end

  1. more important I want to only let users access it through the
    autocomplete functionality. I don’t want them to see all the options.
    If this is your greatest issue, you could try looking at encoding the
    array so humans will have a difficult time seeing the values?

jsarray = [‘f^o^o’, ‘b^a^r’]
for (int i=0; i < jsarray.length; i++)
jsarray[i].replace(/^/, ‘’);

Of course you should use slightly better encryption :wink:

You could have a hash that maps encoded letters to their real
counterparts?

enc_hash = {b: “a”,
c: “b”,
…}

jsarray = new Array();
//these are the ‘encrypted’ values that the original jsarray would have
had
encoded_array = [‘bc’, ‘cb’]

for(int word=0; word < encoded_array.length; word++)
{
endstr = “”;
for(int letter=0; letter < encoded_array[word].length; letter++)
endstr += enc_hash[encoded_array[word][letter]];
jsarray.push(enstr)
}

jsarray == [‘ab’, ‘ba’] // true

It’s been a while since I did anything with javascript so the above
might not work, but I got carried away and couldn’t stop :wink:

A third possibility would be to look at the Unobtrusive Javascript
Plugin (http://ujs4rails.com). I’ve never used it, but it sounded like
they magically got all your regular JS out of the html file being served
to the client? I might have misunderstood what they do but it should
still be a good source of inspiration? This could let you define the
jsarray exactly as you do now, but have it somewhere (an automatically
generated .js file that gets served alongside the html without you
telling it to? I don’t know how they do it) other than the html source
of the page.

I can’t think of any other ways at the moment, but maybe someone else in
here has faced a similar problem?

Cheery-o
Gustav P.

As for hiding information from people, you don’t put it in Javascript.
It
doesn’t matter how hard you try, if you want something hidden, keep it
on
the server because JavaScript and HTML sources are impossible to “hide”.
Seeing as you want autocomplete, you’re going at it entirely wrong.
Autocomplete should be AJAX calls back to the server as the contents of
the
text-field change for the reason you mentioned earlier: the list of
possible
choices can be HUGE.

Besides, Rails already includes everything you need for autocomplete:
Peak Obsession

THanks Jason.

I already done it this way but it was slowwww. Every key the user
enters
contacts the server over the network, issues a query against the
database (against about 2500 entries that pretty much don’t change) and
returns the results. The overhead is too much (At least for my use case)
and therefore I chose to use the LocalAutocompleter which requires you
to pass in a javascript array instead of querying the database on the
server. And that’s where my problem comes from. According to you there
is no solution to hiding it?

Alon.