Merge pull request #2449 from rabuzarus/1404_reworked_autocomplete

new autocompletion
This commit is contained in:
Tobias Diekershoff 2016-04-16 08:16:21 +02:00
commit bbd5878734
64 changed files with 3102 additions and 1380 deletions

60
include/DirSearch.php Normal file
View file

@ -0,0 +1,60 @@
<?php
/**
* @file include/DirSearch.php
* @brief This file includes the DirSearch class with directory related functions
*/
/**
* @brief This class handels directory related functions
*/
class DirSearch {
/**
* @brief Search global contact table by nick or name
* *
* @param string $search Name or nick
* @param string $mode Search mode
* @return array with search results
*/
public static function global_search_by_name($search, $mode = '') {
if($search) {
// check supported networks
if (get_config('system','diaspora_enabled'))
$diaspora = NETWORK_DIASPORA;
else
$diaspora = NETWORK_DFRN;
if (!get_config('system','ostatus_disabled'))
$ostatus = NETWORK_OSTATUS;
else
$ostatus = NETWORK_DFRN;
// check if fo
if($mode === "community")
$extra_sql = " AND `community`";
else
$extra_sql = "";
$results = q("SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`nick`, `gcontact`.`photo`,
`gcontact`.`network`, `gcontact`.`keywords`, `gcontact`.`addr`, `gcontact`.`community`
FROM `gcontact`
LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
WHERE (`contact`.`id` > 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND
(`gcontact`.`name` REGEXP '%s' OR `gcontact`.`nick` REGEXP '%s') $extra_sql
GROUP BY `gcontact`.`nurl`
ORDER BY `gcontact`.`updated` DESC ",
intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND),
dbesc(NETWORK_DFRN), dbesc($ostatus), dbesc($diaspora),
dbesc(escape_tags($search)), dbesc(escape_tags($search)));
return $results;
}
}
}

182
include/Smilies.php Normal file
View file

@ -0,0 +1,182 @@
<?php
/**
* @file include/Smilies.php
* @brief This file contains the Smilies class which contains functions to handle smiles
*/
/**
* This class contains functions to handle smiles
*/
class Smilies {
/**
* @brief Function to list all smilies
*
* Get an array of all smilies, both internal and from addons.
*
* @return array
* 'texts' => smilie shortcut
* 'icons' => icon in html
*
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array)
*/
public static function get_list() {
$texts = array(
'&lt;3',
'&lt;/3',
'&lt;\\3',
':-)',
';-)',
':-(',
':-P',
':-p',
':-"',
':-&quot;',
':-x',
':-X',
':-D',
'8-|',
'8-O',
':-O',
'\\o/',
'o.O',
'O.o',
'o_O',
'O_o',
":'(",
":-!",
":-/",
":-[",
"8-)",
':beer',
':homebrew',
':coffee',
':facepalm',
':like',
':dislike',
'~friendica',
'red#',
'red#matrix'
);
$icons = array(
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" title="&lt;3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;/3" title="&lt;/3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" title="&lt;\\3" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-smile.gif" alt=":-)" title=":-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-wink.gif" alt=";-)" title=";-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-frown.gif" alt=":-(" title=":-(" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-P" title=":-P" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-tongue-out.gif" alt=":-p" title=":-P" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-x" title=":-x" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" title=":-X" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" title=":-D" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" title="8-|" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" title="8-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-surprised.gif" alt=":-O" title="8-O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-thumbsup.gif" alt="\\o/" title="\\o/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o.O" title="o.O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O.o" title="O.o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="o_O" title="o_O" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-Oo.gif" alt="O_o" title="O_o" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cry.gif" alt=":\'(" title=":\'("/>',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-foot-in-mouth.gif" alt=":-!" title=":-!" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-undecided.gif" alt=":-/" title=":-/" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-embarassed.gif" alt=":-[" title=":-[" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-cool.gif" alt="8-)" title="8-)" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":beer" title=":beer" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/beer_mug.gif" alt=":homebrew" title=":homebrew" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/coffee.gif" alt=":coffee" title=":coffee" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-facepalm.gif" alt=":facepalm" title=":facepalm" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/like.gif" alt=":like" title=":like" />',
'<img class="smiley" src="' . app::get_baseurl() . '/images/dislike.gif" alt=":dislike" title=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . app::get_baseurl() . '/images/friendica-16.png" alt="~friendica" title="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red#" title="red#" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . app::get_baseurl() . '/images/rm-16.png" alt="red#matrix" title="red#matrix" />matrix</a>'
);
$params = array('texts' => $texts, 'icons' => $icons);
call_hooks('smilie', $params);
return $params;
}
/**
* @brief Replaces text emoticons with graphical images
*
* It is expected that this function will be called using HTML text.
* We will escape text between HTML pre and code blocks from being
* processed.
*
* At a higher level, the bbcode [nosmile] tag can be used to prevent this
* function from being executed by the prepare_text() routine when preparing
* bbcode source for HTML display
*
* @param string $s
* @param boolean $sample
*
* @return string HML Output of the Smilie
*/
public static function replace($s, $sample = false) {
if(intval(get_config('system','no_smilies'))
|| (local_user() && intval(get_pconfig(local_user(),'system','no_smilies'))))
return $s;
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','self::encode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','self::encode',$s);
$params = self::get_list();
$params['string'] = $s;
if($sample) {
$s = '<div class="smiley-sample">';
for($x = 0; $x < count($params['texts']); $x ++) {
$s .= '<dl><dt>' . $params['texts'][$x] . '</dt><dd>' . $params['icons'][$x] . '</dd></dl>';
}
}
else {
$params['string'] = preg_replace_callback('/&lt;(3+)/','self::preg_heart',$params['string']);
$s = str_replace($params['texts'],$params['icons'],$params['string']);
}
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','self::decode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','self::decode',$s);
return $s;
}
private function encode($m) {
return(str_replace($m[1],base64url_encode($m[1]),$m[0]));
}
private function decode($m) {
return(str_replace($m[1],base64url_decode($m[1]),$m[0]));
}
/**
* @brief expand <3333 to the correct number of hearts
*
* @param string $x
* @return string HTML Output
*
* @todo: Rework because it doesn't work correctly
*/
private function preg_heart($x) {
if(strlen($x[1]) == 1)
return $x[0];
$t = '';
for($cnt = 0; $cnt < strlen($x[1]); $cnt ++)
$t .= '<img class="smiley" src="' . app::get_baseurl() . '/images/smiley-heart.gif" alt="&lt;3" />';
$r = str_replace($x[0],$t,$x[0]);
return $r;
}
}

View file

@ -1,13 +1,15 @@
<?php
/**
* @file include/acl_selectors.php
*/
require_once("include/contact_selectors.php");
require_once("include/contact_widgets.php");
require_once("include/DirSearch.php");
require_once("include/features.php");
require_once("mod/proxy.php");
/**
*
*/
/**
* @package acl_selectors
@ -257,7 +259,7 @@ function prune_deadguys($arr) {
if(! $arr)
return $arr;
$str = dbesc(implode(',',$arr));
$r = q("select id from contact where id in ( " . $str . ") and blocked = 0 and pending = 0 and archive = 0 ");
$r = q("SELECT `id` FROM `contact` WHERE `id` IN ( " . $str . ") AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 ");
if($r) {
$ret = array();
foreach($r as $rr)
@ -397,9 +399,10 @@ function acl_lookup(&$a, $out_type = 'json') {
$count = (x($_REQUEST,'count') ? $_REQUEST['count'] : 100);
$search = (x($_REQUEST,'search') ? $_REQUEST['search'] : "");
$type = (x($_REQUEST,'type') ? $_REQUEST['type'] : "");
$mode = (x($_REQUEST,'mode') ? $_REQUEST['mode'] : "");
$conv_id = (x($_REQUEST,'conversation') ? $_REQUEST['conversation'] : null);
// For use with jquery.autocomplete for private mail completion
// For use with jquery.textcomplete for private mail completion
if(x($_REQUEST,'query') && strlen($_REQUEST['query'])) {
if(! $type)
@ -428,6 +431,7 @@ function acl_lookup(&$a, $out_type = 'json') {
$sql_extra2 .= " ".unavailable_networks();
// autocomplete for editor mentions
if ($type=='' || $type=='c'){
$r = q("SELECT COUNT(*) AS c FROM `contact`
WHERE `uid` = %d AND `self` = 0
@ -476,7 +480,7 @@ function acl_lookup(&$a, $out_type = 'json') {
if ($type=='' || $type=='g'){
$r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') as uids
$r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
FROM `group`,`group_member`
WHERE `group`.`deleted` = 0 AND `group`.`uid` = %d
AND `group_member`.`gid`=`group`.`id`
@ -505,7 +509,7 @@ function acl_lookup(&$a, $out_type = 'json') {
if ($type==''){
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, forum FROM `contact`
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != ''
AND NOT (`network` IN ('%s', '%s'))
$sql_extra2
@ -516,7 +520,7 @@ function acl_lookup(&$a, $out_type = 'json') {
}
elseif ($type=='c'){
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, forum FROM `contact`
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND `self` = 0 AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 AND `notify` != ''
AND NOT (`network` IN ('%s'))
$sql_extra2
@ -538,36 +542,41 @@ function acl_lookup(&$a, $out_type = 'json') {
);
}
elseif($type == 'a') {
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag` FROM `contact`
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND `pending` = 0
$sql_extra2
ORDER BY `name` ASC ",
intval(local_user())
);
}
elseif($type == 'x') {
// autocomplete for global contact search (e.g. navbar search)
$r = navbar_complete($a);
$contacts = array();
if($r) {
foreach($r as $g) {
$contacts[] = array(
"photo" => $g['photo'],
"name" => $g['name'],
"nick" => (x($g['addr']) ? $g['addr'] : $g['url']),
"network" => $g['network'],
"link" => $g['url'],
"forum" => (x($g['community']) ? 1 : 0),
);
}
}
$o = array(
'start' => $start,
'count' => $count,
'items' => $contacts,
);
echo json_encode($o);
killme();
}
else
$r = array();
if($type == 'm' || $type == 'a') {
$x = array();
$x['query'] = $search;
$x['photos'] = array();
$x['links'] = array();
$x['suggestions'] = array();
$x['data'] = array();
if(count($r)) {
foreach($r as $g) {
$x['photos'][] = proxy_url($g['micro'], false, PROXY_SIZE_MICRO);
$x['links'][] = $g['url'];
$x['suggestions'][] = htmlentities($g['name']);
$x['data'][] = intval($g['id']);
}
}
echo json_encode($x);
killme();
}
if(count($r)) {
foreach($r as $g){
$contacts[] = array(
@ -578,7 +587,7 @@ function acl_lookup(&$a, $out_type = 'json') {
"network" => $g['network'],
"link" => $g['url'],
"nick" => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
"forum" => $g['forum']
"forum" => ((x($g['forum']) || x($g['prv'])) ? 1 : 0),
);
}
}
@ -591,14 +600,10 @@ function acl_lookup(&$a, $out_type = 'json') {
function _contact_link($i){ return dbesc($i['link']); }
$known_contacts = array_map(_contact_link, $contacts);
$unknow_contacts=array();
$r = q("select
`author-avatar`,`author-name`,`author-link`
from item where parent=%d
and (
`author-name` LIKE '%%%s%%' OR
`author-link` LIKE '%%%s%%'
) and
`author-link` NOT IN ('%s')
$r = q("SELECT `author-avatar`,`author-name`,`author-link`
FROM `item` WHERE `parent` = %d
AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
AND `author-link` NOT IN ('%s')
GROUP BY `author-link`
ORDER BY `author-name` ASC
",
@ -654,4 +659,49 @@ function acl_lookup(&$a, $out_type = 'json') {
killme();
}
/**
* @brief Searching for global contacts for autocompletion
*
* @param App $a
* @return array with the search results
*/
function navbar_complete(&$a) {
// logger('navbar_complete');
if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
return;
}
// check if searching in the local global contact table is enabled
$localsearch = get_config('system','poco_local_search');
$search = $prefix.notags(trim($_REQUEST['search']));
$mode = $_REQUEST['mode'];
// don't search if search term has less than 2 characters
if(! $search || mb_strlen($search) < 2)
return array();
if(substr($search,0,1) === '@')
$search = substr($search,1);
if($localsearch) {
$x = DirSearch::global_search_by_name($search, $mode);
return $x;
}
if(! $localsearch) {
$p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : '');
$x = z_fetch_url(get_server().'/lsearch?f=' . $p . '&search=' . urlencode($search));
if($x['success']) {
$t = 0;
$j = json_decode($x['body'],true);
if($j && $j['results']) {
return $j['results'];
}
}
}
return;
}

