public static function trigger($document, $type, $data = array(), $node = null) 
    {
        // trigger: function(type, data, elem, donative, extra) {
        $documentID = phpQuery::getDocumentID($document);
        $namespace = null;
        if (strpos($type, '.') !== false) {
            list($name, $namespace) = explode('.', $type);
        } else {
            $name = $type;
        }
        if (! $node) {
            if (self::issetGlobal($documentID, $type)) {
                $pq = phpQuery::getDocument($documentID);
                // TODO check add($pq->document)
                $pq->find('*')->add($pq->document)
                    ->trigger($type, $data);
            }
        } else {
            if (isset($data[0]) && $data[0] instanceof DOMEvent) {
                $event = $data[0];
                $event->relatedTarget = $event->target;
                $event->target = $node;
                $data = array_slice($data, 1);
            } else {
                $event = new DOMEvent(
                    array(
                    'type' => $type,
                    'target' => $node,
                    'timeStamp' => time(),
                    )
                );
            }
            $i = 0;
            while($node) {
                // TODO whois
                phpQuery::debug(
                    "Triggering ".($i?"bubbled ":'')."event '{$type}' on "
                    ."node \n"
                );//.phpQueryObject::whois($node)."\n");
                $event->currentTarget = $node;
                $eventNode = self::getNode($documentID, $node);
                if (isset($eventNode->eventHandlers)) {
                    foreach($eventNode->eventHandlers as $eventType => $handlers) {
                        $eventNamespace = null;
                        if (strpos($type, '.') !== false) {
                            list($eventName, $eventNamespace) = explode('.', $eventType);
                        } else {
                            $eventName = $eventType;
                        }
                        if ($name != $eventName) {
                            continue;
                        }
                        if ($namespace && $eventNamespace && $namespace != $eventNamespace) {
                            continue;
                        }
                        foreach($handlers as $handler) {
                            phpQuery::debug("Calling event handler\n");
                            $event->data = $handler['data']
                            ? $handler['data']
                            : null;
                            $params = array_merge(array($event), $data);
                            $return = phpQuery::callbackRun($handler['callback'], $params);
                            if ($return === false) {
                                $event->bubbles = false;
                            }
                        }
                    }
                }
                // to bubble or not to bubble...
                if (! $event->bubbles) {
                    break;
                }
                $node = $node->parentNode;
                $i++;
            }
        }
    }