Permalink
Browse files

all kinds of stuff

  • Loading branch information...
1 parent d8a7a55 commit f38635142bcce4b8727b02451088207f7e01243b kangax committed Apr 8, 2008
Showing with 462 additions and 0 deletions.
  1. +73 −0 draghelper.js
  2. +57 −0 event.register.js
  3. +46 −0 event.simulate.js
  4. +222 −0 helpers.js
  5. +23 −0 key_observer.js
  6. +41 −0 set_builder.js
View
73 draghelper.js
@@ -0,0 +1,73 @@
+/**
+ * Simplified version of a UI.DragHelper
+ * http://svn.prototype-ui.com/public/prototype-ui/trunk/src/util/drag.js
+ *
+ */
+ (function() {
+ var initPointer, currentDraggable, dragging;
+
+ document.observe('mousedown', onMousedown);
+
+ function onMousedown(event) {
+ var draggable = event.findElement('[ui:draggable="true"]');
+
+ if (draggable) {
+ // prevent default browser action
+ event.stop();
+ currentDraggable = draggable;
+ initPointer = event.pointer();
+
+ document.observe("mousemove", onMousemove)
+ .observe("mouseup", onMouseup);
+ }
+ };
+
+ function onMousemove(event) {
+ event.stop();
+
+ if (dragging)
+ fire('drag:updated', event);
+ else {
+ dragging = true;
+ fire('drag:started', event);
+ }
+ };
+
+ function onMouseup(event) {
+ document.stopObserving('mousemove', onMousemove)
+ .stopObserving('mouseup', onMouseup);
+
+ if (dragging) {
+ dragging = false;
+ fire('drag:ended', event);
+ }
+ };
+
+ function fire(eventName, mouseEvent) {
+ var pointer = mouseEvent.pointer();
+
+ currentDraggable.fire(eventName, {
+ dx: pointer.x - initPointer.x,
+ dy: pointer.y - initPointer.y,
+ mouseEvent: mouseEvent
+ })
+ };
+
+ Element.addMethods({
+ enableDrag: function(element) {
+ element = $(element);
+ element.writeAttribute('ui:draggable', 'true');
+ return element;
+ },
+
+ disableDrag: function(element){
+ element = $(element);
+ element.writeAttribute('ui:draggable', null);
+ return element;
+ },
+
+ isDraggable: function(element) {
+ return $(element).readAttribute('ui:draggable') == 'true';
+ }
+ });
+ })();
View
57 event.register.js
@@ -0,0 +1,57 @@
+(function() {
+ var rules = { };
+ var eventManager = function(event) {
+ var element = event.target;
+ do {
+ if (element.nodeType == 1) {
+ element = Element.extend(element);
+ for (var selector in rules[event.type]) {
+ if (matches(rules[event.type][selector]._selector, element)) {
+ for (var i=0, handlers=rules[event.type][selector], l=handlers.length; i<l; ++i) {
+ handlers[i].call(element, Object.extend(event, { _target: element }));
+ }
+ }
+ }
+ }
+ } while (element = element.parentNode)
+ }
+ var matches = function(selectors, element) {
+ for (var i=0, l=selectors.length; i<l; ++i) {
+ if (selectors[i].match(element)) return true;
+ }
+ return false;
+ }
+ Event.register = function(selector, eventName, handler) {
+ // observe event only once
+ if (!rules[eventName]) {
+ rules[eventName] = { };
+ document.observe(eventName, eventManager);
+ }
+ var _selector = [ ], expr = selector.strip();
+ // instantiate Selector's
+ Selector.split(selector).each(function(s) { _selector.push(new Selector(s)) })
+ // store instantiated Selector for faster matching
+ if (!rules[eventName][expr]) {
+ rules[eventName][expr] = Object.extend([ ], { _selector: _selector });
+ }
+ // associate handler with expression
+ rules[eventName][expr].push(handler);
+ }
+ Event.unregister = function(selector, eventName) {
+ if (eventName) {
+ rules[eventName][selector] = null;
+ delete rules[eventName][selector];
+ }
+ else {
+ for (var eventName in rules) {
+ selector ? rules[eventName][selector] : rules[eventName] = null;
+ delete (selector ? rules[eventName][selector] : rules[eventName]);
+ }
+ }
+ }
+ Event.observe(window, 'unload', Event.unregister.curry(null, null));
+ Event.element = function(event) {
+ event = Event.extend(event); var node = event._target || event.target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ };
+})();
View
46 event.simulate.js
@@ -0,0 +1,46 @@
+Event.simulate = function(element, eventName) {
+
+ var options = Object.extend({
+ pointerX: 0,
+ pointerY: 0,
+ button: 0,
+ ctrlKey: false,
+ altKey: false,
+ shiftKey: false,
+ metaKey: false,
+ bubbles: true,
+ cancelable: true
+ }, arguments[2] || { } );
+
+ var eventMatchers = {
+ 'HTMLEvents': /load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll/,
+ 'MouseEvents': /click|mousedown|mouseup|mouseover|mousemove|mouseout/
+ };
+
+ var oEvent, eventType = null;
+
+ for (var name in eventMatchers) {
+ if (eventMatchers[name].test(eventName)) eventType = name;
+ }
+
+ if (!eventType) throw new SyntaxError('Only HTMLEvents and MouseEvents interfaces are supported');
+
+ if (document.createEvent) {
+ oEvent = document.createEvent(eventType);
+ if (eventType == 'HTMLEvents') {
+ oEvent.initEvent(eventName, options.bubbles, options.cancelable);
+ }
+ else {
+ oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView,
+ options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, $(element));
+ }
+ $(element).dispatchEvent(oEvent);
+ }
+ else {
+ options.clientX = options.pointerX;
+ options.clientY = options.pointerY;
+ oEvent = Object.extend(document.createEventObject(), options);
+ $(element).fireEvent('on' + eventName, oEvent);
+ }
+}
View
222 helpers.js
@@ -0,0 +1,222 @@
+/**
+ * @usage $("myElement").contains(" some text... ");
+ * @params element HTMLElement
+ * @params content String text to match against
+ * @return Boolean true if element's innerHTML property matches with specified text
+ *
+ */
+Element.Methods.contains = function(element, content) {
+ element = $(element);
+ return !!element.innerHTML.stripTags().match(RegExp.escape(content))
+}
+
+
+/**
+ * @usage $w(" MyApp util Dom ").namespace(Prototype); //=> Prototype.MyApp.util.Dom
+ * @params arguments[0] Root object to begin nesting with
+ * @return
+ *
+ */
+Array.prototype.namespace = function() {
+ this.inject(arguments[0] || window, function(object, property) {
+ return object[property] = object[property] || { };
+ })
+}
+
+/**
+ * Returns negated function
+ *
+ * e.g. Find all hidden elements:
+ *
+ * $$('*').findAll(function(element) { return !element.visible() }); // old way
+ * $$('*').findAll(Element.visible.negate()); // using negate
+ *
+ */
+Function.prototype.negate = function() {
+ var f = this;
+ return function() {
+ return !f.apply(f, arguments);
+ }
+}
+
+/**
+ * Calls and returns function
+ *
+ * myElement.toggle();
+ * input.observe('change', myElement.toggle); // old way
+ *
+ * input.observe('change', myElement.toggle.invoke()); // using invoke
+ */
+Function.prototype.invoke = function() {
+ this.apply(this, $A(arguments)); return this;
+}
+
+
+/**
+ * Preventing IE from caching Ajax requests
+ *
+ */
+Ajax.Responders.register({
+ onCreate: function(req) {
+ req.url += (/\?/.test(req.url) ? '&' : '?') + '_token=' + Date.now();
+ }
+})
+
+
+/**
+ * Strip event handlers when removing an element
+ *
+ */
+Element.Methods.remove = Element.Methods.remove.wrap(
+ function(proceed, element) {
+ element = $(element);
+ [element].concat(element.descendants()).each(Element.stopObserving);
+ return proceed(element);
+ }
+)
+
+
+/**
+ * Removes element from the document, returning it's HTML representation
+ *
+ */
+Element.Methods.toTemplate = function(element) {
+ if (!(element = $(element))) return null;
+ return element.wrap().show().up().remove().innerHTML;
+}
+
+
+/**
+ * Are any of the form fields empty?
+ *
+ */
+Field.Methods.isEmpty = function(element) {
+ return $(element).getElements().any(Element.present);
+}
+
+
+/**
+ * Little helper to change element's attribute given pattern and replacement (RegExp object)
+ * Encapsulates verbose el.writeAttribute(attr, el.readAttribute(attr))
+ *
+ */
+Element.Methods.replaceAttribute = function(element, attr, pattern, replacement) {
+ element = $(element);
+ return el.writeAttribute(attr, element.readAttribute(attr)
+ .replace(new RegExp(pattern), replacement)
+ )
+}
+
+
+/**
+ * Replaces innerHTML of an element given pattern and replacement
+ *
+ */
+Element.Methods.replaceHTML = function(element, pattern, replacement) {
+ element = $(element);
+ return element.update(
+ element.innerHTML.replace(new RegExp(pattern), replacement)
+ );
+}
+
+
+Element.Methods.toHTML = function(element) {
+ element = $(element);
+ try {
+ var xmlSerializer = new XMLSerializer();
+ return element.nodeType == 4
+ ? element.nodeValue
+ : xmlSerializer.serializeToString(element);
+ } catch(e) {
+ return element.xml
+ || element.outerHTML
+ || element.cloneNode(true).wrap().innerHTML;
+ }
+}
+
+
+(function(){
+ Prototype.Q = {}
+ for (var method in Element.methods) {
+ Prototype.Q[method] = function(){ return Prototype.Q }
+ }
+ $ = $.wrap(function(){
+ var args = $A(arguments), proceed = args.shift();
+ return proceed.apply(proceed, args) || Prototype.Q;
+ })
+})()
+
+
+/*
+
+Label support in Safari 2
+
+*/
+document.observe('click', function(e) {
+ var target = e.findElement('label[for]');
+ if (!target) return;
+ var input = $(target.readAttribute('for'));
+ if (!input) return;
+ input.focus();
+ if (input.type && (/radio|checkbox/).test(input.type)) {
+ input.click();
+ }
+})
+
+
+/**
+ * Boosts Field#present to work somewhat more reasonably
+ * with any form control (element with type attribute)
+ *
+ * - "reset, submit, button and hidden" always return true
+ * - "text, password and file" return true if value attribute is anything but whitespace
+ * - "checkbox" return true if checked attribute is not false
+ * - "radio" return true if either checked attribute is not false
+ * or any of the input elements with the same name have checked attribute and it's not false
+ * - "select" return true if selectedIndex attribute is not -1
+ *
+ */
+Field.Methods.present = function(element) {
+ if (!(element = $(element)) && !element.type) return;
+ var t = element.type;
+ return ((/text|password|file/.test(t) && !element.value.blank()) ||
+ /reset|submit|button|hidden/.test(t) ||
+ (t == 'checkbox' && element.checked) ||
+ (t == 'radio' && (element.checked || $$('input[name=' + element.name + ']:checked').length))
+ (/select-one|select-multiple/.test(t) && element.selectedIndex != -1));
+}
+
+/**
+ * Change Element#observe to imlicitly stop event when executing event handler
+ *
+ * $(someLink)._observe('click', function(e) { ... }) // <= event is stopped automatically
+ */
+Element.addMethods({
+ _observe: Element.observe.wrap(function(proceed, element, eventName, handler) {
+ return proceed.call(proceed, element, eventName, function(e) {
+ Event.stop(e); handler.call(e.target, e);
+ })
+ })
+});
+
+/**
+ * Simple helpers for injecting script/link elements into the document
+ *
+ */
+Prototype.addScript = function(url) {
+ // caching head element as a function property
+ (arguments.callee._head = arguments.callee._head || $$('head')[0])
+ .insert(new Element('script', { type: 'text/javascript', src: url }))
+}
+Prototype.addStylesheet = function() {
+ // caching head element as a function property
+ (arguments.callee._head = arguments.callee._head || $$('head')[0])
+ .insert(new Element('style', { type: 'text/css', rel: 'stylesheet', href: url }))
+}
+
+Function.prototype._new = function() {
+ var __method = this, args = arguments;
+ function C() { return __method.apply(this, args); };
+ C.prototype = __method.prototype;
+ return new C;
+}
View
23 key_observer.js
@@ -0,0 +1,23 @@
+/*
+
+Example:
+
+document.observe('key:esc', helpWindow.close);
+document.observe('key:space', focusNextField);
+
+*/
+
+
+(function() {
+ var hash = { 32: 'space', 19: 'pause' };
+ var handler = function(e) {
+ if (!hash[e.keyCode]) return;
+ if (e.type == 'keydown' && e.keyCode != Event.KEY_TAB) return;
+ document.fire('key:' + hash[e.keyCode], e);
+ }
+ for (var prop in Event) {
+ if (prop.startsWith('KEY_'))
+ hash[Event[prop]] = prop.replace('KEY_', '').toLowerCase();
+ }
+ document.observe('keyup', handler).observe('keydown', handler);
+})();
View
41 set_builder.js
@@ -0,0 +1,41 @@
+/*
+
+
+var numbers = [1,2,3,4,5,6,7,8,9];
+
+
+var lessThanFive = numbers.findAll(function(n) { return n<5 });
+// vs
+var lessThanFive = SetBuilder('x | x <- numbers, x<5');
+
+
+var moreThanFiveSquare = numbers.findAll(function(n) { return n>5 }).map(function(n) { return n*n });
+// or
+var moreThanFiveSquare = numbers.inject([], function(result, n) { if (n>5) result.push(n); return result });
+// vs
+var moreThanFiveSquare = SetBuilder('x*x | x <- numbers, x>5');
+
+
+*/
+
+SetBuilder = function(expr, scope) {
+ var scope = scope || this,
+ re = /([^|]*)\|([^<]*)<-([^,]*),([^$]*)$/,
+ match = expr.match(re),
+ id, action, source, condition, results = [];
+
+ if (!match) throw new Error('Error parsing expression');
+
+ match = match.invoke('strip');
+
+ id = match[2];
+ source = match[3];
+ action = match[1].replace(id, '_', 'g');
+ condition = match[4].replace(id, '_', 'g');
+
+ scope[source].each(function(_) {
+ if (eval(condition)) results.push(eval(action))
+ })
+
+ return results;
+}

0 comments on commit f386351

Please sign in to comment.