Commit 13b8de40 authored by hannes's avatar hannes

languages, autosuggestion etc

chinese, galician, mention autosuggestion (goodbye codemirror!),
compact json api for some actions (for faster scrolling), optimized
png:s, etc
parent b2f42097
......@@ -83,6 +83,9 @@ class QvitterPlugin extends Plugin {
array('action' => 'apiqvitterupdatebackgroundcolor'));
$m->connect('api/qvitter/checklogin.json',
array('action' => 'apiqvitterchecklogin'));
$m->connect('api/qvitter/allfollowing/:id.json',
array('action' => 'apiqvitterallfollowing',
'id' => Nickname::INPUT_FMT));
$m->connect('api/qvitter/statuses/friends_timeline.json',
array('action' => 'apiqvitterfriends'));
$m->connect('api/qvitter/statuses/friends_timeline/:id.json',
......
<?php
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
· ·
· Everybody I'm following and all groups I'm member of ·
· (to use for auto-suggestions) ·
· ·
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
· ·
· ·
· Q V I T T E R ·
· ·
· http://github.com/hannesmannerheim/qvitter ·
· ·
· ·
· ·
· <o) ·
· /_//// ·
· (____/ ·
· (o< ·
· o> \\\\_\ ·
· \\) \____) ·
· ·
· ·
· Qvitter is free software: you can redistribute it and / or modify it ·
· under the terms of the GNU Affero General Public License as published by ·
· the Free Software Foundation, either version three of the License or (at ·
· your option) any later version. ·
· ·
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
· more details. ·
· ·
· You should have received a copy of the GNU Affero General Public License ·
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
· ·
· Contact h@nnesmannerhe.im if you have any questions. ·
· ·
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
if (!defined('GNUSOCIAL')) { exit(1); }
class ApiQvitterAllFollowingAction extends ApiBareAuthAction
{
var $profiles = null;
var $users_stripped = null;
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
protected function prepare(array $args=array())
{
parent::prepare($args);
$this->count = 5000; // max 5000, completely arbitrary...
$this->target = $this->getTargetProfile($this->arg('id'));
if (!($this->target instanceof Profile)) {
// TRANS: Client error displayed when requesting a list of followers for a non-existing user.
$this->clientError(_('No such user.'), 404);
}
$this->profiles = $this->getProfiles();
// only keep id, name, nickname and avatar filename
foreach($this->profiles as $p) {
try {
$avatar = Avatar::byProfile($p, AVATAR_STREAM_SIZE);
$avatar = $avatar->filename;
} catch (Exception $e) {
$avatar = false;
}
$this_user = array($p->fullname,$p->nickname,$avatar);
$this->users_stripped[$p->id] = $this_user;
}
return true;
}
/**
* Handle the request
*
* @param array $args $_REQUEST data (unused)
*
* @return void
*/
protected function handle()
{
parent::handle();
$this->initDocument('json');
$this->showJsonObjects($this->users_stripped);
$this->endDocument('json');
}
/**
* Get profiles
*
* @return array Profiles
*/
protected function getProfiles()
{
$offset = ($this->page - 1) * $this->count;
$limit = $this->count + 1;
$subs = null;
if (isset($this->tag)) {
$subs = $this->target->getTaggedSubscriptions(
$this->tag, $offset, $limit
);
} else {
$subs = $this->target->getSubscribed(
$offset,
$limit
);
}
$profiles = array();
while ($subs->fetch()) {
$profiles[] = clone($subs);
}
return $profiles;
}
}
......@@ -151,12 +151,14 @@ class QvitterAction extends ApiAction
?>
<script>
window.defaultAvatarStreamSize = <?php print json_encode(Avatar::defaultImage(AVATAR_STREAM_SIZE)) ?>;
window.textLimit = <?php print json_encode((int)common_config('site','textlimit')) ?>;
window.registrationsClosed = <?php print json_encode($registrationsclosed) ?>;
window.siteTitle = <?php print json_encode($sitetitle) ?>;
window.loggedIn = <?php print json_encode($logged_in_user_obj) ?>;
window.timeBetweenPolling = <?php print QvitterPlugin::settings("timebetweenpolling"); ?>;
window.apiRoot = '<?php print common_path("api/", true); ?>';
window.avatarRoot = '<?php print common_path("avatar/", true); ?>';
window.fullUrlToThisQvitterApp = '<?php print $qvitterpath; ?>';
window.siteRootDomain = '<?php print $siterootdomain; ?>';
window.siteInstanceURL = '<?php print $instanceurl; ?>';
......@@ -180,7 +182,8 @@ class QvitterAction extends ApiAction
#new-queets-bar,
.menu-container div,
#user-header:hover #user-name,
.cm-mention, .cm-tag, .cm-group, .cm-url, .cm-email {
.cm-mention, .cm-tag, .cm-group, .cm-url, .cm-email,
div.syntax-middle span {
color:#0084B4;/*COLOREND*/
}
.topbar .global-nav,
......@@ -211,12 +214,15 @@ class QvitterAction extends ApiAction
<li><a id="logout"></a></li>
<li class="language dropdown-divider"></li>
<li class="language"><a class="language-link" title="Arabic" data-lang-code="ar">العربيّة</a></li>
<li class="language"><a class="language-link" title="简体中文" data-lang-code="zh_cn">简体中文</a></li>
<li class="language"><a class="language-link" title="繁體中文" data-lang-code="zh_tw">繁體中文</a></li>
<li class="language"><a class="language-link" title="German" data-lang-code="de">Deutsch</a></li>
<li class="language"><a class="language-link" title="English" data-lang-code="en">English</a></li>
<li class="language"><a class="language-link" title="Spanish" data-lang-code="es">Español</a></li>
<li class="language"><a class="language-link" title="Esperanto" data-lang-code="eo">Esperanto</a></li>
<li class="language"><a class="language-link" title="Farsi" data-lang-code="fa">فارسی</a></li>
<li class="language"><a class="language-link" title="French" data-lang-code="fr">français</a></li>
<li class="language"><a class="language-link" title="Galego" data-lang-code="gl">Galego</a></li>
<li class="language"><a class="language-link" title="Italian" data-lang-code="it">Italiano</a></li>
<li class="language"><a class="language-link" title="Swedish" data-lang-code="sv">svenska</a></li>
</ul>
......@@ -246,12 +252,15 @@ class QvitterAction extends ApiAction
<span class="caret-inner"></span>
</li>
<li><a class="language-link" title="Arabic" data-lang-code="ar">العربيّة</a></li>
<li><a class="language-link" title="简体中文" data-lang-code="zh_cn">简体中文</a></li>
<li><a class="language-link" title="繁體中文" data-lang-code="zh_tw">繁體中文</a></li>
<li><a class="language-link" title="German" data-lang-code="de">Deutsch</a></li>
<li><a class="language-link" title="English" data-lang-code="en">English</a></li>
<li><a class="language-link" title="Spanish" data-lang-code="es">Español</a></li>
<li><a class="language-link" title="Esperanto" data-lang-code="eo">Esperanto</a></li>
<li><a class="language-link" title="Farsi" data-lang-code="fa">فارسی</a></li>
<li><a class="language-link" title="French" data-lang-code="fr">français</a></li>
<li><a class="language-link" title="Galego" data-lang-code="gl">Galego</a></li>
<li><a class="language-link" title="Italian" data-lang-code="it">Italiano</a></li>
<li><a class="language-link" title="Swedish" data-lang-code="sv">svenska</a></li>
</ul>
......@@ -311,13 +320,15 @@ class QvitterAction extends ApiAction
<a><div id="user-groups"><strong></strong><div class="label"></div></div></a>
</div>
<div id="user-footer">
<textarea id="codemirror-queet-box"></textarea>
<div id="queet-box" class="queet-box"></div>
<div id="queet-toolbar">
<div id="queet-box-extras"></div>
<div id="queet-button">
<span id="queet-counter"></span>
<button id="queet"></button>
<div id="queet-box" class="queet-box queet-box-syntax" data-start-text=""></div>
<div class="syntax-middle"></div>
<div class="syntax-two" contenteditable="true"></div>
<div class="mentions-suggestions"></div>
<div class="queet-toolbar">
<div class="queet-box-extras"></div>
<div class="queet-button">
<span class="queet-counter"></span>
<button></button>
</div>
</div>
</div>
......@@ -343,16 +354,15 @@ class QvitterAction extends ApiAction
<div id="footer"></div>
</div>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/codemirror.4.0.js"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery-2.0.2.min.js"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery-ui-1.10.3.min.js"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery.easing.1.3.js"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lib/jquery.minicolors.min.js"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/dom-functions.js?v=19"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/misc-functions.js?v=13"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/ajax-functions.js?v=7"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lan.js?v=15"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/qvitter.js?v=14"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/dom-functions.js?v=20"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/misc-functions.js?v=14"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/ajax-functions.js?v=8"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/lan.js?v=17"></script>
<script type="text/javascript" src="<?php print $qvitterpath; ?>js/qvitter.js?v=16"></script>
</body>
</html>
......
......@@ -93,7 +93,7 @@ class ApiQvitterAction extends ApiAction
$simplified_statuses->s[$i][9] = $s['statusnet_in_groups'];
$simplified_statuses->s[$i][10] = $s['user']['id'];
$simplified_statuses->s[$i][11] = $s['statusnet_conversation_id'];
$simplified_statuses->s[$i][12] = $s['source'];
$simplified_statuses->s[$i][12] = $s['source'];
$simplified_statuses->u[$s['user']['id']][0] = $s['user']['screen_name'];
$simplified_statuses->u[$s['user']['id']][1] = $s['user']['name'];
......@@ -111,7 +111,41 @@ class ApiQvitterAction extends ApiAction
$simplified_statuses->u[$s['user']['id']][13] = $s['user']['statuses_count'];
$simplified_statuses->u[$s['user']['id']][14] = $s['user']['following'];
$simplified_statuses->u[$s['user']['id']][15] = $s['user']['statusnet_blocking'];
$simplified_statuses->u[$s['user']['id']][16] = $s['user']['statusnet_profile_url'];
$simplified_statuses->u[$s['user']['id']][16] = $s['user']['statusnet_profile_url'];
if(isset($s['retweeted_status'])) {
$simplified_statuses->s[$i][13][0] = $s['retweeted_status']['id'];
$simplified_statuses->s[$i][13][1] = strtotime($s['retweeted_status']['created_at']);
$simplified_statuses->s[$i][13][2] = $s['retweeted_status']['text'];
$simplified_statuses->s[$i][13][3] = $s['retweeted_status']['statusnet_html'];
$simplified_statuses->s[$i][13][4] = $s['retweeted_status']['in_reply_to_status_id'];
$simplified_statuses->s[$i][13][5] = $s['retweeted_status']['in_reply_to_user_id'];
$simplified_statuses->s[$i][13][6] = $s['retweeted_status']['in_reply_to_screen_name'];
$simplified_statuses->s[$i][13][7] = $s['retweeted_status']['favorited'];
$simplified_statuses->s[$i][13][8] = $s['retweeted_status']['repeated'];
$simplified_statuses->s[$i][13][9] = $s['retweeted_status']['statusnet_in_groups'];
$simplified_statuses->s[$i][13][10] = $s['retweeted_status']['user']['id'];
$simplified_statuses->s[$i][13][11] = $s['retweeted_status']['statusnet_conversation_id'];
$simplified_statuses->s[$i][13][12] = $s['retweeted_status']['source'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][0] = $s['retweeted_status']['user']['screen_name'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][1] = $s['retweeted_status']['user']['name'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][2] = $s['retweeted_status']['user']['location'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][3] = $s['retweeted_status']['user']['description'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][4] = $s['retweeted_status']['user']['profile_image_url_profile_size'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][5] = $s['retweeted_status']['user']['profile_image_url_original'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][6] = $s['retweeted_status']['user']['groups_count'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][7] = $s['retweeted_status']['user']['linkcolor'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][8] = $s['retweeted_status']['user']['backgroundcolor'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][9] = $s['retweeted_status']['user']['url'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][10] = $s['retweeted_status']['user']['followers_count'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][11] = $s['retweeted_status']['user']['friends_count'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][12] = $s['retweeted_status']['user']['favourites_count'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][13] = $s['retweeted_status']['user']['statuses_count'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][14] = $s['retweeted_status']['user']['following'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][15] = $s['retweeted_status']['user']['statusnet_blocking'];
$simplified_statuses->u[$s['retweeted_status']['user']['id']][16] = $s['retweeted_status']['user']['statusnet_profile_url'];
}
$i++;
}
......
This diff is collapsed.
img/default-avatar-mini.png

