Forum Archive

How to use ui.Webview.evaluate_javascript()?

AceNinjaFire

Hey everyone I made a ui application that opens uses a custom view with a webview with a few other textviews ,buttons, and etc to run js on the webpage presented on the webview and display the results on a textview.

In the docs it doesn’t explain how the js should be structured in order to get the results from the snippets used. So I was wondering if anyone can tell me how to correctly use the method?

I’m gonna include code from my application (excluding animation functions I use for each separate view) and I’ll wait for responses. I appreciate any help I can get, and thanks in advance!!!


class browser(ui.View):
    def did_load(self):
        self.html = 0
        html_view = ui.load_view('html_view')
        self.add_subview(html_view)
        self['html_view'].x = 400
    def go(self):
        v = self.superview
        url_bar = v['url input']
        webview = v['webview1']
        webview.load_url('http://'+url_bar.text)

# this is located on a custom view that
#is a subview to the view containing the webview
class html_view(ui.View):
    #this is a button located on the subview
    #that initiates the "webview.evaluate_javascript()" method
    def runjs(self):


        #this is the subview
        v = self.superview

        #this is the main view
        bv = v.superview

        #the textview that the script is entered in
        script = v['js field'].text

        #the variable that contains the result of
        #the method
        result = bv['webview1'].evaluate_javascript(script)

        #Printing result for testing purposes
        print(result)

        #setting a textview to the result''
        v['result'].text = result
cvp

@AceNinjaFire try this, then see the script, only as a small sample. Hoping it will help
Run it, wait some seconds and watch the topic scrolling and the avatars images

# webview and its scrollview, download image, javascript
import clipboard
import console
from   objc_util import *
import requests
import ui
class MyView(ui.View):
    def __init__(self,w,h):
        self.width = w
        self.height = h

        webview = ui.WebView()
        webview.frame = self.frame
        webview.delegate = self
        self.add_subview(webview)

        t = 'https://forum.omz-software.com/topic/'
        url = clipboard.get()   
        if not url.startswith(t):
            url = t + '3317/introduction'
        webview.load_url(url)
        # get scrollview of webview via its ObjectiveC object
        self.scrollview = ObjCInstance(webview).subviews()[0].scrollView()

        # print html source file during tests
        #r = requests.get(url)
        #source =r.text
        #print(source)

        c = ui.Button(name='close')
        c.frame = (10,20,32,32)
        c.background_image = ui.Image.named('iob:ios7_close_outline_32')
        c.tint_color = 'red'
        c.action = self.close_button
        self.add_subview(c)

        b = ui.Button(name='avatar')
        d = 64
        b.frame = (10,10,d,d)
        b.font =('Menlo',d/2)
        b.background_color = 'cyan'
        b.corner_radius = d/2
        b.border_color ='blue'
        b.border_width = 1
        b.hidden = True
        self.add_subview(b)

        self.top = 0

    def close_button(self,sender):
        self.close()

    def webview_did_finish_load(self, webview):
        # search posts, users, profile images
        """
        <div class="clearfix">
            <div class="icon pull-left">
                <a href="/user/xxxxxx">
                    <img src="yyyyyyyyyyyyy  align="left" itemprop="image" />           
                </a>
        """
        t_img = '<img src="'
        t_usr = '<a href="/user/'
        self.users = {}
        self.posts = {}
        # number of elements of class "icon pull-left"  
        n_posts = int(webview.evaluate_javascript('document.getElementsByClassName("icon pull-left").length'))
        for i in range(0,n_posts):
            webview.evaluate_javascript('ele=document.getElementsByClassName("icon pull-left")['+str(i)+'];')
            html = webview.evaluate_javascript('ele.innerHTML')
            #print(html)
            i = html.find(t_usr)
            j = html.find('"',i+len(t_usr))
            usr = html[i+len(t_usr):j]
            #print(usr)
            if usr not in self.users:
                i = html.find(t_img)
                j = html.find('"',i+len(t_img))
                url = html[i+len(t_img):j]
                #print(url)
                if url[0] == '/':
                    url = 'https://forum.omz-software.com' + url
                r = requests.get(url)
                image_data = r.content
                self.users[usr] = image_data
            o = int(webview.evaluate_javascript('ele.getBoundingClientRect().top'))
            self.posts[o] = usr

        self.update_interval = 1/60

    def update(self):
        self.top = self.top + 1
        self.scrollview.setContentOffset_(CGPoint(0,self.top))
        if self.top in self.posts:
            usr = self.posts[self.top]
            #print(self.top,usr)
            if self.users[usr]:
                self['avatar'].title = ''               
                self['avatar'].background_image = ui.Image.from_data(self.users[usr])
            else:
                self['avatar'].title = usr
                siz = self['avatar'].width/2
                while True:
                    w,h = ui.measure_string(usr,font=('Menlo',siz))
                    #print(usr,siz,w,self['avatar'].width)
                    if w < self['avatar'].width:
                        self['avatar'].font = ('Menlo',siz)
                        break
                    siz = siz - 1
                self['avatar'].background_image = None
            self['avatar'].hidden = False
            self['avatar'].y = 100