View file

@ -2,7 +2,7 @@
function nav(&$a) {
/**
/*
*
* Build page header and site navigation bars
*
@ -11,7 +11,9 @@ function nav(&$a) {
if(!(x($a->page,'nav')))
$a->page['nav'] = '';
/**
$a->page['htmlhead'] .= replace_macros(get_markup_template('nav_head.tpl'), array());
/*
* Placeholder div for popup panel
*/
@ -19,7 +21,7 @@ function nav(&$a) {
$nav_info = nav_info($a);
/**
/*
* Build the page
*/
@ -34,7 +36,8 @@ function nav(&$a) {
'$userinfo' => $nav_info['userinfo'],
'$sel' => $a->nav_sel,
'$apps' => $a->apps,
'$clear_notifs' => t('Clear notifications')
'$clear_notifs' => t('Clear notifications'),
'$search_hint' => t('@name, !forum, #tags, content')
));
call_hooks('page_header', $a->page['nav']);
@ -45,7 +48,7 @@ function nav_info(&$a) {
$ssl_state = ((local_user()) ? true : false);
/**
/*
*
* Our network is distributed, and as you visit friends some of the
* sites look exactly the same - it isn't always easy to know where you are.
@ -61,7 +64,7 @@ function nav_info(&$a) {
// nav links: array of array('href', 'text', 'extra css classes', 'title')
$nav = Array();
/**
/*
* Display login or logout
*/
@ -92,7 +95,7 @@ function nav_info(&$a) {
}
/**
/*
* "Home" should also take you home from an authenticated remote profile connection
*/
@ -143,7 +146,7 @@ function nav_info(&$a) {
$nav['about'] = Array('friendica', t('Information'), "", t('Information about this friendica instance'));
/**
/*
*
* The following nav links are only show to logged in users
*
@ -187,7 +190,7 @@ function nav_info(&$a) {
$nav['contacts'] = array('contacts', t('Contacts'),"", t('Manage/edit friends and contacts'));
}
/**
/*
* Admin page
*/
if (is_site_admin()){
@ -198,7 +201,7 @@ function nav_info(&$a) {
$nav['navigation'] = array('navigation/', t('Navigation'), "", t('Site map'));
/**
/*
*
* Provide a banner/logo/whatever
*
@ -221,7 +224,7 @@ function nav_info(&$a) {
}
/*
/**
* Set a menu item in navbar as selected
*
*/

View file

@ -1286,3 +1286,18 @@ function short_link($url) {
}
return $slinky->short();
}};
/**
* @brief Encodes content to json
*
* This function encodes an array to json format
* and adds an application/json HTTP header to the output.
* After finishing the process is getting killed.
*
* @param array $x The input content
*/
function json_return_and_die($x) {
header("content-type: application/json");
echo json_encode($x);
killme();
}

View file

@ -2,6 +2,7 @@
require_once("include/template_processor.php");
require_once("include/friendica_smarty.php");
require_once("include/Smilies.php");
require_once("include/map.php");
require_once("mod/proxy.php");
@ -1079,160 +1080,6 @@ function get_mood_verbs() {
return $arr;
}
if(! function_exists('smilies')) {
/**
* Replaces text emoticons with graphical images
*
* It is expected that this function will be called using HTML text.
* We will escape text between HTML pre and code blocks from being
* processed.
*
* At a higher level, the bbcode [nosmile] tag can be used to prevent this
* function from being executed by the prepare_text() routine when preparing
* bbcode source for HTML display
*
* @param string $s
* @param boolean $sample
* @return string
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array, 'string' => $s)
*/
function smilies($s, $sample = false) {
$a = get_app();
if(intval(get_config('system','no_smilies'))
|| (local_user() && intval(get_pconfig(local_user(),'system','no_smilies'))))
return $s;
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_encode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_encode',$s);
$texts = array(
'&lt;3',
'&lt;/3',
'&lt;\\3',
':-)',
';-)',
':-(',
':-P',
':-p',
':-"',
':-&quot;',
':-x',
':-X',
':-D',
'8-|',
'8-O',
':-O',
'\\o/',
'o.O',
'O.o',
'o_O',
'O_o',
":'(",
":-!",
":-/",
":-[",
"8-)",
':beer',
':homebrew',
':coffee',
':facepalm',
':like',
':dislike',
'~friendica',
'red#',
'red#matrix'
);
$icons = array(
'<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" title="&lt;3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;/3" title="&lt;/3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" title="&lt;\\3" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-smile.gif" alt=":-)" title=":-)" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-wink.gif" alt=";-)" title=";-)" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-frown.gif" alt=":-(" title=":-(" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-P" title=":-P" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-p" title=":-P" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-x" title=":-x" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-X" title=":-X" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-laughing.gif" alt=":-D" title=":-D" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-|" title="8-|" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-O" title="8-O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt=":-O" title="8-O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-thumbsup.gif" alt="\\o/" title="\\o/" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o.O" title="o.O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O.o" title="O.o" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o_O" title="o_O" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O_o" title="O_o" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-cry.gif" alt=":\'(" title=":\'("/>',
'<img class="smiley" src="' . z_root() . '/images/smiley-foot-in-mouth.gif" alt=":-!" title=":-!" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-undecided.gif" alt=":-/" title=":-/" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-embarassed.gif" alt=":-[" title=":-[" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-cool.gif" alt="8-)" title="8-)" />',
'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":beer" title=":beer" />',
'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":homebrew" title=":homebrew" />',
'<img class="smiley" src="' . z_root() . '/images/coffee.gif" alt=":coffee" title=":coffee" />',
'<img class="smiley" src="' . z_root() . '/images/smiley-facepalm.gif" alt=":facepalm" title=":facepalm" />',
'<img class="smiley" src="' . z_root() . '/images/like.gif" alt=":like" title=":like" />',
'<img class="smiley" src="' . z_root() . '/images/dislike.gif" alt=":dislike" title=":dislike" />',
'<a href="http://friendica.com">~friendica <img class="smiley" src="' . z_root() . '/images/friendica-16.png" alt="~friendica" title="~friendica" /></a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red#" title="red#" />matrix</a>',
'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red#matrix" title="red#matrix" />matrix</a>'
);
$params = array('texts' => $texts, 'icons' => $icons, 'string' => $s);
call_hooks('smilie', $params);
if($sample) {
$s = '<div class="smiley-sample">';
for($x = 0; $x < count($params['texts']); $x ++) {
$s .= '<dl><dt>' . $params['texts'][$x] . '</dt><dd>' . $params['icons'][$x] . '</dd></dl>';
}
}
else {
$params['string'] = preg_replace_callback('/&lt;(3+)/','preg_heart',$params['string']);
$s = str_replace($params['texts'],$params['icons'],$params['string']);
}
$s = preg_replace_callback('/<pre>(.*?)<\/pre>/ism','smile_decode',$s);
$s = preg_replace_callback('/<code>(.*?)<\/code>/ism','smile_decode',$s);
return $s;
}}
function smile_encode($m) {
return(str_replace($m[1],base64url_encode($m[1]),$m[0]));
}
function smile_decode($m) {
return(str_replace($m[1],base64url_decode($m[1]),$m[0]));
}
/**
* expand <3333 to the correct number of hearts
*
* @param string $x
* @return string
*/
function preg_heart($x) {
$a = get_app();
if(strlen($x[1]) == 1)
return $x[0];
$t = '';
for($cnt = 0; $cnt < strlen($x[1]); $cnt ++)
$t .= '<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" />';
$r = str_replace($x[0],$t,$x[0]);
return $r;
}
if(! function_exists('day_translate')) {
/**
* Translate days and months names
@ -1549,7 +1396,7 @@ function prepare_text($text) {
if(stristr($text,'[nosmile]'))
$s = bbcode($text);
else
$s = smilies(bbcode($text));
$s = Smilies::replace(bbcode($text));
return trim($s);
}}

490
js/autocomplete.js Normal file
View file

@ -0,0 +1,490 @@
/**
* @brief Friendica people autocomplete
*
* require jQuery, jquery.textcomplete
*
* for further documentation look at:
* http://yuku-t.com/jquery-textcomplete/
*
* https://github.com/yuku-t/jquery-textcomplete/blob/master/doc/how_to_use.md
*/
function contact_search(term, callback, backend_url, type, mode) {
// Check if there is a conversation id to include the unkonwn contacts of the conversation
var conv_id = document.activeElement.id.match(/\d+$/);
// Check if there is a cached result that contains the same information we would get with a full server-side search
var bt = backend_url+type;
if(!(bt in contact_search.cache)) contact_search.cache[bt] = {};
var lterm = term.toLowerCase(); // Ignore case
for(var t in contact_search.cache[bt]) {
if(lterm.indexOf(t) >= 0) { // A more broad search has been performed already, so use those results
// Filter old results locally
var matching = contact_search.cache[bt][t].filter(function (x) { return (x.name.toLowerCase().indexOf(lterm) >= 0 || (typeof x.nick !== 'undefined' && x.nick.toLowerCase().indexOf(lterm) >= 0)); }); // Need to check that nick exists because groups don't have one
matching.unshift({forum:false, text: term, replace: term});
setTimeout(function() { callback(matching); } , 1); // Use "pseudo-thread" to avoid some problems
return;
}
}
var postdata = {
start:0,
count:100,
search:term,
type:type,
};
if(conv_id !== null)
postdata['conversation'] = conv_id[0];
if(mode !== null)
postdata['mode'] = mode;
$.ajax({
type:'POST',
url: backend_url,
data: postdata,
dataType: 'json',
success: function(data){
// Cache results if we got them all (more information would not improve results)
// data.count represents the maximum number of items
if(data.items.length -1 < data.count) {
contact_search.cache[bt][lterm] = data.items;
}
var items = data.items.slice(0);
items.unshift({taggable:false, text: term, replace: term});
callback(items);
},
}).fail(function () {callback([]); }); // Callback must be invoked even if something went wrong.
}
contact_search.cache = {};
function contact_format(item) {
// Show contact information if not explicitly told to show something else
if(typeof item.text === 'undefined') {
var desc = ((item.label) ? item.nick + ' ' + item.label : item.nick);
var forum = ((item.forum) ? 'forum' : '');
if(typeof desc === 'undefined') desc = '';
if(desc) desc = ' ('+desc+')';
return "<div class='{0}' title='{4}'><img class='acpopup-img' src='{1}'><span class='acpopup-contactname'>{2}</span><span class='acpopup-sub-text'>{3}</span><div class='clear'></div></div>".format(forum, item.photo, item.name, desc, item.link);
}
else
return "<div>" + item.text + "</div>";
}
function editor_replace(item) {
if(typeof item.replace !== 'undefined') {
return '$1$2' + item.replace;
}
// $2 ensures that prefix (@,@!) is preserved
var id = item.id;
// 16 chars of hash should be enough. Full hash could be used if it can be done in a visually appealing way.
// 16 chars is also the minimum length in the backend (otherwise it's interpreted as a local id).
if(id.length > 16)
id = item.id.substring(0,16);
return '$1$2' + item.nick.replace(' ', '') + '+' + id + ' ';
}
function basic_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.name+' ';
}
function trim_replace(item) {
if(typeof item.replace !== 'undefined')
return '$1'+item.replace;
return '$1'+item.name;
}
function submit_form(e) {
$(e).parents('form').submit();
}
function getWord(text, caretPos) {
var index = text.indexOf(caretPos);
var postText = text.substring(caretPos, caretPos+8);
if ((postText.indexOf("[/list]") > 0) || postText.indexOf("[/ul]") > 0 || postText.indexOf("[/ol]") > 0) {
return postText;
}
}
function getCaretPosition(ctrl) {
var CaretPos = 0; // IE Support
if (document.selection) {
ctrl.focus();
var Sel = document.selection.createRange();
Sel.moveStart('character', -ctrl.value.length);
CaretPos = Sel.text.length;
}
// Firefox support
else if (ctrl.selectionStart || ctrl.selectionStart == '0')
CaretPos = ctrl.selectionStart;
return (CaretPos);
}
function setCaretPosition(ctrl, pos){
if(ctrl.setSelectionRange) {
ctrl.focus();
ctrl.setSelectionRange(pos,pos);
}
else if (ctrl.createTextRange) {
var range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
function listNewLineAutocomplete(id) {
var text = document.getElementById(id);
var caretPos = getCaretPosition(text)
var word = getWord(text.value, caretPos);
if (word != null) {
var textBefore = text.value.substring(0, caretPos);
var textAfter = text.value.substring(caretPos, text.length);
$('#' + id).val(textBefore + '\r\n[*] ' + textAfter);
setCaretPosition(text, caretPos + 5);
return true;
}
}
function string2bb(element) {
if(element == 'bold') return 'b';
else if(element == 'italic') return 'i';
else if(element == 'underline') return 'u';
else if(element == 'overline') return 'o';
else if(element == 'strike') return 's';
else return element;
}
/**
* jQuery plugin 'editor_autocomplete'
*/
(function( $ ) {
$.fn.editor_autocomplete = function(backend_url) {
// Autocomplete contacts
contacts = {
match: /(^|\s)(@\!*)([^ \n]+)$/,
index: 3,
search: function(term, callback) { contact_search(term, callback, backend_url, 'c'); },
replace: editor_replace,
template: contact_format,
};
// Autocomplete smilies e.g. ":like"
smilies = {
match: /(^|\s)(:[a-z]{2,})$/,
index: 2,
search: function(term, callback) { $.getJSON('smilies/json').done(function(data) { callback($.map(data, function(entry) { return entry.text.indexOf(term) === 0 ? entry : null; })); }); },
template: function(item) { return item.icon + ' ' + item.text; },
replace: function(item) { return "$1" + item.text + ' '; },
};
this.attr('autocomplete','off');
this.textcomplete([contacts,smilies], {className:'acpopup', zIndex:10000});
};
})( jQuery );
/**
* jQuery plugin 'search_autocomplete'
*/
(function( $ ) {
$.fn.search_autocomplete = function(backend_url) {
// Autocomplete contacts
contacts = {
match: /(^@)([^\n]{2,})$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, 'x', 'contact'); },
replace: basic_replace,
template: contact_format,
};
// Autocomplete forum accounts
community = {
match: /(^!)([^\n]{2,})$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, 'x', 'community'); },
replace: basic_replace,
template: contact_format,
};
this.attr('autocomplete', 'off');
var a = this.textcomplete([contacts, community], {className:'acpopup', maxCount:100, zIndex: 10000, appendTo:'nav'});
a.on('textComplete:select', function(e, value, strategy) { submit_form(this); });
};
})( jQuery );
(function( $ ) {
$.fn.contact_autocomplete = function(backend_url, typ, autosubmit, onselect) {
if(typeof typ === 'undefined') typ = '';
if(typeof autosubmit === 'undefined') autosubmit = false;
// Autocomplete contacts
contacts = {
match: /(^)([^\n]+)$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, typ); },
replace: basic_replace,
template: contact_format,
};
this.attr('autocomplete','off');
var a = this.textcomplete([contacts], {className:'acpopup', zIndex:10000});
if(autosubmit)
a.on('textComplete:select', function(e,value,strategy) { submit_form(this); });
if(typeof onselect !== 'undefined')
a.on('textComplete:select', function(e, value, strategy) { onselect(value); });
};
})( jQuery );
(function( $ ) {
$.fn.name_autocomplete = function(backend_url, typ, autosubmit, onselect) {
if(typeof typ === 'undefined') typ = '';
if(typeof autosubmit === 'undefined') autosubmit = false;
// Autocomplete contacts
names = {
match: /(^)([^\n]+)$/,
index: 2,
search: function(term, callback) { contact_search(term, callback, backend_url, typ); },
replace: trim_replace,
template: contact_format,
};
this.attr('autocomplete','off');
var a = this.textcomplete([names], {className:'acpopup', zIndex:10000});
if(autosubmit)
a.on('textComplete:select', function(e,value,strategy) { submit_form(this); });
if(typeof onselect !== 'undefined')
a.on('textComplete:select', function(e, value, strategy) { onselect(value); });
};
})( jQuery );
(function( $ ) {
$.fn.bbco_autocomplete = function(type) {
if(type=='bbcode') {
var open_close_elements = ['bold', 'italic', 'underline', 'overline', 'strike', 'quote', 'code', 'spoiler', 'map', 'nobb', 'list', 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td', 'center', 'color', 'font', 'size'];
var open_elements = ['*', 'hr'];
var elements = open_close_elements.concat(open_elements);
}
bbco = {
match: /\[(\w*\**)$/,
search: function (term, callback) {
callback($.map(elements, function (element) {
return element.indexOf(term) === 0 ? element : null;
}));
},
index: 1,
replace: function (element) {
element = string2bb(element);
if(open_elements.indexOf(element) < 0) {
if(element === 'list' || element === 'ol' || element === 'ul') {
return ['\[' + element + '\]' + '\n\[*\] ', '\n\[/' + element + '\]'];
}
else if(element === 'table') {
return ['\[' + element + '\]' + '\n\[tr\]', '\[/tr\]\n\[/' + element + '\]'];
}
else {
return ['\[' + element + '\]', '\[/' + element + '\]'];
}
}
else {
return '\[' + element + '\] ';
}
}
};
this.attr('autocomplete','off');
var a = this.textcomplete([bbco], {className:'acpopup', zIndex:10000});
a.on('textComplete:select', function(e, value, strategy) { value; });
a.keypress(function(e){
e.stopImmediatePropagation();
if (e.keyCode == 13) {
var x = listNewLineAutocomplete(this.id);
if(x)
e.preventDefault();
}
});
};
})( jQuery );
/**
* Friendica people autocomplete legacy
* code which is needed for tinymce
*
* require jQuery, jquery.textareas
*/
function ACPopup(elm,backend_url){
this.idsel=-1;
this.element = elm;
this.searchText="";
this.ready=true;
this.kp_timer = false;
this.url = backend_url;
this.conversation_id = null;
var conv_id = this.element.id.match(/\d+$/);
if (conv_id) this.conversation_id = conv_id[0];
console.log("ACPopup elm id",this.element.id,"conversation",this.conversation_id);
var w = 530;
var h = 130;
if(tinyMCE.activeEditor == null) {
style = $(elm).offset();
w = $(elm).width();
h = $(elm).height();
}
else {
// I can't find an "official" way to get the element who get all
// this fraking thing that is tinyMCE.
// This code will broke again at some point...
var container = $(tinyMCE.activeEditor.getContainer()).find("table");
style = $(container).offset();
w = $(container).width();
h = $(container).height();
}
style.top=style.top+h;
style.width = w;
style.position = 'absolute';
/* style['max-height'] = '150px';
style.border = '1px solid red';
style.background = '#cccccc';
style.overflow = 'auto';
style['z-index'] = '100000';
*/
style.display = 'none';
this.cont = $("<div class='acpopup-mce'></div>");
this.cont.css(style);
$("body").append(this.cont);
}
ACPopup.prototype.close = function(){
$(this.cont).remove();
this.ready=false;
}
ACPopup.prototype.search = function(text){
var that = this;
this.searchText=text;
if (this.kp_timer) clearTimeout(this.kp_timer);
this.kp_timer = setTimeout( function(){that._search();}, 500);
}
ACPopup.prototype._search = function(){
console.log("_search");
var that = this;
var postdata = {
start:0,
count:100,
search:this.searchText,
type:'c',
conversation: this.conversation_id,
}
$.ajax({
type:'POST',
url: this.url,
data: postdata,
dataType: 'json',
success:function(data){
that.cont.html("");
if (data.tot>0){
that.cont.show();
$(data.items).each(function(){
var html = "<img src='{0}' height='16px' width='16px'>{1} ({2})".format(this.photo, this.name, this.nick);
var nick = this.nick.replace(' ','');
if (this.id!=='') nick += '+' + this.id;
that.add(html, nick + ' - ' + this.link);
});
} else {
that.cont.hide();
}
}
});
}
ACPopup.prototype.add = function(label, value){
var that=this;
var elm = $("<div class='acpopupitem' title='"+value+"'>"+label+"</div>");
elm.click(function(e){
t = $(this).attr('title').replace(new RegExp(' \- .*'),'');
if(typeof(that.element.container) === "undefined") {
el=$(that.element);
sel = el.getSelection();
sel.start = sel.start- that.searchText.length;
el.setSelection(sel.start,sel.end).replaceSelectedText(t+' ').collapseSelection(false);
that.close();
}
else {
txt = tinyMCE.activeEditor.getContent();
// alert(that.searchText + ':' + t);
newtxt = txt.replace('@' + that.searchText,'@' + t +' ');
tinyMCE.activeEditor.setContent(newtxt);
tinyMCE.activeEditor.focus();
that.close();
}
});
$(this.cont).append(elm);
}
ACPopup.prototype.onkey = function(event){
if (event.keyCode == '13') {
if(this.idsel>-1) {
this.cont.children()[this.idsel].click();
event.preventDefault();
}
else
this.close();
}
if (event.keyCode == '38') { //cursor up
cmax = this.cont.children().size()-1;
this.idsel--;
if (this.idsel<0) this.idsel=cmax;
event.preventDefault();
}
if (event.keyCode == '40' || event.keyCode == '9') { //cursor down
cmax = this.cont.children().size()-1;
this.idsel++;
if (this.idsel>cmax) this.idsel=0;
event.preventDefault();
}
if (event.keyCode == '38' || event.keyCode == '40' || event.keyCode == '9') {
this.cont.children().removeClass('selected');
$(this.cont.children()[this.idsel]).addClass('selected');
}
if (event.keyCode == '27') { //ESC
this.close();
}
}

View file

@ -1,203 +0,0 @@
/**
* Friendica people autocomplete
*
* require jQuery, jquery.textareas
*/
function ACPopup(elm,backend_url){
this.idsel=-1;
this.element = elm;
this.searchText="";
this.ready=true;
this.kp_timer = false;
this.url = backend_url;
this.conversation_id = null;
var conv_id = this.element.id.match(/\d+$/);
if (conv_id) this.conversation_id = conv_id[0];
console.log("ACPopup elm id",this.element.id,"conversation",this.conversation_id);
var w = 530;
var h = 130;
if(tinyMCE.activeEditor == null) {
style = $(elm).offset();
w = $(elm).width();
h = $(elm).height();
}
else {
// I can't find an "official" way to get the element who get all
// this fraking thing that is tinyMCE.
// This code will broke again at some point...
var container = $(tinyMCE.activeEditor.getContainer()).find("table");
style = $(container).offset();
w = $(container).width();
h = $(container).height();
}
style.top=style.top+h;
style.width = w;
style.position = 'absolute';
/* style['max-height'] = '150px';
style.border = '1px solid red';
style.background = '#cccccc';
style.overflow = 'auto';
style['z-index'] = '100000';
*/
style.display = 'none';
this.cont = $("<div class='acpopup'></div>");
this.cont.css(style);
$("body").append(this.cont);
}
ACPopup.prototype.close = function(){
$(this.cont).remove();
this.ready=false;
}
ACPopup.prototype.search = function(text){
var that = this;
this.searchText=text;
if (this.kp_timer) clearTimeout(this.kp_timer);
this.kp_timer = setTimeout( function(){that._search();}, 500);
}
ACPopup.prototype._search = function(){
console.log("_search");
var that = this;
var postdata = {
start:0,
count:100,
search:this.searchText,
type:'c',
conversation: this.conversation_id,
}
$.ajax({
type:'POST',
url: this.url,
data: postdata,
dataType: 'json',
success:function(data){
that.cont.html("");
if (data.tot>0){
that.cont.show();
$(data.items).each(function(){
var html = "<img src='{0}' height='16px' width='16px'>{1} ({2})".format(this.photo, this.name, this.nick);
var nick = this.nick.replace(' ','');
if (this.id!=='') nick += '+' + this.id;
that.add(html, nick + ' - ' + this.link);
});
} else {
that.cont.hide();
}
}
});
}
ACPopup.prototype.add = function(label, value){
var that=this;
var elm = $("<div class='acpopupitem' title='"+value+"'>"+label+"</div>");
elm.click(function(e){
t = $(this).attr('title').replace(new RegExp(' \- .*'),'');
if(typeof(that.element.container) === "undefined") {
el=$(that.element);
sel = el.getSelection();
sel.start = sel.start- that.searchText.length;
el.setSelection(sel.start,sel.end).replaceSelectedText(t+' ').collapseSelection(false);
that.close();
}
else {
txt = tinyMCE.activeEditor.getContent();
// alert(that.searchText + ':' + t);
newtxt = txt.replace('@' + that.searchText,'@' + t +' ');
tinyMCE.activeEditor.setContent(newtxt);
tinyMCE.activeEditor.focus();
that.close();
}
});
$(this.cont).append(elm);
}
ACPopup.prototype.onkey = function(event){
if (event.keyCode == '13') {
if(this.idsel>-1) {
this.cont.children()[this.idsel].click();
event.preventDefault();
}
else
this.close();
}
if (event.keyCode == '38') { //cursor up
cmax = this.cont.children().size()-1;
this.idsel--;
if (this.idsel<0) this.idsel=cmax;
event.preventDefault();
}
if (event.keyCode == '40' || event.keyCode == '9') { //cursor down
cmax = this.cont.children().size()-1;
this.idsel++;
if (this.idsel>cmax) this.idsel=0;
event.preventDefault();
}
if (event.keyCode == '38' || event.keyCode == '40' || event.keyCode == '9') {
this.cont.children().removeClass('selected');
$(this.cont.children()[this.idsel]).addClass('selected');
}
if (event.keyCode == '27') { //ESC
this.close();
}
}
function ContactAutocomplete(element,backend_url){
this.pattern=/@([^ \n]+)$/;
this.popup=null;
var that = this;
$(element).unbind('keydown');
$(element).unbind('keyup');
$(element).keydown(function(event){
if (that.popup!==null) that.popup.onkey(event);
});
$(element).keyup(function(event){
cpos = $(this).getSelection();
if (cpos.start==cpos.end){
match = $(this).val().substring(0,cpos.start).match(that.pattern);
if (match!==null){
if (that.popup===null){
that.popup = new ACPopup(this, backend_url);
}
if (that.popup.ready && match[1]!==that.popup.searchText) that.popup.search(match[1]);
if (!that.popup.ready) that.popup=null;
} else {
if (that.popup!==null) {that.popup.close(); that.popup=null;}
}
}
});
}
/**
* jQuery plugin 'contact_autocomplete'
*/
(function( $ ){
$.fn.contact_autocomplete = function(backend_url) {
this.each(function(){
new ContactAutocomplete(this, backend_url);
});
};
})( jQuery );

View file

@ -494,7 +494,9 @@
$('body').css('cursor', 'auto');
}
/* autocomplete @nicknames */
$(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
/* autocomplete bbcode */
+ $(".comment-edit-form textarea").bbco_autocomplete('bbcode');
// setup videos, since VideoJS won't take care of any loaded via AJAX
if(typeof videojs != 'undefined') videojs.autoSetup();

View file

@ -0,0 +1,335 @@
# Change Log
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/) by version 1.0.0.
This change log adheres to [keepachangelog.com](http://keepachangelog.com).
## [Unreleased]
## [1.3.3] - 2016-04-04
### Fixed
- Fix uncaught TypeError.
## [1.3.2] - 2016-03-27
### Fixed
- Fix dropdown position problem with `line-height: normal`.
## [1.3.1] - 2016-03-23
### Fixed
- Fix `input[type=search]` support.
## [1.3.0] - 2016-03-20
### Added
- Add optional "id" strategy parameter.
## [1.2.2] - 2016-03-19
### Fixed
- Remove dropdown element after `textcomplete('destroy')`.
- Skip search after pressing tab.
- Fix dropdown-menu positioning problem using textarea-caret package.
## [1.2.1] - 2016-03-14
### Fixed
- Build dist files.
## [1.2.0] - 2016-03-14
### Added
- Support `input[type=search]` ([#236](https://github.com/yuku-t/jquery-textcomplete/pull/236))
## [1.1.0] - 2016-03-10
### Added
- Add the ability to insert HTML into a "contenteditable" field. ([#217](https://github.com/yuku-t/jquery-textcomplete/pull/217))
### Fixed
- Position relative to appendTo element. ([#234](https://github.com/yuku-t/jquery-textcomplete/pull/234))
- Avoid dropdown bumping into right edge of window. ([#235](https://github.com/yuku-t/jquery-textcomplete/pull/235))
- Fix top position issue when window is scrolled up and parents has fix position. ([#229](https://github.com/yuku-t/jquery-textcomplete/pull/229))
## [1.0.0] - 2016-02-29
### Changed
- Adheres keepachangelog.com.
## [0.8.2] - 2016-02-29
### Added
- Add deactivate method to Completer. ([#233](https://github.com/yuku-t/jquery-textcomplete/pull/233))
## [0.8.1] - 2015-10-22
### Added
- Add condition to ignore skipUnchangedTerm for empty text. ([#210](https://github.com/yuku-t/jquery-textcomplete/pull/210))
## [0.8.0] - 2015-08-31
### Changed
- If undefined is returned from a replace callback dont replace the text. ([#204](https://github.com/yuku-t/jquery-textcomplete/pull/204))
## [0.7.3] - 2015-08-27
### Added
- Add `Strategy#el` and `Strategy#$el` which returns current input/textarea element and corresponding jquery object respectively.
## [0.7.2] - 2015-08-26
### Fixed
- Reset \_term after selected ([#170](https://github.com/yuku-t/jquery-textcomplete/pull/170))
## [0.7.1] - 2015-08-19
### Changed
- Remove RTL support because of some bugs.
## [0.7.0] - 2015-07-02
### Add
- Add support for a "no results" message like the header/footer. ([#179](https://github.com/yuku-t/jquery-textcomplete/pull/179))
- Yield the search term to the template function. ([#177](https://github.com/yuku-t/jquery-textcomplete/pull/177))
- Add amd wrapper. ([#167](https://github.com/yuku-t/jquery-textcomplete/pull/167))
- Add touch devices support. ([#163](https://github.com/yuku-t/jquery-textcomplete/pull/163))
### Changed
- Stop sharing a dropdown element.
## [0.6.1] - 2015-06-30
### Fixed
- Fix bug that Dropdown.\_fitToBottom does not consider window scroll
## [0.6.0] - 2015-06-30
### Added
- Now dropdown elements have "textcomplete-dropdown" class.
## [0.5.2] - 2015-06-29
### Fixed
- Keep dropdown list in browser window. ([#172](https://github.com/yuku-t/jquery-textcomplete/pull/172))
## [0.5.1] - 2015-06-08
### Changed
- Now a replace function is invoked with a user event.
## [0.5.0] - 2015-06-08
### Added
- Support `onKeydown` option.
## [0.4.0] - 2015-03-10
### Added
- Publish to [npmjs](https://www.npmjs.com/package/jquery-textcomplete).
- Support giving a function which returns a regexp to `match` option for dynamic matching.
## [0.3.9] - 2015-03-03
### Fixed
- Deactivate dropdown on escape. ([#155](https://github.com/yuku-t/jquery-textcomplete/pull/155))
## [0.3.8] - 2015-02-26
### Fixed
- Fix completion with enter key. ([#154](https://github.com/yuku-t/jquery-textcomplete/pull/154))
- Fix empty span node is inserted. ([#153](https://github.com/yuku-t/jquery-textcomplete/pull/153))
## [0.3.7] - 2015-01-21
### Added
- Support input([type=text]. [#149](https://github.com/yuku-t/jquery-textcomplete/pull/149))
## [0.3.6] - 2014-12-11
### Added
- Support element.contentEditable compatibility check. ([#147](https://github.com/yuku-t/jquery-textcomplete/pull/147))
### Fixed
- Fixes the fire function for events with additional parameters. ([#145](https://github.com/yuku-t/jquery-textcomplete/pull/145))
## [0.3.5] - 2014-12-11
### Added
- Adds functionality to complete selection on space key. ([#141](https://github.com/yuku-t/jquery-textcomplete/pull/141))
### Fixed
- Loading script in head and destroy method bugfixes. ([#143](https://github.com/yuku-t/jquery-textcomplete/pull/143))
## [0.3.4] - 2014-12-03
### Fixed
- Fix error when destroy is called before the field is focused. ([#138](https://github.com/yuku-t/jquery-textcomplete/pull/138))
- Fix IE bug where it would only trigger when tha carrot was at the end of the line. ([#133](https://github.com/yuku-t/jquery-textcomplete/pull/133))
## [0.3.3] - 2014-09-25
### Added
- Add `className` option.
- Add `match` as the third argument of a search function.
### Fixed
- Ignore `.textcomplete('destory')` on non-initialized elements. ([#118](https://github.com/yuku-t/jquery-textcomplete/pull/118))
- Trigger completer with the current text by default. ([#119](https://github.com/yuku-t/jquery-textcomplete/pull/119))
- Hide dropdown before destroying it. ([#120](https://github.com/yuku-t/jquery-textcomplete/pull/120))
- Don't throw an exception even if a jquery click event is manually triggered. ([#121](https://github.com/yuku-t/jquery-textcomplete/pull/121))
## [0.3.2] - 2014-09-16
### Added
- Add `IETextarea` adapter which supports IE8
- Add `idProperty` option.
- Add `adapter` option.
### Changed
- Rename `Input` as `Adapter`.
## [0.3.1] - 2014-09-10
### Added
- Add `context` strategy option.
- Add `debounce` option.
### Changed
- Recycle `.dropdown-menu` element if available.
## [0.3.0] - 2014-09-10
### Added
- Consider the `tab-size` of textarea.
- Add `zIndex` option.
### Fixed
- Revive `header` and `footer` options.
- Revive `height` option.
## [0.3.0-beta2] - 2014-09-09
### Fixed
- Make sure that all demos work fine.
## [0.3.0-beta1] - 2014-08-31
### Fixed
- Huge refactoring.
## [0.2.6] - 2014-08-16
### Fixed
- Repair contenteditable.
## [0.2.5] - 2014-08-07
### Added
- Enhance contenteditable support. ([#98](https://github.com/yuku-t/jquery-textcomplete/pull/98))
- Support absolute left/right placement. ([#96](https://github.com/yuku-t/jquery-textcomplete/pull/96))
- Support absolute height, scrollbar, pageup and pagedown. ([#87](https://github.com/yuku-t/jquery-textcomplete/pull/87))
## [0.2.4] - 2014-07-02
### Fixed
- Fix horizonal position on contentEditable elements. ([#92](https://github.com/yuku-t/jquery-textcomplete/pull/92))
## [0.2.3] - 2014-06-24
### Added
- Option to supply list view position function. ([#88](https://github.com/yuku-t/jquery-textcomplete/pull/88))
## [0.2.2] - 2014-06-08
### Added
- Append dropdown element to body element by default.
- Tiny refactoring. [#84]
- Ignore tab key when modifier keys are being pushed. ([#85](https://github.com/yuku-t/jquery-textcomplete/pull/85))
- Manual triggering.
## [0.2.1] - 2014-05-15
### Added
- Support `appendTo` option.
- `header` and `footer` supports a function.
### Changed
- Remove textcomplate-wrapper element.
## [0.2.0] - 2014-05-02
### Added
- Contenteditable support.
- Several bugfixes.
- Support `header` and `footer` setting.
## [0.1.4.1] - 2014-04-04
### Added
- Support placement option.
- Emacs-style prev/next keybindings.
- Replay searchFunc for the last term on slow network env.
### Fixed
- Several bugfixes.
## [0.1.3] - 2014-04-07
### Added
- Support RTL positioning.
### Fixed
- Several bugfixes.
## [0.1.2] - 2014-02-08
### Added
- Enable to append strategies on the fly.
- Enable to stop autocompleting.
- Enable to apply multiple textareas at once.
- Don't show popup on pressing arrow up and down keys.
- Hide dropdown by pressing ESC key.
- Prevent showing a dropdown when it just autocompleted.
## [0.1.1] - 2014-02-02
### Added
- Introduce `textComplete:show`, `textComplete:hide` and `textComplete:select` events.
## [0.1.0] - 2013-10-28
### Added
- Now strategies argument is an Array of strategy objects.
## [0.0.4] - 2013-10-28
### Added
- Up and Down arrows cycle instead of exit.
- Support Zepto.
- Support jQuery.overlay.
### Fixed
- Several bugfixes.
## [0.0.3] - 2013-09-11
### Added
- Some performance improvement.
- Implement lazy callbacking on search function.
## [0.0.2] - 2013-09-08
### Added
- Support IE8.
- Some performance improvement.
- Implement cache option.
## 0.0.1 - 2013-09-02
### Added
- Initial release.
[Unreleased]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.3...HEAD
[1.3.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.2...v1.3.3
[1.3.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.1...v1.3.2
[1.3.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.3.0...v1.3.1
[1.3.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.2.2...v1.3.0
[1.2.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.2.1...v1.2.2
[1.2.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.2.0...v1.2.1
[1.2.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.8.2...v1.0.0
[0.8.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.8.1...v0.8.2
[0.8.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.8.0...v0.8.1
[0.8.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.3...v0.8.0
[0.7.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.2...v0.7.3
[0.7.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.1...v0.7.2
[0.7.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.7.0...v0.7.1
[0.7.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.6.1...v0.7.0
[0.6.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.5.2...v0.6.0
[0.5.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.9...v0.4.0
[0.3.9]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.8...v0.3.9
[0.3.8]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.7...v0.3.8
[0.3.7]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.6...v0.3.7
[0.3.6]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.5...v0.3.6
[0.3.5]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.4...v0.3.5
[0.3.4]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.3...v0.3.4
[0.3.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.2...v0.3.3
[0.3.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.0-beta2...v0.3.0
[0.3.0-beta2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.3.0-beta1...v0.3.0-beta2
[0.3.0-beta1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.6...v0.3.0-beta1
[0.2.6]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.4.1...v0.2.0
[0.1.4.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.3...v0.1.4.1
[0.1.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.4...v0.1.0
[0.0.4]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.3...v0.0.4
[0.0.3]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.2...v0.0.3
[0.0.2]: https://github.com/yuku-t/jquery-textcomplete/compare/v0.0.1...v0.0.2

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013-2014 Yuku Takahashi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,54 @@
Autocomplete for Textarea
=========================
[![npm version](https://badge.fury.io/js/jquery-textcomplete.svg)](http://badge.fury.io/js/jquery-textcomplete)
[![Bower version](https://badge.fury.io/bo/jquery-textcomplete.svg)](http://badge.fury.io/bo/jquery-textcomplete)
[![Analytics](https://ga-beacon.appspot.com/UA-4932407-14/jquery-textcomplete/readme)](https://github.com/igrigorik/ga-beacon)
Introduces autocompleting power to textareas, like a GitHub comment form has.
![Demo](http://yuku-t.com/jquery-textcomplete/media/images/demo.gif)
[Demo](http://yuku-t.com/jquery-textcomplete/).
Synopsis
--------
```js
$('textarea').textcomplete([{
match: /(^|\b)(\w{2,})$/,
search: function (term, callback) {
var words = ['google', 'facebook', 'github', 'microsoft', 'yahoo'];
callback($.map(words, function (word) {
return word.indexOf(term) === 0 ? word : null;
}));
},
replace: function (word) {
return word + ' ';
}
}]);
```
Dependencies
------------
- jQuery (>= 1.7.0) OR Zepto (>= 1.0)
Documents
---------
See [doc](https://github.com/yuku-t/jquery-textcomplete/tree/master/doc) dir.
License
-------
Licensed under the MIT License.
Credits
-------
### Contributors
Patches and code improvements were contributed by:
https://github.com/yuku-t/jquery-textcomplete/graphs/contributors

View file

@ -0,0 +1,33 @@
/* Sample */
.dropdown-menu {
border: 1px solid #ddd;
background-color: white;
}
.dropdown-menu li {
border-top: 1px solid #ddd;
padding: 2px 5px;
}
.dropdown-menu li:first-child {
border-top: none;
}
.dropdown-menu li:hover,
.dropdown-menu .active {
background-color: rgb(110, 183, 219);
}
/* SHOULD not modify */
.dropdown-menu {
list-style: none;
padding: 0;
margin: 0;
}
.dropdown-menu a:hover {
cursor: pointer;
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +0,0 @@
This is jquery.autocomplete from
http://www.devbridge.com/projects/autocomplete/jquery/

View file

@ -1,395 +0,0 @@
/**
* Ajax Autocomplete for jQuery, version 1.1.3
* (c) 2010 Tomas Kirda
*
* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
* For details, see the web site: http://www.devbridge.com/projects/autocomplete/jquery/
*
* Last Review: 04/19/2010
* Heavily modified for contact completion in Friendica (add photos, hover tips. etc.) 11-May-2012 mike@macgirvin.com
*/
/*jslint onevar: true, evil: true, nomen: true, eqeqeq: true, bitwise: true, regexp: true, newcap: true, immed: true */
/*global window: true, document: true, clearInterval: true, setInterval: true, jQuery: true */
(function($) {
var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');
function fnFormatResult(value, data, currentValue) {
var pattern = '(' + currentValue.replace(reEscape, '\\$1') + ')';
return value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
}
function Autocomplete(el, options) {
this.el = $(el);
this.el.attr('autocomplete', 'off');
this.suggestions = [];
this.data = [];
this.badQueries = [];
this.selectedIndex = -1;
this.currentValue = this.el.val();
this.intervalId = 0;
this.cachedResponse = [];
this.onChangeInterval = null;
this.ignoreValueChange = false;
this.serviceUrl = options.serviceUrl;
this.isLocal = false;
this.options = {
autoSubmit: false,
minChars: 1,
maxHeight: 300,
deferRequestBy: 0,
width: 0,
highlight: true,
params: {},
fnFormatResult: fnFormatResult,
delimiter: null,
zIndex: 9999
};
this.initialize();
this.setOptions(options);
}
$.fn.autocomplete = function(options) {
return new Autocomplete(this.get(0)||$('<input />'), options);
};
Autocomplete.prototype = {
killerFn: null,
initialize: function() {
var me, uid, autocompleteElId;
me = this;
uid = Math.floor(Math.random()*0x100000).toString(16);
autocompleteElId = 'Autocomplete_' + uid;
this.killerFn = function(e) {
if ($(e.target).parents('.autocomplete').size() === 0) {
me.killSuggestions();
me.disableKillerFn();
}
};
if (!this.options.width) { this.options.width = this.el.width(); }
this.mainContainerId = 'AutocompleteContainter_' + uid;
$('<div id="' + this.mainContainerId + '" style="position:absolute;z-index:9999;"><div class="autocomplete-w1"><div class="autocomplete" id="' + autocompleteElId + '" style="display:none; width:300px;"></div></div></div>').appendTo('body');
this.container = $('#' + autocompleteElId);
this.fixPosition();
if (window.opera) {
this.el.keypress(function(e) { me.onKeyPress(e); });
} else {
this.el.keydown(function(e) { me.onKeyPress(e); });
}
this.el.keyup(function(e) { me.onKeyUp(e); });
this.el.blur(function() { me.enableKillerFn(); });
this.el.focus(function() { me.fixPosition(); });
},
setOptions: function(options){
var o = this.options;
$.extend(o, options);
if(o.lookup){
this.isLocal = true;
if($.isArray(o.lookup)){ o.lookup = { suggestions:o.lookup, data:[] }; }
}
$('#'+this.mainContainerId).css({ zIndex:o.zIndex });
this.container.css({ maxHeight: o.maxHeight + 'px', width:o.width });
},
clearCache: function(){
this.cachedResponse = [];
this.badQueries = [];
},
disable: function(){
this.disabled = true;
},
enable: function(){
this.disabled = false;
},
fixPosition: function() {
var offset = this.el.offset();
$('#' + this.mainContainerId).css({ top: (offset.top + this.el.innerHeight()) + 'px', left: offset.left + 'px' });
},
enableKillerFn: function() {
var me = this;
$(document).bind('click', me.killerFn);
},
disableKillerFn: function() {
var me = this;
$(document).unbind('click', me.killerFn);
},
killSuggestions: function() {
var me = this;
this.stopKillSuggestions();
this.intervalId = window.setInterval(function() { me.hide(); me.stopKillSuggestions(); }, 300);
},
stopKillSuggestions: function() {
window.clearInterval(this.intervalId);
},
onKeyPress: function(e) {
if (this.disabled || !this.enabled) { return; }
// return will exit the function
// and event will not be prevented
switch (e.keyCode) {
case 27: //KEY_ESC:
this.el.val(this.currentValue);
this.hide();
break;
case 9: //KEY_TAB:
case 13: //KEY_RETURN:
if (this.selectedIndex === -1) {
this.hide();
return;
}
this.select(this.selectedIndex);
if(e.keyCode === 9){ return; }
break;
case 38: //KEY_UP:
this.moveUp();
break;
case 40: //KEY_DOWN:
this.moveDown();
break;
default:
return;
}
e.stopImmediatePropagation();
e.preventDefault();
},
onKeyUp: function(e) {
if(this.disabled){ return; }
switch (e.keyCode) {
case 38: //KEY_UP:
case 40: //KEY_DOWN:
return;
}
clearInterval(this.onChangeInterval);
if (this.currentValue !== this.el.val()) {
if (this.options.deferRequestBy > 0) {
// Defer lookup in case when value changes very quickly:
var me = this;
this.onChangeInterval = setInterval(function() { me.onValueChange(); }, this.options.deferRequestBy);
} else {
this.onValueChange();
}
}
},
onValueChange: function() {
clearInterval(this.onChangeInterval);
this.currentValue = this.el.val();
var q = this.getQuery(this.currentValue);
this.selectedIndex = -1;
if (this.ignoreValueChange) {
this.ignoreValueChange = false;
return;
}
if (q === '' || q.length < this.options.minChars) {
this.hide();
} else {
this.getSuggestions(q);
}
},
getQuery: function(val) {
var d, arr;
d = this.options.delimiter;
if (!d) { return $.trim(val); }
arr = val.split(d);
return $.trim(arr[arr.length - 1]);
},
getSuggestionsLocal: function(q) {
var ret, arr, len, val, i;
arr = this.options.lookup;
len = arr.suggestions.length;
ret = { suggestions:[], data:[] };
q = q.toLowerCase();
for(i=0; i< len; i++){
val = arr.suggestions[i];
if(val.toLowerCase().indexOf(q) === 0){
ret.suggestions.push(val);
ret.data.push(arr.data[i]);
}
}
return ret;
},
getSuggestions: function(q) {
var cr, me;
cr = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q];
if (cr && $.isArray(cr.suggestions)) {
this.suggestions = cr.suggestions;
this.data = cr.data;
this.suggest();
} else if (!this.isBadQuery(q)) {
me = this;
me.options.params.query = q;
$.get(this.serviceUrl, me.options.params, function(txt) { me.processResponse(txt); }, 'text');
}
},
isBadQuery: function(q) {
var i = this.badQueries.length;
while (i--) {
if (q.indexOf(this.badQueries[i]) === 0) { return true; }
}
return false;
},
hide: function() {
this.enabled = false;
this.selectedIndex = -1;
this.container.hide();
},
suggest: function() {
if (this.suggestions.length === 0) {
this.hide();
return;
}
var me, len, div, f, v, i, s, mOver, mClick, l, img;
me = this;
len = this.suggestions.length;
f = this.options.fnFormatResult;
v = this.getQuery(this.currentValue);
mOver = function(xi) { return function() { me.activate(xi); }; };
mClick = function(xi) { return function() { me.select(xi); }; };
this.container.hide().empty();
for (i = 0; i < len; i++) {
s = this.suggestions[i];
l = this.links[i];
img = '<img height="24" width="24" src="' + this.photos[i] + '" alt="' + s + '" />&nbsp;';
div = $((me.selectedIndex === i ? '<div class="selected"' : '<div') + ' title="' + l + '">' + img + f(s, this.data[i], v) + '</div>');
div.mouseover(mOver(i));
div.click(mClick(i));
this.container.append(div);
}
this.enabled = true;
this.container.show();
},
processResponse: function(text) {
var response;
try {
response = eval('(' + text + ')');
} catch (err) { return; }
if (!$.isArray(response.data)) { response.data = []; }
if(!this.options.noCache){
this.cachedResponse[response.query] = response;
if (response.suggestions.length === 0) { this.badQueries.push(response.query); }
}
if (response.query === this.getQuery(this.currentValue)) {
this.photos = response.photos;
this.links = response.links;
this.suggestions = response.suggestions;
this.data = response.data;
this.suggest();
}
},
activate: function(index) {
var divs, activeItem;
divs = this.container.children();
// Clear previous selection:
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
$(divs.get(this.selectedIndex)).removeClass();
}
this.selectedIndex = index;
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
activeItem = divs.get(this.selectedIndex);
$(activeItem).addClass('selected');
}
return activeItem;
},
deactivate: function(div, index) {
div.className = '';
if (this.selectedIndex === index) { this.selectedIndex = -1; }
},
select: function(i) {
var selectedValue, f;
selectedValue = this.suggestions[i];
if (selectedValue) {
this.el.val(selectedValue);
if (this.options.autoSubmit) {
f = this.el.parents('form');
if (f.length > 0) { f.get(0).submit(); }
}
this.ignoreValueChange = true;
this.hide();
this.onSelect(i);
}
},
moveUp: function() {
if (this.selectedIndex === -1) { return; }
if (this.selectedIndex === 0) {
this.container.children().get(0).className = '';
this.selectedIndex = -1;
this.el.val(this.currentValue);
return;
}
this.adjustScroll(this.selectedIndex - 1);
},
moveDown: function() {
if (this.selectedIndex === (this.suggestions.length - 1)) { return; }
this.adjustScroll(this.selectedIndex + 1);
},
adjustScroll: function(i) {
var activeItem, offsetTop, upperBound, lowerBound;
activeItem = this.activate(i);
offsetTop = activeItem.offsetTop;
upperBound = this.container.scrollTop();
lowerBound = upperBound + this.options.maxHeight - 25;
if (offsetTop < upperBound) {
this.container.scrollTop(offsetTop);
} else if (offsetTop > lowerBound) {
this.container.scrollTop(offsetTop - this.options.maxHeight + 25);
}
this.el.val(this.getValue(this.suggestions[i]));
},
onSelect: function(i) {
var me, fn, s, d;
me = this;
fn = me.options.onSelect;
s = me.suggestions[i];
d = me.data[i];
me.el.val(me.getValue(s));
if ($.isFunction(fn)) { fn(s, d, me.el); }
},
getValue: function(value){
var del, currVal, arr, me;
me = this;
del = me.options.delimiter;
if (!del) { return value; }
currVal = me.currentValue;
arr = currVal.split(del);
if (arr.length === 1) { return value; }
return currVal.substr(0, currVal.length - arr[arr.length - 1].length) + value;
}
};
}(jQuery));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,390 +0,0 @@
/**
* Ajax Autocomplete for jQuery, version 1.1.3
* (c) 2010 Tomas Kirda
*
* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
* For details, see the web site: http://www.devbridge.com/projects/autocomplete/jquery/
*
* Last Review: 04/19/2010
*/
/*jslint onevar: true, evil: true, nomen: true, eqeqeq: true, bitwise: true, regexp: true, newcap: true, immed: true */
/*global window: true, document: true, clearInterval: true, setInterval: true, jQuery: true */
(function($) {
var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');
function fnFormatResult(value, data, currentValue) {
var pattern = '(' + currentValue.replace(reEscape, '\\$1') + ')';
return value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
}
function Autocomplete(el, options) {
this.el = $(el);
this.el.attr('autocomplete', 'off');
this.suggestions = [];
this.data = [];
this.badQueries = [];
this.selectedIndex = -1;
this.currentValue = this.el.val();
this.intervalId = 0;
this.cachedResponse = [];
this.onChangeInterval = null;
this.ignoreValueChange = false;
this.serviceUrl = options.serviceUrl;
this.isLocal = false;
this.options = {
autoSubmit: false,
minChars: 1,
maxHeight: 300,
deferRequestBy: 0,
width: 0,
highlight: true,
params: {},
fnFormatResult: fnFormatResult,
delimiter: null,
zIndex: 9999
};
this.initialize();
this.setOptions(options);
}
$.fn.autocomplete = function(options) {
return new Autocomplete(this.get(0)||$('<input />'), options);
};
Autocomplete.prototype = {
killerFn: null,
initialize: function() {
var me, uid, autocompleteElId;
me = this;
uid = Math.floor(Math.random()*0x100000).toString(16);
autocompleteElId = 'Autocomplete_' + uid;
this.killerFn = function(e) {
if ($(e.target).parents('.autocomplete').size() === 0) {
me.killSuggestions();
me.disableKillerFn();
}
};
if (!this.options.width) { this.options.width = this.el.width(); }
this.mainContainerId = 'AutocompleteContainter_' + uid;
$('<div id="' + this.mainContainerId + '" style="position:absolute;z-index:9999;"><div class="autocomplete-w1"><div class="autocomplete" id="' + autocompleteElId + '" style="display:none; width:300px;"></div></div></div>').appendTo('body');
this.container = $('#' + autocompleteElId);
this.fixPosition();
if (window.opera) {
this.el.keypress(function(e) { me.onKeyPress(e); });
} else {
this.el.keydown(function(e) { me.onKeyPress(e); });
}
this.el.keyup(function(e) { me.onKeyUp(e); });
this.el.blur(function() { me.enableKillerFn(); });
this.el.focus(function() { me.fixPosition(); });
},
setOptions: function(options){
var o = this.options;
$.extend(o, options);
if(o.lookup){
this.isLocal = true;
if($.isArray(o.lookup)){ o.lookup = { suggestions:o.lookup, data:[] }; }
}
$('#'+this.mainContainerId).css({ zIndex:o.zIndex });
this.container.css({ maxHeight: o.maxHeight + 'px', width:o.width });
},
clearCache: function(){
this.cachedResponse = [];
this.badQueries = [];
},
disable: function(){
this.disabled = true;
},
enable: function(){
this.disabled = false;
},
fixPosition: function() {
var offset = this.el.offset();
$('#' + this.mainContainerId).css({ top: (offset.top + this.el.innerHeight()) + 'px', left: offset.left + 'px' });
},
enableKillerFn: function() {
var me = this;
$(document).bind('click', me.killerFn);
},
disableKillerFn: function() {
var me = this;
$(document).unbind('click', me.killerFn);
},
killSuggestions: function() {
var me = this;
this.stopKillSuggestions();
this.intervalId = window.setInterval(function() { me.hide(); me.stopKillSuggestions(); }, 300);
},
stopKillSuggestions: function() {
window.clearInterval(this.intervalId);
},
onKeyPress: function(e) {
if (this.disabled || !this.enabled) { return; }
// return will exit the function
// and event will not be prevented
switch (e.keyCode) {
case 27: //KEY_ESC:
this.el.val(this.currentValue);
this.hide();
break;
case 9: //KEY_TAB:
case 13: //KEY_RETURN:
if (this.selectedIndex === -1) {
this.hide();
return;
}
this.select(this.selectedIndex);
if(e.keyCode === 9){ return; }
break;
case 38: //KEY_UP:
this.moveUp();
break;
case 40: //KEY_DOWN:
this.moveDown();
break;
default:
return;
}
e.stopImmediatePropagation();
e.preventDefault();
},
onKeyUp: function(e) {
if(this.disabled){ return; }
switch (e.keyCode) {
case 38: //KEY_UP:
case 40: //KEY_DOWN:
return;
}
clearInterval(this.onChangeInterval);
if (this.currentValue !== this.el.val()) {
if (this.options.deferRequestBy > 0) {
// Defer lookup in case when value changes very quickly:
var me = this;
this.onChangeInterval = setInterval(function() { me.onValueChange(); }, this.options.deferRequestBy);
} else {
this.onValueChange();
}
}
},
onValueChange: function() {
clearInterval(this.onChangeInterval);
this.currentValue = this.el.val();
var q = this.getQuery(this.currentValue);
this.selectedIndex = -1;
if (this.ignoreValueChange) {
this.ignoreValueChange = false;
return;
}
if (q === '' || q.length < this.options.minChars) {
this.hide();
} else {
this.getSuggestions(q);
}
},
getQuery: function(val) {
var d, arr;
d = this.options.delimiter;
if (!d) { return $.trim(val); }
arr = val.split(d);
return $.trim(arr[arr.length - 1]);
},
getSuggestionsLocal: function(q) {
var ret, arr, len, val, i;
arr = this.options.lookup;
len = arr.suggestions.length;
ret = { suggestions:[], data:[] };
q = q.toLowerCase();
for(i=0; i< len; i++){
val = arr.suggestions[i];
if(val.toLowerCase().indexOf(q) === 0){
ret.suggestions.push(val);
ret.data.push(arr.data[i]);
}
}
return ret;
},
getSuggestions: function(q) {
var cr, me;
cr = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q];
if (cr && $.isArray(cr.suggestions)) {
this.suggestions = cr.suggestions;
this.data = cr.data;
this.suggest();
} else if (!this.isBadQuery(q)) {
me = this;
me.options.params.query = q;
$.get(this.serviceUrl, me.options.params, function(txt) { me.processResponse(txt); }, 'text');
}
},
isBadQuery: function(q) {
var i = this.badQueries.length;
while (i--) {
if (q.indexOf(this.badQueries[i]) === 0) { return true; }
}
return false;
},
hide: function() {
this.enabled = false;
this.selectedIndex = -1;
this.container.hide();
},
suggest: function() {
if (this.suggestions.length === 0) {
this.hide();
return;
}
var me, len, div, f, v, i, s, mOver, mClick;
me = this;
len = this.suggestions.length;
f = this.options.fnFormatResult;
v = this.getQuery(this.currentValue);
mOver = function(xi) { return function() { me.activate(xi); }; };
mClick = function(xi) { return function() { me.select(xi); }; };
this.container.hide().empty();
for (i = 0; i < len; i++) {
s = this.suggestions[i];
div = $((me.selectedIndex === i ? '<div class="selected"' : '<div') + ' title="' + s + '">' + f(s, this.data[i], v) + '</div>');
div.mouseover(mOver(i));
div.click(mClick(i));
this.container.append(div);
}
this.enabled = true;
this.container.show();
},
processResponse: function(text) {
var response;
try {
response = eval('(' + text + ')');
} catch (err) { return; }
if (!$.isArray(response.data)) { response.data = []; }
if(!this.options.noCache){
this.cachedResponse[response.query] = response;
if (response.suggestions.length === 0) { this.badQueries.push(response.query); }
}
if (response.query === this.getQuery(this.currentValue)) {
this.suggestions = response.suggestions;
this.data = response.data;
this.suggest();
}
},
activate: function(index) {
var divs, activeItem;
divs = this.container.children();
// Clear previous selection:
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
$(divs.get(this.selectedIndex)).removeClass();
}
this.selectedIndex = index;
if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
activeItem = divs.get(this.selectedIndex);
$(activeItem).addClass('selected');
}
return activeItem;
},
deactivate: function(div, index) {
div.className = '';
if (this.selectedIndex === index) { this.selectedIndex = -1; }
},
select: function(i) {
var selectedValue, f;
selectedValue = this.suggestions[i];
if (selectedValue) {
this.el.val(selectedValue);
if (this.options.autoSubmit) {
f = this.el.parents('form');
if (f.length > 0) { f.get(0).submit(); }
}
this.ignoreValueChange = true;
this.hide();
this.onSelect(i);
}
},
moveUp: function() {
if (this.selectedIndex === -1) { return; }
if (this.selectedIndex === 0) {
this.container.children().get(0).className = '';
this.selectedIndex = -1;
this.el.val(this.currentValue);
return;
}
this.adjustScroll(this.selectedIndex - 1);
},
moveDown: function() {
if (this.selectedIndex === (this.suggestions.length - 1)) { return; }
this.adjustScroll(this.selectedIndex + 1);
},
adjustScroll: function(i) {
var activeItem, offsetTop, upperBound, lowerBound;
activeItem = this.activate(i);
offsetTop = activeItem.offsetTop;
upperBound = this.container.scrollTop();
lowerBound = upperBound + this.options.maxHeight - 25;
if (offsetTop < upperBound) {
this.container.scrollTop(offsetTop);
} else if (offsetTop > lowerBound) {
this.container.scrollTop(offsetTop - this.options.maxHeight + 25);
}
this.el.val(this.getValue(this.suggestions[i]));
},
onSelect: function(i) {
var me, fn, s, d;
me = this;
fn = me.options.onSelect;
s = me.suggestions[i];
d = me.data[i];
me.el.val(me.getValue(s));
if ($.isFunction(fn)) { fn(s, d, me.el); }
},
getValue: function(value){
var del, currVal, arr, me;
me = this;
del = me.options.delimiter;
if (!del) { return value; }
currVal = me.currentValue;
arr = currVal.split(del);
if (arr.length === 1) { return value; }
return currVal.substr(0, currVal.length - arr[arr.length - 1].length) + value;
}
};
}(jQuery));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -1,6 +0,0 @@

.autocomplete-w1 { background:url(img/shadow.png) no-repeat bottom right; position:absolute; top:0px; left:0px; margin:8px 0 0 6px; /* IE6 fix: */ _background:none; _margin:0; }
.autocomplete { border:1px solid #999; background:#FFF; cursor:default; text-align:left; max-height:350px; overflow:auto; margin:-6px 6px 6px -6px; /* IE6 specific: */ _height:350px; _margin:0; _overflow-x:hidden; }
.autocomplete .selected { background:#F0F0F0; }
.autocomplete div { padding:2px 5px; white-space:nowrap; }
.autocomplete strong { font-weight:normal; color:#3399FF; }

View file

@ -1,3 +1,21 @@
<?php
function smilies_content(&$a) { return smilies('',true); }
/**
* @file mod/smilies.php
*/
require_once("include/Smilies.php");
function smilies_content(&$a) {
if ($a->argv[1]==="json"){
$tmp = Smilies::get_list();
$results = array();
for($i = 0; $i < count($tmp['texts']); $i++) {
$results[] = array('text' => $tmp['texts'][$i], 'icon' => $tmp['icons'][$i]);
}
json_return_and_die($results);
}
else {
return Smilies::replace('',true);
}
}

View file

@ -8,7 +8,6 @@ JSFILES=(
"js/acl.js"
"js/ajaxupload.js"
"js/country.js"
"js/fk.autocomplete.js"
"js/jquery.htmlstream.js"
"js/main.js"
"js/webtoolkit.base64.js"

View file

@ -209,6 +209,59 @@ key { display: inline; background-color: #eee; color: #666; padding:0.2em; font-
/* notifications unseen */
.notify-unseen { background-color: #cceeFF; }
/* autocomplete popup */
ul.acpopup {
list-style: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
}
nav .acpopup {
width: 290px;
max-height: 450px;
max-width: 300px;
overflow-y: auto;
overflow-x: hidden;
margin-top: 0px;
}
img.acpopup-img {
float: left;
width: 36px;
height: 36px;
margin-right: 5px;
vertical-align: middle;
}
.acpopup-contactname {
padding-top: 2px;
font-weight: bold;
line-height: 1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.acpopup-sub-text {
color: #777;
font-size: 0.833em;
line-height: 1em;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.textcomplete-item a {
color: inherit;
overflow: hidden;
text-overflow: ellipsis;
clear: both;
white-space: nowrap;
padding: 3px 20px;
display: block;
}
.textcomplete-item a:hover {
text-decoration: none;
}
/* plain text editor upload/select popup */
.fbrowser .path a { padding: 5px; }

View file

@ -1,18 +1,7 @@
<script src="{{$baseurl}}/library/jquery_ac/friendica.complete.js" ></script>
<script>
$(document).ready(function() {
var a;
a = $("#contacts-search").autocomplete({
serviceUrl: '{{$base}}/acl',
minChars: 2,
width: 350,
$("#contacts-search").contact_autocomplete(baseurl + '/acl', 'a', true);
});
a.setOptions({ params: { type: 'a' }});
});
</script>

View file

@ -1,9 +1,9 @@
<script>
$(document).ready(function() {
$(".comment-edit-wrapper textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-edit-wrapper textarea").editor_autocomplete(baseurl+"/acl");
// make auto-complete work in more places
$(".wall-item-comment-wrapper textarea").contact_autocomplete(baseurl+"/acl");
$(".wall-item-comment-wrapper textarea").editor_autocomplete(baseurl+"/acl");
});
</script>

View file

@ -148,6 +148,9 @@
$(document).ready(function() {
{{if $editselect = 'none'}}
$("#comment-edit-text-desc").bbco_autocomplete('bbcode');
{{/if}}
$('#event-share-checkbox').change(function() {

View file

@ -33,7 +33,8 @@
<!-- <script type="text/javascript" src="js/jquery-migrate.js" ></script>-->
<script type="text/javascript" src="js/jquery-migrate.js" ></script>
<script type="text/javascript" src="js/jquery.textinputs.js" ></script>
<script type="text/javascript" src="js/fk.autocomplete.js" ></script>
<script type="text/javascript" src="library/jquery-textcomplete/jquery.textcomplete.min.js" ></script>
<script type="text/javascript" src="js/autocomplete.js" ></script>
<script type="text/javascript" src="library/colorbox/jquery.colorbox-min.js"></script>
<script type="text/javascript" src="library/jgrowl/jquery.jgrowl_minimized.js"></script>
<script type="text/javascript" src="library/datetimepicker/jquery.datetimepicker.js"></script>

View file

@ -23,7 +23,8 @@ function initEditor(cb){
if(plaintext == 'none') {
$("#profile-jot-text-loading").hide();
$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
$("#profile-jot-text").contact_autocomplete(baseurl+"/acl");
$("#profile-jot-text").editor_autocomplete(baseurl+"/acl");
$("#profile-jot-text").bbco_autocomplete('bbcode');
editor = true;
$("a#jot-perms-icon").colorbox(colorbox_options);
$(".jothidden").show();

View file

@ -1,18 +1,8 @@
<script src="{{$baseurl}}/library/jquery_ac/friendica.complete.js" ></script>
<script>$(document).ready(function() {
var a;
a = $("#recip").autocomplete({
serviceUrl: '{{$base}}/acl',
minChars: 2,
width: 350,
onSelect: function(value,data) {
$("#recip-complete").val(data);
}
<script>
$(document).ready(function() {
$("#recip").name_autocomplete(baseurl + '/acl', 'm', false, function(data) {
$("#recip-complete").val(data.id);
});
});
</script>

View file

@ -44,7 +44,7 @@ if(plaintext != 'none') {
});
}
else
$("#prvmail-text").contact_autocomplete(baseurl+"/acl");
$("#prvmail-text").editor_autocomplete(baseurl+"/acl");
</script>
@ -63,6 +63,11 @@ else
}
);
{{if $editselect = 'none'}}
$("#prvmail-text").bbco_autocomplete('bbcode');
{{/if}}
});
function jotGetLink() {

View file

View file

@ -1,18 +1,8 @@
<script src="{{$baseurl}}/library/jquery_ac/friendica.complete.js" ></script>
<script>$(document).ready(function() {
var a;
a = $("#poke-recip").autocomplete({
serviceUrl: '{{$base}}/acl',
minChars: 2,
width: 350,
onSelect: function(value,data) {
$("#poke-recip-complete").val(data);
}
<script>
$(document).ready(function() {
$("#poke-recip").name_autocomplete(baseurl + '/acl', 'a', true, function(data) {
$("#poke-recip-complete").val(data.id);
});
a.setOptions({ params: { type: 'a' }});
});
</script>

View file

@ -44,7 +44,7 @@ if(plaintext != 'none') {
});
}
else
$("#prvmail-text").contact_autocomplete(baseurl+"/acl");
$("#prvmail-text").editor_autocomplete(baseurl+"/acl");
</script>

View file

@ -3308,6 +3308,12 @@ aside input[type='text'] {
/* autocomplete popup */
.acpopup {
background-color:#ffffff;
overflow:auto;
z-index:100000;
border:1px solid #cccccc;
}
.acpopup-mce {
max-height:150px;
background-color:#ffffff;
overflow:auto;
@ -3326,6 +3332,12 @@ aside input[type='text'] {
.acpopupitem.selected {
color: #FFFFFF; background: #3465A4;
}
.textcomplete-item.active {
color: #FFFFFF; background: #3465A4;
}
.active a .acpopup-sub-text {
color: #fff;
}
/* popup notifications */
div.jGrowl div.notice {

View file

@ -388,7 +388,7 @@
$('body').css('cursor', 'auto');
}
/* autocomplete @nicknames */
$(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
// setup videos, since VideoJS won't take care of any loaded via AJAX
if(typeof videojs != 'undefined') videojs.autoSetup();

View file

@ -103,25 +103,27 @@ $(document).ready(function() {
switch(window.autocompleteType) {
case 'msg-header':
var a = $("#recip").autocomplete({
serviceUrl: baseurl + '/acl',
minChars: 2,
width: 350,
onSelect: function(value,data) {
$("#recip-complete").val(data);
}
$("#recip").name_autocomplete(baseurl + '/acl', '', false, function(data) {
$("#recip-complete").val(data.id);
});
break;
case 'contacts-head':
var a = $("#contacts-search").autocomplete({
serviceUrl: baseurl + '/acl',
minChars: 2,
width: 350,
$("#contacts-search").contact_autocomplete(baseurl + '/acl', 'a', true);
$("#contacts-search").keyup(function(event){
if(event.keyCode == 13){
$("#contacts-search").click();
}
});
$(".autocomplete-w1 .selected").keyup(function(event){
if(event.keyCode == 13){
$("#contacts-search").click();
}
});
a.setOptions({ params: { type: 'a' }});
break;
case 'display-head':
$(".comment-wwedit-wrapper textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-wwedit-wrapper textarea").editor_autocomplete(baseurl+"/acl");
break;
default:
break;
@ -286,7 +288,7 @@ function initEditor(cb){
if(plaintext == 'none') {
// $("#profile-jot-text-loading").hide();
$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
$("#profile-jot-text").contact_autocomplete(baseurl+"/acl");
$("#profile-jot-text").editor_autocomplete(baseurl+"/acl");
editor = true;
/* $("a#jot-perms-icon").colorbox({
'inline' : true,

View file

@ -4210,6 +4210,64 @@ aside input[type='text'] {
.acpopupitem.selected {
color: #FFFFFF; background: #3465A4;
}
ul.acpopup {
list-style: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
}
nav .acpopup {
width: 290px;
margin-left: -35px;
max-height: 450px;
max-width: 300px;
overflow-y: auto;
overflow-x: hidden;
margin-top: 0px;
}
img.acpopup-img {
float: left;
width: 36px;
height: 36px;
margin-right: 5px;
vertical-align: middle;
}
.acpopup-contactname {
padding-top: 2px;
font-weight: bold;
line-height: 1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.acpopup-sub-text {
color: #777;
font-size: 0.833em;
line-height: 1em;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.textcomplete-item a {
color: inherit;
overflow: hidden;
text-overflow: ellipsis;
clear: both;
white-space: nowrap;
padding: 3px 20px;
display: block;
}
.textcomplete-item a:hover {
text-decoration: none;
}
.textcomplete-item.active {
color: #FFFFFF; background: #3465A4;
}
.active a .acpopup-sub-text {
color: #fff;
}
/* popup notifications */
div.jGrowl div.notice {

View file

@ -1,5 +1,2 @@
<script src="{{$baseurl}}/library/jquery_ac/friendica.complete.min.js" ></script>

View file

@ -7,7 +7,8 @@
<script type="text/javascript" src="{{$baseurl}}/library/jgrowl/jquery.jgrowl_minimized.js"></script>
<script type="text/javascript" src="{{$baseurl}}/library/datetimepicker/jquery.datetimepicker.js"></script>
<script type="text/javascript" src="{{$baseurl}}/js/fk.autocomplete.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/library/jquery-textcomplete/jquery.textcomplete.min.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/autocomplete.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/view/theme/frost-mobile/js/acl.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/webtoolkit.base64.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/view/theme/frost-mobile/js/main.js" ></script>

View file

@ -1,5 +1,2 @@
<script src="{{$baseurl}}/library/jquery_ac/friendica.complete.min.js" ></script>

View file

@ -402,7 +402,7 @@
$('body').css('cursor', 'auto');
}
/* autocomplete @nicknames */
$(".comment-edit-form textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-edit-form textarea").editor_autocomplete(baseurl+"/acl");
collapseHeight();

View file

@ -214,25 +214,27 @@ $(document).ready(function() {
switch(window.autocompleteType) {
case 'msg-header':
var a = $("#recip").autocomplete({
serviceUrl: baseurl + '/acl',
minChars: 2,
width: 350,
onSelect: function(value,data) {
$("#recip-complete").val(data);
}
$("#recip").name_autocomplete(baseurl + '/acl', '', false, function(data) {
$("#recip-complete").val(data.id);
});
break;
case 'contacts-head':
var a = $("#contacts-search").autocomplete({
serviceUrl: baseurl + '/acl',
minChars: 2,
width: 350,
$("#contacts-search").contact_autocomplete(baseurl + '/acl', 'a', true);
$("#contacts-search").keyup(function(event){
if(event.keyCode == 13){
$("#contacts-search").click();
}
});
$(".autocomplete-w1 .selected").keyup(function(event){
if(event.keyCode == 13){
$("#contacts-search").click();
}
});
a.setOptions({ params: { type: 'a' }});
break;
case 'display-head':
$(".comment-wwedit-wrapper textarea").contact_autocomplete(baseurl+"/acl");
$(".comment-wwedit-wrapper textarea").editor_autocomplete(baseurl+"/acl");
break;
default:
break;
@ -587,7 +589,7 @@ function initEditor(cb){
plaintextFn : function() {
$("#profile-jot-text-loading").hide();
$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
$("#profile-jot-text").contact_autocomplete(baseurl+"/acl");
$("#profile-jot-text").editor_autocomplete(baseurl+"/acl");
$(".jothidden").show();
if (typeof cb!="undefined") cb();
}
@ -660,7 +662,7 @@ function msgInitEditor() {
});
},
plaintextFn : function() {
$("#prvmail-text").contact_autocomplete(baseurl+"/acl");
$("#prvmail-text").editor_autocomplete(baseurl+"/acl");
}
}
InitMCEEditor(editorData);

View file

@ -4064,13 +4064,15 @@ aside input[type='text'] {
/* autocomplete popup */
.acpopup {
max-height:150px;
.acpopup, .acpopup-mce {
background-color:#ffffff;
overflow:auto;
z-index:100000;
border:1px solid #cccccc;
}
.acpopup-mce {
max-height:150px;
}
.acpopupitem {
background-color:#ffffff; padding: 4px;
clear:left;
@ -4084,6 +4086,65 @@ aside input[type='text'] {
color: #FFFFFF; background: #3465A4;
}
ul.acpopup {
list-style: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
}
nav .acpopup {
width: 290px;
margin-left: -35px;
max-height: 450px;
max-width: 300px;
overflow-y: auto;
overflow-x: hidden;
margin-top: 0px;
}
img.acpopup-img {
float: left;
width: 36px;
height: 36px;
margin-right: 5px;
vertical-align: middle;
}
.acpopup-contactname {
padding-top: 2px;
font-weight: bold;
line-height: 1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.acpopup-sub-text {
color: #777;
font-size: 0.833em;
line-height: 1em;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
.textcomplete-item a {
color: inherit;
overflow: hidden;
text-overflow: ellipsis;
clear: both;
white-space: nowrap;
padding: 3px 20px;
display: block;
}
.textcomplete-item a:hover {
text-decoration: none;
}
.textcomplete-item.active {
color: #FFFFFF; background: #3465A4;
}
.active a .acpopup-sub-text {
color: #fff;
}
/* popup notifications */
div.jGrowl div.notice {
background: #511919 url("../../../images/icons/48/notice.png") no-repeat 5px center;

View file

@ -1,5 +1,2 @@
<script src="{{$baseurl}}/library/jquery_ac/friendica.complete.min.js" ></script>

View file

@ -19,7 +19,8 @@
<script type="text/javascript" src="{{$baseurl}}/view/theme/frost/js/acl.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/webtoolkit.base64.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/fk.autocomplete.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/library/jquery-textcomplete/jquery.textcomplete.min.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/js/autocomplete.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/view/theme/frost/js/main.js" ></script>
<script type="text/javascript" src="{{$baseurl}}/view/theme/frost/js/theme.js"></script>

View file

@ -1,5 +1,2 @@
<script src="{{$baseurl}}/library/jquery_ac/friendica.complete.min.js" ></script>

View file

@ -744,8 +744,12 @@ ul.menu-popup .toolbar a:hover {
}
/* autocomplete popup */
.autocomplete,
.acpopup {
.acpopup-mce {
max-height: 150px;
}
.autocomplete,
.acpopup-mce,
.acpopup {
background-color: #ffffff;
color: #2d2d2d;
border: 1px solid #364e59;
@ -774,6 +778,15 @@ ul.menu-popup .toolbar a:hover {
.acpopupitem.selected {
background-color: #bdcdd4;
}
.textcomplete-item {
color: #2d2d2d;
}
.textcomplete-item a:hover {
color: #2d2d2d;
}
.textcomplete-item.active {
background-color: #bdcdd4;
}
#nav-notifications-menu {
width: 400px;
max-height: 550px;

View file

@ -744,8 +744,12 @@ ul.menu-popup .toolbar a:hover {
}
/* autocomplete popup */
.autocomplete,
.acpopup {
.acpopup-mce {
max-height: 150px;
}
.autocomplete,
.acpopup-mce,
.acpopup {
background-color: #ffffff;
color: #2d2d2d;
border: 1px solid #364e59;
@ -774,6 +778,15 @@ ul.menu-popup .toolbar a:hover {
.acpopupitem.selected {
background-color: #ccff42;
}
.textcomplete-item {
color: #2d2d2d;
}
.textcomplete-item a:hover {
color: #2d2d2d;
}
.textcomplete-item.active {
background-color: #ccff42;
}
#nav-notifications-menu {
width: 400px;
max-height: 550px;

View file

@ -744,8 +744,12 @@ ul.menu-popup .toolbar a:hover {
}
/* autocomplete popup */
.autocomplete,
.acpopup {
.acpopup-mce {
max-height: 150px;
}
.autocomplete,
.acpopup-mce,
.acpopup {
background-color: #ffffff;
color: #2d2d2d;
border: 1px solid #364e59;
@ -774,6 +778,15 @@ ul.menu-popup .toolbar a:hover {
.acpopupitem.selected {
background-color: #c0a3c7;
}
.textcomplete-item {
color: #2d2d2d;
}
.textcomplete-item a:hover {
color: #2d2d2d;
}
.textcomplete-item.active {
background-color: #c0a3c7;
}
#nav-notifications-menu {
width: 400px;
max-height: 550px;

View file

@ -265,9 +265,10 @@ ul.menu-popup {
}
/* autocomplete popup */
.autocomplete, .acpopup-mce { max-height:150px; }
.autocomplete,
.acpopup-mce,
.acpopup {
max-height:150px;
background-color:@MenuBg;
color: @Menu;
border:1px solid @MenuBorder;
@ -291,6 +292,15 @@ ul.menu-popup {
background-color: @MenuItemHoverBg;
}
}
.textcomplete-item {
color: @MenuItem;
a:hover{
color: @MenuItem;
}
&.active{
background-color: @MenuItemHoverBg;
}
}
#nav-notifications-menu {

View file

@ -4377,8 +4377,7 @@ a.active {
}
/* autocomplete popup */
.acpopup {
max-height: 150px;
.acpopup, acpopup-mce {
overflow: auto;
z-index: 100000;
color: #2e3436;
@ -4395,6 +4394,10 @@ a.active {
-webkit-box-shadow: 0 0 8px #BDBDBD;
}
.acpopup-mce {
max-height: 150px;
}
.acpopupitem {
color: #2e3436;
padding: 4px;
@ -4405,7 +4408,7 @@ a.active {
margin-right: 4px;
}
.acpopupitem.selected {
.acpopupitem.selected, .textcomplete-item.active {
color: #efefef;
background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #1873a2), color-stop(1, #6da6c4) );
background: -moz-linear-gradient( center top, #1873a2 5%, #6da6c4 100% );
@ -4414,6 +4417,10 @@ a.active {
order-bottom: none;
}
.textcomplete-item a:hover, .textcomplete-item a:hover .acpopup-sub-text, .textcomplete-item.active a .acpopup-sub-text {
color: #efefef;
}
.qcomment {
opacity: 0.8;
filter: alpha(opacity=0);

View file

@ -12,7 +12,8 @@ function initEditor(cb){
if(plaintext == 'none') {
$("#profile-jot-text-loading").hide();
$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
$("#profile-jot-text").contact_autocomplete(baseurl+"/acl");
$("#profile-jot-text").editor_autocomplete(baseurl+"/acl");
$("#profile-jot-text").bbco_autocomplete('bbcode');
$(".jothidden").show();
editor = true;
$("a#jot-perms-icon").colorbox({

View file

@ -43,7 +43,7 @@ nav a {
color: #737373;
}
nav #search-box #search-text {
nav #nav-search-box #nav-search-text {
border-radius: 5px;
}

View file

@ -7,6 +7,6 @@ nav ul li .menu-popup {
right: 0px;
}
nav #search-box #search-text {
nav #nav-search-box #nav-search-text {
width: 100px;
}

View file

@ -159,7 +159,7 @@ section {
top: 44px;
}
nav #search-box #search-text {
nav #nav-search-box #nav-search-text {
background-color: initial;
border-style: solid;
border-width: 1px;

View file

@ -146,7 +146,7 @@ section {
top: 44px;
}
nav #search-box #search-text {
nav #nav-search-box #nav-search-text {
background-color: initial;
border-style: solid;
border-width: 1px;

View file

@ -429,7 +429,7 @@ code {
.sidebar-group-li:hover, #sidebar-new-group:hover, #sidebar-edit-groups:hover,#forum-widget-collapse:hover,
#sidebar-ungrouped:hover, .side-link:hover, .nets-ul li:hover, #forumlist-sidebar li:hover, #forumlist-sidebar-right li:hover,
.nets-all:hover, .saved-search-li:hover, li.tool:hover, .admin.link:hover, aside h4 a:hover, right_aside h4 a:hover, #message-new:hover,
#sidebar-photos-albums li:hover, .photos-upload-link:hover {
#sidebar-photos-albums li:hover, .photos-upload-link:hover, .textcomplete-item.active {
/* background-color: #ddd; */
/* background-color: #e5e5e5; */
background-color: #F5F5F5;
@ -641,7 +641,7 @@ nav ul li .menu-popup {
right: auto;
}
nav #search-box #search-text {
nav #nav-search-box #nav-search-text {
/*background-image: url('icons/lupe.png');
background-repeat:no-repeat; */
padding-left:0px;
@ -900,15 +900,22 @@ ul.menu-popup .empty {
color: #9eabb0;
}
/* autocomplete popup */
.acpopup {
max-height: 150px;
.acpopup, .acpopup-mce {
background-color: #ffffff;
color: #2d2d2d;
border: 1px solid #MenuBorder;
overflow: auto;
z-index: 100000;
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7);
}
acpopup-mce {
color: #2d2d2d;
max-height: 150px;
}
nav .acpopup {
top: 31px !important;
margin-left: -23px
}
.acpopupitem {
color: #2d2d2d;
padding: 4px;
@ -921,6 +928,27 @@ ul.menu-popup .empty {
.acpopupitem.selected {
background-color: #bdcdd4;
}
.textcomplete-item {
float: none;
}
.textcomplete-item a {
color: #737373;
}
.textcomplete-item a:hover {
color: #000;
padding: 3px 20px;
}
.textcomplete-item a .forum, .forum .acpopup-sub-text {
color: #36C;
opacity: 0.8;
}
.textcomplete-item a .forum:hover {
opacity: 1.0;
}
img.acpopup-img {
border-radius: 4px;
}
#nav-notifications-menu {
width: 400px;
max-height: 550px;

View file

@ -34,7 +34,7 @@
<div id="event-desc-text">{{$d_text}}</div>
<textarea id="comment-edit-text-desc" rows="8" cols="64" name="desc">{{$d_orig}}</textarea>
<textarea id="comment-edit-text-desc" rows="8" cols="64" name="desc" autocomplete="off">{{$d_orig}}</textarea>
<div id="event-desc-text-edit-bb" class="comment-edit-bb">
<a title="{{$edimg}}" data-role="insert-formatting" data-comment="{{$comment}}" data-bbcode="img" data-id="desc"><i class="icon-picture"></i></a>
<a title="{{$edurl}}" data-role="insert-formatting" data-comment="{{$comment}}" data-bbcode="url" data-id="desc"><i class="icon-link"></i></a>

View file

@ -80,9 +80,9 @@
{{/if}}
{{if $nav.search}}
<li role="search" id="search-box">
<li role="search" id="nav-search-box">
<form method="get" action="{{$nav.search.0}}">
<input accesskey="s" id="search-text" class="nav-menu-search" type="text" value="" name="search">
<input accesskey="s" id="nav-search-text" class="nav-menu-search" type="text" value="" name="search" placeholder=" {{$search_hint}}">
<select name="search-option">
<option value="fulltext">{{$nav.searchoption.0}}</option>
<option value="tags">{{$nav.searchoption.1}}</option>

View file

@ -0,0 +1,6 @@
<script>
$(document).ready(function() {
$("#nav-search-text").search_autocomplete(baseurl + '/acl');
});
</script>