Code mostly related to manipulating wiki links, plus a new link pulldown:
* Implemented a new controller.Notebooks.lookup_note_id() method to get only a note's id given its title. * Added some new link resolution code to Editor and Wiki, to fill in a link's id according to its destination note. * Factored out some of the link finding code into a common Editor.find_link_at_cursor() method. * Factored out query parsing into a common parse_query() function, which operates on a link node. * Added new Link_pulldown class-thingy to represent the little pulldown you see when the cursor's on a link. * Refactored Pulldown's positioning code to support offset positioning (needed for elements within an iframe).
This commit is contained in:
parent
ec9cd1066c
commit
69caeaf655
|
@ -217,6 +217,48 @@ class Notebooks( object ):
|
|||
note = note,
|
||||
)
|
||||
|
||||
@expose( view = Json )
|
||||
@strongly_expire
|
||||
@wait_for_update
|
||||
@grab_user_id
|
||||
@async
|
||||
@update_client
|
||||
@validate(
|
||||
notebook_id = Valid_id(),
|
||||
note_title = Valid_string( min = 1, max = 500 ),
|
||||
user_id = Valid_id( none_okay = True ),
|
||||
)
|
||||
def lookup_note_id( self, notebook_id, note_title, user_id ):
|
||||
"""
|
||||
Return a note's id by looking up its title.
|
||||
|
||||
@type notebook_id: unicode
|
||||
@param notebook_id: id of notebook the note is in
|
||||
@type note_title: unicode
|
||||
@param note_title: title of the note id to return
|
||||
@type user_id: unicode or NoneType
|
||||
@param user_id: id of current logged-in user (if any), determined by @grab_user_id
|
||||
@rtype: json dict
|
||||
@return: { 'note_id': noteid or None }
|
||||
@raise Access_error: the current user doesn't have access to the given notebook
|
||||
@raise Validation_error: one of the arguments is invalid
|
||||
"""
|
||||
self.check_access( notebook_id, user_id, self.__scheduler.thread )
|
||||
if not ( yield Scheduler.SLEEP ):
|
||||
raise Access_error()
|
||||
|
||||
self.__database.load( notebook_id, self.__scheduler.thread )
|
||||
notebook = ( yield Scheduler.SLEEP )
|
||||
|
||||
if notebook is None:
|
||||
note = None
|
||||
else:
|
||||
note = notebook.lookup_note_by_title( note_title )
|
||||
|
||||
yield dict(
|
||||
note_id = note and note.object_id or None,
|
||||
)
|
||||
|
||||
@expose( view = Json )
|
||||
@wait_for_update
|
||||
@grab_user_id
|
||||
|
|
|
@ -261,6 +261,44 @@ class Test_notebooks( Test_controller ):
|
|||
note = result[ "note" ]
|
||||
assert note == None
|
||||
|
||||
def test_lookup_note_id( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_post( "/notebooks/lookup_note_id/", dict(
|
||||
notebook_id = self.notebook.object_id,
|
||||
note_title = self.note.title,
|
||||
), session_id = self.session_id )
|
||||
|
||||
assert result.get( "note_id" ) == self.note.object_id
|
||||
|
||||
def test_lookup_note_id_without_login( self ):
|
||||
result = self.http_post( "/notebooks/lookup_note_id/", dict(
|
||||
notebook_id = self.notebook.object_id,
|
||||
note_title = self.note.title,
|
||||
), session_id = self.session_id )
|
||||
|
||||
assert result.get( "error" )
|
||||
|
||||
def test_lookup_note_id_with_unknown_notebook( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_post( "/notebooks/lookup_note_id/", dict(
|
||||
notebook_id = self.unknown_notebook_id,
|
||||
note_title = self.note.title,
|
||||
), session_id = self.session_id )
|
||||
|
||||
assert result.get( "error" )
|
||||
|
||||
def test_lookup_unknown_note_id( self ):
|
||||
self.login()
|
||||
|
||||
result = self.http_post( "/notebooks/lookup_note_id/", dict(
|
||||
notebook_id = self.notebook.object_id,
|
||||
note_title = "unknown title",
|
||||
), session_id = self.session_id )
|
||||
|
||||
assert result.get( "note_id" ) == None
|
||||
|
||||
def test_save_note( self, startup = False ):
|
||||
self.login()
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
body {
|
||||
padding: 1em;
|
||||
font-size: 100%;
|
||||
line-height: 140%;
|
||||
}
|
||||
|
||||
|
|
|
@ -300,3 +300,15 @@ ol li {
|
|||
margin-left: 2em;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
.field_label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.text_field {
|
||||
margin-right: 0.5em;
|
||||
padding: 0.25em;
|
||||
border: #999999 1px solid;
|
||||
-moz-border-radius: 0.5em;
|
||||
-webkit-border-radius: 0.5em;
|
||||
}
|
||||
|
|
|
@ -179,7 +179,6 @@ Editor.prototype.finish_init = function () {
|
|||
this.scrape_title();
|
||||
if ( this.init_focus )
|
||||
this.focus();
|
||||
signal( this, "state_changed", this );
|
||||
}
|
||||
|
||||
Editor.prototype.highlight = function ( scroll ) {
|
||||
|
@ -247,6 +246,24 @@ Editor.prototype.resize = function () {
|
|||
setElementDimensions( this.iframe, dimensions );
|
||||
}
|
||||
|
||||
Editor.prototype.resolve_link = function ( link ) {
|
||||
// in case the link is to ourself, first grab the most recent version of our title
|
||||
this.scrape_title();
|
||||
|
||||
var id;
|
||||
var link_title = scrapeText( link );
|
||||
var editor = note_titles[ link_title ];
|
||||
// if the link's title corresponds to an open note id, set that as the link's destination
|
||||
if ( editor ) {
|
||||
id = editor.id;
|
||||
link.href = "/notebooks/" + this.notebook_id + "?note_id=" + id;
|
||||
// otherwise, resolve the link by looking up the link's title on the server
|
||||
} else {
|
||||
signal( this, "resolve_link", link_title, link );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Editor.prototype.key_pressed = function ( event ) {
|
||||
signal( this, "key_pressed", this, event );
|
||||
|
||||
|
@ -287,34 +304,17 @@ Editor.prototype.mouse_clicked = function ( event ) {
|
|||
|
||||
event.stop();
|
||||
|
||||
// in case the link is to ourself, first grab the most recent version of our title
|
||||
this.scrape_title();
|
||||
|
||||
var id;
|
||||
var link_title = scrapeText( link );
|
||||
var editor = note_titles[ link_title ];
|
||||
var href_leaf = link.href.split( "?note_id=" ).pop();
|
||||
// if the link's title corresponds to an open note id, set that as the link's destination
|
||||
if ( editor ) {
|
||||
id = editor.id;
|
||||
link.href = "/notebooks/" + this.notebook_id + "?note_id=" + id;
|
||||
// if this is a new link, get a new note id and set it for the link's destination
|
||||
} else if ( href_leaf == "new" ) {
|
||||
signal( this, "load_editor_by_title", link_title, this.iframe.id );
|
||||
return;
|
||||
// otherwise, use the id from link's current destination
|
||||
} else {
|
||||
// the last part of the current link's href is the note id
|
||||
id = href_leaf;
|
||||
}
|
||||
|
||||
// find the note corresponding to the linked id, or create a new note
|
||||
// if the note corresponding to the linked id is already open, highlight it
|
||||
var query = parse_query( link );
|
||||
var link_title = query.title || scrapeText( link );
|
||||
var id = query.note_id;
|
||||
var iframe = getElement( "note_" + id );
|
||||
if ( iframe ) {
|
||||
iframe.editor.highlight();
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, load the note for that id
|
||||
signal( this, "load_editor", link_title, this.iframe.id, id );
|
||||
}
|
||||
|
||||
|
@ -385,24 +385,22 @@ Editor.prototype.start_link = function () {
|
|||
|
||||
this.exec_command( "createLink", "/notebooks/" + this.notebook_id + "?note_id=new" );
|
||||
|
||||
var links = getElementsByTagAndClassName( "a", null, parent = this.document );
|
||||
for ( var i in links ) {
|
||||
var link = links[ i ];
|
||||
var link_title = scrapeText( link );
|
||||
var char_code = link_title.charCodeAt( 0 );
|
||||
// look for links titled with a space or nbsp character
|
||||
if ( link_title.length == 1 && char_code == 0x20 || char_code == 0xa0 ) {
|
||||
for ( var j in link.childNodes ) {
|
||||
var child = link.childNodes[ j ];
|
||||
if ( child.nodeType == 3 ) // type of text node
|
||||
child.nodeValue = "";
|
||||
}
|
||||
selection.collapse( link, 0 );
|
||||
// nuke the link title and collapse the selection, yielding a tasty new link that's completely
|
||||
// titleless and unselected
|
||||
var link = this.find_link_at_cursor();
|
||||
if ( link ) {
|
||||
for ( var j in link.childNodes ) {
|
||||
var child = link.childNodes[ j ];
|
||||
if ( child.nodeType == 3 ) // type of text node
|
||||
child.nodeValue = "";
|
||||
}
|
||||
selection.collapse( link, 0 );
|
||||
}
|
||||
// otherwise, just create a link with the selected text as the link title
|
||||
} else {
|
||||
this.exec_command( "createLink", "/notebooks/" + this.notebook_id + "?note_id=new" );
|
||||
var link = this.find_link_at_cursor();
|
||||
signal( this, "resolve_link", scrapeText( link ), link );
|
||||
}
|
||||
} else if ( this.document.selection ) { // browsers such as IE
|
||||
var range = this.document.selection.createRange();
|
||||
|
@ -413,13 +411,18 @@ Editor.prototype.start_link = function () {
|
|||
range.text = " ";
|
||||
range.moveStart( "character", -1 );
|
||||
range.select();
|
||||
this.exec_command( "createLink", "/notebooks/" + this.notebook_id + "?note_id=new" );
|
||||
} else {
|
||||
this.exec_command( "createLink", "/notebooks/" + this.notebook_id + "?note_id=new" );
|
||||
var link = this.find_link_at_cursor();
|
||||
signal( this, "resolve_link", scrapeText( link ), link );
|
||||
}
|
||||
|
||||
this.exec_command( "createLink", "/notebooks/" + this.notebook_id + "?note_id=new" );
|
||||
}
|
||||
}
|
||||
|
||||
Editor.prototype.end_link = function () {
|
||||
var link = this.find_link_at_cursor();
|
||||
|
||||
if ( this.iframe.contentWindow && this.iframe.contentWindow.getSelection ) { // browsers such as Firefox
|
||||
this.exec_command( "unlink" );
|
||||
} else if ( this.document.selection ) { // browsers such as IE
|
||||
|
@ -439,6 +442,49 @@ Editor.prototype.end_link = function () {
|
|||
range.select();
|
||||
range.pasteHTML( "" );
|
||||
}
|
||||
|
||||
var query = parse_query( link );
|
||||
var link_title = query.title || scrapeText( link );
|
||||
signal( this, "resolve_link", link_title, link );
|
||||
}
|
||||
|
||||
Editor.prototype.find_link_at_cursor = function () {
|
||||
if ( this.iframe.contentWindow && this.iframe.contentWindow.getSelection ) { // browsers such as Firefox
|
||||
var selection = this.iframe.contentWindow.getSelection();
|
||||
var link = selection.anchorNode;
|
||||
|
||||
while ( link.nodeName != "A" ) {
|
||||
link = link.parentNode;
|
||||
if ( !link )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( link ) return link;
|
||||
|
||||
// well, that didn't work, so try the selection's focus node instead
|
||||
link = selection.focusNode;
|
||||
|
||||
while ( link.nodeName != "A" ) {
|
||||
link = link.parentNode;
|
||||
if ( !link )
|
||||
return null;
|
||||
}
|
||||
|
||||
return link;
|
||||
} else if ( this.document.selection ) { // browsers such as IE
|
||||
var range = this.document.selection.createRange();
|
||||
var link = range.parentElement();
|
||||
|
||||
while ( link.nodeName != "A" ) {
|
||||
link = link.parentNode;
|
||||
if ( !link )
|
||||
return null;
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Editor.prototype.focus = function () {
|
||||
|
@ -514,3 +560,9 @@ Editor.prototype.shutdown = function( event ) {
|
|||
} catch ( e ) { }
|
||||
} } );
|
||||
}
|
||||
|
||||
// convenience function for parsing a link that has an href URL containing a query string
|
||||
function parse_query( link ) {
|
||||
return parseQueryString( link.href.split( "?" ).pop() );
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ function Wiki() {
|
|||
this.notebook_id = getElement( "notebook_id" ).value;
|
||||
this.read_write = false;
|
||||
this.startup_notes = new Array(); // map of startup notes: note id to bool
|
||||
this.link_pulldowns = new Array(); // map of link pulldowns: link object to pulldown
|
||||
this.invoker = new Invoker();
|
||||
|
||||
connect( this.invoker, "error_message", this, "display_error" );
|
||||
|
@ -176,6 +177,19 @@ Wiki.prototype.create_blank_editor = function ( event ) {
|
|||
Wiki.prototype.load_editor = function ( note_title, from_iframe_id, note_id, revision ) {
|
||||
var self = this;
|
||||
|
||||
// if there's not a valid destination note id, then load by title instead of by id
|
||||
if ( note_id == "new" || note_id == "null" ) {
|
||||
this.invoker.invoke(
|
||||
"/notebooks/load_note_by_title", "GET", {
|
||||
"notebook_id": this.notebook_id,
|
||||
"note_title": note_title,
|
||||
"revision": revision
|
||||
},
|
||||
function ( result ) { self.parse_loaded_editor( result, from_iframe_id, note_title, revision ); }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.invoker.invoke(
|
||||
"/notebooks/load_note", "GET", {
|
||||
"notebook_id": this.notebook_id,
|
||||
|
@ -186,15 +200,27 @@ Wiki.prototype.load_editor = function ( note_title, from_iframe_id, note_id, rev
|
|||
);
|
||||
}
|
||||
|
||||
Wiki.prototype.load_editor_by_title = function ( note_title, from_iframe_id ) {
|
||||
var self = this;
|
||||
Wiki.prototype.resolve_link = function ( note_title, link, force ) {
|
||||
// if the link already has an id and the force flag isn't set, then the link is already resolved,
|
||||
// so we can just bail
|
||||
if ( link.href ) {
|
||||
var id = parse_query( link ).note_id;
|
||||
if ( id != "new" && id != "null" && !force )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( note_title.length == 0 )
|
||||
return;
|
||||
|
||||
var self = this;
|
||||
this.invoker.invoke(
|
||||
"/notebooks/load_note_by_title", "GET", {
|
||||
"/notebooks/lookup_note_id", "GET", {
|
||||
"notebook_id": this.notebook_id,
|
||||
"note_title": note_title
|
||||
},
|
||||
function ( result ) { self.parse_loaded_editor( result, from_iframe_id, note_title ); }
|
||||
function ( result ) {
|
||||
link.href = "/notebooks/" + self.notebook_id + "?note_id=" + result.note_id;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -222,7 +248,6 @@ Wiki.prototype.parse_loaded_editor = function ( result, from_iframe_id, note_tit
|
|||
|
||||
Wiki.prototype.create_editor = function ( id, note_text, deleted_from, revisions_list, from_iframe_id, note_title, read_write, highlight, focus ) {
|
||||
this.clear_messages();
|
||||
this.clear_pulldowns();
|
||||
|
||||
var self = this;
|
||||
if ( isUndefinedOrNull( id ) ) {
|
||||
|
@ -266,7 +291,7 @@ Wiki.prototype.create_editor = function ( id, note_text, deleted_from, revisions
|
|||
}
|
||||
|
||||
connect( editor, "load_editor", this, "load_editor" );
|
||||
connect( editor, "load_editor_by_title", this, "load_editor_by_title" );
|
||||
connect( editor, "resolve_link", this, "resolve_link" );
|
||||
connect( editor, "hide_clicked", function ( event ) { self.hide_editor( event, editor ) } );
|
||||
connect( editor, "submit_form", function ( url, form ) {
|
||||
self.invoker.invoke( url, "POST", null, null, form );
|
||||
|
@ -277,16 +302,38 @@ Wiki.prototype.create_editor = function ( id, note_text, deleted_from, revisions
|
|||
|
||||
Wiki.prototype.editor_state_changed = function ( editor ) {
|
||||
this.update_toolbar();
|
||||
this.display_link_pulldown( editor );
|
||||
}
|
||||
|
||||
Wiki.prototype.display_link_pulldown = function ( editor ) {
|
||||
var link = editor.find_link_at_cursor();
|
||||
|
||||
if ( !link ) {
|
||||
this.clear_pulldowns();
|
||||
return;
|
||||
}
|
||||
|
||||
var pulldown = this.link_pulldowns[ link ];
|
||||
if ( pulldown )
|
||||
pulldown.update_position();
|
||||
|
||||
// if the cursor is now on a link, display a link pulldown if there isn't already one open
|
||||
if ( hasElementClass( "createLink", "button_down" ) ) {
|
||||
if ( !pulldown ) {
|
||||
this.clear_pulldowns();
|
||||
new Link_pulldown( this, this.notebook_id, this.invoker, editor, link );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Wiki.prototype.editor_focused = function ( editor, fire_and_forget ) {
|
||||
this.clear_messages();
|
||||
this.clear_pulldowns();
|
||||
|
||||
if ( editor )
|
||||
addElementClass( editor.iframe, "focused_note_frame" );
|
||||
|
||||
if ( this.focused_editor && this.focused_editor != editor ) {
|
||||
this.clear_pulldowns();
|
||||
removeElementClass( this.focused_editor.iframe, "focused_note_frame" );
|
||||
|
||||
// if the formerly focused editor is completely empty, then remove it as the user leaves it and switches to this editor
|
||||
|
@ -388,6 +435,8 @@ Wiki.prototype.toggle_link_button = function ( event ) {
|
|||
this.focused_editor.start_link();
|
||||
else
|
||||
this.focused_editor.end_link();
|
||||
|
||||
this.display_link_pulldown( this.focused_editor );
|
||||
}
|
||||
|
||||
event.stop();
|
||||
|
@ -666,26 +715,50 @@ Wiki.prototype.toggle_editor_options = function ( event, editor ) {
|
|||
connect( window, "onload", function ( event ) { new Wiki(); } );
|
||||
|
||||
|
||||
function Pulldown( wiki, notebook_id, pulldown_id, button ) {
|
||||
function Pulldown( wiki, notebook_id, pulldown_id, anchor, relative_to ) {
|
||||
this.wiki = wiki;
|
||||
this.notebook_id = notebook_id;
|
||||
this.div = createDOM( "div", { "id": pulldown_id, "class": "pulldown" } );
|
||||
this.div.pulldown = this;
|
||||
this.anchor = anchor;
|
||||
this.relative_to = relative_to;
|
||||
|
||||
addElementClass( this.div, "invisible" );
|
||||
|
||||
appendChildNodes( document.body, this.div );
|
||||
|
||||
var self = this;
|
||||
|
||||
// position the pulldown under the button that opened it
|
||||
var position = getElementPosition( button );
|
||||
var button_dimensions = getElementDimensions( button );
|
||||
var div_dimensions = getElementDimensions( this.div );
|
||||
position.y += button_dimensions.h;
|
||||
var position = calculate_position( anchor, relative_to );
|
||||
setElementPosition( this.div, position );
|
||||
|
||||
removeElementClass( this.div, "invisible" );
|
||||
}
|
||||
}
|
||||
|
||||
function calculate_position( anchor, relative_to ) {
|
||||
// position the pulldown under the anchor
|
||||
var position = getElementPosition( anchor );
|
||||
|
||||
if ( relative_to ) {
|
||||
var relative_pos = getElementPosition( relative_to );
|
||||
if ( relative_pos ) {
|
||||
position.x += relative_pos.x;
|
||||
position.y += relative_pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
var anchor_dimensions = getElementDimensions( anchor );
|
||||
|
||||
// if the anchor has no height, move the position down a bit an arbitrary amount
|
||||
if ( anchor_dimensions.h == 0 )
|
||||
position.y += 8;
|
||||
else
|
||||
position.y += anchor_dimensions.h + 4;
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
Pulldown.prototype.update_position = function () {
|
||||
var position = calculate_position( this.anchor, this.relative_to );
|
||||
setElementPosition( this.div, position );
|
||||
}
|
||||
|
||||
Pulldown.prototype.shutdown = function () {
|
||||
removeElement( this.div );
|
||||
|
@ -773,9 +846,132 @@ Changes_pulldown.prototype.link_clicked = function( event, note_id ) {
|
|||
event.stop();
|
||||
}
|
||||
|
||||
Options_pulldown.prototype.shutdown = function () {
|
||||
Changes_pulldown.prototype.shutdown = function () {
|
||||
Pulldown.prototype.shutdown.call( this );
|
||||
|
||||
for ( var i in this.links )
|
||||
disconnectAll( this.links[ i ] );
|
||||
}
|
||||
|
||||
|
||||
function Link_pulldown( wiki, notebook_id, invoker, editor, link ) {
|
||||
wiki.link_pulldowns[ link ] = this;
|
||||
this.link = link;
|
||||
|
||||
Pulldown.call( this, wiki, notebook_id, "link_" + editor.id, link, editor.iframe );
|
||||
|
||||
this.invoker = invoker;
|
||||
this.editor = editor;
|
||||
this.title_field = createDOM( "input", { "class": "text_field", "size": "25", "maxlength": "256" } );
|
||||
this.note_preview = createDOM( "span", {} );
|
||||
this.previous_title = "";
|
||||
|
||||
var self = this;
|
||||
connect( this.title_field, "onclick", function ( event ) { self.title_field_clicked( event ); } );
|
||||
connect( this.title_field, "onchange", function ( event ) { self.title_field_changed( event ); } );
|
||||
connect( this.title_field, "onblur", function ( event ) { self.title_field_changed( event ); } );
|
||||
connect( this.title_field, "onkeydown", function ( event ) { self.title_field_key_pressed( event ); } );
|
||||
|
||||
appendChildNodes( this.div, createDOM( "span", { "class": "field_label" }, "links to: " ) );
|
||||
appendChildNodes( this.div, this.title_field );
|
||||
appendChildNodes( this.div, this.note_preview );
|
||||
|
||||
var query = parse_query( link );
|
||||
var link_title = query.title || scrapeText( link );
|
||||
var id = query.note_id;
|
||||
if ( id == "new" || id == "null" ) {
|
||||
this.title_field.value = link_title;
|
||||
replaceChildNodes( self.note_preview, "empty note" );
|
||||
return;
|
||||
}
|
||||
|
||||
// if this link has an actual destination note id set, then load that note, displaying its title
|
||||
// and a preview of its contents
|
||||
this.invoker.invoke(
|
||||
"/notebooks/load_note", "GET", {
|
||||
"notebook_id": this.notebook_id,
|
||||
"note_id": id
|
||||
},
|
||||
function ( result ) {
|
||||
if ( result.note ) {
|
||||
self.title_field.value = result.note.title;
|
||||
self.display_preview( result.note.title, result.note.contents );
|
||||
} else {
|
||||
self.title_field.value = link_title;
|
||||
replaceChildNodes( self.note_preview, "empty note" );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Link_pulldown.prototype = Pulldown;
|
||||
Link_pulldown.prototype.constructor = Link_pulldown;
|
||||
|
||||
Link_pulldown.prototype.display_preview = function ( title, contents ) {
|
||||
var contents_node = createDOM( "span", {} );
|
||||
contents_node.innerHTML = contents;
|
||||
var contents = scrapeText( contents_node );
|
||||
|
||||
// remove the title from the scraped contents text
|
||||
if ( contents.indexOf( title ) == 0 )
|
||||
contents = contents.substr( title.length );
|
||||
|
||||
if ( contents.length == 0 ) {
|
||||
replaceChildNodes( this.note_preview, "empty note" );
|
||||
} else {
|
||||
var max_preview_length = 40;
|
||||
var preview = contents.substr( 0, max_preview_length ) + ( ( contents.length > max_preview_length ) ? "..." : "" );
|
||||
replaceChildNodes( this.note_preview, preview );
|
||||
}
|
||||
}
|
||||
|
||||
Link_pulldown.prototype.title_field_clicked = function ( event ) {
|
||||
event.stop();
|
||||
}
|
||||
|
||||
Link_pulldown.prototype.title_field_changed = function ( event ) {
|
||||
// if the title is actually unchanged, then bail
|
||||
if ( this.title_field.value == this.previous_title )
|
||||
return;
|
||||
|
||||
var self = this;
|
||||
replaceChildNodes( this.note_preview, "" );
|
||||
this.previous_title = this.title_field.value;
|
||||
|
||||
this.invoker.invoke(
|
||||
"/notebooks/load_note_by_title", "GET", {
|
||||
"notebook_id": this.notebook_id,
|
||||
"note_title": this.title_field.value
|
||||
},
|
||||
function ( result ) {
|
||||
if ( result.note ) {
|
||||
self.link.href = "/notebooks/" + self.notebook_id + "?note_id=" + result.note.object_id;
|
||||
self.display_preview( result.note.title, result.note.contents );
|
||||
} else {
|
||||
self.link.href = "/notebooks/" + self.notebook_id + "?title=" + self.title_field.value + "¬e_id=null";
|
||||
replaceChildNodes( self.note_preview, "empty note" );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Link_pulldown.prototype.title_field_key_pressed = function ( event ) {
|
||||
// if enter is pressed, consider the title field altered. this is necessary because IE neglects
|
||||
// to issue an onchange event when enter is pressed in an input field
|
||||
if ( event.key().code == 13 ) {
|
||||
this.title_field_changed();
|
||||
event.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Link_pulldown.prototype.update_position = function ( anchor, relative_to ) {
|
||||
Pulldown.prototype.update_position.call( this, anchor, relative_to );
|
||||
}
|
||||
|
||||
Link_pulldown.prototype.shutdown = function () {
|
||||
Pulldown.prototype.shutdown.call( this );
|
||||
|
||||
disconnectAll( this.title_field );
|
||||
if ( this.link )
|
||||
delete this.wiki.link_pulldowns[ this.link ];
|
||||
}
|
||||
|
|
Reference in New Issue