=== modified file 'doc/styles.css' --- doc/styles.css 2007-03-06 22:25:50 +0000 +++ doc/styles.css 2007-06-29 12:58:41 +0000 @@ -4,6 +4,7 @@ padding: 0; text-align: center; font-family: sans-serif; +color: #333; } #container { @@ -140,6 +141,7 @@ .doc { margin-left: 0.05em; +color: #555; } .cls .doc { margin-left: 1em; === modified file 'examples/alerts.py' --- examples/alerts.py 2007-06-14 12:04:11 +0000 +++ examples/alerts.py 2007-06-29 12:58:41 +0000 @@ -7,6 +7,7 @@ import pykhtml + page = """ @@ -16,32 +17,44 @@ """ def alertHandler(browser, text): + #import time + #browser.eval("window.foobaz = 'hi'") print "alert:", text - # if the text of the alert was 'And another...', then - # we create another alert to showcase the fact that we + # if the text of the alert was 'Another alert', then + # we create one morealert to showcase the fact that we # can evaluate javascript dynamically - if text == 'And another...': + if text == 'Another alert': browser.eval("alert('Dynamic alert!')") # else if the text was 'Dynamic alert!' (from the alert - # we ran dynamically), then that's the last alert. Stop - # PyKHTML + # we ran dynamically ;)), then that's the last alert. + # Stop PyKHTML elif text == 'Dynamic alert!': + #print "stopping" pykhtml.stopEventLoop() +def promptHandler(text, defaultText): + print "prompt: %s (default %s)" % (text, repr(defaultText)) + if text == "What is your name?": + return "Paul" + def main(): browser = pykhtml.Browser() # install our function be called when there are - # alerts in the JavaScript source code + # alerts/prompts in the JavaScript source code browser.onAlert = pykhtml.partial(alertHandler, browser) + browser.onPrompt = promptHandler # load our markup browser.setHtml(page) #pykhtml.timer(3, pykhtml.stopEventLoop) === modified file 'pykhtml/__init__.py' --- pykhtml/__init__.py 2007-06-14 12:04:11 +0000 +++ pykhtml/__init__.py 2007-06-29 12:58:41 +0000 @@ -185,9 +185,15 @@ # QVariant to Python types def _variantToPython(variant): - return _variantConverters[variant.type()](variant) + converter = _variantConverters.get(variant.type(), None) + if not converter: + if variant.isNull(): + return None + else: + return variant + return converter(variant) + _variantConverters = { - qt.QVariant.Invalid: (lambda v: v), qt.QVariant.Bool: (lambda v: bool(v.toBool())), qt.QVariant.Double: (lambda v: v.toDouble()), qt.QVariant.Int: (lambda v: v.toInt()), @@ -226,6 +232,7 @@ class EventLoopAlreadyStartedError(Exception): pass + eventLoopStarted = False def startEventLoop(): """ Starts the PyKHTML event loop. PyKHTML works with an asynchronous callback mechanism -- a little like Twisted does. Calls to open a new webpage aren't synchronous, as with urllib, for example. """ @@ -361,6 +368,7 @@ else: this = this._ value = self.part.executeScript(this, script) + #print value.type() return _variantToPython(value) def _setOnNextLoad(self, callback): @@ -384,39 +392,42 @@ document.dispatchEvent(event); } window.prompt = function(text, defaultValue) { - window._promptEventMessage = s; - window._promptDefaultValue = s; + window._promptEventMessage = text; + window._promptDefaultValue = defaultValue; var event = document.createEvent('Event'); event.initEvent('PromptEvent', true, true); - document.dispatchEvent(event); + document.dispatchEvent(event); + // fortunately, dispatchEvent is synchronous + return window._promptResponse || null; } """) # which we can listen to from here node = dom.Node(self.document._d, self) # _handleFoo adds the parameters stored in the window # object accordingly as you cannot pass data via event objects. - # A little sucky, but it works - node.addEvent("AlertEvent", self._handleAlert) - # XX enable prompt when we pass stuff back, add confirm - #node.addEvent("PromptEvent", self._handlePrompt) + # A little sucky, but it works. + # What is even more sucky is that all custom events are + # being sent to all handlers, so the method code must be + # guarded with an event type check. Bizarre, really; nothing + # in the javascript docs indicates this should happen. + node.addEvent("AlertEvent", self._handleAlert, True) + node.addEvent("PromptEvent", self._handlePrompt, False) + + def _handlePrompt(self, e): + if str(e.type().string()) == "PromptEvent": + message = self.eval("window._promptEventMessage") + defaultText = self.eval("window._promptDefaultValue") + ret = self.onPrompt(message, defaultText) + if ret: + ret = repr(ret) + else: + ret = "null" + self.eval("window._promptResponse = %s" % ret) def _handleAlert(self, e): - message = self.eval("window._alertEventMessage") - self.onAlert(message) - - def _handlePrompt(self, e): - message = self.eval("window._promptEventMessage") - defaultText = self.eval("window._promptDefaultValue") - # if there is no default text, it will be a QVariant. - # make it None. - try: - defaultText.isNull() - except AttributeError: - pass - else: - if defaultText.isNull(): - defaultText = None - self.onPrompt(message, defaultText) + if str(e.type().string()) == "AlertEvent": + message = self.eval("window._alertEventMessage") + self.onAlert(message) def onAlert(self, s): """ Set this to any callable that you want to receive alert messages. The default implementation just does nothing """ === modified file 'pykhtml/dom.py' --- pykhtml/dom.py 2007-06-14 12:04:11 +0000 +++ pykhtml/dom.py 2007-06-29 12:58:41 +0000 @@ -22,7 +22,8 @@ class ElementNotFoundError(Exception): pass - + + class Node(object): """ Node and all of its subclasses provide you with access to the page's DOM. Instantiating the classes themselves won't do you much good. """