1.64 KB | W: | H:

img/default-avatar-mini.png

1.5 KB | W: | H:

img/default-avatar-mini.png
img/default-avatar-mini.png
img/default-avatar-mini.png
img/default-avatar-mini.png
  • 2-up
  • Swipe
  • Onion skin
img/default-avatar-profile.png

11 KB | W: | H:

img/default-avatar-profile.png

8.9 KB | W: | H:

img/default-avatar-profile.png
img/default-avatar-profile.png
img/default-avatar-profile.png
img/default-avatar-profile.png
  • 2-up
  • Swipe
  • Onion skin
img/default-avatar-stream.png

4.38 KB | W: | H:

img/default-avatar-stream.png

3.82 KB | W: | H:

img/default-avatar-stream.png
img/default-avatar-stream.png
img/default-avatar-stream.png
img/default-avatar-stream.png
  • 2-up
  • Swipe
  • Onion skin
img/jquery.minicolors.png

75.6 KB | W: | H:

img/jquery.minicolors.png

66.8 KB | W: | H:

img/jquery.minicolors.png
img/jquery.minicolors.png
img/jquery.minicolors.png
img/jquery.minicolors.png
  • 2-up
  • Swipe
  • Onion skin
img/mela.jpg

447 KB | W: | H:

img/mela.jpg