def main():
    console.clear()
    w, h = ui.get_screen_size()
    disp = 'full_screen'
    back = MyView(w,h)
    back.background_color='white'
    back.present(disp, hide_title_bar=True)     

if __name__ == '__main__':
    main() 
cvp

@AceNinjaFire Or it is better to try @mikael 's WKWebView

AceNinjaFire

@cvp

Damn!!!

Thank you!! I have no experience with using the objc_util module at all😅, but I’ll have to look at it now. You helped me solve a problem I was having lol, I appreciate it.

Would you know of a good tutorial for using the module? I’ve looked at the doc before but it’s not an easy read.

cvp

@AceNinjaFire said:

it’s not an easy read.

That's sure, at least 😀
I don't know any other doc but we learn by practicing or by finding some examples in this marvelous forum

cvp

@AceNinjaFire I just wanted to delete my post because I told myself that it probably did not respond to your request ...Perhpas, it was a little bit too complex to start. Sorry for that.

AceNinjaFire

@cvp

You’re good lol. Complex or not I appreciate it, since the only way I’ll learn is by example or experimentation. I’m using the example you gave to reference to the objc_util module and what it does. I’m still far from understanding it but it’ll definitely be useful if it works the way I think it does.

EDIT: also you introduced a few ui functions I was unaware of which helped me solve another problem I was having lol. I really need to read the docs more completely going forward.

JonB

Was the original request how to get data back from a JavaScript script? Or how to execute any JavaScript at all? Are you still looking for an answer there?

cvp

@JonB You are right to ask it. That's the reason why I sincerely wanted to remove my post because I answered too quickly, but he seemed to be happy with my answer 😢 thus I could not remove it.

AceNinjaFire

@JonB

Yea that was my original question, but after looking at @cvp ‘s code I realized you had to structure it in a way to get the value normally (document.location.href) without assigning it to a value like (var url = document.location.href).

cvp answered my original question and answered a question I didn’t even have yet. So yea I was happy with it lol.

AceNinjaFire

@cvp

Do you want me to remove your post? I’ve already copied and pasted it into a script file.

JonB

By the way, if you ever need to communicate from JavaScript to python (for instance, if you are using JavaScript UI elements) you can implement a custom webview delegate. Also, if you are doing much js coding you may want to implement on_error logging... See

https://forum.omz-software.com/topic/1804/debugging-in-javascript-in-pythonista

@mikael's wkwebbiew has a lot more features.

AceNinjaFire

@JonB

Dang thanks man, and that’s definitely something I’ll look into. I’ve been looking for a reason to delve into js again after my initial dive into it. What types of projects have you done bridging the two together?