Commits

Anonymous committed e0a59bd

fix safari bug

Comments (0)

Files changed (2)

static/js/lib/selection.js

+/**
+ * @author Ryan Johnson <http://saucytiger.com/>
+ * @copyright 2008 PersonalGrid Corporation <http://personalgrid.com/>
+ * @package LivePipe UI
+ * @license MIT
+ * @url http://livepipe.net/control/selection
+ * @require prototype.js, effects.js, draggable.js, livepipe.js
+ */
+
+if(typeof(Prototype) == "undefined")
+	throw "Control.Selection requires Prototype to be loaded.";
+if(typeof(Object.Event) == "undefined")
+	throw "Control.Selection requires Object.Event to be loaded.";
+
+Control.Selection = {
+	options: {
+		resize_layout_timeout: 125,
+		selected: Prototype.emptyFunction,
+		deselected: Prototype.emptyFunction,
+		change: Prototype.emptyFunction,
+		selection_id: 'control_selection',
+		selection_style: {
+			zIndex: 999,
+			cursor: 'default',
+			border: '1px dotted #000'
+		},
+		filter: function(element){
+			return true;
+		},
+		drag_proxy: false,
+		drag_proxy_threshold: 1,
+		drag_proxy_options: {}
+	},
+	selectableElements: [],
+	elements: [],
+	selectableObjects: [],
+	objects: [],
+	active: false,
+	container: false,
+	resizeTimeout: false,
+	load: function(options){
+		Control.Selection.options = Object.extend(Control.Selection.options,options || {});
+		Control.Selection.selection_div = $(document.createElement('div'));
+		Control.Selection.selection_div.id = Control.Selection.options.selection_id;
+		Control.Selection.selection_div.style.display = 'none';
+		Control.Selection.selection_div.setStyle(Control.Selection.options.selection_style);
+		Control.Selection.border_width = parseInt(Control.Selection.selection_div.getStyle('border-top-width')) * 2;
+		Control.Selection.container = Prototype.Browser.IE ? window.container : window;
+		$(document.body).insert(Control.Selection.selection_div);
+		Control.Selection.enable();
+		if(Control.Selection.options.drag_proxy && typeof(Draggable) != 'undefined')
+			Control.Selection.DragProxy.load();
+		Event.observe(window,'resize',function(){
+			if(Control.Selection.resizeTimeout)
+				window.clearTimeout(Control.Selection.resizeTimeout);
+			Control.Selection.resizeTimeout = window.setTimeout(Control.Selection.recalculateLayout,Control.Selection.options.resize_layout_timeout);
+		});
+		if(Prototype.Browser.IE){
+			var body = $$('body').first();
+			body.observe('mouseleave',Control.Selection.stop);
+			body.observe('mouseup',Control.Selection.stop);
+		}
+	},
+	enable: function(){
+		if(Prototype.Browser.IE){
+			document.onselectstart = function(){
+				return false;
+			}
+		}
+		Event.observe(Control.Selection.container,'mousedown',Control.Selection.start);
+		Event.observe(Control.Selection.container,'mouseup',Control.Selection.stop);
+	},
+	disable: function(){
+		if(Prototype.Browser.IE){
+			document.onselectstart = function(){
+				return true;
+			}
+		}
+		Event.stopObserving(Control.Selection.container,'mousedown',Control.Selection.start);
+		Event.stopObserving(Control.Selection.container,'mouseup',Control.Selection.stop);
+	},
+	recalculateLayout: function(){
+		Control.Selection.selectableElements.each(function(element){
+			var dimensions = element.getDimensions();
+			var offset = element.cumulativeOffset();
+			var scroll_offset = element.cumulativeScrollOffset();
+			if(!element._control_selection)
+				element._control_selection = {};
+			element._control_selection.top = offset[1] - scroll_offset[1];
+			element._control_selection.left = offset[0] - scroll_offset[0];
+			element._control_selection.width = dimensions.width;
+			element._control_selection.height = dimensions.height;
+		});
+	},
+	addSelectable: function(element,object,activation_targets,activation_target_callback){
+		element = $(element);
+		if(activation_targets)
+			activation_targets = activation_targets.each ? activation_targets : [activation_targets];
+		var dimensions = element.getDimensions();
+		var offset = Position.cumulativeOffset(element);
+		element._control_selection = {
+			activation_targets: activation_targets,
+			is_selected: false,
+			top: offset[1],
+			left: offset[0],
+			width: dimensions.width,
+			height: dimensions.height,
+			activationTargetMouseMove: function(){
+				Control.Selection.notify('activationTargetMouseMove',element);
+				if(activation_targets){
+					activation_targets.each(function(activation_target){
+						activation_target.stopObserving('mousemove',element._control_selection.activationTargetMouseMove);
+					});
+				}
+				Control.Selection.DragProxy.container.stopObserving('mousemove',element._control_selection.activationTargetMouseMove);
+			},
+			activationTargetMouseDown: function(event){
+				if(!Control.Selection.elements.include(element))
+					Control.Selection.select(element);
+				Control.Selection.DragProxy.start(event);
+				Control.Selection.DragProxy.container.hide();
+				if(activation_targets){
+					activation_targets.each(function(activation_target){
+						activation_target.observe('mousemove',element._control_selection.activationTargetMouseMove);
+					});
+				}
+				Control.Selection.DragProxy.container.observe('mousemove',element._control_selection.activationTargetMouseMove);
+			},
+			activationTargetClick: function(){
+				Control.Selection.select(element);
+				if(typeof(activation_target_callback) == "function")
+					activation_target_callback();
+				if(activation_targets){
+					activation_targets.each(function(activation_target){
+						activation_target.stopObserving('mousemove',element._control_selection.activationTargetMouseMove);
+					});
+				}
+				Control.Selection.DragProxy.container.stopObserving('mousemove',element._control_selection.activationTargetMouseMove);
+			}
+		};
+		element.onselectstart = function(){
+			return false;
+		};
+		element.unselectable = 'on';
+		element.style.MozUserSelect = 'none';
+		if(activation_targets){
+			activation_targets.each(function(activation_target){
+				activation_target.observe('mousedown',element._control_selection.activationTargetMouseDown);
+				activation_target.observe('click',element._control_selection.activationTargetClick);
+			});
+		}
+		Control.Selection.selectableElements.push(element);
+		Control.Selection.selectableObjects.push(object);
+	},
+	removeSelectable: function(element){
+		element = $(element);
+		if(element._control_selection.activation_targets){
+			element._control_selection.activation_targets.each(function(activation_target){
+				activation_target.stopObserving('mousedown',element._control_selection.activationTargetMouseDown);
+			});
+			element._control_selection.activation_targets.each(function(activation_target){
+				activation_target.stopObserving('click',element._control_selection.activationTargetClick);
+			});
+		}
+		element._control_selection = null;
+		element.onselectstart = function() {
+			return true;
+		};
+		element.unselectable = 'off';
+		element.style.MozUserSelect = '';
+		var position = 0;
+		Control.Selection.selectableElements.each(function(selectable_element,i){
+			if(selectable_element == element){
+				position = i;
+				throw $break;
+			}
+		});
+		Control.Selection.selectableElements = Control.Selection.selectableElements.without(element);
+		Control.Selection.selectableObjects = Control.Selection.selectableObjects.slice(0,position).concat(Control.Selection.selectableObjects.slice(position + 1))
+	},
+	select: function(selected_elements){
+		if(typeof(selected_elements) == "undefined" || !selected_elements)
+			selected_elements = [];
+		if(!selected_elements.each && !selected_elements._each)
+			selected_elements = [selected_elements];
+		//comparing the arrays directly wouldn't equate to true in safari so we need to compare each item
+		var selected_items_have_changed = !(Control.Selection.elements.length == selected_elements.length && Control.Selection.elements.all(function(item,i){
+			return selected_elements[i] == item;
+		}));
+		if(!selected_items_have_changed)
+			return;
+		var selected_objects_indexed_by_element = {};
+		var selected_objects = selected_elements.collect(function(selected_element){
+			var selected_object = Control.Selection.selectableObjects[Control.Selection.selectableElements.indexOf(selected_element)];
+			selected_objects_indexed_by_element[selected_element] = selected_object;
+			return selected_object;
+		});
+		if(Control.Selection.elements.length == 0 && selected_elements.length != 0){
+			selected_elements.each(function(element){
+				Control.Selection.notify('selected',element,selected_objects_indexed_by_element[element]);
+			});
+		}else{
+			Control.Selection.elements.each(function(element){
+				if(!selected_elements.include(element)){
+					Control.Selection.notify('deselected',element,selected_objects_indexed_by_element[element]);
+				}
+			});
+			selected_elements.each(function(element){
+				if(!Control.Selection.elements.include(element)){
+					Control.Selection.notify('selected',element,selected_objects_indexed_by_element[element]);
+				}
+			});
+		}
+		Control.Selection.elements = selected_elements;
+		Control.Selection.objects = selected_objects;
+		Control.Selection.notify('change',Control.Selection.elements,Control.Selection.objects);
+	},
+	deselect: function(){
+		if(Control.Selection.notify('deselect') === false)
+			return false;
+		Control.Selection.elements.each(function(element){
+			Control.Selection.notify('deselected',element,Control.Selection.selectableObjects[Control.Selection.selectableElements.indexOf(element)]);
+		});
+		Control.Selection.objects = [];
+		Control.Selection.elements = [];
+		Control.Selection.notify('change',Control.Selection.objects,Control.Selection.elements);
+		return true;
+	},
+	//private
+	start: function(event){
+		if(!event.isLeftClick() || Control.Selection.notify('start',event) === false)
+			return false;
+		if(!event.shiftKey && !event.altKey)
+			Control.Selection.deselect();
+		Event.observe(Control.Selection.container,'mousemove',Control.Selection.onMouseMove);
+		Event.stop(event);
+		return false;
+	},
+	stop: function(){
+		Event.stopObserving(Control.Selection.container,'mousemove',Control.Selection.onMouseMove);
+		Control.Selection.active = false;
+		Control.Selection.selection_div.setStyle({
+			display: 'none',
+			top: null,
+			left: null,
+			width: null,
+			height: null
+		});
+		Control.Selection.start_mouse_coordinates = {};
+		Control.Selection.current_mouse_coordinates = {};
+	},
+	mouseCoordinatesFromEvent: function(event){
+		return {
+			x: Event.pointerX(event),
+			y: Event.pointerY(event)
+		};
+	},
+	onClick: function(event,element,source){
+		var selection = [];
+		if(event.shiftKey){
+			selection = Control.Selection.elements.clone();
+			if(!selection.include(element))
+				selection.push(element);
+		}else if(event.altKey){
+			selection = Control.Selection.elements.clone();
+			if(selection.include(element))
+				selection = selection.without(element);
+		}else{
+			selection = [element];
+		}
+		Control.Selection.select(selection);
+		if(source == 'click')
+			Event.stop(event);
+	},
+	onMouseMove: function(event){
+		if(!Control.Selection.active){
+			Control.Selection.active = true;
+			Control.Selection.start_mouse_coordinates = Control.Selection.mouseCoordinatesFromEvent(event);
+		}else{
+			Control.Selection.current_mouse_coordinates = Control.Selection.mouseCoordinatesFromEvent(event);
+			Control.Selection.drawSelectionDiv();
+			var current_selection = Control.Selection.selectableElements.findAll(function(element){
+				return Control.Selection.options.filter(element) && Control.Selection.elementWithinSelection(element);
+			});
+			if(event.shiftKey && !event.altKey){
+				Control.Selection.elements.each(function(element){
+					if(!current_selection.include(element))
+						current_selection.push(element);
+				});
+			}else if(event.altKey && !event.shiftKey){
+				current_selection = Control.Selection.elements.findAll(function(element){
+					return !current_selection.include(element);
+				});
+			}
+			Control.Selection.select(current_selection);
+		}
+	},
+	drawSelectionDiv: function(){
+		if(Control.Selection.start_mouse_coordinates == Control.Selection.current_mouse_coordinates){
+			Control.Selection.selection_div.style.display = 'none';
+		}else{
+			Control.Selection.viewport = document.viewport.getDimensions();
+			Control.Selection.selection_div.style.position = 'absolute';
+			Control.Selection.current_direction = (Control.Selection.start_mouse_coordinates.y > Control.Selection.current_mouse_coordinates.y ? 'N' : 'S') + (Control.Selection.start_mouse_coordinates.x < Control.Selection.current_mouse_coordinates.x ? 'E' : 'W');
+			Control.Selection.selection_div.setStyle(Control.Selection['dimensionsFor' + Control.Selection.current_direction]());
+			Control.Selection.selection_div.style.display = 'block';
+		}
+	},
+	dimensionsForNW: function(){
+		return {
+			top: (Control.Selection.start_mouse_coordinates.y - (Control.Selection.start_mouse_coordinates.y - Control.Selection.current_mouse_coordinates.y)) + 'px',
+			left: (Control.Selection.start_mouse_coordinates.x - (Control.Selection.start_mouse_coordinates.x - Control.Selection.current_mouse_coordinates.x)) + 'px',
+			width: (Control.Selection.start_mouse_coordinates.x - Control.Selection.current_mouse_coordinates.x) + 'px',
+			height: (Control.Selection.start_mouse_coordinates.y - Control.Selection.current_mouse_coordinates.y) + 'px'
+		};
+	},
+	dimensionsForNE: function(){
+		return {
+			top: (Control.Selection.start_mouse_coordinates.y - (Control.Selection.start_mouse_coordinates.y - Control.Selection.current_mouse_coordinates.y)) + 'px',
+			left: Control.Selection.start_mouse_coordinates.x + 'px',
+			width: Math.min((Control.Selection.viewport.width - Control.Selection.start_mouse_coordinates.x) - Control.Selection.border_width,Control.Selection.current_mouse_coordinates.x - Control.Selection.start_mouse_coordinates.x) + 'px',
+			height: (Control.Selection.start_mouse_coordinates.y - Control.Selection.current_mouse_coordinates.y) + 'px'
+		};
+	},
+	dimensionsForSE: function(){
+		return {
+			top: Control.Selection.start_mouse_coordinates.y + 'px',
+			left: Control.Selection.start_mouse_coordinates.x + 'px',
+			width: Math.min((Control.Selection.viewport.width - Control.Selection.start_mouse_coordinates.x) - Control.Selection.border_width,Control.Selection.current_mouse_coordinates.x - Control.Selection.start_mouse_coordinates.x) + 'px',
+			height: Math.min((Control.Selection.viewport.height - Control.Selection.start_mouse_coordinates.y) - Control.Selection.border_width,Control.Selection.current_mouse_coordinates.y - Control.Selection.start_mouse_coordinates.y) + 'px'
+		};
+	},
+	dimensionsForSW: function(){
+		return {
+			top: Control.Selection.start_mouse_coordinates.y + 'px',
+			left: (Control.Selection.start_mouse_coordinates.x - (Control.Selection.start_mouse_coordinates.x - Control.Selection.current_mouse_coordinates.x)) + 'px',
+			width: (Control.Selection.start_mouse_coordinates.x - Control.Selection.current_mouse_coordinates.x) + 'px',
+			height: Math.min((Control.Selection.viewport.height - Control.Selection.start_mouse_coordinates.y) - Control.Selection.border_width,Control.Selection.current_mouse_coordinates.y - Control.Selection.start_mouse_coordinates.y) + 'px'
+		};
+	},
+	inBoundsForNW: function(element,selection){
+		return (
+			((element.left > selection.left || element.right > selection.left) && selection.right > element.left) &&
+			((element.top > selection.top || element.bottom > selection.top) && selection.bottom > element.top)
+		);
+	},
+	inBoundsForNE: function(element,selection){
+		return (
+			((element.left < selection.right || element.left < selection.right) && selection.left < element.right) &&
+			((element.top > selection.top || element.bottom > selection.top) && selection.bottom > element.top)
+		);
+	},
+	inBoundsForSE: function(element,selection){
+		return (
+			((element.left < selection.right || element.left < selection.right) && selection.left < element.right) &&
+			((element.bottom < selection.bottom || element.top < selection.bottom) && selection.top < element.bottom)
+		);
+	},
+	inBoundsForSW: function(element,selection){
+		return (
+			((element.left > selection.left || element.right > selection.left) && selection.right > element.left) &&
+			((element.bottom < selection.bottom || element.top < selection.bottom) && selection.top < element.bottom)
+		);
+	},
+	elementWithinSelection: function(element){
+		if(Control.Selection['inBoundsFor' + Control.Selection.current_direction]({
+			top: element._control_selection.top,
+			left: element._control_selection.left,
+			bottom: element._control_selection.top + element._control_selection.height,
+			right: element._control_selection.left + element._control_selection.width
+		},{
+			top: parseInt(Control.Selection.selection_div.style.top),
+			left: parseInt(Control.Selection.selection_div.style.left),
+			bottom: parseInt(Control.Selection.selection_div.style.top) + parseInt(Control.Selection.selection_div.style.height),
+			right: parseInt(Control.Selection.selection_div.style.left) + parseInt(Control.Selection.selection_div.style.width)
+		})){
+			element._control_selection.is_selected = true;
+			return true;
+		}else{
+			element._control_selection.is_selected = false;
+			return false;
+		}
+	},
+	DragProxy: {
+	    active: false,
+		xorigin: 0,
+		yorigin: 0,
+		load: function(){
+			Control.Selection.DragProxy.container = $(document.createElement('div'));
+			Control.Selection.DragProxy.container.id = 'control_selection_drag_proxy';
+			Control.Selection.DragProxy.container.setStyle({
+				position: 'absolute',
+				top: '1px',
+				left: '1px',
+				zIndex: 99999
+			});
+			Control.Selection.DragProxy.container.hide();
+			document.body.appendChild(Control.Selection.DragProxy.container);
+			Control.Selection.observe('selected',Control.Selection.DragProxy.selected);
+			Control.Selection.observe('deselected',Control.Selection.DragProxy.deselected);
+		},
+		start: function(event){            
+			if(event.isRightClick()){
+				Control.Selection.DragProxy.container.hide();
+				return;
+			}		    
+			if(Control.Selection.DragProxy.xorigin == Event.pointerX(event) && Control.Selection.DragProxy.yorigin == Event.pointerY(event))
+				return;    		
+		    Control.Selection.DragProxy.active = true;
+			Control.Selection.DragProxy.container.setStyle({
+				position: 'absolute',
+				top: Event.pointerY(event) + 'px',
+				left: Event.pointerX(event) + 'px'
+			});			
+			Control.Selection.DragProxy.container.observe('mouseup',Control.Selection.DragProxy.onMouseUp);			
+			Control.Selection.DragProxy.container.show();
+			Control.Selection.DragProxy.container._draggable = new Draggable(Control.Selection.DragProxy.container,Object.extend({
+				onEnd: Control.Selection.DragProxy.stop
+			},Control.Selection.options.drag_proxy_options));
+			Control.Selection.DragProxy.container._draggable.eventMouseDown(event);			
+			Control.Selection.DragProxy.notify('start',Control.Selection.DragProxy.container,Control.Selection.elements);
+		},
+		stop: function(){
+			window.setTimeout(function(){
+				Control.Selection.DragProxy.active = false;
+				Control.Selection.DragProxy.container.hide();
+    			if(Control.Selection.DragProxy.container._draggable){
+					Control.Selection.DragProxy.container._draggable.destroy();
+					Control.Selection.DragProxy.container._draggable = null;
+    			}
+    			Control.Selection.DragProxy.notify('stop');
+		    },1);
+		},
+		onClick: function(event){
+			Control.Selection.DragProxy.xorigin = Event.pointerX(event);
+			Control.Selection.DragProxy.yorigin = Event.pointerY(event);
+			if(event.isRightClick())
+				Control.Selection.DragProxy.container.hide();
+			if(Control.Selection.elements.length >= Control.Selection.options.drag_proxy_threshold && !(event.shiftKey || event.altKey) && (Control.Selection.DragProxy.xorigin != Event.pointerX(event) || Control.Selection.DragProxy.yorigin != Event.pointerY(event))){
+				Control.Selection.DragProxy.start(event);
+				Event.stop(event);
+			}
+		},
+		onMouseUp: function(event){
+			Control.Selection.DragProxy.stop();
+			Control.Selection.DragProxy.container.stopObserving('mouseup',Control.Selection.DragProxy.onMouseUp);
+		},
+		selected: function(element){
+			element.observe('mousedown',Control.Selection.DragProxy.onClick);
+		},
+		deselected: function(element){
+			element.stopObserving('mousedown',Control.Selection.DragProxy.onClick);
+		}
+	}
+};
+Object.Event.extend(Control.Selection);
+Object.Event.extend(Control.Selection.DragProxy);

static/js/src/page.js

           });  
 
           this.toolbar.addButton('Link',function(){
-              var selection = this.getSelection();
-
               function display_link_type(selected) {
                   $('link_from_'+ selected).show();
                   $('link_from_'+self.link_types_hide[selected]).hide();
               }, false);
               
               var tb = this;
+              var selection = this.getSelection();  
               $("slink").observe('click', function(e) {
                   Event.stop(e);
                   var link_type = $('link_type').getValue();
 ;                     tb.replaceSelection('[' + (link_text == '' ? 'Link Text' : link_text) + '](' + (url == '' ? 'http://link_url/' : url).replace(/^(?!(f|ht)tps?:\/\/)/,'http://') + ')');
                   }
                   self.link_window.close();
-                    return false;
+                  return false;
               }, false);
+              return
           },{  
               id: 'markdown_link_button'  
           });