426 KB | W: | H:

img/mela.jpg
img/mela.jpg
img/mela.jpg
img/mela.jpg
  • 2-up
  • Swipe
  • Onion skin
img/sprite.png

48.2 KB | W: | H:

img/sprite.png

40.4 KB | W: | H:

img/sprite.png
img/sprite.png
img/sprite.png
img/sprite.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -107,32 +107,6 @@ function getFromAPI(stream, actionOnSuccess) {
});
}
/* ·
·
· Post queet
·
· @param queetText_txt: the text to post
· @param actionOnSuccess: callback function, false on error, data on success
·
· · · · · · · · · · · · · */
function postQueetToAPI(queetText_txt, actionOnSuccess) {
$.ajax({ url: window.apiRoot + 'statuses/update.json?t=' + timeNow(),
type: "POST",
data: {
status: queetText_txt,
source: 'Qvitter'
},
dataType: "json",
error: function(data){ actionOnSuccess(false); console.log(data); },
success: function(data) {
actionOnSuccess(data);
}
});
}
/* ·
·
......@@ -238,7 +212,7 @@ function APIJoinOrLeaveGroup(joinOrLeave,group_id,this_element,actionOnSuccess)
/* ·
·
· Post reply
· Post queet
·
· @param queetText_txt: the text to post
· @param in_reply_to_status_id: the local id for the queet to reply to
......@@ -246,7 +220,7 @@ function APIJoinOrLeaveGroup(joinOrLeave,group_id,this_element,actionOnSuccess)
·
· · · · · · · · · · · · · */
function postReplyToAPI(queetText_txt, in_reply_to_status_id, actionOnSuccess) {
function postQueetToAPI(queetText_txt, in_reply_to_status_id, actionOnSuccess) {
$.ajax({ url: window.apiRoot + 'statuses/update.json?t=' + timeNow(),
type: "POST",
data: {
......@@ -352,45 +326,4 @@ function getFavsOrRequeetsForQueet(apiaction,qid,actionOnSuccess) {
}
});
}
/* ·
·
· Shorten urls in box
·
· @param apiaction: i.e. 'favs' or 'requeets'
· @param qid: the queet id
· @param actionOnSuccess: callback function
·
· params included to pass along to countCharsInQueetBox
·
· · · · · · · · · · · · · */
function shortenUrlsInBox(box,cnt,btn) {
// wrap urls
// var allurls = findUrls(box.html().replace(/&amp;/gi,'&').replace(/&nbsp;/gi,' '));
// $.each(allurls,function(key,obj){
// if(obj.substring(0,15) != 'http://qttr.at/' && obj.length > 20) { // don't shorten if link is qttr.at or very short already
// box.html(box.html().replace(/&amp;/gi,'&').replace(obj,'<a class="shortening">' + obj + '</a>'));
// placeCaretAtEnd(document.getElementById(box.attr('id')));
// }
// });
//
// // shorten urls vith qttr.at
// $.each(box.find('a.shortening'),function(key,obj){
// display_spinner();
// var urlEncodedUrl = encodeURIComponent($(obj).html().replace(/&amp;/gi,'&'));
// $.ajax({ url: "http://qttr.at/yourls-api.php?format=jsonp&action=shorturl&signature=b6afeec983&url=" + urlEncodedUrl, type: "GET", dataType: "jsonp", success: function(data) {
// if(typeof data.shorturl != 'undefined') {
// $(obj).before(data.shorturl);
// }
// else {
// $(obj).before($(obj).html());
// }
// $(obj).remove();
// remove_spinner();
// placeCaretAtEnd(document.getElementById(box.attr('id')));
// countCharsInQueetBox(box,cnt,btn);
// }});
// });
}
\ No newline at end of file
......@@ -779,6 +779,7 @@ function expand_queet(q,doScrolling) {
if(!sel && !q.find('.queet-button').children('button').hasClass('enabled')) { // don't collapse if text is selected, or if queet has an active queet button
q.addClass('collapsing');
q.css('overflow','hidden');
q.find('.stream-item-expand').html(window.sL.expand);
if(q.hasClass('conversation')) {
q.removeClass('expanded');
......@@ -946,6 +947,23 @@ function expand_queet(q,doScrolling) {
/* ·
·
· Get an inline queet box
·
· @return the html for the queet box
·
· · · · · · · · · */
function queetBoxHtml() {
var startText = encodeURIComponent(window.sL.compose);
return '<div class="inline-reply-queetbox"><div class="queet-box queet-box-syntax" data-start-text="' + startText + '">' + decodeURIComponent(startText) + '</div><div class="syntax-middle"></div><div class="syntax-two" contenteditable="true"></div><div class="mentions-suggestions"></div><div class="queet-toolbar toolbar-reply"><div class="queet-box-extras"></div><div class="queet-button"><span class="queet-counter"></span><button>' + window.sL.queetVerb + '</button></div></div></div>';
}
/* ·
·
· Get a reply form
......@@ -981,7 +999,9 @@ function replyFormHtml(q,qid) {
}
});
return '<div class="inline-reply-queetbox"><span class="inline-reply-caret"><span class="caret-inner"></span></span><img class="reply-avatar" src="' + $('#user-avatar').attr('src') + '" /><div class="queet-box-template" id="queet-box-template-' + qid + '" data-start-text="' + user_screen_name_text + reply_to_screen_name_text + more_reply_tos_text + '">' + window.sL.replyTo + ' ' + user_screen_name_html + reply_to_screen_name_html + more_reply_tos + '&nbsp;<br></div></div>';
var startText = encodeURIComponent(window.sL.replyTo + ' ' + user_screen_name_html + reply_to_screen_name_html + more_reply_tos + '&nbsp;<br>');
var repliesText = encodeURIComponent(user_screen_name_text + reply_to_screen_name_text + more_reply_tos_text + '&nbsp;&nbsp;');
return '<div class="inline-reply-queetbox"><span class="inline-reply-caret"><span class="caret-inner"></span></span><img class="reply-avatar" src="' + $('#user-avatar').attr('src') + '" /><div class="queet-box queet-box-syntax" id="queet-box-' + qid + '" data-start-text="' + startText + '" data-replies-text="' + repliesText + '">' + decodeURIComponent(startText) + '</div><div class="syntax-middle"></div><div class="syntax-two" contenteditable="true"></div><div class="mentions-suggestions"></div><div class="queet-toolbar toolbar-reply"><div class="queet-box-extras"></div><div class="queet-button"><span class="queet-counter"></span><button>' + window.sL.queetVerb + '</button></div></div></div>';
}
......@@ -1018,54 +1038,6 @@ function popUpAction(popupId, heading, bodyHtml, footerHtml){
}
/* ·
·
· Expand inline reply form
·
· @param box: jQuery object for the queet box that we want to expand
·
· · · · · · · · · · · · · */
function expandInlineQueetBox(box) {
// remove the "reply/svara/etc" before the mentions
var new_mentions_html = '';
$.each(box.find('a'),function(key,obj){
new_mentions_html = new_mentions_html + $(obj).html() + ' ';
});
// insert textarea before, activate and display codemirror
box.before('<textarea id="codemirror-' + box.attr('id') + '"></textarea>');
window['codemirror-' + box.attr('id')] = CodeMirror.fromTextArea(document.getElementById('codemirror-' + box.attr('id')), {
// submit on enter
onKeyEvent: function(editor, event) {
event = $.event.fix(event);
var enterKeyHasBeenPressed = event.type == "keyup" && event.keyCode == 13 && (event.ctrlKey || event.altKey);
if(enterKeyHasBeenPressed ){
console.log('#q-' + box.attr('id') + ' .queet-toolbar button');
$('#' + box.attr('id')).siblings('.queet-toolbar').find('button').trigger('click');
}
}
});
box.siblings('.CodeMirror').css('display','block');
window['codemirror-' + box.attr('id')].setValue(new_mentions_html);
window['codemirror-' + box.attr('id')].focus();
window['codemirror-' + box.attr('id')].setCursor(window['codemirror-' + box.attr('id')].lineCount(), 0)
box.css('display','none');
// show toolbar/button
box.after('<div class="queet-toolbar"><div class="queet-box-extras"></div><div class="queet-button"><span class="queet-counter"></span><button>' + window.sL.queetVerb + '</button></div><div style="clear:both;"></div></div>');
// count chars
countCharsInQueetBox(window['codemirror-' + box.attr('id')].getValue(),box.parent().find('.queet-toolbar .queet-counter'),box.parent().find('.queet-toolbar button'));
// activate char counter
window['codemirror-' + box.attr('id')].on('change',function () {
countCharsInQueetBox(window['codemirror-' + box.attr('id')].getValue(),box.parent().find('.queet-toolbar .queet-counter'),box.parent().find('.queet-toolbar button'));
});
}
/* ·
......@@ -1357,7 +1329,7 @@ function checkForHiddenConversationQueets(qid) {
· · · · · · · · · · · · · */
function addToFeed(feed, after, extraClasses) {
$.each(feed.reverse(), function (key,obj) {
var extraClassesThisRun = extraClasses;
......
This diff is collapsed.
This diff is collapsed.
......@@ -313,16 +313,21 @@ function timestampToTwitterDate(timestamp) {
function decodeQvitterCompactFormat(data) {
// empty object? return empty array instead...
if($.isEmptyObject(data)) {
return [];
}
// leave data unchanged if we don't recognize it
if(typeof data.s == 'undefined') {
else if(typeof data.s == 'undefined') {
return data;
}
}
// decode
else {
var users = new Object();
var i = 0;
$.each(data.u, function(k,v){
users[k] = new Object;
users[k].id = k;
users[k].screen_name = v[0];
users[k].name = (v[1]==0?null:v[1]);
users[k].location = (v[2]==0?null:v[2]);
......@@ -360,6 +365,25 @@ function decodeQvitterCompactFormat(data) {
unqvitter[i].statusnet_conversation_id = v[11];
unqvitter[i].uri = window.siteInstanceURL + 'notice/' + v[0];
unqvitter[i].source = (v[12]==0?null:v[12]);
if(typeof v[13] != 'undefined') {
unqvitter[i].retweeted_status = new Object;
unqvitter[i].retweeted_status.id = v[13][0];
unqvitter[i].retweeted_status.created_at = timestampToTwitterDate(v[13][1]);
unqvitter[i].retweeted_status.text = v[13][2];
unqvitter[i].retweeted_status.statusnet_html = v[13][3];
unqvitter[i].retweeted_status.in_reply_to_status_id = (v[13][4]==0?null:v[13][4]);
unqvitter[i].retweeted_status.in_reply_to_user_id = (v[13][5]==0?null:v[13][5]);
unqvitter[i].retweeted_status.in_reply_to_screen_name = (v[13][6]==0?null:v[13][6]);
unqvitter[i].retweeted_status.favorited = (v[13][7]==0?false:v[13][7]);
unqvitter[i].retweeted_status.repeated = (v[13][8]==0?false:v[13][8]);
unqvitter[i].retweeted_status.statusnet_in_groups = (v[13][9]==0?false:v[13][9]);
unqvitter[i].retweeted_status.user = users[v[13][10]];
unqvitter[i].retweeted_status.statusnet_conversation_id = v[13][11];
unqvitter[i].retweeted_status.uri = window.siteInstanceURL + 'notice/' + v[13][0];
unqvitter[i].retweeted_status.source = (v[13][12]==0?null:v[13][12]);
}
i++;
});
return unqvitter;
......@@ -428,32 +452,6 @@ function convertAttachmentMoreHref() {
}
/* ·
·
· Places the caret at the end of the contenteditable
·
· @param el: the contenteditable-element
·
· · · · · · · · · · · · · */
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
/* ·
·
......@@ -536,7 +534,8 @@ function qOrAmp(stream) {
function countCharsInQueetBox(src,trgt,btn) {
var numchars = $.trim(src).length;
var $src_txt = $('<div/>').append($.trim(src.html()).replace(/&nbsp;/gi,' ').replace(/<br>/i,'').replace(/<br>/gi,"x"));
var numchars = ($.trim($src_txt.text())).length;
// limited
if(window.textLimit > 0) {
......@@ -548,9 +547,10 @@ function countCharsInQueetBox(src,trgt,btn) {
btn.addClass('enabled');
// deactivate button if it's equal to the start text
var startText = btn.closest('.inline-reply-queetbox').children('.queet-box-template').attr('data-start-text');
if(typeof startText != 'undefined') {
if($.trim(startText) == $.trim(src)) {
var queetBox = btn.closest('.inline-reply-queetbox').children('.queet-box-syntax');
if(typeof queetBox.attr('data-replies-text') != 'undefined') {
var $startText = $('<div/>').append(decodeURIComponent(queetBox.attr('data-replies-text')));
if($.trim($startText.text()) == $.trim($src_txt.text())) {
btn.removeClass('enabled');
btn.addClass('disabled');
}
......@@ -646,4 +646,120 @@ jQuery.fn.outerHTML = function(s) {
return s
? this.before(s).remove()
: jQuery("<p>").append(this.eq(0).clone()).html();
};
\ No newline at end of file
};
/* ·
·
· Stuff to get and set selection/caret in contenteditables
·
· · · · · · · · · · · · · */
function getSelectionInElement(element) {
var caretOffset = Array(0,0);
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
var range = win.getSelection().getRangeAt(0);
var preCaretRangeEnd = range.cloneRange();
preCaretRangeEnd.selectNodeContents(element);
preCaretRangeEnd.setEnd(range.endContainer, range.endOffset);
caretOffset[1] = preCaretRangeEnd.toString().length;
var preCaretRangeStart = range.cloneRange();
preCaretRangeStart.selectNodeContents(element);
preCaretRangeStart.setEnd(range.startContainer, range.startOffset);
caretOffset[0] = preCaretRangeStart.toString().length;
return caretOffset;
}
function getTextNodesIn(node) {
var textNodes = [];
if (node.nodeType == 3) {
textNodes.push(node);
}
else {
var children = node.childNodes;
for (var i = 0, len = children.length; i < len; ++i) {
textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
}
}
return textNodes;
}
function setSelectionRange(el, start, end) {
if (document.createRange && window.getSelection) {
var range = document.createRange();
range.selectNodeContents(el);
var textNodes = getTextNodesIn(el);
var foundStart = false;
var charCount = 0, endCharCount;
for (var i = 0, textNode; textNode = textNodes[i++]; ) {
endCharCount = charCount + textNode.length;
if(endCharCount == start && endCharCount == end) {
endCharCount = endCharCount+1;
}
if (!foundStart && start