=== removed file 'doc/text-shadow.js' --- doc/text-shadow.js 2007-02-10 19:24:59 +0000 +++ doc/text-shadow.js 1970-01-01 00:00:00 +0000 @@ -1,365 +0,0 @@ -if(window.addEventListener)window.addEventListener('load',textShadows,false); -else if(window.attachEvent)window.attachEvent('onload',textShadows); -function setStyles(o,s){ - var i; - s=s.split(';'); - for(i in s){ - var p=s[i].split(':'); - o.style[p[0]]=p[1]; - } -} -function textShadows(){ - var ua=navigator.userAgent; - if(ua.indexOf('KHTML')>=0&&!(ua.indexOf('Safari')>=0))return; - var ss=document.styleSheets,a; - for(a in ss){ - var theRules=[],b; - if(ss[a].cssRules)theRules=ss[a].cssRules; - else if(ss[a].rules)theRules=ss[a].rules; - for(b in theRules){ - var selector=theRules[b].selectorText,r=theRules[b].style.cssText; - if(/text-shadow/.test(r)){ - r=r.replace(/([ ,]) /g,'$1').replace(/.*text-shadow[ :]+/,'').replace(/[ ]*;.*/,''); - var shadows=r.split(','),k,els=cssQuery(selector),l; - for(l in els){ - var x=parseInt(els[l].offsetLeft),y=parseInt(els[l].offsetTop),el3=els[l].cloneNode(true); - setStyles(el3,'position:absolute;zIndex:50;margin:0'); - for(k in shadows){ - var parts=shadows[k].split(' '); - var newX=x+parseInt(parts[1]),newY=y+parseInt(parts[2]),rad=parseInt(parts[3]); - for(m=0-rad;m<=rad;++m)for(n=0-rad;n<=rad;++n)showShadow(els[l],newX+m,newY+n,parts[0]); - var el2=el3.cloneNode(true); - setStyles(el2,'left:'+x+'px;top:'+y+'px'); - els[l].parentNode.appendChild(el2); - } - } - } - } - } -} -function showShadow(el,x,y,color){ - var el2=el.cloneNode(true); - setStyles(el2,'position:absolute;color:'+color+';left:'+x+'px;top:'+y+'px;margin:0;textShadow:none;zIndex:49'); - el2.style.opacity='.08'; - el2.style.filter='alpha(opacity=8)'; - el.parentNode.appendChild(el2); -} - - - -/* - This work is licensed under a Creative Commons License. - - License: http://creativecommons.org/licenses/by/1.0/ - - You are free: - - to copy, distribute, display, and perform the work - to make derivative works - to make commercial use of the work - - Under the following conditions: - - Attribution. You must give the original author credit - - Author: Dean Edwards/2004 - Web: http://dean.edwards.name/ -*/ - -/* keeping code tidy! */ - -/* extendible css query function for common platforms - - tested on IE5.0/5.5/6.0, Mozilla 1.6/Firefox 0.8, Opera 7.23/7.5 - (all windows platforms - somebody buy me a mac!) -*/ - -// ----------------------------------------------------------------------- -// css query engine -// ----------------------------------------------------------------------- - -var cssQuery=function() { - var version="1.0.1"; // timestamp: 2004/05/25 - - // constants - var STANDARD_SELECT=/^[^>\+~\s]/; - var STREAM=/[\s>\+~:@#\.]|[^\s>\+~:@#\.]+/g; - var NAMESPACE=/\|/; - var IMPLIED_SELECTOR=/([\s>\+~\,]|^)([\.:#@])/g; - var ASTERISK ="$1*$2"; - var WHITESPACE=/^\s+|\s*([\+\,>\s;:])\s*|\s+$/g; - var TRIM="$1"; - var NODE_ELEMENT=1; - var NODE_TEXT=3; - var NODE_DOCUMENT=9; - - // sniff for explorer (cos of one little bug) - var isMSIE=/MSIE/.test(navigator.appVersion), isXML; - - // cache results for faster processing - var cssCache={}; - - // this is the query function - function cssQuery(selector, from) { - if (!selector) return []; - var useCache=arguments.callee.caching && !from; - from=(from) ? (from.constructor == Array) ? from : [from] : [document]; - isXML=checkXML(from[0]); - // process comma separated selectors - var selectors=parseSelector(selector).split(","); - var match=[]; - for (var i in selectors) { - // convert the selector to a stream - selector=toStream(selectors[i]); - // process the stream - var j=0, token, filter, cacheSelector="", filtered=from; - while (j < selector.length) { - token=selector[j++]; - filter=selector[j++]; - cacheSelector += token + filter; - // process a token/filter pair - filtered=(useCache && cssCache[cacheSelector]) ? cssCache[cacheSelector] : select(filtered, token, filter); - if (useCache) cssCache[cacheSelector]=filtered; - } - match=match.concat(filtered); - } - // return the filtered selection - return match; - }; - cssQuery.caching=false; - cssQuery.reset=function() { - cssCache={}; - }; - cssQuery.toString=function () { - return "function cssQuery() {\n [version " + version + "]\n}"; - }; - - var checkXML=(isMSIE) ? function(node) { - if (node.nodeType != NODE_DOCUMENT) node=node.document; - return node.mimeType == "XML Document"; - } : function(node) { - if (node.nodeType == NODE_DOCUMENT) node=node.documentElement; - return node.localName != "HTML"; - }; - - function parseSelector(selector) { - return selector - // trim whitespace - .replace(WHITESPACE, TRIM) - // encode attribute selectors - .replace(attributeSelector.ALL, attributeSelector.ID) - // e.g. ".class1" --> "*.class1" - .replace(IMPLIED_SELECTOR, ASTERISK); - }; - - // convert css selectors to a stream of tokens and filters - // it's not a real stream. it's just an array of strings. - function toStream(selector) { - if (STANDARD_SELECT.test(selector)) selector=" " + selector; - return selector.match(STREAM) || []; - }; - - var pseudoClasses={ // static - // CSS1 - "link": function(element) { - for (var i=0; i < document.links; i++) { - if (document.links[i] == element) return true; - } - }, - "visited": function(element) { - // can't do this without jiggery-pokery - }, - // CSS2 - "first-child": function(element) { - return !previousElement(element); - }, - // CSS3 - "last-child": function(element) { - return !nextElement(element); - }, - "root": function(element) { - var document=element.ownerDocument || element.document; - return Boolean(element == document.documentElement); - }, - "empty": function(element) { - for (var i=0; i < element.childNodes.length; i++) { - if (isElement(element.childNodes[i]) || element.childNodes[i].nodeType == NODE_TEXT) return false; - } - return true; - } - // add your own... - }; - - var QUOTED=/([\'\"])[^\1]*\1/; - function quote(value) {return (QUOTED.test(value)) ? value : "'" + value + "'"}; - function unquote(value) {return (QUOTED.test(value)) ? value.slice(1, -1) : value}; - - var attributeSelectors=[]; - - function attributeSelector(attribute, compare, value) { - // properties - this.id=attributeSelectors.length; - // build the test expression - var test="element."; - switch (attribute.toLowerCase()) { - case "id": - test += "id"; - break; - case "class": - test += "className"; - break; - default: - test += "getAttribute('" + attribute + "')"; - } - // continue building the test expression - switch (compare) { - case "=": - test += "==" + quote(value); - break; - case "~=": - test="/(^|\\s)" + unquote(value) + "(\\s|$)/.test(" + test + ")"; - break; - case "|=": - test="/(^|-)" + unquote(value) + "(-|$)/.test(" + test + ")"; - break; - } - push(attributeSelectors, new Function("element", "return " + test)); - }; - attributeSelector.prototype.toString=function() { - return attributeSelector.PREFIX + this.id; - }; - // constants - attributeSelector.PREFIX="@"; - attributeSelector.ALL=/\[([^~|=\]]+)([~|]?=?)([^\]]+)?\]/g; - // class methods - attributeSelector.ID=function(match, attribute, compare, value) { - return new attributeSelector(attribute, compare, value); - }; - - // select a set of matching elements. - // "from" is an array of elements. - // "token" is a character representing the type of filter - // e.g. ">" means child selector - // "filter" represents the tag name, id or class name that is being selected - // the function returns an array of matching elements - function select(from, token, filter) { - //alert("token="+token+",filter="+filter); - var namespace=""; - if (NAMESPACE.test(filter)) { - filter=filter.split("|"); - namespace=filter[0]; - filter=filter[1]; - } - var filtered=[], i; - switch (token) { - case " ": // descendant - for (i in from) { - var subset=getElementsByTagNameNS(from[i], filter, namespace); - for (var j=0; j < subset.length; j++) { - if (isElement(subset[j]) && (!namespace || compareNamespace(subset[j], namespace))) - push(filtered, subset[j]); - } - } - break; - case ">": // child - for (i in from) { - var subset=from[i].childNodes; - for (var j=0; j < subset.length; j++) - if (compareTagName(subset[j], filter, namespace)) push(filtered, subset[j]); - } - break; - case "+": // adjacent (direct) - for (i in from) { - var adjacent=nextElement(from[i]); - if (adjacent && compareTagName(adjacent, filter, namespace)) push(filtered, adjacent); - } - break; - case "~": // adjacent (indirect) - for (i in from) { - var adjacent=from[i]; - while (adjacent=nextElement(adjacent)) { - if (adjacent && compareTagName(adjacent, filter, namespace)) push(filtered, adjacent); - } - } - break; - case ".": // class - filter=new RegExp("(^|\\s)" + filter + "(\\s|$)"); - for (i in from) if (filter.test(from[i].className)) push(filtered, from[i]); - break; - case "#": // id - for (i in from) if (from[i].id == filter) push(filtered, from[i]); - break; - case "@": // attribute selector - filter=attributeSelectors[filter]; - for (i in from) if (filter(from[i])) push(filtered, from[i]); - break; - case ":": // pseudo-class (static) - filter=pseudoClasses[filter]; - for (i in from) if (filter(from[i])) push(filtered, from[i]); - break; - } - return filtered; - }; - - var getElementsByTagNameNS=(isMSIE) ? function(from, tagName) { - return (tagName == "*" && from.all) ? from.all : from.getElementsByTagName(tagName); - } : function(from, tagName, namespace) { - return (namespace) ? from.getElementsByTagNameNS("*", tagName) : from.getElementsByTagName(tagName); - }; - - function compareTagName(element, tagName, namespace) { - if (namespace && !compareNamespace(element, namespace)) return false; - return (tagName == "*") ? isElement(element) : (isXML) ? (element.tagName == tagName) : (element.tagName == tagName.toUpperCase()); - }; - - var PREFIX=(isMSIE) ? "scopeName" : "prefix"; - function compareNamespace(element, namespace) { - return element[PREFIX] == namespace; - }; - - // return the previous element to the supplied element - // previousSibling is not good enough as it might return a text or comment node - function previousElement(element) { - while ((element=element.previousSibling) && !isElement(element)) continue; - return element; - }; - - // return the next element to the supplied element - function nextElement(element) { - while ((element=element.nextSibling) && !isElement(element)) continue; - return element; - }; - - function isElement(node) { - return Boolean(node.nodeType == NODE_ELEMENT && node.tagName != "!"); - }; - - - // use a baby push function because IE5.0 doesn't support Array.push - function push(array, item) { - array[array.length]=item; - }; - - // fix IE5.0 String.replace - if ("i".replace(/i/,function(){return""})) { - // preserve String.replace - var string_replace=String.prototype.replace; - // create String.replace for handling functions - var function_replace=function(regexp, replacement) { - var match, newString="", string=this; - while ((match=regexp.exec(string))) { - // five string replacement arguments is sufficent for cssQuery - newString += string.slice(0, match.index) + replacement(match[0], match[1], match[2], match[3], match[4]); - string=string.slice(match.lastIndex); - } - return newString + string; - }; - // replace String.replace - String.prototype.replace=function (regexp, replacement) { - this.replace=(typeof replacement == "function") ? function_replace : string_replace; - return this.replace(regexp, replacement); - }; - } - - return cssQuery; -}(); === added file '.bzrignore' --- .bzrignore 1970-01-01 00:00:00 +0000 +++ .bzrignore 2007-02-12 23:13:40 +0000 @@ -0,0 +1,3 @@ +*.pyc +arial.ttf +makedocs.py === added file 'examples/dynamicdom.py' --- examples/dynamicdom.py 1970-01-01 00:00:00 +0000 +++ examples/dynamicdom.py 2007-02-12 23:13:40 +0000 @@ -0,0 +1,58 @@ + +import sys +sys.path.append("..") + +import pykhtml + +# the HTML document we're gonna load. Notice that +# it contains javascript and manipulates the DOM +page = """ + + + + + Test + + + + + + +""" + +def checkForDomChanges(browser, previousData): + data = browser.document.serialized + if data != previousData: + print "DOM changed!" + print "New text: %s", repr(browser.document.getElementById("mydiv").text) + print len(pykhtml.application.children()) + pykhtml.stopEventLoop() + else: + print "DOM not changed. Checking in 1 second..." + pykhtml.timer(1, pykhtml.curry(checkForDomChanges, browser, data)) + print len(pykhtml.application.children()) + +def main(): + browser = pykhtml.Browser() + # load our markup + browser.setHtml(page) + # to see if the DOM has changed we poll and access + # browser.document.serialized and compare its to + # the previous calling. Note the use of pykhtml.curry + # to bind the serialised data to the function + pykhtml.timer(1, pykhtml.curry(checkForDomChanges, browser, browser.document.serialized)) + pykhtml.startEventLoop() + +if __name__ == "__main__": + main() + === modified file 'doc/pykhtml.dom.htm' --- doc/pykhtml.dom.htm 2007-02-11 19:31:51 +0000 +++ doc/pykhtml.dom.htm 2007-02-12 23:13:40 +0000 @@ -4,8 +4,8 @@ pykhtml.dom module documentation - - + +
@@ -13,7 +13,7 @@

