]>
git.wh0rd.org - tt-rss.git/blob - functions.js
1 var notify_silent
= false ;
2 var loading_progress
= 0 ;
3 var sanity_check_done
= false ;
5 /* add method to remove element from array */
7 Array
. prototype . remove = function ( s
) {
8 for ( var i
= 0 ; i
< this . length
; i
++) {
9 if ( s
== this [ i
]) this . splice ( i
, 1 );
13 /* create console.log if it doesn't exist */
15 if (! window
. console
) console
= {};
16 console
. log
= console
. log
|| function ( msg
) { };
17 console
. warn
= console
. warn
|| function ( msg
) { };
18 console
. error
= console
. error
|| function ( msg
) { };
20 function exception_error ( location
, e
, ext_info
) {
21 var msg
= format_exception_error ( location
, e
);
23 if (! ext_info
) ext_info
= false ;
28 if ( ext_info
. responseText
) {
29 ext_info
= ext_info
. responseText
;
33 var content
= "<div class= \" fatalError \" >" +
34 "<pre>" + msg
+ "</pre>" ;
37 content
+= "<div><b>Additional information:</b></div>" +
38 "<textarea readonly= \" 1 \" >" + ext_info
+ "</textarea>" ;
41 content
+= "<div><b>Stack trace:</b></div>" +
42 "<textarea readonly= \" 1 \" >" + e
. stack
+ "</textarea>" ;
46 content
+= "<div class='dlgButtons'>" ;
48 content
+= "<button dojoType= \" dijit.form.Button \" " +
49 "onclick= \" dijit.byId('exceptionDlg').report() \" >" +
50 __ ( 'Report to tt-rss.org' ) + "</button> " ;
51 content
+= "<button dojoType= \" dijit.form.Button \" " +
52 "onclick= \" dijit.byId('exceptionDlg').hide() \" >" +
53 __ ( 'Close' ) + "</button>" ;
57 var dialog
= new dijit
. Dialog ({
59 title
: "Unhandled exception" ,
60 style
: "width: 600px" ,
62 if ( confirm ( __ ( "Are you sure to report this exception to tt-rss.org? The report will include your browser information. Your IP would be saved in the database." ))) {
68 browserName
: navigator
. appName
,
69 browserVersion
: navigator
. appVersion
,
70 browserPlatform
: navigator
. platform
,
71 browserCookies
: navigator
. cookieEnabled
,
74 var url
= "http://tt-rss.org/report.php?" + params
. toQueryString ();
90 function format_exception_error ( location
, e
) {
94 var base_fname
= e
. fileName
. substring ( e
. fileName
. lastIndexOf ( "/" ) + 1 );
96 msg
= "Exception: " + e
. name
+ ", " + e
. message
+
97 " \n Function: " + location
+ "()" +
98 " \n Location: " + base_fname
+ ":" + e
. lineNumber
;
100 } else if ( e
. description
) {
101 msg
= "Exception: " + e
. description
+ " \n Function: " + location
+ "()" ;
103 msg
= "Exception: " + e
+ " \n Function: " + location
+ "()" ;
106 console
. error ( "EXCEPTION: " + msg
);
111 function param_escape ( arg
) {
112 if ( typeof encodeURIComponent
!= 'undefined' )
113 return encodeURIComponent ( arg
);
118 function param_unescape ( arg
) {
119 if ( typeof decodeURIComponent
!= 'undefined' )
120 return decodeURIComponent ( arg
);
122 return unescape ( arg
);
125 var notify_hide_timerid
= false ;
127 function hide_notify () {
130 n
. style
. display
= "none" ;
134 function notify_silent_next () {
135 notify_silent
= true ;
138 function notify_real ( msg
, no_hide
, n_type
) {
141 notify_silent
= false ;
146 var nb
= $( "notify_body" );
148 if (! n
|| ! nb
) return ;
150 if ( notify_hide_timerid
) {
151 window
. clearTimeout ( notify_hide_timerid
);
155 if ( n
. style
. display
== "block" ) {
156 notify_hide_timerid
= window
. setTimeout ( "hide_notify()" , 0 );
160 n
. style
. display
= "block" ;
172 if ( typeof __
!= 'undefined' ) {
177 n
. className
= "notify" ;
178 } else if ( n_type
== 2 ) {
179 n
. className
= "notifyProgress" ;
180 msg
= "<img src='" + getInitParam ( "sign_progress" )+ "'> " + msg
;
181 } else if ( n_type
== 3 ) {
182 n
. className
= "notifyError" ;
183 msg
= "<img src='" + getInitParam ( "sign_excl" )+ "'> " + msg
;
184 } else if ( n_type
== 4 ) {
185 n
. className
= "notifyInfo" ;
186 msg
= "<img src='" + getInitParam ( "sign_info" )+ "'> " + msg
;
189 // msg = "<img src='images/live_com_loading.gif'> " + msg;
194 notify_hide_timerid
= window
. setTimeout ( "hide_notify()" , 3000 );
198 function notify ( msg
, no_hide
) {
199 notify_real ( msg
, no_hide
, 1 );
202 function notify_progress ( msg
, no_hide
) {
203 notify_real ( msg
, no_hide
, 2 );
206 function notify_error ( msg
, no_hide
) {
207 notify_real ( msg
, no_hide
, 3 );
211 function notify_info ( msg
, no_hide
) {
212 notify_real ( msg
, no_hide
, 4 );
215 function setCookie ( name
, value
, lifetime
, path
, domain
, secure
) {
221 d
. setTime ( d
. getTime () + ( lifetime
* 1000 ));
224 console
. log ( "setCookie: " + name
+ " => " + value
+ ": " + d
);
226 int_setCookie ( name
, value
, d
, path
, domain
, secure
);
230 function int_setCookie ( name
, value
, expires
, path
, domain
, secure
) {
231 document
. cookie
= name
+ "=" + escape ( value
) +
232 (( expires
) ? "; expires=" + expires
. toGMTString () : "" ) +
233 (( path
) ? "; path=" + path
: "" ) +
234 (( domain
) ? "; domain=" + domain
: "" ) +
235 (( secure
) ? "; secure" : "" );
238 function delCookie ( name
, path
, domain
) {
239 if ( getCookie ( name
)) {
240 document
. cookie
= name
+ "=" +
241 (( path
) ? ";path=" + path
: "" ) +
242 (( domain
) ? ";domain=" + domain
: "" ) +
243 ";expires=Thu, 01-Jan-1970 00:00:01 GMT" ;
248 function getCookie ( name
) {
250 var dc
= document
. cookie
;
251 var prefix
= name
+ "=" ;
252 var begin
= dc
. indexOf ( "; " + prefix
);
254 begin
= dc
. indexOf ( prefix
);
255 if ( begin
!= 0 ) return null ;
260 var end
= document
. cookie
. indexOf ( ";" , begin
);
264 return unescape ( dc
. substring ( begin
+ prefix
. length
, end
));
267 function gotoPreferences () {
268 document
. location
. href
= "prefs.php" ;
271 function gotoMain () {
272 document
. location
. href
= "tt-rss.php" ;
275 function gotoExportOpml () {
276 document
. location
. href
= "opml.php?op=Export" ;
280 /** * @(#)isNumeric.js * * Copyright (c) 2000 by Sundar Dorai-Raj
281 * * @author Sundar Dorai-Raj
282 * * Email: sdoraira@vt.edu
283 * * This program is free software; you can redistribute it and/or
284 * * modify it under the terms of the GNU General Public License
285 * * as published by the Free Software Foundation; either version 2
286 * * of the License, or (at your option) any later version,
287 * * provided that any use properly credits the author.
288 * * This program is distributed in the hope that it will be useful,
289 * * but WITHOUT ANY WARRANTY; without even the implied warranty of
290 * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
291 * * GNU General Public License for more details at http://www.gnu.org * * */
293 var numbers
= ".0123456789" ;
294 function isNumeric ( x
) {
295 // is x a String or a character?
297 // remove negative sign
299 for ( j
= 0 ; j
< x
. length
; j
++) {
300 // call isNumeric recursively for each character
301 number
= isNumeric ( x
. substring ( j
, j
+ 1 ));
302 if (! number
) return number
;
307 // if x is number return true
308 if ( numbers
. indexOf ( x
)>= 0 ) return true ;
314 function toggleSelectRowById ( sender
, id
) {
316 return toggleSelectRow ( sender
, row
);
319 function toggleSelectListRow ( sender
) {
320 var row
= sender
. parentNode
;
321 return toggleSelectRow ( sender
, row
);
324 /* this is for dijit Checkbox */
325 function toggleSelectListRow2 ( sender
) {
326 var row
= sender
. domNode
. parentNode
;
327 return toggleSelectRow ( sender
, row
);
330 function tSR ( sender
, row
) {
331 return toggleSelectRow ( sender
, row
);
334 /* this is for dijit Checkbox */
335 function toggleSelectRow2 ( sender
, row
) {
337 if (! row
) row
= sender
. domNode
. parentNode
. parentNode
;
339 if ( sender
. checked
&& ! row
. hasClassName ( 'Selected' ))
340 row
. addClassName ( 'Selected' );
342 row
. removeClassName ( 'Selected' );
346 function toggleSelectRow ( sender
, row
) {
348 if (! row
) row
= sender
. parentNode
. parentNode
;
350 if ( sender
. checked
&& ! row
. hasClassName ( 'Selected' ))
351 row
. addClassName ( 'Selected' );
353 row
. removeClassName ( 'Selected' );
356 function checkboxToggleElement ( elem
, id
) {
358 Effect
. Appear ( id
, { duration
: 0.5 });
360 Effect
. Fade ( id
, { duration
: 0.5 });
364 function dropboxSelect ( e
, v
) {
365 for ( i
= 0 ; i
< e
. length
; i
++) {
366 if ( e
[ i
]. value
== v
) {
373 // originally stolen from http://www.11tmr.com/11tmr.nsf/d6plinks/MWHE-695L9Z
374 // bugfixed just a little bit :-)
375 function getURLParam ( strParamName
){
377 var strHref
= window
. location
. href
;
379 if ( strHref
. indexOf ( "#" ) == strHref
. length
- 1 ) {
380 strHref
= strHref
. substring ( 0 , strHref
. length
- 1 );
383 if ( strHref
. indexOf ( "?" ) > - 1 ){
384 var strQueryString
= strHref
. substr ( strHref
. indexOf ( "?" ));
385 var aQueryString
= strQueryString
. split ( "&" );
386 for ( var iParam
= 0 ; iParam
< aQueryString
. length
; iParam
++ ){
387 if ( aQueryString
[ iParam
]. indexOf ( strParamName
+ "=" ) > - 1 ){
388 var aParam
= aQueryString
[ iParam
]. split ( "=" );
389 strReturn
= aParam
[ 1 ];
397 function leading_zero ( p
) {
399 if ( s
. length
== 1 ) s
= "0" + s
;
403 function make_timestamp () {
406 return leading_zero ( d
. getHours ()) + ":" + leading_zero ( d
. getMinutes ()) +
407 ":" + leading_zero ( d
. getSeconds ());
411 function closeErrorBox () {
413 if ( Element
. visible ( "errorBoxShadow" )) {
414 Element
. hide ( "dialog_overlay" );
415 Element
. hide ( "errorBoxShadow" );
421 function closeInfoBox ( cleanup
) {
423 dialog
= dijit
. byId ( "infoBox" );
425 if ( dialog
) dialog
. hide ();
428 //exception_error("closeInfoBox", e);
434 function displayDlg ( id
, param
, callback
) {
436 notify_progress ( "Loading, please wait..." , true );
438 var query
= "?op=dlg&id=" +
439 param_escape ( id
) + "¶m=" + param_escape ( param
);
441 new Ajax
. Request ( "backend.php" , {
443 onComplete : function ( transport
) {
444 infobox_callback2 ( transport
);
445 if ( callback
) callback ( transport
);
451 function infobox_callback2 ( transport
) {
455 if ( dijit
. byId ( "infoBox" )) {
456 dialog
= dijit
. byId ( "infoBox" );
459 //console.log("infobox_callback2");
463 var dtitle
= "Dialog" ;
465 var dlg
= transport
. responseXML
. getElementsByTagName ( "dlg" )[ 0 ];
467 var title
= transport
. responseXML
. getElementsByTagName ( "title" )[ 0 ];
469 title
= title
. firstChild
. nodeValue
;
471 var content
= transport
. responseXML
. getElementsByTagName ( "content" )[ 0 ];
473 content
= content
. firstChild
. nodeValue
;
476 dialog
= new dijit
. Dialog ({
479 style
: "width: 600px" ,
480 onCancel : function () {
483 onExecute : function () {
486 onClose : function () {
491 dialog
. attr ( 'title' , title
);
492 dialog
. attr ( 'content' , content
);
499 exception_error ( "infobox_callback2" , e
);
503 function filterCR ( e
, f
)
508 key
= window
. event
. keyCode
; //IE
510 key
= e
. which
; //firefox
513 if ( typeof f
!= 'undefined' ) {
524 function getInitParam ( key
) {
525 return init_params
[ key
];
528 function setInitParam ( key
, value
) {
529 init_params
[ key
] = value
;
532 function fatalError ( code
, msg
, ext_info
) {
536 window
. location
. href
= "tt-rss.php" ;
537 } else if ( code
== 5 ) {
538 window
. location
. href
= "db-updater.php" ;
541 if ( msg
== "" ) msg
= "Unknown error" ;
544 if ( ext_info
. responseText
) {
545 ext_info
= ext_info
. responseText
;
549 if ( ERRORS
&& ERRORS
[ code
] && ! msg
) {
553 var content
= "<div><b>Error code:</b> " + code
+ "</div>" +
554 "<p>" + msg
+ "</p>" ;
557 content
= content
+ "<div><b>Additional information:</b></div>" +
558 "<textarea style='width: 100%' readonly= \" 1 \" >" +
559 ext_info
+ "</textarea>" ;
562 var dialog
= new dijit
. Dialog ({
563 title
: "Fatal error" ,
564 style
: "width: 600px" ,
574 exception_error ( "fatalError" , e
);
578 function filterDlgCheckType ( sender
) {
582 var ftype
= sender
. value
;
584 // if selected filter type is 5 (Date) enable the modifier dropbox
586 Element
. show ( "filterDlg_dateModBox" );
587 Element
. show ( "filterDlg_dateChkBox" );
589 Element
. hide ( "filterDlg_dateModBox" );
590 Element
. hide ( "filterDlg_dateChkBox" );
595 exception_error ( "filterDlgCheckType" , e
);
600 function filterDlgCheckAction ( sender
) {
604 var action
= sender
. value
;
606 var action_param
= $( "filterDlg_paramBox" );
609 console
. log ( "filterDlgCheckAction: can't find action param box!" );
613 // if selected action supports parameters, enable params field
614 if ( action
== 4 || action
== 6 || action
== 7 ) {
615 new Effect
. Appear ( action_param
, { duration
: 0.5 });
617 Element
. show ( dijit
. byId ( "filterDlg_actionParam" ). domNode
);
618 Element
. hide ( dijit
. byId ( "filterDlg_actionParamLabel" ). domNode
);
620 Element
. show ( dijit
. byId ( "filterDlg_actionParamLabel" ). domNode
);
621 Element
. hide ( dijit
. byId ( "filterDlg_actionParam" ). domNode
);
624 Element
. hide ( action_param
);
628 exception_error ( "filterDlgCheckAction" , e
);
633 function filterDlgCheckDate () {
635 var dialog
= dijit
. byId ( "filterEditDlg" );
637 var reg_exp
= dialog
. attr ( 'value' ). reg_exp
;
639 var query
= "?op=rpc&subop=checkDate&date=" + reg_exp
;
641 new Ajax
. Request ( "backend.php" , {
643 onComplete : function ( transport
) {
645 var reply
= JSON
. parse ( transport
. responseText
);
647 if ( reply
[ 'result' ] == true ) {
648 alert ( __ ( "Date syntax appears to be correct." ));
651 alert ( __ ( "Date syntax is incorrect." ));
658 exception_error ( "filterDlgCheckDate" , e
);
662 function explainError ( code
) {
663 return displayDlg ( "explainError" , code
);
666 function displayHelpInfobox ( topic_id
) {
668 var url
= "backend.php?op=help&tid=" + param_escape ( topic_id
);
670 var w
= window
. open ( url
, "ttrss_help" ,
671 "status=0,toolbar=0,location=0,width=450,height=500,scrollbars=1,menubar=0" );
675 function loading_set_progress ( p
) {
677 loading_progress
+= p
;
679 if ( dijit
. byId ( "loading_bar" ))
680 dijit
. byId ( "loading_bar" ). update ({ progress
: loading_progress
});
682 if ( loading_progress
>= 90 )
686 exception_error ( "loading_set_progress" , e
);
690 function remove_splash () {
692 if ( Element
. visible ( "overlay" )) {
693 console
. log ( "about to remove splash, OMG!" );
694 Element
. hide ( "overlay" );
695 console
. log ( "removed splash!" );
699 function transport_error_check ( transport
) {
701 if ( transport
. responseXML
) {
702 var error
= transport
. responseXML
. getElementsByTagName ( "error" )[ 0 ];
705 var code
= error
. getAttribute ( "error-code" );
706 var msg
= error
. getAttribute ( "error-msg" );
708 fatalError ( code
, msg
);
714 exception_error ( "check_for_error_xml" , e
);
719 function strip_tags ( s
) {
720 return s
. replace ( /<\/?[^>]+(>|$)/g , "" );
723 function truncate_string ( s
, length
) {
724 if (! length
) length
= 30 ;
725 var tmp
= s
. substring ( 0 , length
);
726 if ( s
. length
> length
) tmp
+= "…" ;
730 function hotkey_prefix_timeout () {
733 var date
= new Date ();
734 var ts
= Math
. round ( date
. getTime () / 1000 );
736 if ( hotkey_prefix_pressed
&& ts
- hotkey_prefix_pressed
>= 5 ) {
737 console
. log ( "hotkey_prefix seems to be stuck, aborting" );
738 hotkey_prefix_pressed
= false ;
739 hotkey_prefix
= false ;
740 Element
. hide ( 'cmdline' );
743 setTimeout ( "hotkey_prefix_timeout()" , 1000 );
746 exception_error ( "hotkey_prefix_timeout" , e
);
750 function hideAuxDlg () {
752 Element
. hide ( 'auxDlg' );
754 exception_error ( "hideAuxDlg" , e
);
759 function uploadIconHandler ( rc
) {
763 notify_info ( "Upload complete." );
764 if ( inPreferences ()) {
767 setTimeout ( 'updateFeedList(false, false)' , 50 );
771 notify_error ( "Upload failed: icon is too big." );
774 notify_error ( "Upload failed." );
779 exception_error ( "uploadIconHandler" , e
);
783 function removeFeedIcon ( id
) {
787 if ( confirm ( __ ( "Remove stored feed icon?" ))) {
788 var query
= "backend.php?op=pref-feeds&subop=removeicon&feed_id=" + param_escape ( id
);
792 notify_progress ( "Removing feed icon..." , true );
794 new Ajax
. Request ( "backend.php" , {
796 onComplete : function ( transport
) {
797 notify_info ( "Feed icon removed." );
798 if ( inPreferences ()) {
801 setTimeout ( 'updateFeedList(false, false)' , 50 );
808 exception_error ( "uploadFeedIcon" , e
);
812 function uploadFeedIcon () {
816 var file
= $( "icon_file" );
818 if ( file
. value
. length
== 0 ) {
819 alert ( __ ( "Please select an image file to upload." ));
821 if ( confirm ( __ ( "Upload new icon for this feed?" ))) {
822 notify_progress ( "Uploading, please wait..." , true );
830 exception_error ( "uploadFeedIcon" , e
);
834 function addLabel ( select
, callback
) {
838 var caption
= prompt ( __ ( "Please enter label caption:" ), "" );
840 if ( caption
!= undefined ) {
843 alert ( __ ( "Can't create label: missing caption." ));
847 var query
= "?op=pref-labels&subop=add&caption=" +
848 param_escape ( caption
);
851 query
+= "&output=select" ;
853 notify_progress ( "Loading, please wait..." , true );
855 if ( inPreferences () && ! select
) active_tab
= "labelConfig" ;
857 new Ajax
. Request ( "backend.php" , {
859 onComplete : function ( transport
) {
862 } else if ( inPreferences ()) {
872 exception_error ( "addLabel" , e
);
876 function quickAddFeed () {
878 var query
= "backend.php?op=dlg&id=quickAddFeed" ;
880 if ( dijit
. byId ( "feedAddDlg" ))
881 dijit
. byId ( "feedAddDlg" ). destroyRecursive ();
883 var dialog
= new dijit
. Dialog ({
885 title
: __ ( "Subscribe to Feed" ),
886 style
: "width: 600px" ,
887 execute : function () {
888 if ( this . validate ()) {
889 console
. log ( dojo
. objectToQuery ( this . attr ( 'value' )));
891 var feed_url
= this . attr ( 'value' ). feed
;
893 notify_progress ( __ ( "Subscribing to feed..." ), true );
895 new Ajax
. Request ( "backend.php" , {
896 parameters
: dojo
. objectToQuery ( this . attr ( 'value' )),
897 onComplete : function ( transport
) {
900 var reply
= JSON
. parse ( transport
. responseText
);
902 var rc
= parseInt ( reply
[ 'result' ]);
906 console
. log ( "GOT RC: " + rc
);
911 notify_info ( __ ( "Subscribed to %s" ). replace ( "%s" , feed_url
));
916 alert ( __ ( "Specified URL seems to be invalid." ));
919 alert ( __ ( "Specified URL doesn't seem to contain any feeds." ));
922 notify_progress ( "Searching for feed urls..." , true );
924 new Ajax
. Request ( "backend.php" , {
925 parameters
: 'op=rpc&subop=extractfeedurls&url=' + param_escape ( feed_url
),
926 onComplete : function ( transport
, dialog
, feed_url
) {
930 var reply
= JSON
. parse ( transport
. responseText
);
932 var feeds
= reply
[ 'urls' ];
934 console
. log ( transport
. responseText
);
936 var select
= dijit
. byId ( "feedDlg_feedContainerSelect" );
938 while ( select
. getOptions (). length
> 0 )
939 select
. removeOption ( 0 );
942 for ( var feedUrl
in feeds
) {
943 select
. addOption ({ value
: feedUrl
, label
: feeds
[ feedUrl
]});
947 // if (count > 5) count = 5;
948 // select.size = count;
950 Effect
. Appear ( 'feedDlg_feedsContainer' , { duration
: 0.5 });
955 alert ( __ ( "Couldn't download the specified URL." ));
958 alert ( __ ( "You are already subscribed to this feed." ));
963 exception_error ( "subscribeToFeed" , e
);
974 exception_error ( "quickAddFeed" , e
);
978 function quickAddFilter () {
980 var query
= "backend.php?op=dlg&id=quickAddFilter" ;
982 if ( dijit
. byId ( "filterEditDlg" ))
983 dijit
. byId ( "filterEditDlg" ). destroyRecursive ();
985 dialog
= new dijit
. Dialog ({
987 title
: __ ( "Create Filter" ),
988 style
: "width: 600px" ,
989 execute : function () {
990 if ( this . validate ()) {
992 var query
= "?op=rpc&subop=verifyRegexp®_exp=" +
993 param_escape ( dialog
. attr ( 'value' ). reg_exp
);
995 notify_progress ( "Verifying regular expression..." );
997 new Ajax
. Request ( "backend.php" , {
999 onComplete : function ( transport
) {
1000 var reply
= JSON
. parse ( transport
. responseText
);
1005 if (! reply
[ 'status' ]) {
1006 alert ( "Match regular expression seems to be invalid." );
1009 notify_progress ( "Saving data..." , true );
1011 console
. log ( dojo
. objectToQuery ( dialog
. attr ( 'value' )));
1013 new Ajax
. Request ( "backend.php" , {
1014 parameters
: dojo
. objectToQuery ( dialog
. attr ( 'value' )),
1015 onComplete : function ( transport
) {
1017 notify_info ( transport
. responseText
);
1018 if ( inPreferences ()) {
1031 exception_error ( "quickAddFilter" , e
);
1035 function unsubscribeFeed ( feed_id
, title
) {
1037 var msg
= __ ( "Unsubscribe from %s?" ). replace ( "%s" , title
);
1039 if ( title
== undefined || confirm ( msg
)) {
1040 notify_progress ( "Removing feed..." );
1042 var query
= "?op=pref-feeds&quiet=1&subop=remove&ids=" + feed_id
;
1044 new Ajax
. Request ( "backend.php" , {
1046 onComplete : function ( transport
) {
1048 if ( dijit
. byId ( "feedEditDlg" )) dijit
. byId ( "feedEditDlg" ). hide ();
1050 if ( inPreferences ()) {
1053 if ( feed_id
== getActiveFeedId ())
1054 setTimeout ( "viewfeed(-5)" , 100 );
1064 function backend_sanity_check_callback ( transport
) {
1068 if ( sanity_check_done
) {
1069 fatalError ( 11 , "Sanity check request received twice. This can indicate " +
1070 "presence of Firebug or some other disrupting extension. " +
1071 "Please disable it and try again." );
1075 if (! transport
. responseXML
) {
1077 fatalError ( 3 , "Sanity check: Received reply is not XML" ,
1078 transport
. responseText
);
1083 var reply
= transport
. responseXML
. getElementsByTagName ( "error" )[ 0 ];
1086 fatalError ( 3 , "Sanity check: invalid RPC reply" , transport
. responseText
);
1090 var error_code
= reply
. getAttribute ( "error-code" );
1092 if ( error_code
&& error_code
!= 0 ) {
1093 return fatalError ( error_code
, reply
. getAttribute ( "error-msg" ));
1096 console
. log ( "sanity check ok" );
1098 var params
= transport
. responseXML
. getElementsByTagName ( "init-params" )[ 0 ];
1101 console
. log ( 'reading init-params...' );
1103 params
= JSON
. parse ( params
. firstChild
. nodeValue
);
1108 console
. log ( "IP: " + k
+ " => " + v
);
1112 init_params
= params
;
1115 sanity_check_done
= true ;
1117 init_second_stage ();
1120 exception_error ( "backend_sanity_check_callback" , e
, transport
);
1124 function has_local_storage () {
1126 return 'sessionStorage' in window
&& window
[ 'sessionStorage' ] != null ;
1132 function catSelectOnChange ( elem
) {
1134 /* var value = elem[elem.selectedIndex].value;
1135 var def = elem.getAttribute('default');
1137 if (value == "ADD_CAT") {
1140 dropboxSelect(elem, def);
1142 elem.selectedIndex = 0;
1148 exception_error ( "catSelectOnChange" , e
);
1152 function quickAddCat ( elem
) {
1154 var cat
= prompt ( __ ( "Please enter category title:" ));
1158 var query
= "?op=rpc&subop=quickAddCat&cat=" + param_escape ( cat
);
1160 notify_progress ( "Loading, please wait..." , true );
1162 new Ajax
. Request ( "backend.php" , {
1164 onComplete : function ( transport
) {
1165 var response
= transport
. responseXML
;
1166 var select
= response
. getElementsByTagName ( "select" )[ 0 ];
1167 var options
= select
. getElementsByTagName ( "option" );
1169 dropbox_replace_options ( elem
, options
);
1178 exception_error ( "quickAddCat" , e
);
1182 function genUrlChangeKey ( feed
, is_cat
) {
1185 var ok
= confirm ( __ ( "Generate new syndication address for this feed?" ));
1189 notify_progress ( "Trying to change address..." , true );
1191 var query
= "?op=rpc&subop=regenFeedKey&id=" + param_escape ( feed
) +
1192 "&is_cat=" + param_escape ( is_cat
);
1194 new Ajax
. Request ( "backend.php" , {
1196 onComplete : function ( transport
) {
1197 var reply
= JSON
. parse ( transport
. responseText
);
1198 var new_link
= reply
. link
;
1200 var e
= $( 'gen_feed_url' );
1204 e
. innerHTML
= e
. innerHTML
. replace ( /\&key=.*$/ ,
1205 "&key=" + new_link
);
1207 e
. href
= e
. href
. replace ( /\&key=.*$/ ,
1208 "&key=" + new_link
);
1210 new Effect
. Highlight ( e
);
1215 notify_error ( "Could not change feed URL." );
1220 exception_error ( "genUrlChangeKey" , e
);
1225 function labelSelectOnChange ( elem
) {
1227 /* var value = elem[elem.selectedIndex].value;
1228 var def = elem.getAttribute('default');
1230 if (value == "ADD_LABEL") {
1233 dropboxSelect(elem, def);
1235 elem.selectedIndex = 0;
1237 addLabel(elem, function(transport) {
1241 var response = transport.responseXML;
1242 var select = response.getElementsByTagName("select")[0];
1243 var options = select.getElementsByTagName("option");
1245 dropbox_replace_options(elem, options);
1249 exception_error("addLabel", e);
1255 exception_error ( "labelSelectOnChange" , e
);
1259 function dropbox_replace_options ( elem
, options
) {
1262 while ( elem
. hasChildNodes ())
1263 elem
. removeChild ( elem
. firstChild
);
1267 for ( var i
= 0 ; i
< options
. length
; i
++) {
1268 var text
= options
[ i
]. firstChild
. nodeValue
;
1269 var value
= options
[ i
]. getAttribute ( "value" );
1271 if ( value
== undefined ) value
= text
;
1273 var issel
= options
[ i
]. getAttribute ( "selected" ) == "1" ;
1275 var option
= new Option ( text
, value
, issel
);
1277 if ( options
[ i
]. getAttribute ( "disabled" ))
1278 option
. setAttribute ( "disabled" , true );
1280 elem
. insert ( option
);
1282 if ( issel
) sel_idx
= i
;
1285 // Chrome doesn't seem to just select stuff when you pass new Option(x, y, true)
1286 if ( sel_idx
>= 0 ) elem
. selectedIndex
= sel_idx
;
1289 exception_error ( "dropbox_replace_options" , e
);
1293 // mode = all, none, invert
1294 function selectTableRows ( id
, mode
) {
1296 var rows
= $( id
). rows
;
1298 for ( var i
= 0 ; i
< rows
. length
; i
++) {
1302 if ( row
. id
&& row
. className
) {
1303 var bare_id
= row
. id
. replace ( /^[A-Z]*?-/ , "" );
1304 var inputs
= rows
[ i
]. getElementsByTagName ( "input" );
1306 for ( var j
= 0 ; j
< inputs
. length
; j
++) {
1307 var input
= inputs
[ j
];
1309 if ( input
. getAttribute ( "type" ) == "checkbox" &&
1310 input
. id
. match ( bare_id
)) {
1318 var issel
= row
. hasClassName ( "Selected" );
1320 if ( mode
== "all" && ! issel
) {
1321 row
. addClassName ( "Selected" );
1323 } else if ( mode
== "none" && issel
) {
1324 row
. removeClassName ( "Selected" );
1326 } else if ( mode
== "invert" ) {
1329 row
. removeClassName ( "Selected" );
1332 row
. addClassName ( "Selected" );
1341 exception_error ( "selectTableRows" , e
);
1346 function getSelectedTableRowIds ( id
) {
1350 var elem_rows
= $( id
). rows
;
1352 for ( i
= 0 ; i
< elem_rows
. length
; i
++) {
1353 if ( elem_rows
[ i
]. hasClassName ( "Selected" )) {
1354 var bare_id
= elem_rows
[ i
]. id
. replace ( /^[A-Z]*?-/ , "" );
1360 exception_error ( "getSelectedTableRowIds" , e
);
1366 function editFeed ( feed
, event
) {
1369 return alert ( __ ( "You can't edit this kind of feed." ));
1371 var query
= "backend.php?op=pref-feeds&subop=editfeed&id=" +
1376 if ( dijit
. byId ( "feedEditDlg" ))
1377 dijit
. byId ( "feedEditDlg" ). destroyRecursive ();
1379 dialog
= new dijit
. Dialog ({
1381 title
: __ ( "Edit Feed" ),
1382 style
: "width: 600px" ,
1383 execute : function () {
1384 if ( this . validate ()) {
1385 // console.log(dojo.objectToQuery(this.attr('value')));
1387 notify_progress ( "Saving data..." , true );
1389 new Ajax
. Request ( "backend.php" , {
1390 parameters
: dojo
. objectToQuery ( dialog
. attr ( 'value' )),
1391 onComplete : function ( transport
) {
1403 exception_error ( "editFeed" , e
);
1407 function feedBrowser () {
1409 var query
= "backend.php?op=dlg&id=feedBrowser" ;
1411 if ( dijit
. byId ( "feedAddDlg" ))
1412 dijit
. byId ( "feedAddDlg" ). hide ();
1414 if ( dijit
. byId ( "feedBrowserDlg" ))
1415 dijit
. byId ( "feedBrowserDlg" ). destroyRecursive ();
1417 var dialog
= new dijit
. Dialog ({
1418 id
: "feedBrowserDlg" ,
1419 title
: __ ( "More Feeds" ),
1420 style
: "width: 600px" ,
1421 getSelectedFeeds : function () {
1422 var list
= $$( "#browseFeedList li[id*=FBROW]" );
1423 var selected
= new Array ();
1425 list
. each ( function ( child
) {
1426 var id
= child
. id
. replace ( "FBROW-" , "" );
1428 if ( child
. hasClassName ( 'Selected' )) {
1435 subscribe : function () {
1436 var selected
= this . getSelectedFeeds ();
1437 var mode
= this . attr ( 'value' ). mode
;
1439 if ( selected
. length
> 0 ) {
1440 dijit
. byId ( "feedBrowserDlg" ). hide ();
1442 notify_progress ( "Loading, please wait..." , true );
1444 var query
= "?op=rpc&subop=massSubscribe&ids=" +
1445 param_escape ( selected
. toString ()) + "&mode=" + param_escape ( mode
);
1449 new Ajax
. Request ( "backend.php" , {
1451 onComplete : function ( transport
) {
1452 if ( inPreferences ()) {
1458 alert ( __ ( "No feeds are selected." ));
1462 update : function () {
1463 var query
= dojo
. objectToQuery ( dialog
. attr ( 'value' ));
1465 Element
. show ( 'feed_browser_spinner' );
1467 new Ajax
. Request ( "backend.php" , {
1469 onComplete : function ( transport
) {
1472 Element
. hide ( 'feed_browser_spinner' );
1474 var c
= $( "browseFeedList" );
1476 var reply
= JSON
. parse ( transport
. responseText
);
1478 var r
= reply
[ 'content' ];
1479 var mode
= reply
[ 'mode' ];
1485 dojo
. parser
. parse ( "browseFeedList" );
1488 Element
. show ( dijit
. byId ( 'feed_archive_remove' ). domNode
);
1490 Element
. hide ( dijit
. byId ( 'feed_archive_remove' ). domNode
);
1495 removeFromArchive : function () {
1496 var selected
= this . getSelectedFeeds ();
1498 if ( selected
. length
> 0 ) {
1500 var pr
= __ ( "Remove selected feeds from the archive? Feeds with stored articles will not be removed." );
1503 Element
. show ( 'feed_browser_spinner' );
1505 var query
= "?op=rpc&subop=remarchived&ids=" +
1506 param_escape ( selected
. toString ());;
1508 new Ajax
. Request ( "backend.php" , {
1510 onComplete : function ( transport
) {
1516 execute : function () {
1517 if ( this . validate ()) {
1526 exception_error ( "editFeed" , e
);