cortex-reaver 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -1
- data/bin/cortex_reaver +3 -4
- data/lib/cortex_reaver.rb +270 -110
- data/lib/cortex_reaver/cache.rb +23 -0
- data/lib/cortex_reaver/config.rb +178 -74
- data/lib/cortex_reaver/controller/admin.rb +64 -4
- data/lib/cortex_reaver/controller/comment.rb +4 -4
- data/lib/cortex_reaver/controller/controller.rb +3 -3
- data/lib/cortex_reaver/controller/journal.rb +4 -2
- data/lib/cortex_reaver/controller/main.rb +117 -26
- data/lib/cortex_reaver/controller/page.rb +7 -0
- data/lib/cortex_reaver/controller/photograph.rb +12 -10
- data/lib/cortex_reaver/controller/tag.rb +1 -1
- data/lib/cortex_reaver/controller/user.rb +7 -2
- data/lib/cortex_reaver/helper/attachments.rb +2 -2
- data/lib/cortex_reaver/helper/crud.rb +7 -7
- data/lib/cortex_reaver/helper/feeds.rb +56 -38
- data/lib/cortex_reaver/helper/form.rb +12 -16
- data/lib/cortex_reaver/helper/navigation.rb +35 -16
- data/lib/cortex_reaver/helper/photographs.rb +2 -2
- data/lib/cortex_reaver/helper/sidebar.rb +44 -0
- data/lib/cortex_reaver/helper/tags.rb +32 -9
- data/lib/cortex_reaver/helper/workflow.rb +2 -14
- data/lib/cortex_reaver/layout/blank.rhtml +27 -31
- data/lib/cortex_reaver/layout/text.rhtml +54 -67
- data/lib/cortex_reaver/migrations/014_convert_projects_to_pages.rb +79 -0
- data/lib/cortex_reaver/model/comment.rb +7 -8
- data/lib/cortex_reaver/model/page.rb +5 -3
- data/lib/cortex_reaver/model/photograph.rb +57 -13
- data/lib/cortex_reaver/model/tag.rb +1 -4
- data/lib/cortex_reaver/model/user.rb +6 -3
- data/lib/cortex_reaver/plugin.rb +1 -1
- data/lib/cortex_reaver/plugins/twitter.rb +185 -0
- data/lib/cortex_reaver/public/css/actions.css +31 -0
- data/lib/cortex_reaver/public/css/admin.css +50 -27
- data/lib/cortex_reaver/public/css/attachments.css +11 -0
- data/lib/cortex_reaver/public/css/autotags.css +38 -0
- data/lib/cortex_reaver/public/css/code.css +10 -2
- data/lib/cortex_reaver/public/css/colophon.css +10 -0
- data/lib/cortex_reaver/public/css/commments.css +7 -0
- data/lib/cortex_reaver/public/css/custom.css +1 -0
- data/lib/cortex_reaver/public/css/flash.css +17 -0
- data/lib/cortex_reaver/public/css/fonts.css +22 -0
- data/lib/cortex_reaver/public/css/form.css +15 -3
- data/lib/cortex_reaver/public/css/generics.css +39 -0
- data/lib/cortex_reaver/public/css/icons.css +4 -0
- data/lib/cortex_reaver/public/css/journals.css +3 -0
- data/lib/cortex_reaver/public/css/main.css +30 -312
- data/lib/cortex_reaver/public/css/pagination.css +50 -0
- data/lib/cortex_reaver/public/css/photo-show.css +87 -0
- data/lib/cortex_reaver/public/css/photo.css +28 -97
- data/lib/cortex_reaver/public/css/progress.css +35 -0
- data/lib/cortex_reaver/public/css/sidebar.css +83 -0
- data/lib/cortex_reaver/public/css/table-of-contents.css +26 -0
- data/lib/cortex_reaver/public/css/table.css +3 -0
- data/lib/cortex_reaver/public/css/tags.css +29 -0
- data/lib/cortex_reaver/public/css/text.css +19 -1
- data/lib/cortex_reaver/public/css/top_actions.css +50 -0
- data/lib/cortex_reaver/public/css/users.css +3 -0
- data/lib/cortex_reaver/public/images/admin/icons.png +0 -0
- data/lib/cortex_reaver/public/images/admin/icons.xcf +0 -0
- data/lib/cortex_reaver/public/images/background_tile.png +0 -0
- data/lib/cortex_reaver/public/images/edit_34.png +0 -0
- data/lib/cortex_reaver/public/images/edit_34_prelight.png +0 -0
- data/lib/cortex_reaver/public/images/elided.png +0 -0
- data/lib/cortex_reaver/public/images/grid_34.png +0 -0
- data/lib/cortex_reaver/public/images/grid_34_prelight.png +0 -0
- data/lib/cortex_reaver/public/images/next_11.png +0 -0
- data/lib/cortex_reaver/public/images/next_34.png +0 -0
- data/lib/cortex_reaver/public/images/next_34_prelight.png +0 -0
- data/lib/cortex_reaver/public/images/prev_11.png +0 -0
- data/lib/cortex_reaver/public/images/prev_34.png +0 -0
- data/lib/cortex_reaver/public/images/prev_34_prelight.png +0 -0
- data/lib/cortex_reaver/public/js/admin.js +15 -22
- data/lib/cortex_reaver/public/js/autotags.js +120 -0
- data/lib/cortex_reaver/public/js/jquery.autocomplete.js +135 -176
- data/lib/cortex_reaver/public/js/jquery.color.js +124 -0
- data/lib/cortex_reaver/public/js/jquery.corners.min.js +7 -0
- data/lib/cortex_reaver/public/js/jquery.hotkeys-0.7.9.js +244 -0
- data/lib/cortex_reaver/public/js/jquery.js +4361 -4
- data/lib/cortex_reaver/public/js/jquery.periodicalupdater.js +98 -0
- data/lib/cortex_reaver/public/js/photo.js +3 -32
- data/lib/cortex_reaver/public/robots.txt +3 -0
- data/lib/cortex_reaver/snippets/ramaze/cache/memcached.rb +13 -10
- data/lib/cortex_reaver/snippets/range.rb +9 -0
- data/lib/cortex_reaver/support/attachments.rb +12 -0
- data/lib/cortex_reaver/support/comments.rb +1 -3
- data/lib/cortex_reaver/support/renderer.rb +20 -17
- data/lib/cortex_reaver/support/sequenceable.rb +6 -6
- data/lib/cortex_reaver/support/tags.rb +15 -7
- data/lib/cortex_reaver/version.rb +1 -1
- data/lib/cortex_reaver/view/admin/configuration.rhtml +7 -0
- data/lib/cortex_reaver/view/admin/index.rhtml +3 -0
- data/lib/cortex_reaver/view/admin/regenerate_photo_sizes.rhtml +16 -0
- data/lib/cortex_reaver/view/adminbox.rhtml +34 -44
- data/lib/cortex_reaver/view/comments/comment.rhtml +1 -1
- data/lib/cortex_reaver/view/comments/form.rhtml +1 -2
- data/lib/cortex_reaver/view/comments/post_form.rhtml +2 -10
- data/lib/cortex_reaver/view/head.rhtml +11 -0
- data/lib/cortex_reaver/view/journals/journal.rhtml +3 -3
- data/lib/cortex_reaver/view/journals/show.rhtml +0 -4
- data/lib/cortex_reaver/view/js.rhtml +1 -0
- data/lib/cortex_reaver/view/pages/list.rhtml +3 -23
- data/lib/cortex_reaver/view/pages/row.rhtml +13 -0
- data/lib/cortex_reaver/view/photographs/grid.rhtml +30 -36
- data/lib/cortex_reaver/view/photographs/show.rhtml +42 -108
- data/lib/cortex_reaver/view/sidebar/explore_photos.rhtml +7 -0
- data/lib/cortex_reaver/view/sidebar/photographs.rhtml +15 -0
- data/lib/cortex_reaver/view/sidebar/sections.rhtml +4 -0
- data/lib/cortex_reaver/view/sidebar/twitter.rhtml +12 -0
- data/lib/cortex_reaver/view/tags/show.rhtml +0 -10
- data/lib/cortex_reaver/view/tracker.rhtml +0 -0
- data/lib/cortex_reaver/view/users/list.rhtml +1 -7
- data/lib/cortex_reaver/view/users/login.rhtml +1 -1
- metadata +103 -43
- data/lib/cortex_reaver/controller/project.rb +0 -53
- data/lib/cortex_reaver/helper/template.rb +0 -37
- data/lib/cortex_reaver/model/project.rb +0 -57
- data/lib/cortex_reaver/public/css/ramaze_error.css +0 -90
- data/lib/cortex_reaver/public/images/atom-xml-icon.png +0 -0
- data/lib/cortex_reaver/public/images/body.png +0 -0
- data/lib/cortex_reaver/public/images/border_bottom.png +0 -0
- data/lib/cortex_reaver/public/images/border_bottom_left.png +0 -0
- data/lib/cortex_reaver/public/images/border_bottom_right.png +0 -0
- data/lib/cortex_reaver/public/images/border_left.png +0 -0
- data/lib/cortex_reaver/public/images/border_right.png +0 -0
- data/lib/cortex_reaver/public/images/border_top.png +0 -0
- data/lib/cortex_reaver/public/images/border_top_left.png +0 -0
- data/lib/cortex_reaver/public/images/border_top_right.png +0 -0
- data/lib/cortex_reaver/public/images/header.png +0 -0
- data/lib/cortex_reaver/public/images/header.xcf +0 -0
- data/lib/cortex_reaver/public/images/indicator.gif +0 -0
- data/lib/cortex_reaver/public/images/rss-xml-icon.png +0 -0
- data/lib/cortex_reaver/public/images/sections.png +0 -0
- data/lib/cortex_reaver/public/images/sections_highlight.png +0 -0
- data/lib/cortex_reaver/public/js/jquery.autocompletefb.js +0 -125
- data/lib/cortex_reaver/view/photographs/sidebar.rhtml +0 -7
- data/lib/cortex_reaver/view/projects/form.rhtml +0 -14
- data/lib/cortex_reaver/view/projects/list.rhtml +0 -31
- data/lib/cortex_reaver/view/projects/show.rhtml +0 -42
- data/lib/proto/cortex_reaver.yaml +0 -47
@@ -1,3 +1,22 @@
|
|
1
|
+
h1 a, h2 a, h3 a {
|
2
|
+
color: #202020;
|
3
|
+
}
|
4
|
+
|
5
|
+
#main {
|
6
|
+
background: #fff;
|
7
|
+
}
|
8
|
+
|
9
|
+
/* Colophon */
|
10
|
+
#colophon {
|
11
|
+
color: #555;
|
12
|
+
}
|
13
|
+
|
14
|
+
/* Text entries */
|
15
|
+
.text-entry h2 {
|
16
|
+
margin-bottom: 0;
|
17
|
+
padding-bottom: 0;
|
18
|
+
}
|
19
|
+
|
1
20
|
.text-entry .byline {
|
2
21
|
color: #666;
|
3
22
|
position: relative;
|
@@ -6,7 +25,6 @@
|
|
6
25
|
.text-entry .footer {
|
7
26
|
background: #eee;
|
8
27
|
border-bottom: 1px dashed #aaa;
|
9
|
-
margin-bottom: 1.5em;
|
10
28
|
padding: 2px;
|
11
29
|
}
|
12
30
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#top .actions {
|
2
|
+
top: 30px;
|
3
|
+
position: absolute;
|
4
|
+
padding: 0;
|
5
|
+
margin: 0;
|
6
|
+
}
|
7
|
+
|
8
|
+
#top .actions > li {
|
9
|
+
float: left;
|
10
|
+
display: block;
|
11
|
+
padding: 0;
|
12
|
+
margin-right: 8px;
|
13
|
+
width: 40px;
|
14
|
+
height: 40px;
|
15
|
+
}
|
16
|
+
|
17
|
+
#top .actions > li > a {
|
18
|
+
display: block;
|
19
|
+
height: 40px;
|
20
|
+
overflow: hidden;
|
21
|
+
line-height: 200px;
|
22
|
+
margin: 0;
|
23
|
+
padding: 0;
|
24
|
+
color: transparent;
|
25
|
+
}
|
26
|
+
|
27
|
+
#top .actions a.previous {
|
28
|
+
background:transparent url(/images/prev_34.png) no-repeat scroll center center;
|
29
|
+
}
|
30
|
+
#top .actions a.previous:hover {
|
31
|
+
background-image: url(/images/prev_34_prelight.png);
|
32
|
+
}
|
33
|
+
#top .actions a.up {
|
34
|
+
background:transparent url(/images/grid_34.png) no-repeat scroll center center;
|
35
|
+
}
|
36
|
+
#top .actions a.up:hover {
|
37
|
+
background-image: url(/images/grid_34_prelight.png);
|
38
|
+
}
|
39
|
+
#top .actions a.edit {
|
40
|
+
background:transparent url(/images/edit_34.png) no-repeat scroll center center;
|
41
|
+
}
|
42
|
+
#top .actions a.edit:hover {
|
43
|
+
background-image: url(/images/edit_34_prelight.png);
|
44
|
+
}
|
45
|
+
#top .actions a.next {
|
46
|
+
background:transparent url(/images/next_34.png) no-repeat scroll center center;
|
47
|
+
}
|
48
|
+
#top .actions a.next:hover {
|
49
|
+
background-image: url(/images/next_34_prelight.png);
|
50
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,34 +1,27 @@
|
|
1
1
|
// Show the admin box by default if we have a cookie that asks for it.
|
2
|
-
$(
|
2
|
+
$(document).ready(function() {
|
3
3
|
if(Cookie.get('adminboxopen') == 'true') {
|
4
|
-
$('
|
4
|
+
$('.admin.bar').show();
|
5
5
|
}
|
6
6
|
});
|
7
7
|
|
8
|
-
$(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if ($('#admin_login')) $('#admin_login').focus();
|
21
|
-
} else {
|
22
|
-
// Unfocus tools
|
23
|
-
if ($('#admin_login')) $('#admin_login').blur();
|
24
|
-
}
|
25
|
-
});
|
26
|
-
}
|
8
|
+
$(document).bind('keydown', {combi:'Alt+Ctrl+a',}, function() {
|
9
|
+
// Toggle admin tools
|
10
|
+
var a = $('.admin.bar');
|
11
|
+
a.slideToggle('fast', function() {
|
12
|
+
if ($('.admin.bar:visible')) {
|
13
|
+
// Focus tools
|
14
|
+
if ($('#admin_login')) $('#admin_login').focus();
|
15
|
+
} else {
|
16
|
+
// Unfocus tools
|
17
|
+
if ($('#admin_login')) $('#admin_login').blur();
|
18
|
+
}
|
19
|
+
});
|
27
20
|
});
|
28
21
|
|
29
22
|
// On leaving the page, remember the admin tool state.
|
30
23
|
$(window).unload(function() {
|
31
|
-
if($('
|
24
|
+
if($('.admin.bar').is(':visible')) {
|
32
25
|
Cookie.set('adminboxopen', 'true', 14);
|
33
26
|
} else {
|
34
27
|
Cookie.erase('adminboxopen');
|
@@ -0,0 +1,120 @@
|
|
1
|
+
/**
|
2
|
+
* jquery.autotags.js - awesome tag editing
|
3
|
+
*
|
4
|
+
* Copyright (c) 2009 Kyle Kingsbury (aphyr@aphyr.com)
|
5
|
+
*
|
6
|
+
* Released under the MIT License:
|
7
|
+
* http://www.opensource.org/licenses/mit-license.php
|
8
|
+
*
|
9
|
+
*/
|
10
|
+
|
11
|
+
(function($) {
|
12
|
+
$.fn.autotags = function(settings) {
|
13
|
+
// Configuration
|
14
|
+
var config = {
|
15
|
+
cacheLength: 50
|
16
|
+
};
|
17
|
+
var keys = {
|
18
|
+
backspace: 8,
|
19
|
+
tab: 9,
|
20
|
+
"return": 13,
|
21
|
+
"escape": 27,
|
22
|
+
comma: 188
|
23
|
+
};
|
24
|
+
|
25
|
+
if (settings) $.extend(config, settings);
|
26
|
+
|
27
|
+
return this.each(function () {
|
28
|
+
// MEAT AND POTATOES AND FUNCTIONS (MINUS THE COMESTIBLES)
|
29
|
+
|
30
|
+
// Adds a string to the tag list.
|
31
|
+
function addTag(tag) {
|
32
|
+
var node = document.createElement("li");
|
33
|
+
$(node).append('<span>' + tag + '</span><a href="#" title="Remove tag">x</a>');
|
34
|
+
|
35
|
+
// When clicked, remove the node and save the tags list.
|
36
|
+
$(node).find('a').click(function() {
|
37
|
+
$(node).remove();
|
38
|
+
saveTags();
|
39
|
+
})
|
40
|
+
|
41
|
+
// Add to the list.
|
42
|
+
$list.append(node);
|
43
|
+
}
|
44
|
+
|
45
|
+
// Writes the tag list to the original input field.
|
46
|
+
function saveTags() {
|
47
|
+
$field.val(
|
48
|
+
$.map($list.find('li > span'), function(obj) {
|
49
|
+
return $(obj).text();
|
50
|
+
}).join(',')
|
51
|
+
);
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
// ZOOM ZOOM ZOOM SET UP THE APP!
|
56
|
+
// FILL THE DOM WITH USELESS CRAP!
|
57
|
+
|
58
|
+
// Get original field
|
59
|
+
var $field = $(this);
|
60
|
+
|
61
|
+
// Hide field and append our widget
|
62
|
+
$field.hide();
|
63
|
+
var $container = $field.after('<div class="tag-editor"></div>').next();
|
64
|
+
|
65
|
+
// Tag list
|
66
|
+
$container.append('<ul></ul>');
|
67
|
+
var $list = $container.find('ul');
|
68
|
+
|
69
|
+
// Input field
|
70
|
+
$container.append('<input type="text">');
|
71
|
+
var $input = $container.find('input');
|
72
|
+
|
73
|
+
// Visual clear
|
74
|
+
$container.after('<div style="clear: both"></div>');
|
75
|
+
|
76
|
+
// Add tags from the original field's contents.
|
77
|
+
if ($.trim($field.val()) != '') {
|
78
|
+
$.each($field.val().split(','), function(i, tag) {
|
79
|
+
addTag($.trim(tag));
|
80
|
+
});
|
81
|
+
saveTags();
|
82
|
+
}
|
83
|
+
|
84
|
+
// Add autocomplete functionality!
|
85
|
+
$input.autocomplete(config.url);
|
86
|
+
|
87
|
+
|
88
|
+
// IM CALLING SEXY BACK(YEAH);
|
89
|
+
// THOSE OTHER FUNCTIONS DON'T KNOW HOW TO ACT;
|
90
|
+
|
91
|
+
// Focus input field when any part of the editor is clicked.
|
92
|
+
$container.click(function() {
|
93
|
+
$input.focus();
|
94
|
+
});
|
95
|
+
|
96
|
+
// Handle keypresses in the input box...
|
97
|
+
$input.keydown(function(e, code) {
|
98
|
+
code = code || e.keyCode;
|
99
|
+
if (code == keys['return'] || code == 188 || code == keys.tab) {
|
100
|
+
if ($input.val() != '') {
|
101
|
+
// Accept new tag
|
102
|
+
var newTag = $input.val();
|
103
|
+
$input.val('');
|
104
|
+
addTag(newTag);
|
105
|
+
saveTags();
|
106
|
+
|
107
|
+
// Don't submit/leave/add a comma!
|
108
|
+
return false;
|
109
|
+
}
|
110
|
+
} else if (code == keys.backspace && $input.val() == '') {
|
111
|
+
// Remove the previous tag
|
112
|
+
$list.find("li:last").remove();
|
113
|
+
saveTags();
|
114
|
+
}
|
115
|
+
});
|
116
|
+
});
|
117
|
+
};
|
118
|
+
|
119
|
+
// Private methods
|
120
|
+
})(jQuery);
|
@@ -1,142 +1,13 @@
|
|
1
1
|
/*
|
2
|
-
* Autocomplete
|
2
|
+
* jQuery Autocomplete plugin 1.1
|
3
3
|
*
|
4
|
-
* Copyright (c)
|
4
|
+
* Copyright (c) 2009 Jörn Zaefferer
|
5
5
|
*
|
6
6
|
* Dual licensed under the MIT and GPL licenses:
|
7
7
|
* http://www.opensource.org/licenses/mit-license.php
|
8
8
|
* http://www.gnu.org/licenses/gpl.html
|
9
9
|
*
|
10
|
-
* Revision: $Id: jquery.autocomplete.js
|
11
|
-
*
|
12
|
-
*/
|
13
|
-
|
14
|
-
/**
|
15
|
-
* Provide autocomplete for text-inputs or textareas.
|
16
|
-
*
|
17
|
-
* Depends on dimensions plugin's offset method for correct positioning of the select box and bgiframe plugin
|
18
|
-
* to fix IE's problem with selects.
|
19
|
-
*
|
20
|
-
* @example $("#input_box").autocomplete("my_autocomplete_backend.php");
|
21
|
-
* @before <input id="input_box" />
|
22
|
-
* @desc Autocomplete a text-input with remote data. For small to giant datasets.
|
23
|
-
*
|
24
|
-
* When the user starts typing, a request is send to the specified backend ("my_autocomplete_backend.php"),
|
25
|
-
* with a GET parameter named q that contains the current value of the input box and a paremeter "limit" with
|
26
|
-
* the value specified for the max option.
|
27
|
-
*
|
28
|
-
* A value of "foo" would result in this request url: my_autocomplete_backend.php?q=foo&limit=10
|
29
|
-
*
|
30
|
-
* The result must return with one value on each line. The result is presented in the order
|
31
|
-
* the backend sends it.
|
32
|
-
*
|
33
|
-
* @example $("#input_box").autocomplete(["Cologne", "Berlin", "Munich"]);
|
34
|
-
* @before <input id="input_box" />
|
35
|
-
* @desc Autcomplete a text-input with local data. For small datasets.
|
36
|
-
*
|
37
|
-
* @example $.getJSON("my_backend.php", function(data) {
|
38
|
-
* $("#input_box").autocomplete(data);
|
39
|
-
* });
|
40
|
-
* @before <input id="input_box" />
|
41
|
-
* @desc Autcomplete a text-input with data received via AJAX. For small to medium sized datasets.
|
42
|
-
*
|
43
|
-
* @example $("#mytextarea").autocomplete(["Cologne", "Berlin", "Munich"], {
|
44
|
-
* multiple: true
|
45
|
-
* });
|
46
|
-
* @before <textarea id="mytextarea" />
|
47
|
-
* @desc Autcomplete a textarea with local data (for small datasets). Once the user chooses one
|
48
|
-
* value, a separator is appended (by default a comma, see multipleSeparator option) and more values
|
49
|
-
* are autocompleted.
|
50
|
-
*
|
51
|
-
* @name autocomplete
|
52
|
-
* @cat Plugins/Autocomplete
|
53
|
-
* @type $
|
54
|
-
* @param String|Array urlOrData Pass either an URL for remote-autocompletion or an array of data for local auto-completion
|
55
|
-
* @param Map options Optional settings
|
56
|
-
* @option String inputClass This class will be added to the input box. Default: "ac_input"
|
57
|
-
* @option String resultsClass The class for the UL that will contain the result items (result items are LI elements). Default: "ac_results"
|
58
|
-
* @option String loadingClass The class for the input box while results are being fetched from the server. Default: "ac_loading"
|
59
|
-
* @option Number minChars The minimum number of characters a user has to type before the autocompleter activates. Default: 1
|
60
|
-
* @option Number delay The delay in milliseconds the autocompleter waits after a keystroke to activate itself. Default: 400 for remote, 10 for local
|
61
|
-
* @option Number cacheLength The number of backend query results to store in cache. If set to 1 (the current result), no caching will happen. Do not set below 1. Default: 10
|
62
|
-
* @option Boolean matchSubset Whether or not the autocompleter can use a cache for more specific queries. This means that all matches of "foot" are a subset of all matches for "foo". Usually this is true, and using this options decreases server load and increases performance. Only useful with cacheLength settings bigger than one, like 10. Default: true
|
63
|
-
* @option Boolean matchCase Whether or not the comparison is case sensitive. Important only if you use caching. Default: false
|
64
|
-
* @option Boolean matchContains Whether or not the comparison looks inside (i.e. does "ba" match "foo bar") the search results. Important only if you use caching. Don't mix with autofill. Default: false
|
65
|
-
* @option Booolean mustMatch If set to true, the autocompleter will only allow results that are presented by the backend. Note that illegal values result in an empty input box. Default: false
|
66
|
-
* @option Object extraParams Extra parameters for the backend. If you were to specify { bar:4 }, the autocompleter would call my_autocomplete_backend.php?q=foo&bar=4 (assuming the input box contains "foo"). The param can be a function that is called to calculate the param before each request. Default: none
|
67
|
-
* @option Boolean selectFirst If this is set to true, the first autocomplete value will be automatically selected on tab/return, even if it has not been handpicked by keyboard or mouse action. If there is a handpicked (highlighted) result, that result will take precedence. Default: true
|
68
|
-
* @option Function formatItem Provides advanced markup for an item. For each row of results, this function will be called. The returned value will be displayed inside an LI element in the results list. Autocompleter will provide 4 parameters: the results row, the position of the row in the list of results (starting at 1), the number of items in the list of results and the search term. Default: none, assumes that a single row contains a single value.
|
69
|
-
* @option Function formatResult Similar to formatItem, but provides the formatting for the value to be put into the input field. Again three arguments: Data, position (starting with one) and total number of data. Default: none, assumes either plain data to use as result or uses the same value as provided by formatItem.
|
70
|
-
* @option Boolean multiple Whether to allow more than one autocomplted-value to enter. Default: false
|
71
|
-
* @option String multipleSeparator Seperator to put between values when using multiple option. Default: ", "
|
72
|
-
* @option Number width Specify a custom width for the select box. Default: width of the input element
|
73
|
-
* @option Boolean autoFill Fill the textinput while still selecting a value, replacing the value if more is typed or something else is selected. Default: false
|
74
|
-
* @option Number max Limit the number of items in the select box. Is also sent as a "limit" parameter with a remote request. Default: 10
|
75
|
-
* @option Boolean|Function highlight Whether and how to highlight matches in the select box. Set to false to disable. Set to a function to customize. The function gets the value as the first argument and the search term as the second and must return the formatted value. Default: Wraps the search term in a <strong> element
|
76
|
-
* @option Boolean scroll Whether to scroll when more results than configured via scrollHeight are available. Default: true
|
77
|
-
* @option Number scrollHeight height of scrolled autocomplete control in pixels
|
78
|
-
* @option String attachTo The element to attach the autocomplete list to. Useful if used inside a modal window like Thickbox. Default: body -MM
|
79
|
-
*/
|
80
|
-
|
81
|
-
/**
|
82
|
-
* Handle the result of a search event. Is executed when the user selects a value or a
|
83
|
-
* programmatic search event is triggered (see search()).
|
84
|
-
*
|
85
|
-
* You can add and remove (using unbind("result")) this event at any time.
|
86
|
-
*
|
87
|
-
* @example $('input#suggest').result(function(event, data, formatted) {
|
88
|
-
* $("#result").html( !data ? "No match!" : "Selected: " + formatted);
|
89
|
-
* });
|
90
|
-
* @desc Bind a handler to the result event to display the selected value in a #result element.
|
91
|
-
* The first argument is a generic event object, in this case with type "result".
|
92
|
-
* The second argument refers to the selected data, which can be a plain string value or an array or object.
|
93
|
-
* The third argument is the formatted value that is inserted into the input field.
|
94
|
-
*
|
95
|
-
* @param Function handler The event handler, gets a default event object as first and
|
96
|
-
* the selected list item as second argument.
|
97
|
-
* @name result
|
98
|
-
* @cat Plugins/Autocomplete
|
99
|
-
* @type $
|
100
|
-
*/
|
101
|
-
|
102
|
-
/**
|
103
|
-
* Trigger a search event. See result(Function) for binding to that event.
|
104
|
-
*
|
105
|
-
* A search event mimics the same behaviour as when the user selects a value from
|
106
|
-
* the list of autocomplete items. You can use it to execute anything that does something
|
107
|
-
* with the selected value, beyond simply putting the value into the input and submitting it.
|
108
|
-
*
|
109
|
-
* @example $('input#suggest').search();
|
110
|
-
* @desc Triggers a search event.
|
111
|
-
*
|
112
|
-
* @name search
|
113
|
-
* @cat Plugins/Autocomplete
|
114
|
-
* @type $
|
115
|
-
*/
|
116
|
-
|
117
|
-
/**
|
118
|
-
* Flush (empty) the cache of matched input's autocompleters.
|
119
|
-
*
|
120
|
-
* @example $('input#suggest').flushCache();
|
121
|
-
*
|
122
|
-
* @name flushCache
|
123
|
-
* @cat Plugins/Autocomplete
|
124
|
-
* @type $
|
125
|
-
*/
|
126
|
-
|
127
|
-
/**
|
128
|
-
* Updates the options for the current autocomplete field. This allows
|
129
|
-
* you to change things like the URL, max items to display, etc. If you're
|
130
|
-
* changing the URL, be sure to remember to call the flushCache() method.
|
131
|
-
*
|
132
|
-
* @example $('input#suggest').setOptions({
|
133
|
-
* max: 15
|
134
|
-
* });
|
135
|
-
* @desc Changes the maximum number of items to display to 15.
|
136
|
-
*
|
137
|
-
* @name setOptions
|
138
|
-
* @cat Plugins/Autocomplete
|
139
|
-
* @type $
|
10
|
+
* Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
|
140
11
|
*/
|
141
12
|
|
142
13
|
;(function($) {
|
@@ -154,6 +25,9 @@ $.fn.extend({
|
|
154
25
|
// if highlight is set to false, replace it with a do-nothing function
|
155
26
|
options.highlight = options.highlight || function(value) { return value; };
|
156
27
|
|
28
|
+
// if the formatMatch option is not specified, then use formatItem for backwards compatibility
|
29
|
+
options.formatMatch = options.formatMatch || options.formatItem;
|
30
|
+
|
157
31
|
return this.each(function() {
|
158
32
|
new $.Autocompleter(this, options);
|
159
33
|
});
|
@@ -186,7 +60,8 @@ $.Autocompleter = function(input, options) {
|
|
186
60
|
ESC: 27,
|
187
61
|
COMMA: 188,
|
188
62
|
PAGEUP: 33,
|
189
|
-
PAGEDOWN: 34
|
63
|
+
PAGEDOWN: 34,
|
64
|
+
BACKSPACE: 8
|
190
65
|
};
|
191
66
|
|
192
67
|
// Create $ object for input element
|
@@ -202,7 +77,21 @@ $.Autocompleter = function(input, options) {
|
|
202
77
|
};
|
203
78
|
var select = $.Autocompleter.Select(options, input, selectCurrent, config);
|
204
79
|
|
205
|
-
|
80
|
+
var blockSubmit;
|
81
|
+
|
82
|
+
// prevent form submit in opera when selecting with return key
|
83
|
+
$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
|
84
|
+
if (blockSubmit) {
|
85
|
+
blockSubmit = false;
|
86
|
+
return false;
|
87
|
+
}
|
88
|
+
});
|
89
|
+
|
90
|
+
// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
|
91
|
+
$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
|
92
|
+
// a keypress means the input has focus
|
93
|
+
// avoids issue where input had focus before the autocomplete was applied
|
94
|
+
hasFocus = 1;
|
206
95
|
// track last key pressed
|
207
96
|
lastKeyPressCode = event.keyCode;
|
208
97
|
switch(event.keyCode) {
|
@@ -247,11 +136,11 @@ $.Autocompleter = function(input, options) {
|
|
247
136
|
case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
|
248
137
|
case KEY.TAB:
|
249
138
|
case KEY.RETURN:
|
250
|
-
if( selectCurrent() ){
|
251
|
-
//
|
252
|
-
if( !options.multiple )
|
253
|
-
$input.blur();
|
139
|
+
if( selectCurrent() ) {
|
140
|
+
// stop default to prevent a form submit, Opera needs special handling
|
254
141
|
event.preventDefault();
|
142
|
+
blockSubmit = true;
|
143
|
+
return false;
|
255
144
|
}
|
256
145
|
break;
|
257
146
|
|
@@ -264,8 +153,6 @@ $.Autocompleter = function(input, options) {
|
|
264
153
|
timeout = setTimeout(onChange, options.delay);
|
265
154
|
break;
|
266
155
|
}
|
267
|
-
}).keypress(function() {
|
268
|
-
// having fun with opera - remove this binding and Opera submits the form when we select an entry via return
|
269
156
|
}).focus(function(){
|
270
157
|
// track whether the field has focus, we shouldn't process any
|
271
158
|
// results if the field no longer has focus
|
@@ -309,6 +196,7 @@ $.Autocompleter = function(input, options) {
|
|
309
196
|
}).bind("unautocomplete", function() {
|
310
197
|
select.unbind();
|
311
198
|
$input.unbind();
|
199
|
+
$(input.form).unbind(".autocomplete");
|
312
200
|
});
|
313
201
|
|
314
202
|
|
@@ -323,7 +211,21 @@ $.Autocompleter = function(input, options) {
|
|
323
211
|
if ( options.multiple ) {
|
324
212
|
var words = trimWords($input.val());
|
325
213
|
if ( words.length > 1 ) {
|
326
|
-
|
214
|
+
var seperator = options.multipleSeparator.length;
|
215
|
+
var cursorAt = $(input).selection().start;
|
216
|
+
var wordAt, progress = 0;
|
217
|
+
$.each(words, function(i, word) {
|
218
|
+
progress += word.length;
|
219
|
+
if (cursorAt <= progress) {
|
220
|
+
wordAt = i;
|
221
|
+
return false;
|
222
|
+
}
|
223
|
+
progress += seperator;
|
224
|
+
});
|
225
|
+
words[wordAt] = v;
|
226
|
+
// TODO this should set the cursor to the right position, but it gets overriden somewhere
|
227
|
+
//$.Autocompleter.Selection(input, progress + seperator, progress + seperator);
|
228
|
+
v = words.join( options.multipleSeparator );
|
327
229
|
}
|
328
230
|
v += options.multipleSeparator;
|
329
231
|
}
|
@@ -360,34 +262,41 @@ $.Autocompleter = function(input, options) {
|
|
360
262
|
};
|
361
263
|
|
362
264
|
function trimWords(value) {
|
363
|
-
if (
|
265
|
+
if (!value)
|
364
266
|
return [""];
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
if ( $.trim(value) )
|
370
|
-
result[i] = $.trim(value);
|
267
|
+
if (!options.multiple)
|
268
|
+
return [$.trim(value)];
|
269
|
+
return $.map(value.split(options.multipleSeparator), function(word) {
|
270
|
+
return $.trim(value).length ? $.trim(word) : null;
|
371
271
|
});
|
372
|
-
return result;
|
373
272
|
}
|
374
273
|
|
375
274
|
function lastWord(value) {
|
376
275
|
if ( !options.multiple )
|
377
276
|
return value;
|
378
277
|
var words = trimWords(value);
|
278
|
+
if (words.length == 1)
|
279
|
+
return words[0];
|
280
|
+
var cursorAt = $(input).selection().start;
|
281
|
+
if (cursorAt == value.length) {
|
282
|
+
words = trimWords(value)
|
283
|
+
} else {
|
284
|
+
words = trimWords(value.replace(value.substring(cursorAt), ""));
|
285
|
+
}
|
379
286
|
return words[words.length - 1];
|
380
287
|
}
|
381
288
|
|
382
289
|
// fills in the input box w/the first match (assumed to be the best match)
|
290
|
+
// q: the term entered
|
291
|
+
// sValue: the first matching result
|
383
292
|
function autoFill(q, sValue){
|
384
293
|
// autofill in the complete box w/the first match as long as the user hasn't entered in more data
|
385
294
|
// if the last user key pressed was backspace, don't autofill
|
386
|
-
if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode !=
|
295
|
+
if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
|
387
296
|
// fill in the value (keep the case the user has typed)
|
388
297
|
$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
|
389
298
|
// select the portion of the value not typed by the user (so the next character will erase)
|
390
|
-
|
299
|
+
$(input).selection(previousValue.length, previousValue.length + sValue.length);
|
391
300
|
}
|
392
301
|
};
|
393
302
|
|
@@ -397,6 +306,7 @@ $.Autocompleter = function(input, options) {
|
|
397
306
|
};
|
398
307
|
|
399
308
|
function hideResultsNow() {
|
309
|
+
var wasVisible = select.visible();
|
400
310
|
select.hide();
|
401
311
|
clearTimeout(timeout);
|
402
312
|
stopLoading();
|
@@ -405,7 +315,16 @@ $.Autocompleter = function(input, options) {
|
|
405
315
|
$input.search(
|
406
316
|
function (result){
|
407
317
|
// if no value found, clear the input box
|
408
|
-
if( !result )
|
318
|
+
if( !result ) {
|
319
|
+
if (options.multiple) {
|
320
|
+
var words = trimWords($input.val()).slice(0, -1);
|
321
|
+
$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
|
322
|
+
}
|
323
|
+
else {
|
324
|
+
$input.val( "" );
|
325
|
+
$input.trigger("result", null);
|
326
|
+
}
|
327
|
+
}
|
409
328
|
}
|
410
329
|
);
|
411
330
|
}
|
@@ -432,7 +351,9 @@ $.Autocompleter = function(input, options) {
|
|
432
351
|
// if an AJAX url has been supplied, try loading the data now
|
433
352
|
} else if( (typeof options.url == "string") && (options.url.length > 0) ){
|
434
353
|
|
435
|
-
var extraParams = {
|
354
|
+
var extraParams = {
|
355
|
+
timestamp: +new Date()
|
356
|
+
};
|
436
357
|
$.each(options.extraParams, function(key, param) {
|
437
358
|
extraParams[key] = typeof param == "function" ? param() : param;
|
438
359
|
});
|
@@ -455,6 +376,8 @@ $.Autocompleter = function(input, options) {
|
|
455
376
|
}
|
456
377
|
});
|
457
378
|
} else {
|
379
|
+
// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
|
380
|
+
select.emptyList();
|
458
381
|
failure(term);
|
459
382
|
}
|
460
383
|
};
|
@@ -497,6 +420,7 @@ $.Autocompleter.defaults = {
|
|
497
420
|
extraParams: {},
|
498
421
|
selectFirst: true,
|
499
422
|
formatItem: function(row) { return row[0]; },
|
423
|
+
formatMatch: null,
|
500
424
|
autoFill: false,
|
501
425
|
width: 0,
|
502
426
|
multiple: false,
|
@@ -505,8 +429,7 @@ $.Autocompleter.defaults = {
|
|
505
429
|
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
|
506
430
|
},
|
507
431
|
scroll: true,
|
508
|
-
scrollHeight: 180
|
509
|
-
attachTo: 'body'
|
432
|
+
scrollHeight: 180
|
510
433
|
};
|
511
434
|
|
512
435
|
$.Autocompleter.Cache = function(options) {
|
@@ -518,6 +441,9 @@ $.Autocompleter.Cache = function(options) {
|
|
518
441
|
if (!options.matchCase)
|
519
442
|
s = s.toLowerCase();
|
520
443
|
var i = s.indexOf(sub);
|
444
|
+
if (options.matchContains == "word"){
|
445
|
+
i = s.toLowerCase().search("\\b" + sub.toLowerCase());
|
446
|
+
}
|
521
447
|
if (i == -1) return false;
|
522
448
|
return i == 0 || options.matchContains;
|
523
449
|
};
|
@@ -550,7 +476,7 @@ $.Autocompleter.Cache = function(options) {
|
|
550
476
|
// if rawValue is a string, make an array otherwise just reference the array
|
551
477
|
rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
|
552
478
|
|
553
|
-
var value = options.
|
479
|
+
var value = options.formatMatch(rawValue, i+1, options.data.length);
|
554
480
|
if ( value === false )
|
555
481
|
continue;
|
556
482
|
|
@@ -666,9 +592,9 @@ $.Autocompleter.Select = function (options, input, select, config) {
|
|
666
592
|
.hide()
|
667
593
|
.addClass(options.resultsClass)
|
668
594
|
.css("position", "absolute")
|
669
|
-
.appendTo(
|
595
|
+
.appendTo(document.body);
|
670
596
|
|
671
|
-
list = $("<ul
|
597
|
+
list = $("<ul/>").appendTo(element).mouseover( function(event) {
|
672
598
|
if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
|
673
599
|
active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
|
674
600
|
$(target(event)).addClass(CLASSES.ACTIVE);
|
@@ -676,6 +602,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
|
|
676
602
|
}).click(function(event) {
|
677
603
|
$(target(event)).addClass(CLASSES.ACTIVE);
|
678
604
|
select();
|
605
|
+
// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
|
679
606
|
input.focus();
|
680
607
|
return false;
|
681
608
|
}).mousedown(function() {
|
@@ -701,7 +628,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
|
|
701
628
|
}
|
702
629
|
|
703
630
|
function moveSelect(step) {
|
704
|
-
listItems.slice(active, active + 1).removeClass();
|
631
|
+
listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
|
705
632
|
movePosition(step);
|
706
633
|
var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
|
707
634
|
if(options.scroll) {
|
@@ -741,7 +668,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
|
|
741
668
|
var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
|
742
669
|
if ( formatted === false )
|
743
670
|
continue;
|
744
|
-
var li = $("<li
|
671
|
+
var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
|
745
672
|
$.data(li, "ac_data", data[i]);
|
746
673
|
}
|
747
674
|
listItems = list.find("li");
|
@@ -749,7 +676,9 @@ $.Autocompleter.Select = function (options, input, select, config) {
|
|
749
676
|
listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
|
750
677
|
active = 0;
|
751
678
|
}
|
752
|
-
|
679
|
+
// apply bgiframe if available
|
680
|
+
if ( $.fn.bgiframe )
|
681
|
+
list.bgiframe();
|
753
682
|
}
|
754
683
|
|
755
684
|
return {
|
@@ -781,6 +710,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
|
|
781
710
|
},
|
782
711
|
hide: function() {
|
783
712
|
element && element.hide();
|
713
|
+
listItems && listItems.removeClass(CLASSES.ACTIVE);
|
784
714
|
active = -1;
|
785
715
|
},
|
786
716
|
visible : function() {
|
@@ -822,28 +752,57 @@ $.Autocompleter.Select = function (options, input, select, config) {
|
|
822
752
|
var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
|
823
753
|
return selected && selected.length && $.data(selected[0], "ac_data");
|
824
754
|
},
|
755
|
+
emptyList: function (){
|
756
|
+
list && list.empty();
|
757
|
+
},
|
825
758
|
unbind: function() {
|
826
759
|
element && element.remove();
|
827
760
|
}
|
828
761
|
};
|
829
762
|
};
|
830
763
|
|
831
|
-
$.
|
832
|
-
if(
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
764
|
+
$.fn.selection = function(start, end) {
|
765
|
+
if (start !== undefined) {
|
766
|
+
return this.each(function() {
|
767
|
+
if( this.createTextRange ){
|
768
|
+
var selRange = this.createTextRange();
|
769
|
+
if (end === undefined || start == end) {
|
770
|
+
selRange.move("character", start);
|
771
|
+
selRange.select();
|
772
|
+
} else {
|
773
|
+
selRange.collapse(true);
|
774
|
+
selRange.moveStart("character", start);
|
775
|
+
selRange.moveEnd("character", end);
|
776
|
+
selRange.select();
|
777
|
+
}
|
778
|
+
} else if( this.setSelectionRange ){
|
779
|
+
this.setSelectionRange(start, end);
|
780
|
+
} else if( this.selectionStart ){
|
781
|
+
this.selectionStart = start;
|
782
|
+
this.selectionEnd = end;
|
783
|
+
}
|
784
|
+
});
|
785
|
+
}
|
786
|
+
var field = this[0];
|
787
|
+
if ( field.createTextRange ) {
|
788
|
+
var range = document.selection.createRange(),
|
789
|
+
orig = field.value,
|
790
|
+
teststring = "<->",
|
791
|
+
textLength = range.text.length;
|
792
|
+
range.text = teststring;
|
793
|
+
var caretAt = field.value.indexOf(teststring);
|
794
|
+
field.value = orig;
|
795
|
+
this.selection(caretAt, caretAt + textLength);
|
796
|
+
return {
|
797
|
+
start: caretAt,
|
798
|
+
end: caretAt + textLength
|
799
|
+
}
|
800
|
+
} else if( field.selectionStart !== undefined ){
|
801
|
+
return {
|
802
|
+
start: field.selectionStart,
|
803
|
+
end: field.selectionEnd
|
844
804
|
}
|
845
805
|
}
|
846
|
-
field.focus();
|
847
806
|
};
|
848
807
|
|
849
|
-
})(jQuery);
|
808
|
+
})(jQuery);
|