pykhtml.dom

-

None

+

class Document (inherits object)

Document object for accessing the DOM tree. Don't keep this object around, when the page changes it is invalidated. Just access it through pykhtml.Browser.document whenever you want it.
=== modified file 'doc/pykhtml.htm' --- doc/pykhtml.htm 2007-02-11 19:31:51 +0000 +++ doc/pykhtml.htm 2007-02-12 23:13:40 +0000 @@ -4,8 +4,8 @@ pykhtml module documentation - - + +
@@ -13,7 +13,7 @@

pykhtml

-

None

+

class Browser (inherits object)

A Browser is the main class you use to navigate around and visit different pages. Have a look at Browser.load and Browser.document to access basic use.

__init__(self)

Create a new Browser.
@@ -28,7 +28,7 @@

timer(time, func)

Call the given function after the alloted time. The PyKHTML event loop needs to be running.

init(display=1, _sleep=1)

Initiate the system if necessary (start Xvfb if it's not running, connect to it, start our program instance). This is called automatically when you create a Browser instance, so you shouldn't have to worry about it. You can specify use of a certain display by setting the `display` parameter.

class curry

-
Partial application of parameters. This is used internally but is also very useful with Browser.load as it allows you to pass data to other functions.
EXAMPLE.
+
Partial application of parameters. This is used internally but is also very useful with Browser.load as it allows you to pass data to other functions.
(Provide Example).

pathSearch(name)

Utility function to search for and get the full path of a file in $PATH.

running(name)

Check whether a process of the given name is running.
=== modified file 'examples/pykhtmlsite.py' --- examples/pykhtmlsite.py 2007-02-11 18:58:20 +0000 +++ examples/pykhtmlsite.py 2007-02-12 23:13:40 +0000 @@ -5,7 +5,7 @@ import pykhtml -PyKHTMLUrl = "http://localhost/PyKHTML/" +PyKHTMLUrl = "http://paul.giannaros.org/pykhtml/" def extractBitsFromPage(browser): # getElementsByTagName returns a generator, so we convert === modified file 'makedocs.py' --- makedocs.py 2007-02-11 19:31:51 +0000 +++ makedocs.py 2007-02-12 23:13:40 +0000 @@ -40,7 +40,7 @@ "__repr__" ] -fontPath = "arial.ttf" +#fontPath = "arial.ttf" classToClassList = {} @@ -363,7 +363,7 @@ if moduleName.count("."): subModuleName = moduleName.split(".")[1] module = _getattr(module, subModuleName) - moduleDoc = module.__doc__ + moduleDoc = getDoc(module) itemsToExamine = [] documentedItems = [] for attributeName in dir(module): === modified file 'pykhtml/__init__.py' --- pykhtml/__init__.py 2007-02-11 19:31:51 +0000 +++ pykhtml/__init__.py 2007-02-12 23:13:40 +0000 @@ -22,7 +22,7 @@ class curry: """ Partial application of parameters. This is used internally but is also very useful with [[Browser.load]] as it allows you to pass data to other functions. - EXAMPLE. """ + (Provide Example). """ def __init__(self, fun, *args, **kwargs): self.fun = fun self.pending = args[:]