-
Notifications
You must be signed in to change notification settings - Fork 48
/
all.build.map.js
1 lines (1 loc) · 308 KB
/
all.build.map.js
1
{"version":3,"sources":["node_modules/keymaster/keymaster.js","js/patch_ace.js","js/utils.js","js/offline_simple.js","js/drop_down.js","js/info.js","js/file_model.js","js/settings_pane.js","js/open_pane.js","js/help_pane.js","js/using_apis.js","js/clipboard.js","js/save.js","js/print.js","js/file_pane.js","js/patch_ace_history.js","js/history_tool.js","js/find_pane.js","js/keyboard.js","js/app.js"],"names":["global","k","_handlers","_mods",16,18,17,91,"_scope","_MODIFIERS","⇧","shift","⌥","alt","option","⌃","ctrl","control","⌘","command","_MAP","backspace","tab","clear","enter","return","esc","escape","space","left","up","right","down","del","delete","home","end","pageup","pagedown",",",".","/","`","-","=",";","'","[","]","\\","code","x","toUpperCase","charCodeAt","_downKeys","index","array","item","i","length","compareArray","a1","a2","modifierMap","updateModifierKey","event","dispatch","key","handler","modifiersMatch","scope","keyCode","push","assignKey","filter","call","this","getScope","mods","method","preventDefault","returnValue","stopPropagation","cancelBubble","clearModifier","splice","resetModifiers","keys","getKeys","undefined","split","getMods","shortcut","unbindKey","multipleKeys","j","obj","isPressed","getPressedKeyCodes","slice","tagName","target","srcElement","setScope","deleteScope","handlers","replace","mi","addEvent","object","addEventListener","attachEvent","window","document","previousKey","noConflict","unbind","module","exports","UndoManager","ace","require","original_execute","prototype","execute","id_counter","options","deltaSets","args","ii","delta_array_id","getCurrentId","top_delta_set","$undoStack","oxford_comma","arr","rotate","el","deg","style","transform","webkitTansform","mozTransform","translate","y","str","webkitTransform","text_multi","text","truncate_long_words","textContent","innerHTML","escape_str","hex_print_string","c","toString","console","log","join","js_str_from_utf16","bom","Uint16Array","Uint8Array","buffer","endian","TextDecoder","decode","decode_body","body","substr","String","fromCharCode","decodeURIComponent","e","css_animation","timers","els","cls","callback","delay","classList","remove","offsetTop","old_idx","indexOf","clearTimeout","setTimeout","add","stop_propagation","prevent_default","prevent_default_and_stop_propagation","until_success","executor","before_retry","outer_executor","succeed","reject","rejection_handler","err","pre_retry_result","pre_retry_error","Promise","then","outer_promise","func","ext_from_filename","Math","max","lastIndexOf","Infinity","load_script_async","url","new_el","createElement","async","src","something_el","getElementsByTagName","parentNode","insertBefore","offline_simple","callbacks","delay_chain",0,1,500,1000,2500,5000,10000,60000,"timer","commence_testing","run_test","request_test","kind","foo","trigger","is_online","xhr","XMLHttpRequest","open","Date","getTime","timeout","check_status","status","onprogress","onerror","ontimeout","onload","onreadystatechange","readyState","checkStatus","send","DropDown","val_array","map","val","el_list","className","tabindex","display","el_collapsed","appendChild","ind","event_callbacks","enabled","dd","document_mousedown","removeEventListener","focus","scrollTop","children","on_click","SetInd","getAttribute","setAttribute","FakeEvent","is_stopped","stopImmediatePropagation","evt","fe","IndexOf","GetVal","no_trigger","min","parseInt","title","isOpen","SetSelected","v","dn","menu_id_to_caption","menu_print","menu_sharing","menu_save","menu_history","menu_file","menu_new","menu_open","menu_find","menu_goto","menu_general_settings","menu_shortcuts","menu_drive","menu_help","shortcuts_list","ext_to_mime_type","html","htm","js","pl","xml","cpp","h","json","php","svg","css","java","py","scala","textile","tex","bib","rtf","rtx","sh","sql","as","tooltip_info","save","print","sharing","file history","drive","about","shortcuts","new","settings_file","settings_general","description","WHICH","ENTER","ESC","UP","DOWN","default_settings","ext","wordWrap","wordWrapAt","fontSize","widget_anchor","showGutterHistory","lastDNVersionUsed","newLineDefault","historyRemovedIsExpanded","softTabN","tabIsHard","widgetSub","theme","pane","pane_open","find_regex","find_whole_words","find_case_sensitive","help_inner","find_goto","find_replace","impersonal_settings_keys","const_","auth_timeout","drag_delay_ms","drag_shift_px","min_font_size","max_font_size","max_wrap_at","min_wrap_at","wrap_at_increment","max_soft_tab_n","min_soft_tab_n","detect_tabs_spaces_frac","detect_tabs_tabs_frac","detect_tabs_n_spaces_frac","detect_tabs_n_spaces_frac_for_default","font_size_increment","error_delay_ms","find_history_add_delay","find_history_max_len","clipboard_info_delay","clipboard_max_length","find_max_results_half","find_max_prefix_chars","find_max_suffix_chars","ad_initial_wait","platform","navigator","FileModel","is_loaded","file_id","folder_id","loaded_body","loaded_mime_type","chosen_mime_type","is_read_only","is_shared","properties_chosen","properties","properties_detected_info","change_callbacks","ob","set","syntax","compute_syntax","newline","compute_newline","tabs","n","compute_tabs","update_mime_type","property","old_title","new_title","old_ext","new_ext","first_n","g_settings","get","has_rn","has_solo_n","match","all_modes","modes","caption","detected","getModeForPath","re_whitepace","prop","JSON","parse","indents","n_only_tabs","n_only_space","space_hist","n_with_mixture","n_samp","indents_ii","without_tabs","space_mod_hist","ss","m","settings_pane","theme_drop_down","on_document_ready","theme_chooser","getElementById","button_clear_clipboard","button_clear_find_replace","gutter_history_show","gutter_history_hide","word_wrap_off","word_wrap_at","word_wrap_edge","font_size_dec","font_size_inc","font_size_text","tab_hard","tab_soft","newline_windows","newline_unix","tab_soft_text","tab_soft_dec","tab_soft_inc","word_wrap_at_text","word_wrap_at_dec","word_wrap_at_inc","on_change","themes","Object","themesByName","focus_editor","at","font_size_dec_click","font_size_inc_click","g_clipboard","g_find_history","font_size","new_value","newValue","s","editor","getSession","scrollLine","get_scroll_line","toFixed","open_pane","picker","opener_button_a","open_button_click","gapi","load","view","google","View","ViewId","DOCS","PickerBuilder","enableFeature","Feature","NAV_HIDDEN","setAppId","client_id","setOAuthToken","auth","getToken","access_token","addView","setCallback","picker_callback","build","setVisible","show_error","data","action","Action","PICKED","docs","id","stringify","userId","url_user_id","ids","location","help_pane","show_inner","inner_pane","inner_pane_shortcuts","inner_pane_tips","inner_pane_main","button_shortcuts","button_tips","render_user_name","user_name","create_pane_shortcuts","arry","dict","parts","on_user_name_change","filter_api_errors","is_auth_error","pr_auth","result","error","Error","stack","ga","exDescription","_","type","reason","errors","api_error_to_string","message","dir","handle_auth_error","authorization","popup_active","show_status","err_type","reauth_auto","toggle_permission","reauth_auto_delay_chain","reauth_auto_timer","reauth_auto_delay","race","authorize","auth_map","make_timeout","resolve","bind","reauth_manual","request_user_info","client","request","path","request_file_meta","the_file","params","fields","request_file_body","headers","contentType","make_multipart_boundary","random","request_new","meta","name","request_revision_list","request_revision_body","revision_id","request_save","has_body","has_meta","is_multipart","boundary","request_body","mimeType","request_app_data_document","succ","fail","app_data_realtime_error","realtime_settings","realtime","loadAppDataDocument","request_screw_up_auth_counter","request_screw_up_auth","setToken","clipboard_tool","is_active","showing_pane","clipboard_index","clipboard_info_timer","document_clipboard_left","undo","insert","document_clipboard_right","g_atomic_exec","document_clipboard_keyup","which","ctrlKey","show_pane","toggle_widget","on_paste","on_copy","previous_idx","move","on","on_left","on_right","save_pending_requests","SaveTracker","local","remote","save_local_version_counter","save_server_state","save_local_state","correction_with_undo_id","user_wants_file","create_file","found_something","editor_undo_id","getUndoManager","save_undo_id","NaN","undo_id","check_unsaved","save_body","save_title","save_other","SaveRequest","_parts","displaced_requests","hasOwnProperty","_is_settled","desired","_desired","_tracker","_error","self","_pr","all","pr_file_loaded","_throw_if_not_desired","_on_completion","catch","_on_error","_on_finally","res","version","pop","correction","correction_need","local_undo_id","do_print","line_to_html","printLayer","create","Text","tokens","getTokens","screenColumn","token","value","$renderToken","content","session","doc","getAllLines","Array","printWindow","writeln","cssText","file_pane","history_active","do_save","getValue","read_only_bail","on_title_begin_edit","title_text","title_input","select","on_title_keydown","on_description_begin_edit","description_text","description_input","on_description_keydown","shiftKey","do_share","file_sharing","share_dialog","do_share_sub","share","ShareClient","setItemIds","showSettingsDialog","on_description_end_edit","new_val","on_title_end_edit","on_newline_click","currentTarget","on_syntax_detect_click","on_syntax_dropdown_click","syntax_drop_down","on_tab_click","render_title","title_text_inner","render_description","description_text_inner","render_newline","newline_detect","newline_info","render_syntax","ace_mode_detect","ace_mode_info","render_tabs","user_tabs","tab_detect","tab_info","end_history","history_tool","button_history","button_save","button_print","inner_pane_history","do_history","start","register_controllers","button_share","ace_mode_choose","on_save_shorcut","on_print_shortcut","on_close_pane","patch_editor_history","Range","dom","show_row","row_line_number","markers","first_rendered_row","rendered_row_transitions","colors_background","transition_duration","$blockScrolling","setHighlightActiveLine","setHighlightGutterLine","toScreenRange","screenPosStart","documentToScreenPosition","screenPosEnd","ret","row","column","doc_range","clone","gutterRenderer","getWidth","lastLineNumber","config","characterWidth","getText","removeAllGutterDecorations","$decorations","_signal","renderer","$markerBack","drawFullLineMarker","stringBuilder","range","clazz","extraStyle","top","$getTop","height","lineHeight","insertFullLines_original","insertFullLines","arg_0","arg_1","len","getLength","getLine","insertMergedLines","kk","splice_args","lines","apply","show_rows","first_row","getFirstVisibleRow","last_row","getLastVisibleRow","first_row_old","last_row_old","time_now","now","unshift","from_time","from_color","to_time","to_color","all_marker_els","element","marker_els","dataset","els_to_set","colors_to_set","colors_current","transition","to_color_new","current_color","elapsed_frac","mix_color","backgroundColor","color_to_string","transitionProperty","transitionDuration","getComputedStyle","a","b","frac","color","show_row_","unfold","removeMarker","line_no","fold_start","first_used_row","addFold","previous","addGutterDecoration","addMarker","updateFull","$resetCursorStyle","$cursorStyle","cursorLayer","$cursorLayer","setSmoothBlinking","test","isBlinking","setCssClass","$mouseHandler","setOptions","dragEnabled","revision_meta","worker_has_revision","revision_uses_line","worker","at_idx","from_idx","LineWidgets","Worker","onmessage","on_worker_message","revisions_view","info_overflow","edit","setFontSize","getFontSize","setUseWrapMode","setReadOnly","refresh_revisions_list","destroy","el_old","cloneNode","replaceChild","get_editor","diffed_revision","idx","sections","el_tick","line_is_used","render_single_revision","render_revision_pair","diffed_n","current_version_date_str","time","date_str_to_local","modifiedTime","info","fuse","at_is_used","from_is_used","time_at","time_from","append_tick","tick_box","send_revisions_order_to_worker","resp","r_to_get","id_order","concat","revisions","reverse","at_range","from_range","postMessage","use_order","render_download_status","render_for_settings","send_revision_body_to_worker","revision","n_pending","reset_with_current_body","body_promises","d","toLocaleDateString","month","day","year","toLocaleTimeString","hour","minute","is_resolved","at_meta","from_meta","caption_at","at_time","caption_from","have_at","have_from","uses_line","render_removed_state","state","remove_expand","remove_collapse","ordered_list","debug","find_pane","goto_input_has_focus","AceSearch","AceRange","search_inputs_have_focus","search_results","search_current_match_idx","search_markers","search_marker_current","search_str","search_history_idx","search_history_left_behind_str","search_history_last_modified_time","focus_on_input","goto_input","find_input","Search","button_case_sensitive","button_whole_words","button_regex","replace_input","button_goto","button_replace","goto_wrapper","find_wrapper","replace_wrapper","button_find_replace_all","settings_changed","on_replace_toggled","on_goto_toggled","goto_input_keydown","goto_input_keyup","goto_input_blur","goto_input_focus","find_input_keyup","find_input_keydown","search_inputs_blur","search_inputs_focus","replace_input_keydown","replace_all","find_shortcut_used","sel","getTextRange","getSelectionRange","update_search_history","goto_shortcut_used","replace_shortcut_used","select_search_result_idx","perform_goto","validated_str","num","gotoLine","navigateLineEnd","current_str","top_of_history","toLowerCase","tabIndex","setHighlightSelectedWord","perform_search","relatedTarget","setSelectionRange","selectionEnd","build_search_options","use_reg_exp","sensitive","re","RegExp","needle","wrap","caseSensitive","wholeWord","regExp","search_options","selection","clearSelection","search","findAll","selected_range","getSelection","getRange","current_match_idx","new_idx","search_results_sub","replace_is_showing","max_search_results","n_pre","n_post","show_replace_buttons","col","prefix_range","pre_ellipses","suffix_range","getElementsByClassName","search_result_click","search_replace_result_click","scrollSelectionIntoView","replace_result_idx","replaceAll","$search","$tryReplace","on_find_shortcut","on_replace_shortcut","on_goto_shortcut","esc_pressed","make_keyboard_shortcuts","commands","removeCommands","do_print_shorcut","do_open","do_new","HashHandler","extraKeyEvents","bindKey","win","mac","descr","exec","keyBinding","addKeyboardHandler","ctrl_key","version_str","can_show_drag_drop_error","file_body","file_meta","file_new","authentication","local_settings","unsaved_changes","warned_read_only","change_line_history","last_change","change_line_classes","rootStr","trueN","factor","change_line_classes_rm","extra","widget_text","widget_pending","widget_error_text","widget_error","the_widget","pane_permissions","permissions_showing","widget_content","el_icon","menu_icon_from_pane_id","widget_mouse_down","widget_mouse_down_info","off_left","clientX","off_top","clientY","start_time","is_dragging","button","document_mouse_move_widget","document_mouse_up_widget","pos","getBoundingClientRect","widget_w","offsetWidth","widget_h","offsetHeight","window_w","innerWidth","window_h","innerHeight","anchor","widget_apply_anchor","isArray","widget_menu","bottom","render_document_title","keeps","change_listeners","keep","get_keeps","flag","transfer_to_true_model","real_model","EventType","VALUE_CHANGED","load_default_settings","localStorage","show_app_data_document","getModel","beginCompoundOperation","endCompoundOperation","old_temp_g_settings","getRoot","existing_cloud_keys","createList","removeRange","last_version","setTheme","scrollToLine","setWrapLimitRange","curWrap","setPrintMarginColumn","removeGutterDecoration","screenToDocumentPosition","getScrollTopRow","show_file_meta","props","capabilities","canEdit","shared","aceMode","parents","set_drive_link_to_folder","history","replaceState","host","pathname","show_file_body","setting_session_value","setValue","on_editor_change","n_classes","start_row","end_row","args_for_splice","query_unload","href","show_user_info","user_info","set_editor_newline","setNewLineMode","set_editor_tabs","setUseSoftTabs","setTabSize","set_editor_syntax","mode_str","modes_array","setMode","mode","new_in_folder","document_ready","setAnimatedScroll","enableBasicAutocompletion","enableLiveAutocompletion","pane_clipboard","pane_file","pane_general_settings","pane_help","pane_find","SpecialPromise","onbeforeunload","window_location_to_params_object","folderId","on_error","on_success","pr_meta","pr_body","vals","pr_realtime_loaded"],"mappings":"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","file":"all.build.js","sourcesContent":["// keymaster.js\n// (c) 2011-2013 Thomas Fuchs\n// keymaster.js may be freely distributed under the MIT license.\n\n;(function(global){\n var k,\n _handlers = {},\n _mods = { 16: false, 18: false, 17: false, 91: false },\n _scope = 'all',\n // modifier keys\n _MODIFIERS = {\n '⇧': 16, shift: 16,\n '⌥': 18, alt: 18, option: 18,\n '⌃': 17, ctrl: 17, control: 17,\n '⌘': 91, command: 91\n },\n // special keys\n _MAP = {\n backspace: 8, tab: 9, clear: 12,\n enter: 13, 'return': 13,\n esc: 27, escape: 27, space: 32,\n left: 37, up: 38,\n right: 39, down: 40,\n del: 46, 'delete': 46,\n home: 36, end: 35,\n pageup: 33, pagedown: 34,\n ',': 188, '.': 190, '/': 191,\n '`': 192, '-': 189, '=': 187,\n ';': 186, '\\'': 222,\n '[': 219, ']': 221, '\\\\': 220\n },\n code = function(x){\n return _MAP[x] || x.toUpperCase().charCodeAt(0);\n },\n _downKeys = [];\n\n for(k=1;k<20;k++) _MAP['f'+k] = 111+k;\n\n // IE doesn't support Array#indexOf, so have a simple replacement\n function index(array, item){\n var i = array.length;\n while(i--) if(array[i]===item) return i;\n return -1;\n }\n\n // for comparing mods before unassignment\n function compareArray(a1, a2) {\n if (a1.length != a2.length) return false;\n for (var i = 0; i < a1.length; i++) {\n if (a1[i] !== a2[i]) return false;\n }\n return true;\n }\n\n var modifierMap = {\n 16:'shiftKey',\n 18:'altKey',\n 17:'ctrlKey',\n 91:'metaKey'\n };\n function updateModifierKey(event) {\n for(k in _mods) _mods[k] = event[modifierMap[k]];\n };\n\n // handle keydown event\n function dispatch(event) {\n var key, handler, k, i, modifiersMatch, scope;\n key = event.keyCode;\n\n if (index(_downKeys, key) == -1) {\n _downKeys.push(key);\n }\n\n // if a modifier key, set the key.<modifierkeyname> property to true and return\n if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko\n if(key in _mods) {\n _mods[key] = true;\n // 'assignKey' from inside this closure is exported to window.key\n for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;\n return;\n }\n updateModifierKey(event);\n\n // see if we need to ignore the keypress (filter() can can be overridden)\n // by default ignore key presses if a select, textarea, or input is focused\n if(!assignKey.filter.call(this, event)) return;\n\n // abort if no potentially matching shortcuts found\n if (!(key in _handlers)) return;\n\n scope = getScope();\n\n // for each potential shortcut\n for (i = 0; i < _handlers[key].length; i++) {\n handler = _handlers[key][i];\n\n // see if it's in the current scope\n if(handler.scope == scope || handler.scope == 'all'){\n // check if modifiers match if any\n modifiersMatch = handler.mods.length > 0;\n for(k in _mods)\n if((!_mods[k] && index(handler.mods, +k) > -1) ||\n (_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;\n // call the handler and stop the event if neccessary\n if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){\n if(handler.method(event, handler)===false){\n if(event.preventDefault) event.preventDefault();\n else event.returnValue = false;\n if(event.stopPropagation) event.stopPropagation();\n if(event.cancelBubble) event.cancelBubble = true;\n }\n }\n }\n }\n };\n\n // unset modifier keys on keyup\n function clearModifier(event){\n var key = event.keyCode, k,\n i = index(_downKeys, key);\n\n // remove key from _downKeys\n if (i >= 0) {\n _downKeys.splice(i, 1);\n }\n\n if(key == 93 || key == 224) key = 91;\n if(key in _mods) {\n _mods[key] = false;\n for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;\n }\n };\n\n function resetModifiers() {\n for(k in _mods) _mods[k] = false;\n for(k in _MODIFIERS) assignKey[k] = false;\n };\n\n // parse and assign shortcut\n function assignKey(key, scope, method){\n var keys, mods;\n keys = getKeys(key);\n if (method === undefined) {\n method = scope;\n scope = 'all';\n }\n\n // for each shortcut\n for (var i = 0; i < keys.length; i++) {\n // set modifier keys if any\n mods = [];\n key = keys[i].split('+');\n if (key.length > 1){\n mods = getMods(key);\n key = [key[key.length-1]];\n }\n // convert to keycode and...\n key = key[0]\n key = code(key);\n // ...store handler\n if (!(key in _handlers)) _handlers[key] = [];\n _handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });\n }\n };\n\n // unbind all handlers for given key in current scope\n function unbindKey(key, scope) {\n var multipleKeys, keys,\n mods = [],\n i, j, obj;\n\n multipleKeys = getKeys(key);\n\n for (j = 0; j < multipleKeys.length; j++) {\n keys = multipleKeys[j].split('+');\n\n if (keys.length > 1) {\n mods = getMods(keys);\n key = keys[keys.length - 1];\n }\n\n key = code(key);\n\n if (scope === undefined) {\n scope = getScope();\n }\n if (!_handlers[key]) {\n return;\n }\n for (i = 0; i < _handlers[key].length; i++) {\n obj = _handlers[key][i];\n // only clear handlers if correct scope and mods match\n if (obj.scope === scope && compareArray(obj.mods, mods)) {\n _handlers[key][i] = {};\n }\n }\n }\n };\n\n // Returns true if the key with code 'keyCode' is currently down\n // Converts strings into key codes.\n function isPressed(keyCode) {\n if (typeof(keyCode)=='string') {\n keyCode = code(keyCode);\n }\n return index(_downKeys, keyCode) != -1;\n }\n\n function getPressedKeyCodes() {\n return _downKeys.slice(0);\n }\n\n function filter(event){\n var tagName = (event.target || event.srcElement).tagName;\n // ignore keypressed in any elements that support keyboard data input\n return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');\n }\n\n // initialize key.<modifier> to false\n for(k in _MODIFIERS) assignKey[k] = false;\n\n // set current scope (default 'all')\n function setScope(scope){ _scope = scope || 'all' };\n function getScope(){ return _scope || 'all' };\n\n // delete all handlers for a given scope\n function deleteScope(scope){\n var key, handlers, i;\n\n for (key in _handlers) {\n handlers = _handlers[key];\n for (i = 0; i < handlers.length; ) {\n if (handlers[i].scope === scope) handlers.splice(i, 1);\n else i++;\n }\n }\n };\n\n // abstract key logic for assign and unassign\n function getKeys(key) {\n var keys;\n key = key.replace(/\\s/g, '');\n keys = key.split(',');\n if ((keys[keys.length - 1]) == '') {\n keys[keys.length - 2] += ',';\n }\n return keys;\n }\n\n // abstract mods logic for assign and unassign\n function getMods(key) {\n var mods = key.slice(0, key.length - 1);\n for (var mi = 0; mi < mods.length; mi++)\n mods[mi] = _MODIFIERS[mods[mi]];\n return mods;\n }\n\n // cross-browser events\n function addEvent(object, event, method) {\n if (object.addEventListener)\n object.addEventListener(event, method, false);\n else if(object.attachEvent)\n object.attachEvent('on'+event, function(){ method(window.event) });\n };\n\n // set the handlers globally on document\n addEvent(document, 'keydown', function(event) { dispatch(event) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48\n addEvent(document, 'keyup', clearModifier);\n\n // reset modifiers to false whenever the window is (re)focused.\n addEvent(window, 'focus', resetModifiers);\n\n // store previously defined key\n var previousKey = global.key;\n\n // restore previously defined key and return reference to our key object\n function noConflict() {\n var k = global.key;\n global.key = previousKey;\n return k;\n }\n\n // set window.key and window.key.set/get/deleteScope, and the default filter\n global.key = assignKey;\n global.key.setScope = setScope;\n global.key.getScope = getScope;\n global.key.deleteScope = deleteScope;\n global.key.filter = filter;\n global.key.isPressed = isPressed;\n global.key.getPressedKeyCodes = getPressedKeyCodes;\n global.key.noConflict = noConflict;\n global.key.unbind = unbindKey;\n\n if(typeof module !== 'undefined') module.exports = assignKey;\n\n})(this);\n","\"use strict\";\r\n\r\n/* \r\n monkey patch UndoManager's execute function, so as to store unique ids with each \"delta\".\r\n\r\n Actually, it seems that a \"delta\" is the smallest unit of change in ace, above that is an \r\n \"array of deltas\", and above that is a \"deltaSet\". A deltaSet is the unit which is atomically\r\n undone/redone, so we might want to attach an id to that, but it is constructed in stages,\r\n with new \"arrays of deltas\" being \"merged in\". So instead we actually register the ids on\r\n each \"array of deltas\". The user dosen't need to care about this, they can just use\r\n .getCurrentId to read the unique value for the current state. \r\n\r\n Prior to Feb 2014, it seems there was some code to $serializeDeltas in some manner,\r\n but that is no longer being used. If it were to come back in to use we would have to\r\n change our monkey patching.\r\n\r\n */\r\n\r\n(function(){\r\n\r\nvar UndoManager = ace.require(\"./undomanager\").UndoManager;\r\n\r\nvar original_execute = UndoManager.prototype.execute;\r\n\r\nUndoManager.prototype.id_counter = 0;\r\n\r\nUndoManager.prototype.execute = function(options) {\r\n\r\n var deltaSets = options.args[0];\r\n for(var ii=0; ii<deltaSets.length; ii++)\r\n deltaSets[ii].delta_array_id = ++this.id_counter;\r\n original_execute.call(this, options);\r\n}\r\n\r\nUndoManager.prototype.getCurrentId = function(){\r\n var top_delta_set = this.$undoStack[this.$undoStack.length-1];\r\n if(!top_delta_set)\r\n return 0;\r\n return top_delta_set[top_delta_set.length-1].delta_array_id;\r\n}\r\n\r\n})();\r\n","\"use strict\";\r\n\r\nvar oxford_comma = function(arr){\r\n switch (arr.length){\r\n case 1:\r\n return arr[0];\r\n case 2:\r\n return arr[0] + \" and \" + arr[1];\r\n case 3:\r\n return arr[0] + \", \" + arr[1] + \", and \" + arr[2];\r\n }\r\n}\r\n\r\nvar rotate = function(el, deg){\r\n el.style.transform = \"rotate(\" + deg + 'deg)';\r\n el.style.webkitTansform = \"rotate(\" + deg + 'deg)';\r\n el.style.mozTransform = \"rotate(\" + deg + 'deg)';\r\n}\r\n\r\nvar translate = function(el, x, y){\r\n var str = x==null ? \"\" : \"translate(\" + x + \"px,\" + y + \"px)\";\r\n el.style.transform = str;\r\n el.style.webkitTransform = str;\r\n el.style.mozTransform = str;\r\n}\r\n\r\nvar text_multi = function(el, text, truncate_long_words){\r\n if(truncate_long_words){\r\n text = text.replace(/(\\S{25})\\S*/g,'$1...'); \r\n }\r\n el.textContent = text; \r\n el.innerHTML = el.innerHTML.replace(/\\n/g,'<br/>').replace(/\\t/g,' ');\r\n}\r\n\r\nvar escape_str = function(str){\r\n // http://stackoverflow.com/a/18750001/2399799\r\n str = str || \"\";\r\n return str.replace(/[\\u00A0-\\u9999<>\\&]/g, function(i) {\r\n return '&#' + i.charCodeAt(0) + ';';\r\n });\r\n}\r\n\r\nvar hex_print_string = function(str){\r\n // only for debugging\r\n var c = [];\r\n for(var ii=0; ii<str.length; ii++)\r\n c.push(str.charCodeAt(ii).toString(16))\r\n console.log(c.join(\" \"))\r\n}\r\n\r\nvar js_str_from_utf16 = function(str){\r\n // There's the endianness of the encoding and the endianness of the current CPU.\r\n // we only need to know the \"relative\" endian-ness in order to make a suitable request to TextDecoder.\r\n // I hope!\r\n var bom = new Uint16Array((new Uint8Array([str.charCodeAt(0), str.charCodeAt(1)])).buffer);\r\n var endian = bom[0] === 0xfffe ? 'be' : 'le';\r\n\r\n var arr = new Uint8Array(str.length-2)\r\n for(var ii=2;ii<str.length;ii++)\r\n arr[ii-2] = str.charCodeAt(ii);\r\n \r\n return (new TextDecoder('utf-16' + endian )).decode( new Uint16Array(arr.buffer));\r\n}\r\n\r\nvar decode_body = function(body){\r\n body = body || \"\";\r\n // TODO: it might be better to use TextDecoder for UTF8 as well as 16, but you need a pollyfil for non Chrome/FF\r\n try {\r\n if(body.substr(0,2) == String.fromCharCode.call(null, 0xff, 0xfe) ||\r\n body.substr(0,2) == String.fromCharCode.call(null, 0xfe, 0xff) )\r\n return js_str_from_utf16(body); // reinterpret pairs of single byte chars as actually being utf16\r\n else\r\n return decodeURIComponent(escape(body)); // reinterpreting single byte chars as actually being utf8\r\n } catch (e) {\r\n return body;\r\n }\r\n}\r\n\r\nvar css_animation = (function(){\r\n var timers = []; // we store timers and matching els so we can cancel if needed\r\n var els = [];\r\n\r\n return function(el, cls, callback, delay){\r\n el.classList.remove(cls);\r\n el.offsetTop; //forces class to be removed, so we can actually re-add it.\r\n var old_idx = els.indexOf(el);\r\n if(old_idx != -1){\r\n clearTimeout(timers[old_idx]);\r\n timers.splice(old_idx, 1);\r\n els.splice(old_idx, 1);\r\n }\r\n els.push(el);\r\n timers.push(setTimeout(callback, delay)); //this is better than trying to use the endtransition event\r\n el.classList.add(cls);\r\n }\r\n})();\r\n\r\nvar stop_propagation = function(e){\r\n e.stopPropagation();\r\n}\r\n\r\nvar prevent_default = function(e){\r\n e.preventDefault(); \r\n}\r\n\r\nvar prevent_default_and_stop_propagation = function(e){\r\n e.stopPropagation();\r\n e.preventDefault();\r\n}\r\n\r\nvar until_success = function(executor){\r\n /* This was confusing to write, so when I finished I turned it into an S.O. answer:\r\n http://stackoverflow.com/a/35782428/2399799 \r\n An explanation and proper example is given there.*/\r\n \r\n var before_retry = undefined;\r\n var outer_executor = function(succeed, reject){\r\n var rejection_handler = function(err){\r\n if(before_retry){\r\n try {\r\n var pre_retry_result = before_retry(err);\r\n if(pre_retry_result)\r\n return succeed(pre_retry_result);\r\n } catch (pre_retry_error){\r\n return reject(pre_retry_error);\r\n }\r\n }\r\n return new Promise(executor).then(succeed, rejection_handler); \r\n }\r\n return new Promise(executor).then(succeed, rejection_handler);\r\n }\r\n\r\n var outer_promise = new Promise(outer_executor);\r\n outer_promise.before_retry = function(func){\r\n before_retry = func;\r\n return outer_promise;\r\n }\r\n return outer_promise;\r\n}\r\n\r\n\r\n\r\n\r\nvar ext_from_filename = function(str){\r\n // http://stackoverflow.com/a/12900504/2399799\r\n str = str || \"\"\r\n return str.slice((Math.max(0, str.lastIndexOf(\".\")) || Infinity) + 1);\r\n}\r\n\r\nvar load_script_async = function(url){\r\n // method used by ga, which seems to work nicely\r\n var new_el = document.createElement('script');\r\n new_el.async = 1;\r\n new_el.src = url;\r\n var something_el = document.getElementsByTagName('script')[0];\r\n something_el.parentNode.insertBefore(new_el, something_el); \r\n}","var offline_simple = (function(){\r\n\r\n/*\r\nThis is very losely based on https://github.com/HubSpot/offline/blob/master/js/offline.js.\r\nBut much simplified. Here we don't do anything until some external function calls \r\n.commence_testing, at that point we begin issuing a series of requests for the favicon.\r\nAs soon as one succeeds we trigger an 'online' event, which intereeted parties can listen\r\nfor using the .addEventListener('online', foo) method. The requests follow an exponential\r\nbackoff, capped at a 1 request per minute. \r\n*/\r\n\r\nvar callbacks = [];\r\n\r\nvar delay_chain = {0: 1, 1:500, 500: 1000, 1000: 2500, 2500: 5000, 5000: 10000, 10000: 60000, 60000: 60000}\r\nvar delay = 0;\r\nvar timer = 0;\r\n\r\n\r\nvar commence_testing = function(){\r\n\tif(timer) return;\r\n\tdelay = 0;\r\n\tclearTimeout(timer);\r\n\ttimer = setTimeout(run_test, delay)\r\n}\r\n\r\nvar request_test = function(){\r\n\tdelay = delay_chain[delay];\r\n\tclearTimeout(timer); // just in case\r\n\tconsole.log(\"Test of internet access will be made in \" + delay + \"ms.\")\r\n\ttimer = setTimeout(run_test, delay)\t\r\n}\r\n\r\nvar addEventListener = function(kind, foo){\r\n\tif(kind !== \"online\") throw \"only 'online' events please.\"\r\n\tcallbacks.push(foo);\r\n}\r\n\r\nvar trigger = function(kind){\r\n\tif(kind !== \"online\") throw \"only 'online' events please.\"\r\n\tconsole.log(\"internet is available\");\r\n\tfor(var ii=0; ii<callbacks.length; ii++)\r\n\t\tcallbacks[ii]({is_online: true});\r\n}\r\n\r\nvar run_test = function() {\r\n\ttimer = 0;\r\n\tconsole.log(\"testing for internet access\")\r\n var xhr = new XMLHttpRequest;\r\n xhr.open('HEAD', \"/favicon.ico?_=\" + ((new Date()).getTime()), true);\r\n if (xhr.timeout != null) \r\n \txhr.timeout = 5000;\r\n\r\n\tvar check_status = function(){\r\n \tif (xhr.status && xhr.status < 12000) \r\n \t\ttrigger('online');\r\n \telse\r\n \t\trequest_test();\r\n }\r\n\r\n if (xhr.onprogress === null) {\r\n\t xhr.onerror = request_test;\r\n\t xhr.ontimeout = request_test;\r\n\t xhr.onload = check_status;\r\n\t} else {\r\n\t\txhr.onreadystatechange = function(){\r\n\t\t\tif (xhr.readyState === 4)\r\n \t\tcheckStatus();\r\n \telse if (xhr.readyState === 0)\r\n \t\trequest_test();\r\n\t\t}\r\n\t}\r\n\r\n try {\r\n xhr.send();\r\n } catch (e) {\r\n request_test();\r\n }\r\n}\r\n\r\n\r\nreturn {\r\n\taddEventListener: addEventListener,\r\n\tcommence_testing: commence_testing\r\n}\r\n\r\n})();\r\n","\"use strict\";\r\n\r\nvar DropDown = function(val_array){\r\n //constructor, must use <new>\r\n \r\n var str = val_array.map(function(val){\r\n return \"<div class='dropdown_item' title='\" + escape_str(val) + \"'>\" + escape_str(val) + \"</div>\";\r\n }).join(\"\");\r\n \r\n this.val_array = val_array.slice(0); \r\n this.el_list = document.createElement('div');\r\n this.el_list.className ='dropdown_item_list';\r\n this.el_list.tabindex =-1\r\n this.el_list.style.display = 'none';\r\n this.el_list.innerHTML = str;\r\n\r\n this.el_collapsed = document.createElement('div');\r\n this.el_collapsed.className = 'dropdown_collapsed';\r\n \r\n this.el = document.createElement('div');\r\n this.el.className = 'dropdown';\r\n this.el.appendChild(this.el_list)\r\n this.el.appendChild(this.el_collapsed);\r\n this.ind = 0;\r\n this.el_collapsed.textContent = val_array[0];\r\n this.event_callbacks = {}; //map of callback lists\r\n this.open = false;\r\n this.enabled = true;\r\n \r\n var dd = this;\r\n\r\n this.document_mousedown = function(e){\r\n dd.el_list.style.display = 'none';\r\n dd.open = false;\r\n dd.trigger(\"blur\");\r\n document.removeEventListener('mousedown', dd.document_mousedown);\r\n }\r\n\r\n this.el_collapsed.addEventListener('mousedown',function(){\r\n if(!dd.enabled)\r\n return;\r\n if(!dd.trigger(\"click\"))\r\n return;\r\n dd.el.parentNode.classList.add(\"selected\");\r\n dd.el_list.style.display = '';\r\n this.open = true;\r\n setTimeout(function(){\r\n dd.el_list.focus();\r\n dd.el_list.scrollTop = dd.el_list.children[dd.ind].offsetTop;\r\n document.addEventListener('mousedown', dd.document_mousedown)\r\n },1);\r\n });\r\n var on_click = function(e){\r\n dd.SetInd(this.getAttribute('data-ind'));\r\n dd.el_list.style.display = 'none';\r\n dd.open = false;\r\n e.stopPropagation();\r\n document.removeEventListener('mousedown', dd.document_mousedown);\r\n };\r\n for(var ii=0; ii<this.el_list.children.length; ii++){\r\n this.el_list.children[ii].setAttribute('data-ind', ii);\r\n this.el_list.children[ii].addEventListener(\"click\", on_click); \r\n }\r\n\r\n return this;\r\n}\r\n\r\nDropDown.FakeEvent = function(){//static subclass\r\n this.is_stopped = false;\r\n}\r\nDropDown.FakeEvent.prototype.preventDefault = function(){\r\n this.is_stopped = true;\r\n}\r\n\r\nDropDown.FakeEvent.prototype.stopImmediatePropagation = function(){\r\n this.is_stopped = true;\r\n}\r\n\r\nDropDown.prototype.addEventListener = function(evt, func){\r\n if(!(evt in this.event_callbacks))\r\n this.event_callbacks[evt] = [];\r\n this.event_callbacks[evt].push(func);\r\n}\r\n\r\nDropDown.prototype.trigger = function(evt, args){\r\n var fe = new DropDown.FakeEvent();\r\n if(evt in this.event_callbacks){\r\n for(var ii = 0; ii<this.event_callbacks[evt].length; ii++)\r\n this.event_callbacks[evt][ii].call(this, fe);\r\n if(fe.is_stopped)\r\n return false;\r\n }\r\n return true;\r\n}\r\nDropDown.prototype.IndexOf = function(val){\r\n return this.val_array.indexOf(val);\r\n}\r\n\r\nDropDown.prototype.GetVal = function(){\r\n return this.val_array[this.ind];\r\n}\r\n\r\nDropDown.prototype.SetInd = function(ind,no_trigger){\r\n ind = Math.min(Math.max(parseInt(ind), 0), this.val_array.length-1);\r\n if(ind === this.ind)\r\n return;\r\n this.el_list.children[this.ind].classList.remove(\"selected\");\r\n this.el_collapsed.textContent = this.val_array[ind];\r\n this.el_collapsed.title = escape_str(this.val_array[ind]);\r\n this.ind = ind;\r\n this.el_list.children[ind].classList.add(\"selected\");\r\n if(!no_trigger)\r\n this.trigger(\"change\",{ind:ind,str:this.val_array[ind],isOpen: this.open});\r\n}\r\n\r\nDropDown.prototype.SetSelected = function(v){\r\n if(v)\r\n this.el.parentNode.classList.add(\"selected\");\r\n else\r\n this.el.parentNode.classList.remove(\"selected\");\r\n}\r\n","\"use strict\";\r\n\r\ndn.menu_id_to_caption = {\r\n'menu_print': 'print',\r\n'menu_sharing': 'sharing',\r\n'menu_save': 'save',\r\n'menu_history': 'history',\r\n'menu_file': 'current file',\r\n'menu_new': 'new',\r\n'menu_open': 'new/open',\r\n'menu_find': 'find/replace',\r\n'menu_goto': 'goto line',\r\n'menu_general_settings': 'general settings',\r\n'menu_shortcuts': 'shortcuts',\r\n'menu_drive': 'drive',\r\n'menu_help': 'about/help'};\r\n\r\n\r\ndn.shortcuts_list = [\r\n\"cut|Ctrl-X|Cmd-X\", \r\n\"copy|Ctrl-C|Cmd-C\",\r\n\"paste|Ctrl-V|Cmd-V\",\r\n\"cycle clipboard|Cltr-[V then left or right arrow]|Cmd-[V then left or right arrow]\",\r\n\"select all|Ctrl-A|Cmd-A\",\r\n\"find|Ctrl(-Alt)-F\",\r\n\"replace|Ctrl-R\",\r\n\"go to line|Ctrl(-Alt)-L\",\r\n\"undo|Ctrl-Z|Cmd-Z\",\r\n\"redo|Ctrl-Shift-Z,Ctrl-Y|Cmd-Shift-Z,Cmd-Y\",\r\n\"autocomplete|Ctrl-Space|Cmd-Space\",\r\n\" | \",\r\n\"toggle widget|Esc\",\r\n\"save|Ctrl-S|Cmd-S\",\r\n\"print|Ctrl(-Alt)-P|Cmd-P\",\r\n\"file history|Ctrl-H|Cmd-H\",\r\n\"new|Ctrl(-Alt)-N\",\r\n\"open|Ctrl(-Alt)-O\",\r\n\" | \",\r\n\"to upper case|Ctrl-U\",\r\n\"to lower case|Ctr-Shift-U\",\r\n\"modify selection|Shift-(Ctrl-)(Alt-) {Down, Up, Left, Right, End, Home, PageDown, PageUp, End}|Shift-(Cmd-)(Alt-) {Down, Up, Left, Right, End, Home, PageDown,End}\",\r\n\"copy lines down|Ctrl-Alt-Down|Cmd-Option-Down\",\r\n\"copy lines up|Ctrl-Alt-Up|Cmd-Option-Up\",\r\n\"center selection||Ctrl-L\",\r\n\"fold all|Alt-0|Option-0\",\r\n\"unfold all|Alt-Shift-0|Option-Shift-0\",\r\n\"go to end|Ctrl-End,Ctrl-Down|Cmd-End,Cmd-Down\",\r\n\"go to line end|Alt-Right,End|Cmd-Right,End,Ctrl-E\",\r\n\"go to line start|Alt-Left,Home|Cmd-Left,Home,Ctrl-A\",\r\n\"go to page down|PageDown|Option-PageDown,Ctrl-V\",\r\n\"go to page up|PageUp|Option-PageUp\",\r\n\"go to start|Ctrl-Home,Ctrl-Up|Cmd-Home,Cmd-Up\",\r\n\"go to word left|Ctrl-Left|Option-Left\",\r\n\"go to word right|Ctrl-Right|Option-Right\",\r\n\"indent|Tab\",\r\n\"outdent|Shift-Tab\",\r\n\"overwrite|Insert\",\r\n\"remove line|Ctrl-D|Cmd-D\",\r\n\"remove to line end||Ctrl-K\",\r\n\"remove to linestart||Option-Backspace\",\r\n\"remove word left||Alt-Backspace,Ctrl-Alt-Backspace\",\r\n\"remove word right||Alt-Delete\",\r\n\"split line||Ctrl-O\",\r\n\"toggle comment|Ctrl-7|Cmd-7\",\r\n\"transpose letters|Ctrl-T\"\r\n]\r\n\r\ndn.ext_to_mime_type = {\r\nhtml:\"text/html\",\r\nhtm:\"text/html\",\r\njs:\"text/javascript\",\r\npl:\"application/x-perl\",\r\nxml:\"text/xml\",\r\nc:\"text/x-csrc\",\r\ncpp:\"text/x-c++src\",\r\nh:\"text/x-chdr\",\r\njson:\"application/json\",\r\nphp:\"application/x-php\",\r\nsvg:\"text/html\",\r\ncss:\"text/css\",\r\njava:\"text/x-java\",\r\npy:\"text/x-python\",\r\nscala:\"scala\",\r\ntextile:\"textile\",\r\ntex:\"application/x-tex\",\r\nbib:\"application/x-tex\",\r\nrtf:\"application/rtf\",\r\nrtx:\"application/rtf\",\r\nsh:\"application/x-sh\",\r\nsql:\"text/x-sql\",\r\nas:\"text/x-actionscript\"\r\n//everything else is hopefully ok to be text/plain.\r\n}\r\n\r\ndn.tooltip_info = { //keys correspond to icon data-info attr, which will be the same as keys in SHORTCUTS_LIST\r\n \"save\" : \"Save file contents. \",\r\n \"print\": \"Open print view in a new tab. \",\r\n \"sharing\": \"View and modify file's sharing status.\",\r\n \"file history\": \"Explore the file history. \",\r\n \"drive\": \"Show this file in Google Drive. \",\r\n \"about\": \"Drive Notepad website.\",\r\n \"shortcuts\": \"Keyboard shortcuts.\",\r\n \"new\": \"Create new file in a new tab. \",\r\n \"open\": \"Launch open dialoag. \",\r\n \"settings_file\": \"Properties of the current file.\",\r\n \"settings_general\": \"Your general Drive Notepad preferences.\",\r\n \"title\": \"Click to edit the file's title.\",\r\n \"description\": \"Click to edit the file's description.\"\r\n}\r\n\r\n// TODO: use keymaster rather than relying on this\r\nvar WHICH = {\r\nENTER: 13,\r\nESC: 27,\r\nUP: 38,\r\nDOWN: 40\r\n};\r\n\r\ndn.default_settings = {\r\next: 'txt',\r\nwordWrap: [true,null,null],\r\nwordWrapAt: 80,\r\nfontSize: 1,\r\nwidget_anchor: ['l',50,'t',10],\r\nshowGutterHistory: 1,\r\nlastDNVersionUsed: '',\r\nnewLineDefault: 'windows',\r\nhistoryRemovedIsExpanded: true,\r\nsoftTabN: 4,\r\ntabIsHard: 0,\r\nwidgetSub: 'general',\r\ntheme: \"chrome\",\r\npane: '',\r\npane_open: true,\r\nfind_regex: false,\r\nfind_whole_words: false,\r\nfind_case_sensitive: false,\r\nhelp_inner: 'main',\r\nfind_goto: false,\r\nfind_replace: false\r\n}\r\n\r\ndn.impersonal_settings_keys = [\r\n\"wordWrap\",\r\n\"wordWrapAt\",\r\n\"fontSize\",\r\n\"widget_anchor\",\r\n\"showGutterHistory\",\r\n\"historyRemovedIsExpanded\",\r\n\"tabIsHard\",\r\n\"softTabN\",\r\n\"newLineDefault\",\r\n\"widgetSub\",\r\n\"theme\",\r\n\"pane\",\r\n\"pane_open\",\r\n\"find_regex\",\r\n\"find_whole_words\",\r\n\"find_case_sensitive\",\r\n\"help_inner\",\r\n\"find_goto\",\r\n\"find_replace\"\r\n];\r\n\r\ndn.const_ = {\r\nauth_timeout: dn.const_.auth_timeout, // already provided in app.html\r\ndrag_delay_ms: 400,\r\ndrag_shift_px: 40,\r\nmin_font_size: 0.3,\r\nmax_font_size: 5, \r\nmax_wrap_at: 200,\r\nmin_wrap_at: 20,\r\nwrap_at_increment: 10,\r\nmax_soft_tab_n: 10,\r\nmin_soft_tab_n: 2,\r\ndetect_tabs_spaces_frac: 0.9,\r\ndetect_tabs_tabs_frac: 0.9,\r\ndetect_tabs_n_spaces_frac: 0.99,\r\ndetect_tabs_n_spaces_frac_for_default: 0.6, //check\r\nfont_size_increment: 0.15, //check\r\nerror_delay_ms: 5000,//5 seconds\r\nfind_history_add_delay: 3000, //ms\r\nfind_history_max_len: 100,\r\nclipboard_info_delay: 500, //ms\r\nclipboard_max_length: 20, //TODO: decide whether a large clipboard slows page loads and whether we can do anything about it.\r\nfind_max_results_half: 3, \r\nfind_max_prefix_chars: 10,\r\nfind_max_suffix_chars: 60,\r\nad_initial_wait: 4 * 60 * 1000 //ms\r\n};\r\n\r\ndn.platform = (function(){\r\n if(navigator.platform.indexOf(\"Win\") >-1)\r\n return \"Windows\";\r\n else if(navigator.platform.indexOf(\"Linux\") >-1)\r\n return \"Linux\";\r\n else if(navigator.platform.indexOf(\"Mac\")>-1)\r\n return \"Mac\"; \r\n return null;\r\n})();","\"use strict\"\r\n\r\ndn.FileModel = function(){\r\n this.is_loaded = false; // when this is set to true we compute tabs, newlines etc, and continue to do so whenver set() is called.\r\n this.file_id = null;\r\n this.folder_id = null;\r\n this.title = null;\r\n this.description = '';\r\n this.ext = '';\r\n this.loaded_body = '';\r\n this.loaded_mime_type = undefined;\r\n this.chosen_mime_type = 'text/plain';\r\n this.is_read_only = false;\r\n this.is_shared = false;\r\n this.properties_chosen = {}, // combines detection, settings, and file properties\r\n this.properties = {}, // values stored in the file's meta data, defines which button is currently selected\r\n this.properties_detected_info = {} // caption for detection \r\n this.change_callbacks = [];\r\n return this;\r\n}\r\n\r\n// basic events system for a single event called \"change\"\r\ndn.FileModel.prototype.addEventListener = function(kind, c){\r\n if(kind !== \"change\") throw \"only change listeners please!\";\r\n this.change_callbacks.push(c);\r\n}\r\ndn.FileModel.prototype.trigger = function(kind, ob){\r\n if(kind !== \"change\") throw \"only change events please!\";\r\n for(var ii=0; ii<this.change_callbacks.length; ii++)\r\n this.change_callbacks[ii](ob);\r\n}\r\n\r\ndn.FileModel.prototype.set = function(obj){\r\n if(obj.syntax && obj.syntax !== this.properties.syntax){\r\n this.properties.syntax = obj.syntax;\r\n if(this.is_loaded)\r\n this.compute_syntax(); // will trigger \r\n }\r\n if(obj.newline && obj.newline !== this.properties.newline){\r\n this.properties.newline = obj.newline;\r\n if(this.is_loaded)\r\n this.compute_newline(); // will trigger \r\n }\r\n if(obj.tabs && !(this.properties.tabs && obj.tabs.val === this.properties.tabs.val && obj.tabs.n === this.properties.tabs.n)){\r\n this.properties.tabs = obj.tabs;\r\n if(this.is_loaded)\r\n this.compute_tabs(); // will trigger \r\n }\r\n if(obj.title && obj.title !== this.title){\r\n this.update_mime_type(this.title, obj.title); \r\n this.title = obj.title;\r\n this.trigger(\"change\",{property: 'title'})\r\n if(this.is_loaded)\r\n this.compute_syntax(); // will trigger \r\n }\r\n if(obj.description && obj.description !== this.description){\r\n this.description = obj.description;\r\n this.trigger(\"change\",{property: 'description'})\r\n }\r\n if(obj.is_read_only && obj.is_read_only !== this.is_read_only){\r\n this.is_read_only = obj.is_read_only;\r\n this.trigger(\"change\",{property: 'is_read_only'});\r\n }\r\n if(obj.is_shared && obj.is_shared !== this.is_shared){\r\n this.is_shared = obj.is_shared;\r\n this.trigger(\"change\",{property: 'is_shared'});\r\n }\r\n if(obj.loaded_mime_type){\r\n this.loaded_mime_type = obj.loaded_mime_type;\r\n this.chosen_mime_type = this.loaded_mime_type || \"text/plain\";\r\n // see setting of title \r\n }\r\n if(obj.is_loaded && ~this.is_loaded){\r\n this.is_loaded = true;\r\n this.compute_newline(); // these trigger when they are done\r\n this.compute_tabs();\r\n this.compute_syntax();\r\n this.trigger('change', {property: 'is_loaded'});\r\n }\r\n}\r\n\r\n\r\ndn.FileModel.prototype.update_mime_type = function(old_title, new_title){\r\n old_ext = ext_from_filename(old_title);\r\n new_ext = ext_from_filename(new_title);\r\n if(new_ext !== old_ext){\r\n this.loaded_mime_type = undefined; // the loaded mime type is no longer relevant to us\r\n this.chosen_mime_type = dn.ext_to_mime_type[new_ext] || \"text/plain\";\r\n }\r\n}\r\n\r\ndn.FileModel.prototype.compute_newline = function(){\r\n // populates properties _chosen, _detected and _detect_info\r\n // uses this.loaded_body, file's current properties, and dn.g_settings\r\n\r\n var str = this.loaded_body;\r\n\r\n if(this.properties.newline === \"windows\")\r\n this.properties_chosen.newline = \"windows\";\r\n else if(this.properties.newline === \"unix\")\r\n this.properties_chosen.newline = \"unix\";\r\n else\r\n this.properties.newline = \"detect\"; // force it to be the only possible alternative, we set choice below...\r\n \r\n // get dection info string, and if detection mode is active then chose the value...\r\n var first_n = str.indexOf(\"\\n\");\r\n if(first_n === -1){\r\n var val = dn.g_settings.get(\"newLineDefault\");\r\n this.properties_detected_info.newline = \"no newlines detected, default is \" + val + \"-like\";\r\n if(this.properties.newline === \"detect\")\r\n this.properties_chosen.newline = val;\r\n } else {\r\n var has_rn = str.indexOf(\"\\r\\n\") != -1;\r\n var has_solo_n = str.match(/[^\\r]\\n/) ? true : false;\r\n if(has_rn && !has_solo_n){\r\n this.properties_detected_info.newline = \"detected windows-like newlines\";\r\n if(this.properties.newline === \"detect\")\r\n this.properties_chosen.newline = \"windows\";\r\n }else if(has_solo_n && !has_rn){\r\n this.properties_detected_info.newline = \"detected unix-like newlines\";\r\n if(this.properties.newline === \"detect\")\r\n this.properties_chosen.newline = \"unix\";\r\n } else {\r\n var val = dn.g_settings.get(\"newLineDefault\");\r\n this.properties_detected_info.newline = \"mixture of newlines detected, default is \" + val + \"-like\";\r\n this.properties_chosen.newline = val;\r\n }\r\n }\r\n\r\n this.trigger(\"change\", {property: 'newline'});\r\n}\r\n\r\ndn.FileModel.prototype.compute_syntax = function(){\r\n // populates properties _chosen, _detected and _detect_info\r\n // uses this.title, and current file's properties\r\n\r\n var title = this.title;\r\n\r\n // validate specified syntax\r\n this.properties_chosen.syntax = undefined;\r\n if(this.properties.syntax && this.properties.syntax !== \"detect\"){\r\n var all_modes = require(\"ace/ext/modelist\").modes;\r\n for(var ii=0; ii<all_modes.length; ii++)\r\n if(all_modes[ii].caption == this.properties.syntax){\r\n this.properties_chosen.syntax = this.properties.syntax; //valid\r\n break;\r\n }\r\n if(this.properties_chosen.syntax === undefined) // not found\r\n this.properties.syntax = \"detect\"; \r\n }else{\r\n this.properties.syntax = \"detect\"; //force it to be valid\r\n }\r\n\r\n var detected = require(\"ace/ext/modelist\").getModeForPath(title).caption;\r\n this.properties_detected_info.syntax = \"detected \" + detected + \" from file extension\";\r\n if(this.properties_chosen.syntax === undefined)\r\n this.properties_chosen.syntax = detected;\r\n\r\n this.trigger(\"change\", {property: 'syntax'});\r\n}\r\n\r\ndn.FileModel.prototype.re_whitepace = /^([^\\S\\n\\r]+)/mg;\r\n\r\ndn.FileModel.prototype.compute_tabs = function(){\r\n // populates properties _chosen, _detected and _detect_info\r\n // uses this.loaded_body, file's current properties, and dn.g_settings\r\n // tabs have two subproperties, .val and .n, .val can be \"detect\", \"tabs\" or \"spaces\"\r\n // and n is an integer in the valid range, although if .properties.tabs.val != \"spaces\",\r\n // then .properties.tabs.n, may be undefiend, in which case display _chosen.n\r\n\r\n var str = this.loaded_body;\r\n\r\n // firstly, parse the stored tabs property, getting a valid .val and valid .n value.\r\n var prop = this.properties.tabs;\r\n try{\r\n if(prop.val === undefined && prop.n === undefined)\r\n prop = JSON.parse(prop)\r\n prop = {val: prop.val, n: prop.n}; // drop any other nonsense\r\n prop.n = parseInt(prop.n);\r\n if(!(prop.val === \"tab\" || prop.val === \"spaces\")) throw 0\r\n if(!(prop.n >= dn.const_.min_soft_tab_n && prop.n <= dn.const_.max_soft_tab_n))\r\n prop.n = undefined; \r\n if(prop.val === \"spaces\" && prop.n === undefined) throw 0\r\n }catch(e){\r\n prop = {val: \"detect\"};\r\n }\r\n this.properties.tabs = prop; // force it to be whatever we parsed\r\n\r\n if(prop.val === \"tab\")\r\n this.properties_chosen.tabs = prop; // may need to chose n still\r\n else if(prop.val === \"spaces\")\r\n this.properties_chosen.tabs = prop; // n is definitely valid\r\n else\r\n this.properties_chosen.tabs = undefined; // we need to chose val and n \r\n \r\n\r\n // Now do detection....\r\n\r\n // find non-zero-length whitespace at start of all lines\r\n var indents = str.match(this.re_whitepace) || []; \r\n\r\n // build the stats for those lines...\r\n var n_only_tabs = 0;\r\n var n_only_space; // we compute this after the loop\r\n var space_hist = [];\r\n var n_with_mixture = 0;\r\n var n_samp = Math.min(indents.length, 1000);\r\n for(var ii=0; ii<n_samp; ii++){\r\n var indents_ii = indents[ii]\r\n var without_tabs = indents_ii.replace(\"\\t\", \"\");\r\n if(without_tabs.length === 0)\r\n n_only_tabs++;\r\n else if(without_tabs.length !== indents_ii.length)\r\n n_with_mixture++;\r\n else\r\n space_hist[indents_ii.length] = (space_hist[indents_ii.length] || 0) + 1;\r\n }\r\n n_only_space = n_samp - n_with_mixture - n_only_tabs;\r\n\r\n\r\n if(n_only_tabs/n_samp >= dn.const_.detect_tabs_tabs_frac){\r\n // detected tab...\r\n this.properties_detected_info.tabs = \"hard tab indentation detected\";\r\n if(this.properties_chosen.tabs === undefined)\r\n this.properties_chosen.tabs = {val: 'tabs'}\r\n if(this.properties_chosen.tabs.n === undefined)\r\n this.properties_chosen.tabs.n = dn.g_settings.get('softTabN'); // we have to show something for n\r\n\r\n } else if(n_samp === 0 || n_only_space/n_samp < dn.const_.detect_tabs_spaces_frac){\r\n // no detection possible, use default....\r\n\r\n if(this.properties_chosen.tabs === undefined){\r\n this.properties_chosen.tabs = {\r\n val: dn.g_settings.get('tabIsHard') ? 'tabs' : 'spaces',\r\n n: dn.g_settings.get('softTabN')};\r\n }\r\n this.properties_detected_info.tabs =\r\n (n_samp === 0 ?\r\n \"no indentations detected\" \r\n : \"detected mixture of tabs\")\r\n + \", default is \" + (this.properties_chosen.tabs.val == 'tabs' ?\r\n \"hard tabs\"\r\n : dn.g_settings.get('softTabN') + \" spaces\");\r\n \r\n } else {\r\n // detected spaces, but exxactly how many? \r\n\r\n //Build a second space hist, using all \"harmonics\"....\r\n var space_mod_hist = [];\r\n for(var ss=dn.const_.min_soft_tab_n; ss<=dn.const_.max_soft_tab_n; ss++){\r\n for(var ii=ss, m=0; ii<space_hist.length; ii+=ss)\r\n m += space_hist[ii] === undefined ? 0 : space_hist[ii];\r\n space_mod_hist[ss] = m;\r\n }\r\n \r\n // and find the largest indent that passes threshold...\r\n var ss;\r\n for(ss=dn.const_.max_soft_tab_n; ss>=dn.const_.min_soft_tab_n; ss--)\r\n if(space_mod_hist[ss]/n_only_space > dn.const_.detect_tabs_n_spaces_frac){\r\n this.properties_detected_info.tabs = \"detected soft-tabs of \" + ss + \" spaces\"\r\n break;\r\n }\r\n\r\n // if nothing was over threshold, use default space count\r\n if(ss < dn.const_.min_soft_tab_n){\r\n ss = dn.g_settings.get('softTabN'); \r\n if(space_mod_hist[ss]/n_only_space > dn.const_.detect_tabs_n_spaces_frac_for_default)\r\n this.properties_detected_info.tabs = \"detected close match to default of \" + ss + \" spaces\";\r\n else \r\n this.properties_detected_info.tabs = \"detected soft-tabs, assuming default \" + ss + \" spaces\";\r\n }\r\n\r\n // if we need to specify a space count use the ss value we ended up with...\r\n if(this.properties_chosen.tabs === undefined)\r\n this.properties_chosen.tabs = {val: 'spaces'};\r\n if(this.properties_chosen.tabs.n === undefined)\r\n this.properties_chosen.tabs.n = ss;\r\n }\r\n \r\n this.trigger(\"change\", {property: 'tabs'});\r\n}\r\n\r\n","\"use strict\";\r\n\r\ndn.settings_pane = (function(){\r\n\r\nvar el = {};\r\n\r\nvar theme_drop_down;\r\n\r\nvar on_document_ready = function(){\r\n el.theme_chooser = document.getElementById('theme_chooser')\r\n el.button_clear_clipboard = document.getElementById(\"button_clear_clipboard\");\r\n el.button_clear_find_replace = document.getElementById(\"button_clear_find_replace\");\r\n el.gutter_history_show = document.getElementById('gutter_history_show');\r\n el.gutter_history_hide = document.getElementById('gutter_history_hide');\r\n el.word_wrap_off = document.getElementById('word_wrap_off');\r\n el.word_wrap_at = document.getElementById('word_wrap_at');\r\n el.word_wrap_edge = document.getElementById('word_wrap_edge');\r\n el.font_size_dec = document.getElementById('font_size_dec');\r\n el.font_size_inc = document.getElementById('font_size_inc');\r\n el.font_size_text = document.getElementById('font_size_text');\r\n el.tab_hard = document.getElementById('tab_hard');\r\n el.tab_soft = document.getElementById('tab_soft');\r\n el.newline_windows = document.getElementById('newline_menu_windows');\r\n el.newline_unix = document.getElementById('newline_menu_unix');\r\n el.tab_soft_text = document.getElementById('tab_soft_text');\r\n el.tab_soft_dec = document.getElementById('tab_soft_dec');\r\n el.tab_soft_inc = document.getElementById('tab_soft_inc');\r\n el.word_wrap_at_text = document.getElementById('word_wrap_at_text');\r\n el.word_wrap_at_dec = document.getElementById('word_wrap_at_dec');\r\n el.word_wrap_at_inc = document.getElementById('word_wrap_at_inc');\r\n\r\n dn.g_settings.addEventListener(\"VALUE_CHANGED\", on_change); // this does all the view rendering\r\n\r\n var themes = require('ace/ext/themelist');\r\n theme_drop_down = new DropDown(Object.keys(themes.themesByName));\r\n\r\n // annonymous controler functions....\r\n theme_drop_down.addEventListener(\"change\",function(){\r\n dn.g_settings.set(\"theme\",theme_drop_down.GetVal());\r\n })\r\n theme_drop_down.addEventListener(\"blur\",function(){\r\n dn.focus_editor();\r\n })\r\n el.theme_chooser.appendChild(theme_drop_down.el);\r\n el.newline_windows.addEventListener('click', function(){\r\n dn.g_settings.set('newLineDefault', 'windows');\r\n });\r\n el.newline_unix.addEventListener('click', function(){\r\n dn.g_settings.set('newLineDefault', 'unix');\r\n });\r\n el.tab_hard.addEventListener('click', function(){\r\n dn.g_settings.set('tabIsHard', 1)\r\n });\r\n el.tab_soft.addEventListener('click', function(){\r\n dn.g_settings.set('tabIsHard', 0);\r\n });\r\n el.tab_soft_dec.addEventListener('click', function(){\r\n var at = dn.g_settings.get('softTabN') - 1;\r\n at = at < dn.const_.min_soft_tab_n ? dn.const_.min_soft_tab_n : at;\r\n dn.g_settings.set('softTabN',at);\r\n });\r\n el.tab_soft_inc.addEventListener('click', function(){\r\n var at = dn.g_settings.get('softTabN') + 1;\r\n at = at > dn.const_.max_soft_tab_n ? dn.const_.max_soft_tab_n : at;\r\n dn.g_settings.set('softTabN',at);\r\n });\r\n el.font_size_dec.addEventListener('click', font_size_dec_click);\r\n el.font_size_inc.addEventListener('click', font_size_inc_click); \r\n el.word_wrap_off.addEventListener('click', function(){\r\n dn.g_settings.set('wordWrap',[0,0,0])\r\n });\r\n el.word_wrap_at.addEventListener('click', function(){\r\n var at = dn.g_settings.get('wordWrapAt');\r\n dn.g_settings.set('wordWrap',[1,at,at]);\r\n });\r\n el.word_wrap_at_dec.addEventListener('click', function(){\r\n var at = dn.g_settings.get('wordWrapAt') - dn.const_.wrap_at_increment;\r\n at = at < dn.const_.min_wrap_at ? dn.const_.min_wrap_at : at;\r\n dn.g_settings.set('wordWrapAt',at);\r\n });\r\n el.word_wrap_at_inc.addEventListener('click', function(){\r\n var at = dn.g_settings.get('wordWrapAt') + dn.const_.wrap_at_increment;\r\n at = at > dn.const_.max_wrap_at ? dn.const_.max_wrap_at : at;\r\n dn.g_settings.set('wordWrapAt',at);\r\n });\r\n el.word_wrap_edge.addEventListener('click', function(){\r\n dn.g_settings.set('wordWrap',[1,null,null])\r\n });\r\n el.gutter_history_show.addEventListener('click', function(){\r\n dn.g_settings.set('showGutterHistory',1);\r\n });\r\n el.gutter_history_hide.addEventListener('click', function(){\r\n dn.g_settings.set('showGutterHistory',0);\r\n });\r\n\r\n // non-view interactivity...\r\n el.button_clear_clipboard.addEventListener('click', function(){\r\n dn.g_clipboard.clear();\r\n });\r\n el.button_clear_find_replace.addEventListener('click', function(){\r\n dn.g_find_history.clear();\r\n });\r\n\r\n}\r\n\r\n// additional controler functions ::::::::::::::::::::::::::::::::::\r\n\r\nvar font_size_dec_click = function(){\r\n var font_size = dn.g_settings.get('fontSize');\r\n font_size -= dn.const_.font_size_increment;\r\n font_size = font_size < dn.const_.min_font_size ? dn.const_.min_font_size: font_size;\r\n dn.g_settings.set('fontSize', font_size);\r\n}\r\n\r\nvar font_size_inc_click = function(){\r\n var font_size = dn.g_settings.get('fontSize');\r\n font_size += dn.const_.font_size_increment;\r\n font_size = font_size > dn.const_.max_font_size ? dn.const_.max_font_size:font_size;\r\n dn.g_settings.set('fontSize', font_size);\r\n}\r\n\r\n\r\n// view function ::::::::::::::::::::::::::::::::::\r\n\r\nvar on_change = function(e){\r\n var new_value = e.newValue;\r\n\r\n switch(e.property){\r\n\r\n case \"showGutterHistory\":\r\n var s = dn.editor.getSession(); \r\n if(new_value){\r\n el.gutter_history_show.classList.add('selected')\r\n el.gutter_history_hide.classList.remove('selected');\r\n }else{\r\n el.gutter_history_hide.classList.add('selected')\r\n el.gutter_history_show.classList.remove('selected');\r\n }\r\n break;\r\n\r\n case \"wordWrapAt\":\r\n el.word_wrap_at_text.textContent = new_value;\r\n break;\r\n\r\n case \"wordWrap\":\r\n if(!new_value[0])\r\n el.word_wrap_off.classList.add('selected');\r\n else\r\n el.word_wrap_off.classList.remove('selected');\r\n if(new_value[0] && !new_value[1])\r\n el.word_wrap_edge.classList.add('selected');\r\n else\r\n el.word_wrap_edge.classList.remove('selected');\r\n if(new_value[0] && new_value[1])\r\n el.word_wrap_at.classList.add('selected');\r\n else\r\n el.word_wrap_at.classList.remove('selected');\r\n break;\r\n\r\n case \"softTabN\":\r\n el.tab_soft_text.textContent = new_value;\r\n break;\r\n\r\n case \"tabIsHard\": \r\n if(new_value){\r\n el.tab_soft.classList.remove('selected');\r\n el.tab_hard.classList.add('selected');\r\n }else{\r\n el.tab_soft.classList.add('selected');\r\n el.tab_hard.classList.remove('selected');\r\n }\r\n break;\r\n \r\n case \"newLineDefault\":\r\n if(new_value == \"windows\"){\r\n el.newline_unix.classList.remove('selected');\r\n el.newline_windows.classList.add('selected');\r\n }else{\r\n el.newline_unix.classList.add('selected');\r\n el.newline_windows.classList.remove('selected');\r\n }\r\n break;\r\n \r\n case \"fontSize\":\r\n var scrollLine = dn.get_scroll_line();\r\n el.font_size_text.textContent = new_value.toFixed(1);\r\n break;\r\n\r\n case \"theme\":\r\n theme_drop_down.SetInd(theme_drop_down.IndexOf(new_value), true);\r\n break;\r\n \r\n }\r\n}\r\n\r\nreturn {\r\n on_document_ready: on_document_ready\r\n};\r\n\r\n\r\n\r\n})();\r\n","\"use strict;\"\r\n\r\ndn.open_pane = (function(){\r\n\r\nvar el = {};\r\nvar picker;\r\n\r\nvar on_document_ready = function(){\r\n el.opener_button_a = document.getElementById('opener_button_a');\r\n el.opener_button_a.addEventListener('click', open_button_click);\r\n}\r\n\r\n\r\nvar open_button_click = function(){\r\n gapi.load('picker', function(){\r\n var view = new google.picker.View(google.picker.ViewId.DOCS);\r\n try{\r\n if(!picker){\r\n picker = new google.picker.PickerBuilder()\r\n .enableFeature(google.picker.Feature.NAV_HIDDEN)\r\n .setAppId(dn.client_id) /* the drive scope requires explicit permission to open each file, and by providing the client_id here you get it for the chosen file */\r\n .setOAuthToken(gapi.auth.getToken().access_token) /* this gives permission to open the picker..you can do it wtihout a user-specific access_token, but we have one so lets use it */\r\n .addView(view)\r\n .setCallback(picker_callback)\r\n .build(); \r\n if(!picker)\r\n throw \"could not build picker\";\r\n }\r\n picker.setVisible(true);\r\n } catch (e){\r\n dn.show_error(\"\" + e);\r\n }\r\n });\r\n\r\n}\r\n\r\nvar picker_callback = function(data) {\r\n if (data.action == google.picker.Action.PICKED) {\r\n var file_id = data.docs[0].id;\r\n var url = \"?state=\" + JSON.stringify({\r\n action: \"open\",\r\n userId: dn.url_user_id,\r\n ids: [file_id]\r\n });\r\n window.location = url;\r\n }else if(data.action == \"cancel\"){\r\n dn.focus_editor();\r\n }\r\n}\r\n\r\n\r\nreturn {\r\n\ton_document_ready: on_document_ready\r\n};\r\n\r\n})();","\"use strict\";\r\n\r\ndn.help_pane = (function(){\r\n\r\nvar el = {};\r\n\r\nvar show_inner = function(inner_pane){\r\n\t// this is a view function for dn.g_settings['help_inner']\r\n // expects string 'shorcuts' or 'tips', any other values shows main\r\n\r\n el.inner_pane_shortcuts.style.display = 'none';\r\n el.inner_pane_tips.style.display = 'none';\r\n el.inner_pane_main.style.display = 'none';\r\n\r\n el.button_shortcuts.classList.remove('selected');\r\n el.button_tips.classList.remove('selected');\r\n \r\n if(inner_pane == 'tips'){\r\n el.inner_pane_tips.style.display = '';\r\n el.button_tips.classList.add('selected');\r\n } else if(inner_pane == 'shortcuts'){\r\n el.inner_pane_shortcuts.style.display = '';\r\n el.button_shortcuts.classList.add('selected');\r\n } else {\r\n el.inner_pane_main.style.display = '';\r\n }\r\n}\r\n\r\n\r\nvar render_user_name = function(val){\r\n\tel.user_name.textContent = val;\r\n}\r\n\r\nvar create_pane_shortcuts = function(){\r\n//This is hardly the world's most efficient way of doing this....(but it probably doesn't matter)...\r\n\r\n var arry = dn.shortcuts_list;\r\n var dict = {};\r\n var platform = dn.platform;\r\n\r\n if(platform == \"Windows\" || platform == \"Linux\"){\r\n for(var i=0;i<arry.length;i++){\r\n var parts = arry[i].split(\"|\");\r\n if(parts[1].length)\r\n dict[parts[0]] = parts[1];\r\n }\r\n }else if(platform == \"Mac\"){\r\n for(var i=0;i<arry.length;i++){\r\n var parts = arry[i].split(\"|\");\r\n if(parts[1].length)\r\n dict[parts[0]] = parts.length > 2? parts[2] : parts[1];\r\n }\r\n }else{\r\n //TODO: show something here, maybe let user switch, maybe have touch info for ipad & android.\r\n }\r\n \r\n var html = [];\r\n for(var action in dict)\r\n html.push(\"<div class='shortcut_item'><div class='shortcut_action'>\" + \r\n action + \"</div><div class='shortcut_key'>\" + dict[action].replace(\",\",\"<br>\") +\r\n \"</div></div>\");\r\n \r\n // TODO: put shortcuts into element titles, see menu_id_to_caption\r\n //for(var action in dn.tooltip_info)if(action in dict)\r\n // dn.tooltip_info[action] += dict[action];\r\n\t\r\n el.inner_pane_shortcuts.innerHTML = [\r\n \"<div class='widget_box_title shortcuts_title'>Keyboard Shortcuts \",\r\n platform ? \"(\" + platform + \")\" : \"\" ,\r\n \"</div>\",\r\n \"<div class='shortcuts_header_action'>action</div><div class='shortcuts_header_key'>key</div>\",\r\n \"<div class='shortcuts_list'>\",\r\n html.join(''),\r\n \"</div>\"].join('');\r\n\r\n}\r\n\r\nvar on_document_ready = function(){\r\n el.user_name = document.getElementById('user_name');\r\n el.inner_pane_shortcuts = document.getElementById('pane_help_shortcuts');\r\n el.inner_pane_tips = document.getElementById('pane_help_tips');\r\n el.inner_pane_main = document.getElementById('pane_help_main');\r\n el.button_shortcuts = document.getElementById('button_view_shortcuts');\r\n el.button_tips = document.getElementById('button_view_tips');\r\n el.button_shortcuts.addEventListener('click', function(){\r\n if(dn.g_settings.get('help_inner') === 'shortcuts')\r\n dn.g_settings.set('help_inner', 'main');\r\n else\r\n dn.g_settings.set('help_inner', 'shortcuts');\r\n })\r\n el.button_tips.addEventListener('click', function(){\r\n if(dn.g_settings.get('help_inner') === 'tips')\r\n dn.g_settings.set('help_inner', 'main');\r\n else\r\n dn.g_settings.set('help_inner', 'tips');\r\n })\r\n create_pane_shortcuts();\r\n dn.g_settings.addEventListener(\"VALUE_CHANGED\", function(e){\r\n \tif(e.property === 'help_inner')\r\n \t\tshow_inner(e.newValue);\r\n });\r\n \r\n}\r\n\r\n\r\nreturn {\r\n\ton_document_ready: on_document_ready,\r\n\ton_user_name_change: render_user_name\r\n}\r\n\r\n})();","\"use strict\";\r\n\r\n/*\r\n Working with oauth2 APIs has its complexities, some of which\r\n are dealt with by the google client library, but some of which\r\n are exposed for us to deal with.\r\n\r\n These functions do the majority of the fiddly stuff. In particular,\r\n the dn.request_* functions are designed to be used in a promise chain\r\n within a until_success call. See the readme for additional explanation.\r\n\r\n You can insert the request_screw_up_auth into a promise chain to check \r\n how the chain handles unexpected invalidation.\r\n\r\n*/\r\n\r\ndn.filter_api_errors = function(err){\r\n // this is designed for use in conjunction with until_success\r\n if(dn.is_auth_error(err)){\r\n dn.pr_auth.reject(err); //will trigger some kind of re-authnetication\r\n return false; // continue with next attempt\r\n }else{\r\n throw err; // this is an unrecognised error\r\n }\r\n}\r\n\r\ndn.is_auth_error = function(err){\r\n // returns :\r\n // 0 for fatal errors\r\n // 1 for recommended auto refresh\r\n // 2 for recommended manual refresh\r\n // 3 for network error/timeout, recommend test network and retry\r\n // 4 for server error, recommend retry (ideally with exponential backoff)\r\n\r\n if(!err)\r\n return 2;\r\n\r\n \r\n try{\r\n if(err.status > 200){\r\n var str = \"status: \" + err.status + \" \";\r\n if(err.result && err.result.error)\r\n str += JSON.stringify(err.result.error);\r\n str += \" dn.status: \" + JSON.stringify(dn.status);\r\n str += \" stack: \" + (new Error()).stack;\r\n ga('send', 'exception', {'exDescription': str});\r\n }\r\n }catch(_){}\r\n \r\n\r\n if(err.type === \"token_refresh_required\" || err.status === 401)\r\n return 1;\r\n\r\n if(err.status === 403){\r\n var reason = \"\"\r\n try{reason = err.result.error.errors[0].reason;}catch(_){};\r\n\r\n if(reason === \"domainPolicy\")\r\n return 0;\r\n if(reason === \"insufficientFilePermissions\")\r\n return 0; // should only happen if file becomes read-only after the page loads\r\n if(reason === \"cannotDownloadAbusiveFile\")\r\n return 0; // this is not documented but appears in logs\r\n\r\n //TODO: handle other specifics, and include exponential backoff where appropriate\r\n return 1; // a variety of things here\r\n }\r\n if(err.status === 404)\r\n return 0; // file not found\r\n if(err === \"timeout\")\r\n return 3;\r\n if(err.result && err.result.error && err.result.error.code === -1)//network error\r\n return 3;\r\n if(err.status === 400)\r\n return 0; // bad request\r\n if(err.status === 500)\r\n return 4;\r\n return 0;\r\n}\r\n\r\ndn.api_error_to_string = function(err){\r\n if(!err)\r\n return \"Error.\";\r\n var reason = \"\"\r\n try{reason = err.result.error.errors[0].reason;}catch(_){};\r\n if(reason === \"insufficientFilePermissions\")\r\n return \"You do not have permission to modify the file.\";\r\n if(reason === \"domainPolicy\")\r\n return \"Your domain administrators have disabled Drive apps.\"\r\n\r\n if(err.result && err.result.error && err.result.error.message !== undefined){\r\n return \"\" + err.result.error.message;\r\n } else {\r\n console.log(\"Strangely structured error:\")\r\n console.dir(err);\r\n return \"Error. See developer console for details.\"\r\n }\r\n}\r\n\r\ndn.handle_auth_error = function(err){\r\n // this is the error handler for dn.pr_auth\r\n\r\n dn.status.authorization = -1;\r\n dn.status.popup_active = 0;\r\n dn.show_status();\r\n var err_type = dn.is_auth_error(err);\r\n\r\n if(err_type === 0){\r\n dn.show_error(dn.api_error_to_string(err));\r\n }else if(err_type == 1){\r\n dn.reauth_auto();\r\n }else if(err_type == 2){\r\n // user has to click button to trigger reauth-manual\r\n dn.toggle_permission(true);\r\n }else{\r\n // should be network error\r\n dn.show_error(\"network error. retrying...\");\r\n offline_simple.commence_testing(); // we have already registered a listener that will resolve pr_auth when the connection is restored\r\n }\r\n}\r\n\r\ndn.reauth_auto_delay_chain = {0: 1, 1:500, 500: 1000, 1000: 2500, 2500: 5000, 5000: 10000, 10000: 60000, 60000: 60000}\r\ndn.reauth_auto = function(){ \r\n // with roughly-exponetial backoff...\r\n if (!dn.reauth_auto_timer){\r\n // 1ms, 500ms, 1s, 2s, 5s, 10s, 60s.\r\n if(!dn.reauth_auto_delay)\r\n dn.reauth_auto_delay = dn.reauth_auto_delay_chain[0];\r\n else\r\n dn.reauth_auto_delay = dn.reauth_auto_delay_chain[dn.reauth_auto_delay];\r\n dn.status.authorization = 0;\r\n dn.show_status();\r\n console.log(\"issuing auto reauth with delay \" + dn.reauth_auto_delay + \"ms.\")\r\n dn.reauth_auto_timer = setTimeout(function(){\r\n dn.reauth_auto_timer = undefined;\r\n console.log(\"and now running the auto reauth...\")\r\n Promise.race([gapi.auth.authorize(dn.auth_map(true)), make_timeout(dn.const_.auth_timeout)])\r\n .then(dn.pr_auth.resolve.bind(dn.pr_auth),\r\n dn.pr_auth.reject.bind(dn.pr_auth));\r\n }, dn.reauth_auto_delay)\r\n } else {\r\n console.log(\"auto reauth already due to be sent\")\r\n }\r\n}\r\n\r\ndn.reauth_manual = function(){\r\n // if this succeeds it will trigger dn.pr_auth.resolve, which will call \r\n // any pending (and future) success callbacks.\r\n dn.status.popup_active = 1;\r\n dn.status.authorization = 0;\r\n dn.show_status(); \r\n Promise.resolve(gapi.auth.authorize(dn.auth_map(false)))\r\n .then(dn.pr_auth.resolve.bind(dn.pr_auth),\r\n dn.pr_auth.reject.bind(dn.pr_auth));\r\n}\r\n\r\ndn.request_user_info = function(){\r\n // returns thenable\r\n return gapi.client.request({'path' : 'userinfo/v2/me?fields=name'})\r\n}\r\n\r\ndn.request_file_meta = function(){\r\n // returns thenable\r\n return gapi.client.request({\r\n 'path': '/drive/v3/files/' + dn.the_file.file_id,\r\n 'params':{'fields': 'id,name,mimeType,description,parents,capabilities,fileExtension,shared,properties'}});\r\n}\r\n\r\ndn.request_file_body = function(){\r\n // returns thenable\r\n return gapi.client.request({\r\n 'path': '/drive/v3/files/' + dn.the_file.file_id,\r\n 'params':{'alt': 'media'},\r\n 'headers': {'contentType': 'charset=utf-8'}});\r\n}\r\n\r\ndn.make_multipart_boundary = function(){\r\n //for MIME protocol, require a boundary that doesn't exist in the message content.\r\n //we could check explicitly, but this is essentially guaranteed to be fine:\r\n // e.g. \"13860126288389.206091766245663\"\r\n return (new Date).getTime() + \"\" + Math.random()*10;\r\n}\r\n\r\ndn.request_new = function(folder_id, title){\r\n // this is a factory function for building a function-of-no-args-that-returns-a-thenable\r\n var meta = {name: title};\r\n if(folder_id !== undefined)\r\n meta['parents'] = [folder_id];\r\n return function(){\r\n return gapi.client.request({\r\n 'path': '/drive/v3/files/',\r\n 'method': 'POST',\r\n 'params' : {'fields': 'id,name,mimeType,description,parents,capabilities,fileExtension,shared'},\r\n 'body' : JSON.stringify(meta)\r\n });\r\n };\r\n}\r\n\r\ndn.request_revision_list = function(){\r\n // returns thenable\r\n return gapi.client.request({\r\n 'path': '/drive/v3/files/' + dn.the_file.file_id + \"/revisions\"});\r\n}\r\n\r\ndn.request_revision_body = function(revision_id){\r\n // returns a function that returns a thenable\r\n // note that annoyingly you cant use batch requests with alt=media,\r\n return function(){\r\n return gapi.client.request({\r\n 'path': '/download/drive/v3/files/' + dn.the_file.file_id + \"/revisions/\" + revision_id,\r\n 'params':{'alt': 'media'}});\r\n };\r\n}\r\n\r\n\r\ndn.request_save = function(parts){\r\n // this is a factory function for building a function-of-no-args-that-returns-a-thenable\r\n // note the save process is complicated and should only be done via dn.save in save.js\r\n var has_body = parts.body !== undefined;\r\n var meta = {properties: {}};\r\n var has_meta = false;\r\n if(parts.title !== undefined){\r\n has_meta = true;\r\n meta['name'] = parts.title;\r\n }\r\n if(parts.description !== undefined){\r\n has_meta = true;\r\n meta['description'] = parts.description;\r\n }\r\n if(parts.syntax !== undefined){\r\n has_meta = true;\r\n meta.properties['aceMode'] = parts.syntax;\r\n }\r\n if(parts.newline !== undefined){\r\n has_meta = true;\r\n meta.properties['newline'] = parts.newline;\r\n }\r\n if(parts.tabs !== undefined){\r\n has_meta = true;\r\n meta.properties['tabs'] = parts.tabs;\r\n }\r\n var is_multipart = has_body && has_meta;\r\n var params = {'fields': 'version'};\r\n if(has_body)\r\n params['uploadType'] = is_multipart ? 'multipart' : 'media';\r\n\r\n var headers = {}\r\n if(is_multipart){\r\n var boundary = dn.make_multipart_boundary();\r\n request_body = \"--\" + boundary\r\n + \"\\nContent-Type: application/json; charset=UTF-8\\n\\n\" \r\n + JSON.stringify(meta) \r\n + \"\\n--\" + boundary\r\n + \"\\nContent-Type: \" + parts.mimeType + \"; charset=UTF-8\\n\\n\" \r\n + parts.body\r\n + \"\\n--\" + boundary + \"--\" ;\r\n headers['Content-Type'] = 'multipart/related; boundary=\"' + boundary+'\"';\r\n // TODO: check if we need to add the content length ourselves\r\n // Content-Length: number_of_bytes_in_entire_request_body\r\n }else if(has_body){\r\n request_body = parts.body;\r\n headers[\"Content-Type\"] = parts.mimeType;\r\n } else {\r\n request_body = JSON.stringify(meta);\r\n }\r\n\r\n return function(){\r\n return gapi.client.request({\r\n 'path': (has_body ? '/upload' : '') + '/drive/v3/files/' + dn.the_file.file_id,\r\n 'method': 'PATCH',\r\n 'params' : params,\r\n 'headers' : headers,\r\n 'body' : request_body\r\n });\r\n }\r\n\r\n}\r\n\r\ndn.request_app_data_document = function(){\r\n return new Promise(function(succ, fail){\r\n\r\n // we want one error handler for loading, and one for subsequent errors, but the API doesn't\r\n // distinguish between the two, so it's up to us to do so....\r\n dn.app_data_realtime_error = function(err){\r\n if(dn.status.realtime_settings < 1){\r\n fail(err);\r\n }else{\r\n if(err.type === \"token_refresh_required\"){\r\n dn.pr_auth.reject(err);\r\n } else {\r\n console.dir(err);\r\n dn.show_error(\"\" + err);\r\n }\r\n }\r\n }\r\n\r\n gapi.drive.realtime.loadAppDataDocument(succ, null, dn.app_data_realtime_error);\r\n // the null argument is an omptional function for handling the initialization\r\n // the first time the document is loaded;\r\n });\r\n}\r\n\r\n\r\n//*\r\ndn.request_screw_up_auth_counter = 0;\r\ndn.request_screw_up_auth = function(){\r\n if(++dn.request_screw_up_auth_counter < 10){\r\n console.log(\"INVALIDATING TOKEN\")\r\n gapi.auth.setToken(\"this_is_no_longer_valid\");\r\n }\r\n return true;\r\n}\r\n//*/","\"use strict\";\r\n/*\r\n Note that the find history list has its most recent entries at the 0-end, but\r\n the clipboard tool has its most recent entries at the other end.\r\n\r\n*/\r\ndn.clipboard_tool = (function(const_){\r\n\r\nvar is_active = false;\r\nvar showing_pane = false; // there is a delay after being active before we show the pane, note the public is_active method actually uses this value\r\nvar clipboard_index = -1;\r\nvar clipboard_info_timer = 0;\r\n\r\nvar document_clipboard_left = function(e){\r\n if(!is_active)\r\n return false;\r\n if(clipboard_index <= 0)\r\n return true;\r\n clipboard_index--;\r\n dn.editor.undo();\r\n dn.editor.insert(dn.g_clipboard.get(clipboard_index));\r\n return true;\r\n}\r\n\r\nvar document_clipboard_right = function(e){\r\n if(!is_active)\r\n return false;\r\n\r\n dn.g_atomic_exec(function(){\r\n if(clipboard_index >= dn.g_clipboard.length-1)\r\n return true;\r\n clipboard_index++;\r\n dn.editor.undo();\r\n dn.editor.insert(dn.g_clipboard.get(clipboard_index));\r\n })\r\n return true;\r\n}\r\n\r\nvar document_clipboard_keyup = function(e){\r\n if(e.which == 17 || e.which == 91 || !e.ctrlKey){\r\n document.removeEventListener('keyup', document_clipboard_keyup);\r\n is_active = false;\r\n if(showing_pane){\r\n showing_pane = false;\r\n dn.show_pane(dn.g_settings.get('pane'));\r\n dn.toggle_widget(dn.g_settings.get('pane_open'));\r\n }\r\n if(clipboard_info_timer){\r\n clearTimeout(clipboard_info_timer);\r\n clipboard_info_timer = null;\r\n }\r\n }\r\n}\r\n\r\nvar on_paste = function(e){\r\n if (dn.g_clipboard === undefined)\r\n return; // don't bother implementing anything until cloud settings are properly loaded\r\n var text = e.text || \"\";\r\n is_active = true; \r\n document.addEventListener('keyup', document_clipboard_keyup);\r\n \r\n clipboard_index = dn.g_clipboard.lastIndexOf(text); \r\n if(clipboard_index == -1){ //it's possible the user copied some text from outside the DN, in which case we will add it to the clipboard now\r\n clipboard_index = dn.g_clipboard.push(text);\r\n if(dn.g_clipboard.length > const_.clipboard_max_length){\r\n clipboard_index--;\r\n dn.g_clipboard.remove(0);\r\n }\r\n }\r\n if(clipboard_info_timer)\r\n clearTimeout(clipboard_info_timer);\r\n\r\n clipboard_info_timer = setTimeout(function(){\r\n clipboard_info_timer = null;\r\n showing_pane = true; // this prevents g_settings 'pane_open' and 'pane' updates from being rendered\r\n dn.toggle_widget(true); // we can then temporarily exert manual control over the rendering of pane and pane_open\r\n dn.show_pane('pane_clipboard');\r\n }, const_.clipboard_info_delay);\r\n}\r\n\r\nvar on_copy = function(text){\r\n if (dn.g_clipboard === undefined)\r\n return; // don't bother implementing anything until cloud settings are properly loaded\r\n text = text || \"\";\r\n dn.g_atomic_exec(function(){\r\n\r\n var previous_idx = dn.g_clipboard.lastIndexOf(text); \r\n if(previous_idx === -1){\r\n // text is new, add it to the end of the clipboard\r\n dn.g_clipboard.push(text);\r\n if(dn.g_clipboard.length > const_.clipboard_max_length)\r\n dn.g_clipboard.remove(0); \r\n }else{\r\n // the text already exists in the clipboard history, lets bring it to the front\r\n dn.g_clipboard.move(previous_idx, 0)\r\n }\r\n\r\n }); //g_atomic_exec\r\n\r\n}\r\n\r\n\r\nvar on_document_ready = function(){\r\n dn.editor.on(\"paste\", on_paste);\r\n dn.editor.on(\"copy\", on_copy);\r\n}\r\n\r\n\r\nreturn {\r\n on_document_ready: on_document_ready,\r\n on_left: document_clipboard_left, // this and...\r\n on_right: document_clipboard_right, // this, are registered in keyboard.js\r\n is_active: function(){return showing_pane}\r\n};\r\n\r\n})(dn.const_);\r\n\r\n","\"use strict\";\r\n\r\ndn.save_pending_requests = [];\r\n\r\ndn.SaveTracker = function(){\r\n this.local = undefined;\r\n this.remote = undefined;\r\n return this;\r\n}\r\n\r\ndn.save_local_version_counter = 0;\r\n\r\n// this list tracks the state of the server, to the best of our knowledge,\r\n// i.e. based on all the respones we have recieved to date (we use the \r\n// server's \"version\" number to ensure we maintain the same chronology as the server).\r\ndn.save_server_state = {};\r\n\r\n// this is similar to the above but holds SaveRequest instances. Every time\r\n// we construct a new SaveRequest, we update this list.\r\ndn.save_local_state = { };\r\n\r\n\r\ndn.save = function(parts, correction_with_undo_id){\r\n // this is the only method that should be called by other bits of the program\r\n\r\n if(!dn.status.user_wants_file){\r\n // this is the first sign the user has given that they actually want a file \r\n // i.e. they want a new file to be created.\r\n // This is different to all other saves because we wait for it to return before\r\n // issuing any later requests, although we can still put requests into the queue.\r\n dn.create_file(); // this only saves the title, it will set user_wants_file to 1, \r\n // and evetunally settle the Promise dn.pr_file_loaded.\r\n parts.title = undefined; // we don't need to deal with title here\r\n }\r\n\r\n // update the status, and deal undo manager tracking...\r\n var found_something = false;\r\n if(parts.body !== undefined){\r\n var editor_undo_id = correction_with_undo_id === undefined ? \r\n dn.editor.getSession().getUndoManager().getCurrentId()\r\n : correction_with_undo_id;\r\n if(dn.save_undo_id === editor_undo_id){ // during correction requests, save_undo_id will already be NaN, so this test will fail\r\n delete parts.body; // no need to save the body if it's already on the server\r\n // TODO: actually, saves could be in progress, in which case we don't actually know for sure what is on the server\r\n // i.e. you might want to send an \"undo\" save before a mistake save has completed\r\n } else {\r\n found_something = true;\r\n dn.save_undo_id = NaN; // while we are saving the body the document can only be \"dirty\"\r\n parts.undo_id = editor_undo_id; // TODO: when making corrections, we need to copy this across\r\n dn.check_unsaved();\r\n parts.mimeType = parts.mimeType || dn.the_file.chosen_mime_type;\r\n dn.status.save_body = 0;\r\n }\r\n }\r\n if(parts.title !== undefined){\r\n found_something = true;\r\n dn.status.save_title = 0;\r\n }\r\n if(parts.syntax !== undefined ||\r\n parts.description !== undefined ||\r\n parts.newline !== undefined ||\r\n parts.tabs !== undefined){\r\n found_something = true;\r\n dn.status.save_other = 0;\r\n }\r\n \r\n if(!found_something)\r\n return;\r\n\r\n dn.show_status();\r\n\r\n // and construct the (complicated) request..\r\n dn.save_pending_requests.push(new dn.SaveRequest(parts));\r\n}\r\n\r\ndn.SaveRequest = function(parts){\r\n //console.log(\"SaveRequest: \" + JSON.stringify(parts));\r\n this._parts = parts\r\n\r\n // update save_local_state \r\n var displaced_requests = [];\r\n for(var k in this._parts) if(this._parts.hasOwnProperty(k)){\r\n if(dn.save_local_state[k] && !dn.save_local_state[k]._is_settled)\r\n displaced_requests.push(dn.save_local_state[k]);\r\n dn.save_local_state[k] = this;\r\n }\r\n\r\n // see if any of the displaced requests that are still pending, are no longer desired.\r\n // We can't competely cancel pending requests, but we can make it known that they\r\n // should stop trying so hard to complete.\r\n for(var ii=0; ii< displaced_requests.length; ii++){\r\n var desired = false; // if displaced_requests[ii] is responsible for any of save_local_state, then it is desired still \r\n for(var k in dn.save_local_state) if(dn.save_local_state.hasOwnProperty(k))\r\n if(dn.save_local_state[k] == displaced_requests[ii]){\r\n desired = true;\r\n break;\r\n }\r\n if(!desired)\r\n displaced_requests[ii]._desired = false;\r\n }\r\n\r\n\r\n this._desired = true; // see above description and _throw_if_not_desired, to see how this is used\r\n this._tracker = new dn.SaveTracker(); // hold local and remote version numbers\r\n this._tracker.local = ++dn.save_local_version_counter;\r\n this._is_settled = false;\r\n this._error = undefined;\r\n\r\n var self = this;\r\n this._pr =\r\n until_success(function(succ, fail){\r\n Promise.all([dn.pr_auth, dn.pr_file_loaded])\r\n .then(self._throw_if_not_desired.bind(self))\r\n .then(dn.request_save(self._parts))\r\n .then(self._on_completion.bind(self))\r\n .then(succ, fail);\r\n }).before_retry(dn.filter_api_errors)\r\n .catch(self._on_error.bind(self))\r\n .then(self._on_finally.bind(self))\r\n\r\n return this;\r\n}\r\n\r\ndn.SaveRequest.prototype._throw_if_not_desired = function(){\r\n if(!this._desired)\r\n throw \"not desired\"; //caught by on_error, and turned into success\r\n return true;\r\n}\r\n\r\ndn.SaveRequest.prototype._on_error = function(err){\r\n if(err !== \"not desired\")\r\n this._error = err; // an actual error, record it\r\n}\r\n\r\ndn.SaveRequest.prototype._on_completion = function(res){\r\n this._tracker.remote = parseInt(res.result.version);\r\n // update 0 or more entries in dn.save_server_state (see description above)\r\n for(var k in this._parts) if(this._parts.hasOwnProperty(k)){\r\n if(dn.save_server_state[k] === undefined)\r\n dn.save_server_state[k] = new dn.SaveTracker();\r\n if(dn.save_server_state[k].remote === undefined || this._tracker.remote > dn.save_server_state[k].remote){\r\n dn.save_server_state[k].remote = this._tracker.remote;\r\n dn.save_server_state[k].local = this._tracker.local;\r\n }\r\n } \r\n return true; \r\n}\r\n\r\ndn.SaveRequest.prototype._on_finally = function(){\r\n // called when the until_success deems that success has occured\r\n // but that means the request was a legitimate failure, or canaceled,\r\n // though at this point we don't care what happened exactly.\r\n\r\n if(this._error !== undefined){\r\n dn.show_error(\"Saving failed. \" + dn.api_error_to_string(this._error));\r\n console.dir(this._error);\r\n // abandon all requests, but note they may still continue executing\r\n while(dn.save_pending_requests.length)\r\n dn.save_pending_requests.pop()._desired = false;\r\n // and reset out records to be totally \"naive\"\r\n dn.save_server_state = {};\r\n dn.save_local_state = {};\r\n \r\n // show that we're no longer trying to save...\r\n dn.status.save_body = 1;\r\n dn.status.save_title = 1;\r\n dn.status.save_other = 1;\r\n dn.show_status();\r\n return;\r\n }\r\n\r\n // remove from the list of pending requests\r\n this._is_settled = true;\r\n dn.save_pending_requests.splice(dn.save_pending_requests.indexOf(this), 1);\r\n\r\n // if other requests are still pending, let them clean up any mess when they're done..\r\n // TODO: actually, we could do this separately for each key in save_*_state.\r\n if(dn.save_pending_requests.length > 0)\r\n return;\r\n\r\n // dn.save_local_state holds the state we want the server to have, and \r\n // dn.save_server_state holds the state the server ended up with \r\n // (and remember there are no pending requests), so lets build a list\r\n // of corrections to make to the server\r\n var correction = {};\r\n var correction_need = false;\r\n for(var k in dn.save_local_state) if(dn.save_local_state.hasOwnProperty(k))\r\n if(dn.save_server_state[k].local !== dn.save_local_state[k]._tracker.local){\r\n correction[k] = dn.save_local_state[k]._parts[k];\r\n correction_need = true;\r\n }\r\n\r\n // and now we can make the request, if we need to..\r\n dn.status.save_body = 1; \r\n dn.status.save_title = 1;\r\n dn.status.save_other = 1;\r\n\r\n var local_undo_id = dn.save_local_state.body ? dn.save_local_state.body._parts.undo_id : undefined;\r\n if(correction.body === undefined && local_undo_id !== undefined){\r\n dn.save_undo_id = dn.save_local_state.body._parts.undo_id; // we know the server now has this undo point\r\n dn.check_unsaved();\r\n }\r\n\r\n if (correction_need)\r\n dn.save(correction, local_undo_id); // this will set some of the status's to 0 and call show_status\r\n else\r\n dn.show_status();\r\n\r\n}\r\n\r\n\r\n\r\n\r\n","\"use strict\";\r\n\r\ndn.do_print = (function(){\r\n\r\n\r\n var line_to_html = function (n){\r\n var printLayer = Object.create(ace.require('ace/layer/text').Text.prototype); \r\n var tokens = dn.editor.getSession().getTokens(n);\r\n var html = [];\r\n var screenColumn = 0;\r\n for (var i = 0; i < tokens.length; i++) {\r\n var token = tokens[i];\r\n var value = token.value.replace(/\\t/g,' ');//TODO:deal with tabs properly\r\n if(value)\r\n printLayer.$renderToken(html, 0, token, value);\r\n }\r\n return html.join('').replace(/ /g,' ');\r\n}\r\n\r\nreturn function(){\r\n var content = dn.editor.session.doc.getAllLines();\r\n var html = Array(content.length);\r\n\r\n for(var i=0; i<content.length;i++)\r\n html[i] = \"<li><div class='printline'>\" + line_to_html(i) + '</div></li>';\r\n\r\n var printWindow = window.open('','');\r\n printWindow.document.writeln(\r\n \"<html><head><title>\" + dn.the_file.title \r\n + \"</title></head><style>\"\r\n + ace.require('ace/theme/' + dn.g_settings.get('theme')).cssText + \"\\nbody{font-size:\"\r\n + dn.g_settings.get('fontSize') *14 +\"px; white-space:pre-wrap;\" + \r\n \"font-family:'Monaco','Menlo','Ubuntu Mono','Droid Sans Mono','Consolas',monospace;}\"\r\n + \"\\nli{color:gray;}\\n.printline{color:black;}</style>\" + \r\n \"<body class='ace-\"+ dn.g_settings.get('theme').replace('_','-') +\"'><ol id='content'>\" + \r\n html.join(\"\") +\r\n \"</ol></body></html>\");\r\n printWindow.print();\r\n return false;\r\n}\r\n\r\n\r\n})()\r\n","\"use strict\";\r\ndn.file_pane = (function(){\r\n\r\n// this uses an MVC paradigm, with the model described in file_model.js\r\n\r\nvar el = {};\r\n\r\nvar history_active = false;\r\n\r\n// non-MVC functions ::::::::::::::::::::::::::::::::::\r\n\r\nvar do_save = function (e){\r\n e.preventDefault(); //needed for when called as shortcut\r\n if(dn.the_file.is_read_only)\r\n return dn.show_error(\"Cannot save read-only file.\");\r\n dn.save({body: dn.editor.getSession().getValue()});\r\n}\r\n\r\nvar read_only_bail = function(e){\r\n dn.show_error(\"The file is read-only, so you cannot change its properties.\");\r\n e.preventDefault(); // probably redundant here\r\n}\r\n\r\nvar on_title_begin_edit = function(e){ \r\n if(dn.the_file.is_read_only)\r\n return read_only_bail(e); \r\n el.title_text.style.display = 'none';\r\n el.title_input.style.display = '';\r\n el.title_input.focus();\r\n el.title_input.select();\r\n}\r\n\r\nvar on_title_keydown = function(e){\r\n if(e.which == WHICH.ESC){\r\n el.title_input.value = dn.the_file.title;\r\n e.stopPropagation();\r\n dn.focus_editor();\r\n }else if(e.which === WHICH.ENTER){\r\n e.preventDefault();\r\n dn.focus_editor(); // calls blur\r\n }\r\n}\r\n\r\nvar on_description_begin_edit =function(e){ \r\n if(dn.the_file.is_read_only)\r\n return read_only_bail(e); \r\n el.description_text.style.display = 'none';\r\n el.description_input.style.display = '';\r\n el.description_input.focus();\r\n el.description_input.select();\r\n}\r\n\r\nvar on_description_keydown = function(e){\r\n if(e.which == WHICH.ESC){\r\n el.description_input.value = dn.the_file.description;\r\n e.stopPropagation();\r\n dn.focus_editor();\r\n } else if(e.which === WHICH.ENTER && !e.ctrlKey && !e.shiftKey){\r\n e.preventDefault();\r\n dn.focus_editor(); // calls blur\r\n }\r\n}\r\n\r\nvar do_share = function(){\r\n Promise.resolve(dn.pr_file_loaded)\r\n .then(function(){\r\n dn.status.file_sharing = -1; //TODO: see SO question about no callback for share dialog...how are we supposed to know when it's closed and what happened?\r\n dn.the_file.is_shared = 0;\r\n dn.show_status();\r\n\r\n if(el.share_dialog){\r\n do_share_sub();\r\n } else {\r\n gapi.load('drive-share', function(){\r\n el.share_dialog = new gapi.drive.share.ShareClient(dn.client_id);\r\n do_share_sub();\r\n });\r\n }\r\n });\r\n}\r\n\r\nvar do_share_sub = function(){\r\n el.share_dialog.setItemIds([dn.the_file.file_id]);\r\n el.share_dialog.setOAuthToken(gapi.auth.getToken().access_token);\r\n el.share_dialog.showSettingsDialog();\r\n}\r\n\r\nvar do_print = dn.do_print;\r\n\r\n\r\n// controler functions ::::::::::::::::::::::::::::::::::\r\n\r\nvar on_description_end_edit = function(){\r\n el.description_input.style.display = 'none';\r\n el.description_text.style.display = '';\r\n var new_val = el.description_input.value;\r\n if(dn.the_file.description !== new_val){\r\n dn.the_file.set({description: new_val}); \r\n dn.save({description: new_val});\r\n }\r\n dn.focus_editor();\r\n}\r\n\r\nvar on_title_end_edit = function(){\r\n el.title_input.style.display = 'none';\r\n el.title_text.style.display = '';\r\n var new_val = el.title_input.value;\r\n if(dn.the_file.title !== new_val){\r\n dn.the_file.set({title: new_val});\r\n dn.save({title: new_val});\r\n }\r\n dn.focus_editor();\r\n}\r\n\r\nvar on_newline_click = function(e){\r\n if(dn.the_file.is_read_only)\r\n return read_only_bail(e); \r\n\r\n var val = \"detect\";\r\n if(e.currentTarget === el.newline_unix)\r\n val = \"unix\";\r\n else if (e.currentTarget === el.newline_windows)\r\n val = \"windows\";\r\n dn.the_file.set({newline: val});\r\n dn.save({newline: val});\r\n}\r\n\r\nvar on_syntax_detect_click = function(e){\r\n if(dn.the_file.is_read_only)\r\n return read_only_bail(e); \r\n\r\n dn.the_file.set({syntax: \"detect\"});\r\n dn.save({syntax: \"detect\"});\r\n}\r\n\r\nvar on_syntax_dropdown_click = function(e){\r\n if(dn.the_file.is_read_only)\r\n return read_only_bail(e); \r\n\r\n var val = syntax_drop_down.GetVal();\r\n dn.save({syntax: val}); \r\n dn.the_file.set({syntax: val});\r\n}\r\n\r\nvar on_tab_click = function(e){\r\n if(dn.the_file.is_read_only)\r\n return read_only_bail(e); \r\n\r\n var val = {val: \"detect\"};\r\n\r\n if (e.currentTarget === el.tab_soft_inc){\r\n e.stopPropagation();\r\n val = {val: \"spaces\",\r\n n: Math.min(dn.the_file.properties_chosen.tabs.n + 1, dn.const_.max_soft_tab_n)};\r\n } else if (e.currentTarget === el.tab_soft_dec){\r\n e.stopPropagation();\r\n var n = dn.the_file.properties_chosen.tabs.n - 1;\r\n val = {val: \"spaces\",\r\n n: Math.max(dn.the_file.properties_chosen.tabs.n - 1, dn.const_.min_soft_tab_n)};\r\n }else if(e.currentTarget === el.tab_soft){\r\n val = {val: \"spaces\", n: dn.the_file.properties_chosen.tabs.n};\r\n } else if(e.currentTarget === el.tab_hard){\r\n val = {val: \"tab\", n: dn.the_file.properties_chosen.tabs.n};\r\n }\r\n\r\n dn.the_file.set({tabs: val});\r\n dn.save({tabs: JSON.stringify(val)});\r\n}\r\n\r\n// view functions ::::::::::::::::::::::::::::::::::\r\n\r\nvar render_title = function(){\r\n el.title_text_inner.textContent = dn.the_file.title;\r\n el.title_input.value = dn.the_file.title;\r\n}\r\n\r\nvar render_description = function(){\r\n text_multi(el.description_text_inner, dn.the_file.description, true);\r\n el.description_input.value = dn.the_file.description;\r\n}\r\n\r\nvar render_newline = function(){\r\n el.newline_detect.classList.remove('selected');\r\n el.newline_windows.classList.remove('selected');\r\n el.newline_unix.classList.remove('selected');\r\n var val = dn.the_file.properties.newline;\r\n if(val === \"detect\")\r\n el.newline_detect.classList.add('selected');\r\n else if(val === \"windows\")\r\n el.newline_windows.classList.add('selected');\r\n else\r\n el.newline_unix.classList.add('selected'); \r\n el.newline_info.textContent = dn.the_file.properties_detected_info.newline; \r\n}\r\n\r\nvar render_syntax = function(){\r\n syntax_drop_down.SetInd(syntax_drop_down.IndexOf(dn.the_file.properties_chosen.syntax), true);\r\n if(dn.the_file.properties.syntax === \"detect\"){\r\n el.ace_mode_detect.classList.add('selected');\r\n syntax_drop_down.SetSelected(false);\r\n }else{\r\n el.ace_mode_detect.classList.remove('selected');\r\n syntax_drop_down.SetSelected(true);\r\n }\r\n el.ace_mode_info.textContent = dn.the_file.properties_detected_info.syntax;\r\n}\r\n\r\nvar render_tabs = function(){\r\n var user_tabs = dn.the_file.properties.tabs;\r\n\r\n el.tab_soft.classList.remove('selected');\r\n el.tab_hard.classList.remove('selected');\r\n el.tab_detect.classList.remove('selected');\r\n\r\n if(user_tabs.val === \"tab\")\r\n el.tab_hard.classList.add('selected');\r\n else if(user_tabs.val === \"spaces\")\r\n el.tab_soft.classList.add('selected');\r\n else\r\n el.tab_detect.classList.add('selected');\r\n \r\n el.tab_soft_text.textContent = dn.the_file.properties_chosen.tabs.n;\r\n el.tab_info.textContent = dn.the_file.properties_detected_info.tabs;\r\n}\r\n\r\nvar end_history = function(){\r\n if(!history_active)\r\n return;\r\n dn.history_tool.end();\r\n el.button_history.classList.remove('selected');\r\n el.button_save.style.display = '';\r\n el.button_print.style.display = '';\r\n el.inner_pane_history.style.display = 'none';\r\n el.inner_pane_main.style.display = '';\r\n history_active = false;\r\n}\r\n\r\nvar do_history = function(){\r\n Promise.resolve(dn.pr_file_loaded)\r\n .then(function(){\r\n el.button_history.classList.add('selected');\r\n el.button_save.style.display = 'none';\r\n el.button_print.style.display = 'none';\r\n el.inner_pane_history.style.display = '';\r\n el.inner_pane_main.style.display = 'none';\r\n dn.history_tool.start();\r\n history_active = true; \r\n });\r\n}\r\n\r\nvar syntax_drop_down;\r\n\r\nvar register_controllers = function(){\r\n // We wait until the file model is loaded before registering all these controllers.\r\n // Note that when creating a new file, the file model is said to be loaded before\r\n // we get the file_id back from the server, that is because we don't need to wait\r\n // for the server to tell us about existing metadata. In this pre-file_id state,\r\n // we can issue save requests because the save machienery knows to queued them\r\n // up until it the file_id is available.\r\n\r\n // title and description\r\n\r\n el.title_text.addEventListener('click', on_title_begin_edit) \r\n el.title_input.addEventListener(\"blur\", on_title_end_edit); \r\n el.title_input.addEventListener('keydown', on_title_keydown);\r\n\r\n el.description_text.addEventListener('click', on_description_begin_edit) \r\n el.description_input.addEventListener(\"blur\", on_description_end_edit); \r\n el.description_input.addEventListener('keydown', on_description_keydown);\r\n\r\n // File custom props stuff, make use of currentTarget to identify src\r\n\r\n el.newline_detect.addEventListener('click', on_newline_click);\r\n el.newline_windows.addEventListener('click', on_newline_click);\r\n el.newline_unix.addEventListener('click', on_newline_click);\r\n\r\n el.tab_detect.addEventListener('click', on_tab_click);\r\n el.tab_hard.addEventListener('click', on_tab_click);\r\n el.tab_soft_inc.addEventListener('click', on_tab_click);\r\n el.tab_soft_dec.addEventListener('click', on_tab_click);\r\n el.tab_soft.addEventListener('click', on_tab_click); // propagation is stopped if inc or dec are clicked rather than the base button\r\n\r\n el.ace_mode_detect.addEventListener('click', on_syntax_detect_click); \r\n syntax_drop_down.enabled = true; \r\n syntax_drop_down.addEventListener(\"click\", on_syntax_dropdown_click);\r\n syntax_drop_down.addEventListener(\"change\", on_syntax_dropdown_click);\r\n\r\n // File action buttons stuff\r\n el.button_save.addEventListener('click', do_save);\r\n el.button_print.addEventListener('click', do_print);\r\n el.button_share.addEventListener('click', do_share);\r\n el.button_history.addEventListener('click', function(){\r\n if(history_active)\r\n end_history();\r\n else \r\n do_history();\r\n });\r\n}\r\n\r\nvar on_document_ready = function(){\r\n el.title_input = document.getElementById('details_file_title_input');\r\n el.title_text = document.getElementById('details_file_title_text');\r\n el.title_text_inner = document.getElementById('details_file_title_text_inner');\r\n el.description_input = document.getElementById('details_file_description_input');\r\n el.description_text = document.getElementById('details_file_description_text'); \r\n el.description_text_inner = document.getElementById('details_file_description_text_inner'); \r\n el.ace_mode_choose = document.getElementById('file_ace_mode_choose')\r\n el.ace_mode_detect = document.getElementById('file_ace_mode_detect');\r\n el.ace_mode_info = document.getElementById('file_ace_mode_info');\r\n el.newline_detect = document.getElementById('file_newline_detect');\r\n el.newline_windows = document.getElementById('file_newline_windows');\r\n el.newline_unix = document.getElementById('file_newline_unix');\r\n el.newline_info = document.getElementById('file_newline_info');\r\n el.tab_detect = document.getElementById('file_tab_detect');\r\n el.tab_soft_inc = document.getElementById('file_tab_soft_inc');\r\n el.tab_soft_dec = document.getElementById('file_tab_soft_dec');\r\n el.tab_hard = document.getElementById('file_tab_hard');\r\n el.tab_soft = document.getElementById('file_tab_soft');\r\n el.tab_soft_text = document.getElementById('file_tab_soft_text');\r\n el.tab_info = document.getElementById('file_tab_info');\r\n el.button_save = document.getElementById('button_save');\r\n el.button_print = document.getElementById('button_print');\r\n el.button_share = document.getElementById('button_share');\r\n el.button_history = document.getElementById('button_history'); \r\n el.inner_pane_main = document.getElementById('pane_file_main'); \r\n el.inner_pane_history = document.getElementById('pane_file_history'); \r\n \r\n var modes = require(\"ace/ext/modelist\").modes; \r\n syntax_drop_down = new DropDown(modes.map(function(m){return m.caption;}));\r\n syntax_drop_down.enabled = false;\r\n el.ace_mode_choose.appendChild(syntax_drop_down.el); \r\n\r\n dn.history_tool.on_document_ready();\r\n\r\n dn.the_file.addEventListener('change', function(e){\r\n switch(e.property){\r\n case \"syntax\":\r\n render_syntax();\r\n break;\r\n\r\n case \"newline\":\r\n render_newline();\r\n break;\r\n\r\n case \"tabs\":\r\n render_tabs();\r\n break;\r\n\r\n case \"title\":\r\n render_title();\r\n break;\r\n\r\n case \"description\":\r\n render_description();\r\n break;\r\n\r\n case \"is_loaded\":\r\n register_controllers();\r\n break;\r\n }\r\n })\r\n\r\n}\r\n\r\n\r\n\r\nreturn {\r\n on_save_shorcut: do_save,\r\n on_print_shortcut: do_print,\r\n on_document_ready: on_document_ready,\r\n on_close_pane: end_history,\r\n do_history: function(e){\r\n e.preventDefault();\r\n dn.g_settings.set('pane', 'pane_file');\r\n dn.g_settings.set('pane_open', true);\r\n do_history();\r\n }\r\n}\r\n\r\n\r\n\r\n})();","\r\n/*\r\nThe following would probably have been better implemented as a fork of ace. We basically add to and overwrite whatever methods\r\nwe need to in order to acomplish our goals. It's not pretty, but hopefully it's not appaling, given what the result is.\r\n\r\nThe main method exposed to the \"user\" is show_rows, which accepts a 1d array of 0s,1s,2s, and 3s. There is one entry for\r\neach of the lines in the document. 0 means hide the row, 1 means show it in white, 2 means render it marked as \"added\", \r\nand 3 means render it marked as \"removed\".\r\n\r\nThe implementation tries to use as much of ace's machienry as possible, but does have to build some of its own. \r\n\r\nLines are hidden using ace's folding system, with the fold-markers being hidden with css.\r\n\r\nThe gutter numbering is overridden with a custom gutterRenderer.\r\n\r\nLines are marked with ace's addMarker and addGutterDecoration, but transitions are implemented \"manually\"...every time\r\nace completes its rendering, we explicitly apply our own styling logic to the markers it has produced. Specifically, \r\nwe modify the markers that were already visible the last time there was a render, with the state of the markers tracked\r\nwith the array rendered_row_transitions (and the variable first_rendered_row). i.e. markers off-screeen, or newly on screen\r\nare not transitioned to their final state.\r\n\r\nI would ideally like to animate the height transition from show_row[ii] = 0, to show_row[ii] > 0. But that is going to require\r\na lot more messing around with ace.\r\n\r\nSome of the css in app.css is critical to making this look right, but we also have some styles hardcoded here. That's obviously \r\nnot ideal.\r\n\r\ninsertFullLines has also been overriden to ensure the show_rows is updated when lines are inserted.\r\nIt is intended that the document is only modified using that method, i.e. it is readOnly and no other insertion/deletion methods are used.\r\n\r\n\r\nTODO:\r\n transitions possibly dont work on the last line of the document.\r\n*/\r\n\r\ndn.patch_editor_history = function(editor){\r\n var Range = ace.require('./range').Range;\r\n var dom = ace.require(\"./lib/dom\");\r\n\r\n var show_row = [];\r\n var row_line_number = [0];\r\n var markers = [];\r\n var first_rendered_row = -1;\r\n var rendered_row_transitions = []; // array of {from_time, to_time, from_color, to_color}, first element is first_rendered_row\r\n var colors_background = [0xffffff, 0xffffff, 0xbcebe8, 0xffcaca]; //0,1,2,3, TODO: expose this as a setting, or read from css\r\n var transition_duration = 1000; // ms\r\n editor.$blockScrolling = Infinity;\r\n editor.setHighlightActiveLine(false);\r\n editor.setHighlightGutterLine(false);\r\n\r\n // Note that unlike other patches below, this bit changes the actual Range prototype for everyone\r\n // we need to keep the doc range, so we can porvide data-row when rendering markers\r\n Range.prototype.toScreenRange = function(session) {\r\n var screenPosStart = session.documentToScreenPosition(this.start);\r\n var screenPosEnd = session.documentToScreenPosition(this.end);\r\n\r\n ret = new Range(\r\n screenPosStart.row, screenPosStart.column,\r\n screenPosEnd.row, screenPosEnd.column\r\n );\r\n ret.doc_range = this.clone();\r\n return ret;\r\n };\r\n \r\n\r\n editor.session.gutterRenderer = {\r\n getWidth: function(session, lastLineNumber, config) {\r\n return (\"\" + row_line_number[row_line_number.length-1]).length * config.characterWidth;\r\n },\r\n getText: function(session, row) {\r\n if(row >= row_line_number.length)\r\n return \"\" + row;\r\n return row_line_number[row] === -1 ? \"-\" : row_line_number[row];\r\n }\r\n };\r\n\r\n editor.session.removeAllGutterDecorations = function(){\r\n for(var ii=0; ii<this.$decorations.length; ii++)\r\n this.$decorations[ii] = \"\";\r\n this._signal(\"changeBreakpoint\", {});\r\n }\r\n\r\n // add data-row into marker renderer\r\n editor.renderer.$markerBack.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {\r\n var top = this.$getTop(range.start.row, config);\r\n var height = config.lineHeight;\r\n if (range.start.row != range.end.row)\r\n height += this.$getTop(range.end.row, config) - top;\r\n\r\n stringBuilder.push(\r\n \"<div class='\", clazz, \"' data-row='\", range.doc_range.start.row, \"' style='\",\r\n \"height:\", height, \"px;\",\r\n \"top:\", top, \"px;\",\r\n \"left:0;right:0;\", extraStyle || \"\", \"'></div>\"\r\n );\r\n };\r\n\r\n var insertFullLines_original = editor.session.doc.insertFullLines;\r\n editor.session.doc.insertFullLines = function(arg_0, arg_1){\r\n // Takes either two args: at, lines[]\r\n // or 1 arg: [{at, lines}, {at, lines}, ...]\r\n // in the first case, if at=-1, we reset using the new data.\r\n if(arg_0 === -1){\r\n show_row = new Uint8Array(arg_1.length);\r\n for(var ii=0;ii<arg_1.length; ii++)\r\n show_row[ii] = 1;\r\n var len = this.getLength() - 1;\r\n this.remove(new Range(0, 0, len, this.getLine(len).length));\r\n this.insertMergedLines({row: 0, column: 0}, arg_1);\r\n }else{\r\n show_row = Array.prototype.slice.call(show_row, 0); // temporarily convert to standard array for splicing\r\n if(arg_0.length !== undefined){\r\n if(arg_1 !== undefined) throw \"batched insert takes one array\"\r\n for(var kk=0; kk<arg_0.length; kk++){\r\n var splice_args = [arg_0[kk].at, 0];\r\n for(var ii=0; ii<arg_0[kk].lines.length; ii++)\r\n splice_args.push(0);\r\n Array.prototype.splice.apply(show_row, splice_args);\r\n insertFullLines_original.call(this, arg_0[kk].at, arg_0[kk].lines);\r\n }\r\n } else {\r\n var splice_args = [arg_0, 0];\r\n for(var ii=0; ii<arg_1.length; ii++)\r\n splice_args.push(0);\r\n Array.prototype.splice.apply(show_row, splice_args);\r\n insertFullLines_original.call(this, arg_0, arg_1);\r\n }\r\n show_row = new Uint8Array(show_row);\r\n }\r\n editor.show_rows(show_row);\r\n }\r\n\r\n editor.renderer.addEventListener('afterRender', function(){\r\n // TODO: check if it's a kind of render we need to care about\r\n\r\n var first_row = editor.renderer.getFirstVisibleRow();\r\n var last_row = editor.renderer.getLastVisibleRow();\r\n var first_row_old = first_rendered_row;\r\n var last_row_old = first_row_old + rendered_row_transitions.length;\r\n\r\n var time_now = Date.now(); //ms\r\n //console.log(\"Render request: \" + first_row + \":\" + last_row + \", changes:\" + editor.renderer.$changes);\r\n //console.log(JSON.stringify(rendered_row_transitions));\r\n //console.log(\"------\")\r\n\r\n if(first_row_old < first_row){\r\n // remove unneeded rows from the start\r\n for(var row=first_row_old; row<last_row_old && row<first_row; row++)\r\n rendered_row_transitions.shift();\r\n \r\n } else if(first_row_old > first_row ) {\r\n // add some finished-transitioning rows at the start\r\n for(var row=Math.min(last_row, first_row_old)-1; row>=first_row; row--){\r\n rendered_row_transitions.unshift({row: row,\r\n from_time: undefined,\r\n from_color: undefined,\r\n to_time: time_now,\r\n to_color: colors_background[show_row[row]]});\r\n }\r\n }\r\n\r\n // Get the randomly ordered marker elements into a simple map from row to element\r\n var all_marker_els = editor.renderer.$markerBack.element.children;\r\n var marker_els = [];\r\n for(var ii=0; ii<all_marker_els.length; ii++)\r\n if(all_marker_els[ii].dataset.row !== undefined)\r\n marker_els[all_marker_els[ii].dataset.row] = all_marker_els[ii];\r\n\r\n // Firstly we go through all the marker elements produced, set their initial colors,\r\n // and transition durtations. Then we force the colors to take effect with a single\r\n // getComputedStyle call. We can then set the target colors, which we collected into\r\n // a list colors_to_set (which is paired with els_to_set).\r\n var els_to_set = [];\r\n var colors_to_set = [];\r\n var colors_current = [];\r\n for(var row=Math.max(first_row, first_row_old); row<Math.min(last_row, last_row_old); row++){\r\n if(show_row[row] === 0) continue;\r\n var el = marker_els[row];\r\n var transition = rendered_row_transitions[row-first_row];\r\n var to_color_new = colors_background[show_row[row]];\r\n var current_color;\r\n if(transition.to_time > time_now){\r\n // transition unfinished\r\n var elapsed_frac = (time_now - transition.from_time)/ (transition.to_time - transition.from_time); // denom is just transition_duration, unless we make things more complicated \r\n current_color = mix_color(transition.from_color, transition.to_color, elapsed_frac);\r\n }else{\r\n // last transition already finished\r\n current_color = transition.to_color;\r\n }\r\n if(transition.to_color !== to_color_new){\r\n // new transition\r\n transition.from_color = current_color; \r\n transition.from_time = time_now;\r\n transition.to_time = time_now + transition_duration;\r\n transition.to_color = to_color_new;\r\n }\r\n el.style.backgroundColor = color_to_string(current_color);\r\n if(transition.to_time > time_now){\r\n el.style.transitionProperty = ''; // force the color above to take effect before we call getComputedStyle, below (not sure this is neccessarry)\r\n el.style.transitionDuration = (transition.to_time - time_now) + \"ms\";\r\n els_to_set.push(el);\r\n colors_to_set.push(to_color_new);\r\n colors_current.push(current_color);\r\n }\r\n }\r\n if(els_to_set.length)\r\n window.getComputedStyle(els_to_set[0]).backgroundColor;\r\n\r\n while(els_to_set.length){\r\n var el = els_to_set.pop();\r\n el.style.transitionProperty = 'background-color';\r\n el.style.backgroundColor = color_to_string(colors_to_set.pop());\r\n }\r\n\r\n if(last_row_old > last_row){\r\n // remove unneeded rows from the end\r\n for(row=last_row_old-1; row>=last_row && row>=first_row_old; row--)\r\n rendered_row_transitions.pop();\r\n \r\n } else if(last_row_old < last_row) {\r\n // add some finished-transitioning rows at the end\r\n for(row=Math.max(last_row_old, first_row); row<last_row; row++)\r\n rendered_row_transitions.push({row: row,\r\n from_time: undefined,\r\n from_color: undefined,\r\n to_time: time_now,\r\n to_color: colors_background[show_row[row]]}); \r\n }\r\n\r\n first_rendered_row = first_row;\r\n //console.log(\"achieved:\")\r\n //console.log(JSON.stringify(rendered_row_transitions));\r\n })\r\n\r\n var mix_color = function(a, b, frac){\r\n //mixes r,g,b separately, with frac saying how far we have gone from a to b, i.e. a=0, b=1.\r\n return ((((a&0xff0000)>>16)*(1-frac) + ((b&0xff0000)>>16)*frac) << 16 ) |\r\n ((((a&0xff00)>>8)*(1-frac) + ((b&0xff00)>>8)*frac) << 8) |\r\n (a&0xff)*(1-frac) + ((b&0xff)*frac);\r\n }\r\n var color_to_string = function(color){\r\n return \"rgb(\" + ((color & 0xff0000) >> 16) + \", \" + ((color & 0xff00) >> 8) + \", \" + (color & 0xff) + \")\";\r\n }\r\n\r\n editor.show_rows = function(show_row_){\r\n /* show_row is a 1d array the same length as the number of lines in the document,\r\n entries that are falsey are silently folded, the remaining rows have their \r\n numbering altered.\r\n show_row[ii]>=1 are marked with the class \"special_2\", \"special_3\", etc,\r\n and the gutter is marked with gutter_special_2, _3, etc..\r\n\r\n show_row[ii]=3, is shown, but doesn't have a line number\r\n\r\n TODO: check zero-hack for when nothing is showing and/or there are no rows,\r\n and possibly other variations on that.\r\n */\r\n show_row = new Uint8Array(show_row_); //clone from whatever kind of array show_row_ was\r\n\r\n var n = editor.session.doc.getLength();\r\n if(show_row.length !== n) \r\n throw \"bad mask length\";\r\n\r\n editor.session.unfold();\r\n while(markers.length)\r\n editor.session.removeMarker(markers.pop());\r\n editor.session.removeAllGutterDecorations();\r\n\r\n var line_no = 0;\r\n var fold_start = -1;\r\n row_line_number = [];\r\n var first_used_row = -1;\r\n for(var ii=0; ii<n; ii++){\r\n if(show_row[ii]){\r\n row_line_number.push(show_row[ii] === 3 ? -1 : ++line_no);\r\n if(fold_start !== -1){\r\n if(fold_start > 0){\r\n editor.session.addFold(\"\", new Range(fold_start-1, Infinity, ii-1, Infinity));\r\n } else {\r\n // TODO: folding the lines from the very top is a bit messier...\r\n // it may be this version 0,0 rather than Inf, Inf version can be used more generally,\r\n // but it requires changing various other things too.\r\n editor.session.addFold(\"\", new Range(0, 0, ii, 0));\r\n row_line_number[0] = 1;\r\n first_used_row = ii;\r\n }\r\n }\r\n fold_start = -1;\r\n }else{\r\n row_line_number.push(line_no);\r\n if(fold_start === -1)\r\n fold_start = ii;\r\n }\r\n }\r\n if(fold_start !== -1)\r\n editor.session.addFold(\"\", new Range(fold_start-1, Infinity, ii-1, Infinity));\r\n\r\n var previous = -1;\r\n if(first_used_row !== -1){\r\n //dealing further with the top-row hack thing...it's confusing, but this does the job...\r\n if(show_row[first_used_row]>=1)\r\n editor.session.addGutterDecoration(0, \"gutter_special_\" + show_row[first_used_row]);\r\n }\r\n for(var ii=0; ii<n; ii++){\r\n if(show_row[ii]>=1){\r\n markers.push(editor.session.addMarker(new Range(ii, 0, ii, Infinity),\r\n \"special_\" + show_row[ii] + (previous !== show_row[ii] ? \"_first\" : \"\"), \"fullLine\", false));\r\n editor.session.addGutterDecoration(ii, \"gutter_special_\" + show_row[ii]);\r\n }\r\n previous = show_row[ii] ? show_row[ii] : previous;\r\n }\r\n\r\n editor.renderer.updateFull();\r\n };\r\n\r\n\r\n // this isn't that important, but we override the original version here so as to let the cursor blink in readonly mode\r\n editor.$resetCursorStyle = function() {\r\n var style = this.$cursorStyle || \"ace\";\r\n var cursorLayer = this.renderer.$cursorLayer;\r\n if (!cursorLayer)\r\n return;\r\n cursorLayer.setSmoothBlinking(/smooth/.test(style));\r\n cursorLayer.isBlinking = /*!this.$readOnly && */ style != \"wide\";\r\n dom.setCssClass(cursorLayer.element, \"ace_slim-cursors\", /slim/.test(style));\r\n };\r\n // but we have to disable dragging, or the cursor will stop blinking for some reason on failed drags\r\n editor.$mouseHandler.setOptions({dragEnabled: false})\r\n\r\n}\r\n","\"use strict\";\r\n\r\ndn.history_tool = (function(){\r\n\r\nvar el = {};\r\n\r\nvar revision_meta = []; // we clear this each time we call refresh_revisions_list\r\nvar worker_has_revision = {}; // we cache revision bodies on the worker, recording true here when we do using revision id as the key\r\nvar revision_uses_line = []; // for each revision this has a 1d boolean array, giving 1 if the line is used in that revision.\r\n // every time we get a \"delivery\" of new lines from the worker we invalidate all of this. In future,\r\n // when we want to display a particular revision we have to ask the worker for the data.\r\n\r\nvar worker;\r\nvar editor;\r\nvar at_idx = 0; \r\nvar from_idx = 0;\r\n\r\n\r\nvar LineWidgets = ace.require(\"./line_widgets\").LineWidgets;\r\nvar start = function(){\r\n // TODO: add current state to revisions meta and body\r\n\r\n if(worker === undefined){\r\n worker = new Worker(\"js/history_tool_worker.js\");\r\n worker.onmessage = on_worker_message;\r\n }\r\n\r\n dn.el.editor.style.display = 'none';\r\n el.revisions_view.style.display = '';\r\n el.revisions_view.innerHTML = '';\r\n el.info_overflow.style.display = '';\r\n editor = ace.edit(\"revisions_view\");\r\n editor.setFontSize(dn.editor.getFontSize());\r\n dn.patch_editor_history(editor); \r\n editor.session.setUseWrapMode(true);\r\n editor.setReadOnly(true);\r\n refresh_revisions_list();\r\n}\r\n\r\nvar end = function(){\r\n // destroy the editor, and replace its dom element with a newly cloned instance\r\n // this wipes out any event listeners. https://github.com/ajaxorg/ace/issues/2085\r\n // also set the element's contents to be empty\r\n editor.destroy();\r\n editor = undefined;\r\n el.revisions_view.innerHTML = '';\r\n var el_old = el.revisions_view;\r\n el.revisions_view = el_old.cloneNode(true);\r\n el_old.parentNode.replaceChild(el.revisions_view, el_old);\r\n\r\n dn.el.editor.style.display = ''; \r\n el.revisions_view.style.display = 'none';\r\n el.info_overflow.style.display = 'none';\r\n}\r\n\r\nvar get_editor = function(){\r\n return editor;\r\n}\r\n\r\nvar on_worker_message = function(e){\r\n if(!editor) return; // if we closed history tool while worker was busy, we can safely ignore the two possible types of message it might be sending\r\n\r\n var session = editor.getSession();\r\n if(e.data.diffed_revision){\r\n revision_uses_line = []; // invalidate everything we knew about uses_line\r\n // TODO: perhaps we should batch up the newly delivered data and only append it when the user requests an earlier revision\r\n if(e.data.diffed_revision.idx === 0){\r\n session.doc.insertFullLines(-1, e.data.diffed_revision.lines); // resets to supplied lines\r\n } else {\r\n session.doc.insertFullLines(e.data.diffed_revision.sections); // inserts multiple batches of lines\r\n revision_meta[e.data.diffed_revision.idx].el_tick.classList.add('diffed');\r\n }\r\n }\r\n\r\n if(e.data.line_is_used){\r\n var idx = e.data.line_is_used.idx;\r\n revision_uses_line[idx] = new Uint8Array(e.data.line_is_used.buffer);\r\n if(idx === Math.max(at_idx, from_idx)){\r\n // hooray, we've got both at and from, lets render 'em, quick!\r\n if(at_idx === from_idx)\r\n render_single_revision(at_idx);\r\n else\r\n render_revision_pair(at_idx, from_idx);\r\n }else if(Math.max(at_idx, from_idx) >= e.data.line_is_used.diffed_n && idx == Math.min(at_idx, from_idx)){\r\n // well, we've got the mroe recent of the two, and the other one is going to be a while, so lets render what we have\r\n render_single_revision(Math.min(at_idx, from_idx));\r\n }\r\n }\r\n\r\n\r\n}\r\n\r\n\r\nvar render_single_revision = function(idx){\r\n editor.show_rows(revision_uses_line[idx]); // 1=show, 0=hide, which is exactly what we want\r\n var str = \"\";\r\n if(idx === 0){\r\n str = \"Showing the file:\\n\\t\" + current_version_date_str;\r\n }else{\r\n var time = date_str_to_local(revision_meta[idx].modifiedTime)\r\n str = \"Showing file as it was at:\\n\\t\" + time[1] + \" on \" + time[0];\r\n }\r\n text_multi(el.info, str);\r\n}\r\n\r\nvar fuse = function(at_is_used, from_is_used){\r\n // maps: (0,0) => 0 (1,1) => 1 (1,0) => 3 (0,1) => 2\r\n // TODO: maybe there would have been a slightly clever maping to have chosen, but it doesn't matter much.\r\n var map = new Uint8Array([0,2,3,1]);\r\n var show_rows = new Uint8Array(at_is_used.length);\r\n for(var ii=0; ii< show_rows.length; ii++)\r\n show_rows[ii] = map[at_is_used[ii] | (from_is_used[ii] << 1)];\r\n return show_rows;\r\n}\r\n\r\nvar current_version_date_str = \"as it exists in the editor\";\r\n\r\nvar render_revision_pair = function(at_idx, from_idx){\r\n editor.show_rows(fuse(revision_uses_line[at_idx], revision_uses_line[from_idx]));\r\n\r\n var str = \"\"\r\n if(at_idx === 0){\r\n str += \"Showing the file:\\n\\t\" + current_version_date_str;\r\n }else{\r\n var time_at = date_str_to_local(revision_meta[at_idx].modifiedTime);\r\n str += \"Showing file as it was at:\\n\\t\" + time_at[1] + \" on \" + time_at[0];\r\n }\r\n if(from_idx === 0){\r\n str += \"\\nWith changes relative to the file:\\n\\t\" + current_version_date_str;\r\n }else{\r\n var time_from = date_str_to_local(revision_meta[from_idx].modifiedTime);\r\n str += \"\\nWith changes relative to the file at:\\n\\t\" + time_from[1] + \" on \" + time_from[0];\r\n }\r\n text_multi(el.info, str);\r\n}\r\n\r\nvar append_tick = function(){\r\n var el_tick = document.createElement('div');\r\n el_tick.classList.add('revision_tick');\r\n el.tick_box.appendChild(el_tick);\r\n return el_tick;\r\n}\r\n\r\nvar send_revisions_order_to_worker = function(resp){\r\n var r_to_get = [], id_order = [];\r\n revision_meta = revision_meta.concat(resp.result.revisions.reverse()); \r\n el.at_range.max = revision_meta.length - 1;\r\n el.from_range.max = revision_meta.length - 1;\r\n\r\n for(var ii=1; ii<revision_meta.length; ii++){\r\n id_order.push(revision_meta[ii].id);\r\n revision_meta[ii].el_tick = append_tick();\r\n if(!worker_has_revision.hasOwnProperty(revision_meta[ii].id)){\r\n r_to_get.push(revision_meta[ii]) \r\n }else{\r\n revision_meta[ii].el_tick.classList.add('downloaded');\r\n }\r\n }\r\n\r\n worker.postMessage({use_order: id_order});\r\n revision_meta[0].el_tick.classList.add('diffed'); // this is a bit of a hack - if we had rendered it as being diffed before we knew the lenght of the list it would look wrong\r\n render_download_status();\r\n render_for_settings();\r\n return r_to_get;\r\n\r\n}\r\n\r\nvar send_revision_body_to_worker = function(revision_meta){\r\n return function(resp){\r\n if(resp.status !== 200)\r\n throw resp;\r\n worker.postMessage({revision: {\r\n id: revision_meta.id,\r\n body: decode_body(resp.body) /* fix utf-8 issues*/\r\n }});\r\n worker_has_revision[revision_meta.id] = true;\r\n revision_meta.el_tick.classList.add('downloaded');\r\n render_download_status();\r\n return true;\r\n }\r\n}\r\n\r\nvar render_download_status = function(){\r\n var n_pending = 0;\r\n for(var ii=0;ii<revision_meta.length; ii++)\r\n if(!worker_has_revision.hasOwnProperty(revision_meta[ii].id))\r\n n_pending++;\r\n\r\n if(n_pending){\r\n el.info.textContent = \"Downloaded \" + (revision_meta.length - n_pending) \r\n + \" of \" + revision_meta.length + \"...\";\r\n }else{\r\n el.info.textContent = \"Downloaded all revisions.\";\r\n }\r\n\r\n}\r\n\r\nvar refresh_revisions_list = function(){\r\n // TODO: make this cancelable, with race\r\n el.info.textContent = \"Updating revision list...\";\r\n el.tick_box.innerHTML = \"\";\r\n el.at_range.max = 1;\r\n el.from_range.max = 1;\r\n el.at_range.value = 0;\r\n el.from_range.value = 0;\r\n at_idx = 0; \r\n from_idx = 0;\r\n revision_meta = [{id: 'current',\r\n el_tick: append_tick()}];\r\n revision_uses_line = [];\r\n worker.postMessage({reset_with_current_body: dn.editor.getSession().getValue()});\r\n worker_has_revision['current'] = true;\r\n revision_meta[0].el_tick.classList.add('downloaded');\r\n render_for_settings();\r\n\r\n // update the list of revisions, and prepare a list of ids to get bodies for\r\n until_success(function(succ, fail){\r\n Promise.all([dn.pr_auth, dn.pr_file_loaded])\r\n .then(dn.request_revision_list)\r\n .then(send_revisions_order_to_worker)\r\n .then(succ, fail);\r\n }).before_retry(dn.filter_api_errors)\r\n .catch(function(err){\r\n console.log(\"failed to update revisions list\")\r\n dn.show_error(dn.api_error_to_string(err));\r\n throw(err);\r\n }).then(function(r_to_get){\r\n // download all the requested bodies...\r\n // note that annoyingly you cant use gapi batch-ing to do this\r\n var body_promises = []\r\n for(var ii=0; ii<r_to_get.length; ii++){\r\n body_promises.push(\r\n until_success(function(ii, succ, fail){\r\n Promise.resolve(dn.pr_auth)\r\n .then(dn.request_revision_body(r_to_get[ii].id))\r\n .then(send_revision_body_to_worker(r_to_get[ii]))\r\n .then(succ, fail);\r\n }.bind(null, ii)) // need to bind ii, so that it's not the loop iterator object\r\n .before_retry(dn.filter_api_errors)\r\n .catch(function(err){\r\n console.log(\"failed to download revision body\")\r\n dn.show_error(dn.api_error_to_string(err));\r\n throw(err);\r\n })\r\n ); // push \r\n } // loop\r\n\r\n return Promise.all(body_promises)\r\n .then(function(res){\r\n console.log(\"got all bodies!!\");\r\n }).catch(function(err){\r\n console.log(\"failed to get all bodies\")\r\n });\r\n });\r\n \r\n}\r\n\r\n\r\nvar date_str_to_local = function(d){\r\n // returns a 2-tuple of strings like [\"11 Mar 2016\", \"11:45\"]\r\n d = new Date(Date.parse(d));\r\n return [d.toLocaleDateString({}, {month:\"short\", day:\"numeric\", year: \"numeric\"}),\r\n d.toLocaleTimeString({}, {hour: \"numeric\", minute: \"numeric\"})];\r\n}\r\n\r\nvar render_for_settings = function(){\r\n if(!dn.pr_file_loaded.is_resolved() || !editor) return;\r\n\r\n at_idx = parseInt(el.at_range.value);\r\n from_idx = parseInt(el.from_range.value);\r\n var at_meta = revision_meta[at_idx];\r\n var from_meta = revision_meta[from_idx];\r\n\r\n if(at_idx === 0){\r\n text_multi(el.caption_at, \"Current\\ndocument\");\r\n } else {\r\n var at_time = date_str_to_local(at_meta.modifiedTime);\r\n text_multi(el.caption_at, at_time.join(\"\\n\"));\r\n } \r\n\r\n if(from_idx === 0){\r\n text_multi(el.caption_from, \"Current\\ndocument\");\r\n } else {\r\n var from_time = date_str_to_local(from_meta.modifiedTime);\r\n text_multi(el.caption_from, from_time.join(\"\\n\"));\r\n }\r\n\r\n // render as much as possible now, and request the rest to be delviered asap!\r\n var have_at = revision_uses_line[at_idx] !== undefined;\r\n var have_from = revision_uses_line[from_idx] !== undefined;\r\n if(have_at && have_from){\r\n if(at_idx === from_idx)\r\n render_single_revision(at_idx);\r\n else\r\n render_revision_pair(at_idx, from_idx);\r\n } else if(!have_at && have_from){\r\n render_single_revision(from_idx);\r\n worker.postMessage({uses_line: [at_idx]})\r\n } else if(have_at && !have_from){\r\n render_single_revision(at_idx);\r\n worker.postMessage({uses_line: [from_idx]})\r\n } else {\r\n worker.postMessage({uses_line: [from_idx, at_idx]});\r\n }\r\n\r\n\r\n}\r\n\r\nvar render_removed_state = function(state){\r\n if(state){\r\n el.remove_expand.classList.add('selected');\r\n el.remove_collapse.classList.remove('selected');\r\n } else {\r\n el.remove_expand.classList.remove('selected');\r\n el.remove_collapse.classList.add('selected');\r\n }\r\n render_for_settings();\r\n}\r\n\r\n\r\nvar on_document_ready = function(){\r\n el.remove_expand = document.getElementById('revisions_remove_expand');\r\n el.remove_collapse = document.getElementById('revisions_remove_collapse');\r\n el.info = document.getElementById('revision_info');\r\n el.info_overflow = document.getElementById('file_info_overflow');\r\n el.tick_box = document.getElementById('revision_tick_box');\r\n el.at_range = document.getElementById('revision_at_range');\r\n el.from_range = document.getElementById('revision_from_range');\r\n el.caption_at = document.getElementById('revision_caption_at');\r\n el.caption_from = document.getElementById('revision_caption_from');\r\n el.revisions_view = document.getElementById('revisions_view');\r\n el.ordered_list = document.getElementById('revisions_ordered_list');\r\n dn.g_settings.addEventListener('VALUE_CHANGED', function(e){\r\n if(e.property === 'historyRemovedIsExpanded')\r\n render_removed_state(e.newValue);\r\n });\r\n \r\n // controllers\r\n el.remove_expand.addEventListener('click', function(){\r\n dn.g_settings.set('historyRemovedIsExpanded', true);\r\n })\r\n el.remove_collapse.addEventListener('click', function(){\r\n dn.g_settings.set('historyRemovedIsExpanded', false);\r\n })\r\n\r\n el.at_range.addEventListener(\"input\", render_for_settings);\r\n el.from_range.addEventListener(\"input\", render_for_settings);\r\n}\r\n\r\n\r\nreturn {\r\n start: start,\r\n end: end,\r\n on_document_ready: on_document_ready,\r\n get_editor: get_editor,\r\n debug: function(){\r\n m = new Uint8Array(editor.session.doc.getLength());\r\n for(var i=0;i<m.length;i++)\r\n m[i] = Math.random() * 4;\r\n editor.show_rows(m);\r\n console.dir(m);\r\n }\r\n};\r\n\r\n\r\n})();\r\n","\"use strict\";\r\ndn.find_pane = (function(const_){\r\n\r\nvar el = {};\r\nvar goto_input_has_focus = false; // we don't actually need this, but we keep it for analogy with search\r\nvar AceSearch;\r\nvar AceRange;\r\nvar search_inputs_have_focus = false; // either find itself or replace\r\nvar search_results = [];\r\nvar search_current_match_idx = -1;\r\nvar search_markers = [];\r\nvar search_marker_current = undefined;\r\nvar search_str = \"\";\r\nvar search_history_idx = -1; // when walking the find history this is >=0\r\nvar search_history_left_behind_str = \"\"; // although we call update_search_history after every change in search string, \r\n // it won't always result in modifying the 0th entry in history, in such cases,\r\n // we record the actual string here so that we can come back to it if we walk the history\r\nvar search_history_last_modified_time = -1; // set each time we change the history\r\n\r\n\r\n\r\nvar focus_on_input = function(){\r\n if(dn.g_settings.get('find_goto'))\r\n el.goto_input.focus();\r\n else\r\n el.find_input.focus();\r\n}\r\n\r\nvar on_document_ready = function(){\r\n AceSearch = ace.require(\"./search\").Search;\r\n AceRange = ace.require(\"./range\").Range;\r\n\r\n el.button_case_sensitive = document.getElementById('button_find_case_sensitive');\r\n el.button_whole_words = document.getElementById('button_find_whole_words');\r\n el.button_regex = document.getElementById('button_find_regex');\r\n el.find_input = document.getElementById('find_input');\r\n el.goto_input = document.getElementById('goto_input');\r\n el.replace_input = document.getElementById('find_replace_input');\r\n el.info = document.getElementById('find_info');\r\n el.search_results = document.getElementById('find_results');\r\n el.info_overflow = document.getElementById('find_info_overflow');\r\n el.button_goto = document.getElementById('button_goto');\r\n el.button_replace = document.getElementById('button_replace');\r\n el.goto_wrapper = document.getElementById('find_goto_wrapper');\r\n el.find_wrapper = document.getElementById('find_find_wrapper');\r\n el.replace_wrapper = document.getElementById('find_replace_wrapper');\r\n el.button_find_replace_all = document.getElementById('button_find_replace_all');\r\n\r\n dn.g_settings.addEventListener('VALUE_CHANGED', function(e){\r\n var new_value = e.newValue;\r\n switch(e.property){\r\n case 'find_regex':\r\n if(new_value)\r\n el.button_regex.classList.add('selected');\r\n else\r\n el.button_regex.classList.remove('selected');\r\n settings_changed();\r\n break;\r\n\r\n case 'find_whole_words':\r\n if(new_value)\r\n el.button_whole_words.classList.add('selected');\r\n else\r\n el.button_whole_words.classList.remove('selected');\r\n settings_changed();\r\n break;\r\n\r\n case 'find_case_sensitive':\r\n if(new_value)\r\n el.button_case_sensitive.classList.add('selected');\r\n else\r\n el.button_case_sensitive.classList.remove('selected');\r\n settings_changed();\r\n break;\r\n\r\n case 'find_replace':\r\n on_replace_toggled(new_value);\r\n break;\r\n\r\n case 'find_goto':\r\n on_goto_toggled(new_value);\r\n break;\r\n }\r\n })\r\n\r\n el.button_case_sensitive.addEventListener('click', function(){\r\n dn.g_settings.set('find_case_sensitive', !dn.g_settings.get('find_case_sensitive'));\r\n })\r\n el.button_whole_words.addEventListener('click', function(){\r\n dn.g_settings.set('find_whole_words', !dn.g_settings.get('find_whole_words'));\r\n })\r\n el.button_regex.addEventListener('click', function(){\r\n dn.g_settings.set('find_regex', !dn.g_settings.get('find_regex'));\r\n })\r\n el.goto_input.addEventListener('keydown', goto_input_keydown);\r\n el.goto_input.addEventListener('keyup', goto_input_keyup);\r\n el.goto_input.addEventListener('blur', goto_input_blur);\r\n el.goto_input.addEventListener('focus', goto_input_focus);\r\n el.find_input.addEventListener('keyup', find_input_keyup);\r\n el.find_input.addEventListener('keydown', find_input_keydown);\r\n el.find_input.addEventListener('blur', search_inputs_blur);\r\n el.find_input.addEventListener('focus', search_inputs_focus);\r\n el.replace_input.addEventListener('blur', search_inputs_blur);\r\n el.replace_input.addEventListener('focus', search_inputs_focus);\r\n el.replace_input.addEventListener('keydown', replace_input_keydown);\r\n el.button_find_replace_all.addEventListener('click', replace_all);\r\n el.button_replace.addEventListener('click', function(){\r\n dn.g_settings.set('find_replace', !dn.g_settings.get('find_replace'));\r\n dn.g_settings.set('find_goto', false);\r\n el.find_input.focus();\r\n })\r\n el.button_goto.addEventListener('click', function(){\r\n dn.g_settings.set('find_goto', !dn.g_settings.get('find_goto'));\r\n if(dn.g_settings.get('find_goto'))\r\n el.goto_input.focus();\r\n else\r\n el.find_input.focus();\r\n })\r\n}\r\n\r\nvar find_shortcut_used = function(e){\r\n var sel = dn.editor.session.getTextRange(dn.editor.getSelectionRange());\r\n dn.g_settings.set('find_goto', false);\r\n dn.g_settings.set('pane', 'pane_find');\r\n dn.g_settings.set('pane_open', true);\r\n if(sel){\r\n if(sel !== search_str){\r\n search_str = sel;\r\n search_history_idx = -1;\r\n update_search_history();\r\n }\r\n el.find_input.value = sel;\r\n el.find_input.select();\r\n }\r\n el.find_input.focus();\r\n e.preventDefault();\r\n}\r\n\r\nvar goto_shortcut_used = function(e){\r\n dn.g_settings.set('find_goto', true);\r\n dn.g_settings.set('pane', 'pane_find'); // doing this after the find_active=true, tells the change handler not to put focus back to editor\r\n dn.g_settings.set('pane_open', true);\r\n el.goto_input.focus();\r\n e.preventDefault();\r\n}\r\n\r\nvar replace_shortcut_used = function(e){\r\n dn.g_settings.set('find_replace', true);\r\n find_shortcut_used(e); \r\n}\r\n\r\nvar on_goto_toggled = function(new_value){\r\n // This just toggles the display, it does not deal with focus/blur, which may happen afterwards\r\n // as a consequence if the relevant inputs previously had the focus.\r\n\r\n if(new_value){\r\n el.goto_wrapper.style.display = '';\r\n el.find_wrapper.style.display = 'none';\r\n el.button_goto.classList.add('selected');\r\n el.info.textContent = 'goto line inactive';\r\n el.replace_wrapper.style.display = 'none';\r\n }else{\r\n el.goto_wrapper.style.display = 'none';\r\n el.find_wrapper.style.display = '';\r\n el.button_goto.classList.remove('selected');\r\n el.info.textContent = 'search inactive';\r\n if (dn.g_settings.get('find_replace'))\r\n el.replace_wrapper.style.display = '';\r\n }\r\n}\r\n\r\nvar on_replace_toggled = function(new_value){\r\n if(new_value){\r\n el.button_replace.classList.add('selected');\r\n if(!dn.g_settings.get('find_goto'))\r\n el.replace_wrapper.style.display = '';\r\n }else{\r\n el.replace_wrapper.style.display = 'none';\r\n el.button_replace.classList.remove('selected');\r\n }\r\n if(search_inputs_have_focus)\r\n select_search_result_idx(search_current_match_idx);\r\n}\r\n\r\n// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n// goto :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n// the implementation of goto is simpler than for search, so we start with it...\r\n\r\nvar goto_input_focus = function(){\r\n goto_input_has_focus = true;\r\n el.info.textContent = \"type to goto line\";\r\n perform_goto();\r\n}\r\n\r\nvar goto_input_blur = function(e){\r\n goto_input_has_focus = false;\r\n el.info.textContent = \"goto line inactive\"; \r\n //if(!e.relatedTarget)\r\n // dn.focus_editor();\r\n}\r\n\r\nvar perform_goto = function(){\r\n // called by find_goto_input_focus and find_goto_keyup\r\n var validated_str = el.goto_input.value.replace(/[^\\d]/,'');\r\n if (validated_str !== el.goto_input.value)\r\n el.goto_input.value = validated_str;\r\n if(validated_str === \"\")\r\n return;\r\n var num = parseInt(validated_str);\r\n dn.editor.gotoLine(num);\r\n dn.editor.navigateLineEnd();\r\n}\r\n\r\nvar goto_input_keyup = perform_goto; //alias\r\n\r\nvar goto_input_keydown = function(e){\r\n // keydown is fired repeatedly when key remains down\r\n if(e.which == WHICH.DOWN){\r\n el.goto_input.value = parseInt(el.goto_input.value.replace(/[^\\d]/,''))+1;\r\n perform_goto();\r\n e.preventDefault();\r\n }else if(e.which == WHICH.UP){\r\n el.goto_input.value = parseInt(el.goto_input.value.replace(/[^\\d]/,''))-1;\r\n perform_goto();\r\n e.preventDefault();\r\n } else if(e.which == WHICH.ESC){\r\n dn.g_settings.set('pane_open', false);\r\n e.preventDefault();\r\n e.stopPropagation();\r\n dn.focus_editor();\r\n }\r\n}\r\n\r\n\r\n// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n// search :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n// ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n\r\n \r\nvar update_search_history = function(){\r\n // called when the user types in the search box, or when we launch find from shortcut with selection\r\n var current_str = search_str;\r\n search_history_left_behind_str = current_str;\r\n\r\n if(current_str.length === 0 || !dn.g_atomic_exec){ \r\n search_history_idx = -1;\r\n return;\r\n }\r\n\r\n dn.g_atomic_exec(function(){\r\n var time_now = Date.now();\r\n\r\n if(dn.g_find_history.length === 0){\r\n // create a history entry for the first ever time\r\n dn.g_find_history.push(current_str);\r\n search_history_idx = 0;\r\n search_history_last_modified_time = time_now;\r\n return;\r\n }\r\n\r\n var top_of_history = dn.g_find_history.get(0);\r\n\r\n if(current_str.length<top_of_history.length \r\n && current_str.toLowerCase() === top_of_history.substr(0, current_str.length).toLowerCase()){\r\n // current string is a case-insensitive prefix of top_of_history, leave top_of_history as it was\r\n search_history_idx = -1;\r\n return;\r\n }\r\n\r\n if(current_str.toLowerCase()==top_of_history.toLowerCase()){\r\n //case insensitive match, update top_of_history to have same case as current\r\n dn.g_find_history.set(0, current_str);\r\n }else if(current_str.length>top_of_history.length \r\n && top_of_history.toLowerCase() === current_str.substr(0, top_of_history.length).toLowerCase()){\r\n // top_of_history is a case-insensitive prefix of current_str, replace top_of_history with current\r\n dn.g_find_history.set(0, current_str);\r\n } else if(time_now > search_history_last_modified_time + dn.const_.find_history_add_delay){\r\n // it's been a while since changes were made, add the current string as the new top\r\n dn.g_find_history.insert(0, current_str);\r\n if(dn.g_find_history.length > dn.const_.find_history_max_len){\r\n dn.g_find_history.remove(dn.g_find_history.length-1);\r\n }\r\n } else {\r\n // although the current string is at least somewhat different to the top, it's not been that\r\n // long since we modified the top, so lets just replace it with the new string\r\n dn.g_find_history.set(0, current_str);\r\n }\r\n search_history_idx = 0;\r\n search_history_last_modified_time = time_now;\r\n\r\n // TODO: we may like to remove duplicates in history, but without allowing recall to obliterate lots of existing memories\r\n\r\n }); // g_atomic_exec\r\n}\r\n\r\n\r\nvar search_inputs_focus = function(e){\r\n if(e.currentTarget == el.find_input){\r\n el.find_input.tabIndex = 101;\r\n el.replace_input.tabIndex = 102; \r\n } else {\r\n el.find_input.tabIndex = 102;\r\n el.replace_input.tabIndex = 101; \r\n }\r\n if(search_inputs_have_focus)\r\n return; // focus was transfered between replace/find inputs\r\n\r\n search_inputs_have_focus = true;\r\n dn.editor.setHighlightSelectedWord(false); \r\n perform_search();\r\n}\r\n\r\nvar search_inputs_blur = function(e){\r\n if(e.relatedTarget == el.replace_input || e.relatedTarget == el.find_input)\r\n return; // focus is transfering between replace/find inputs\r\n search_inputs_have_focus = false;\r\n\r\n // remove all search_markers\r\n var session = dn.editor.getSession(); \r\n for(var ii=0; ii<search_markers.length; ii++)\r\n session.removeMarker(search_markers[ii]);\r\n if (search_marker_current !== undefined){\r\n session.removeMarker(search_marker_current);\r\n search_marker_current = undefined;\r\n }\r\n\r\n // reset widget display\r\n el.info.textContent = \"search inactive\";\r\n el.search_results.innerHTML = \"\";\r\n el.info_overflow.textContent = \"\";\r\n\r\n // forget last search\r\n search_markers = [];\r\n search_results = [];\r\n search_current_match_idx = -1;\r\n\r\n // forget last selection in input (in preparation for next time it gets focus)\r\n // TODO: in IE11 this brings the focus back to the bluring element which isn't what we wanted at all\r\n el.find_input.setSelectionRange(el.find_input.selectionEnd, el.find_input.selectionEnd);\r\n\r\n // we had this on false during find\r\n dn.editor.setHighlightSelectedWord(true);\r\n\r\n //if(!e.relatedTarget)\r\n // dn.focus_editor();\r\n}\r\n\r\nvar build_search_options = function(){\r\n var str = el.find_input.value;\r\n var use_reg_exp = dn.g_settings.get('find_regex');\r\n var sensitive = dn.g_settings.get('find_case_sensitive');\r\n if(use_reg_exp){\r\n var re = undefined;\r\n re = new RegExp(str, sensitive ? \"g\" : \"gi\"); //cam throw error\r\n }\r\n return {\r\n needle: use_reg_exp ? re : str,\r\n wrap: true,\r\n caseSensitive: sensitive,\r\n wholeWord: dn.g_settings.get('find_whole_words'),\r\n regExp: use_reg_exp };\r\n}\r\n\r\nvar perform_search = function(){\r\n // called by find_input_focus, find_settings_changed, and on keyup in the input, when text has changed\r\n\r\n // clear previous find (but leave selection for now)\r\n var session = dn.editor.getSession(); \r\n for(var ii=0; ii<search_markers.length; ii++)\r\n session.removeMarker(search_markers[ii]);\r\n if(search_marker_current !== undefined){\r\n session.removeMarker(search_marker_current)\r\n search_marker_current = undefined;\r\n }\r\n search_markers = [];\r\n search_results = [];\r\n search_current_match_idx = -1;\r\n el.search_results.innerHTML = \"\"; \r\n el.info_overflow.textContent = \"\";\r\n el.info.textContent = \"\";\r\n search_str = el.find_input.value; // we only store it to make it easier for key_down to check for true changes\r\n\r\n var search_options = undefined;\r\n try{\r\n search_options = build_search_options();\r\n } catch (e){\r\n el.info.textContent = escape_str(e.message); //TODO: could force first letter to lower case\r\n }\r\n\r\n if(search_options === undefined){\r\n // failed regex, don't show any search_results\r\n dn.editor.selection.clearSelection();\r\n\r\n } else if(search_str == \"\"){\r\n // empty string (including empty regex), dont show any search_results\r\n el.info.textContent = \"type to search. \" /*+ dn.ctrl_key + \"-up/down for history.\"*/;\r\n dn.editor.selection.clearSelection();\r\n \r\n } else {\r\n // valid regex or pure search_str search..\r\n\r\n // This is the actual search\r\n var search = new AceSearch();\r\n search.setOptions(search_options);\r\n search_results = search.findAll(session);\r\n\r\n if(search_results.length === 0){\r\n // No search_results to display, life is easy...\r\n el.info.textContent = \"no matches found.\";\r\n el.info_overflow.textContent = \"\";\r\n dn.editor.selection.clearSelection();\r\n\r\n }else{\r\n // Right, we got some search_results ....\r\n\r\n // Work out which result we should consider the current match.\r\n var selected_range = session.getSelection().getRange();\r\n for(var ii=0; ii<search_results.length; ii++) \r\n if(search_results[ii].end.row > selected_range.start.row || \r\n (search_results[ii].end.row == selected_range.start.row &&\r\n search_results[ii].end.column >= selected_range.start.column))\r\n break;\r\n var current_match_idx = (ii == search_results.length ? search_results.length-1 : ii);\r\n\r\n // Add search_markers into the editor to show *all* the search_results\r\n for(var ii=0; ii<search_results.length; ii++)\r\n search_markers.push(session.addMarker(search_results[ii], \"find_match_marker\", \"find_match_marker\", false));\r\n\r\n // augment the search_results with their idx, this is useful for the subselection stuff\r\n for(var ii=0; ii<search_results.length; ii++)\r\n search_results[ii] = {range: search_results[ii], idx: ii};\r\n\r\n // Render a subset of the search_results into the widget and mark & select the current match\r\n select_search_result_idx(current_match_idx);\r\n }\r\n }\r\n\r\n}\r\n\r\nvar select_search_result_idx = function(new_idx){\r\n // This is called within find_perform_search when a new search returns some search_results\r\n // it's also called when we move through the search_results without changing the search and\r\n // when replace_changed is called when find input already has the focus. */\r\n\r\n // Get a small sub set of search_results to show in the widget.\r\n // We carefully implement some wrapping logic, which is a bit fiddly.\r\n search_current_match_idx = new_idx;\r\n\r\n var session = dn.editor.getSession();\r\n if (search_marker_current !== undefined){\r\n session.removeMarker(search_marker_current);\r\n search_marker_current = undefined;\r\n }\r\n\r\n var search_results_sub = [];\r\n \r\n var replace_is_showing = dn.g_settings.get('find_replace');\r\n\r\n var max_search_results = const_.find_max_results_half*2 + (replace_is_showing ? 0 : 1);\r\n\r\n if(search_results.length <= max_search_results){\r\n search_results_sub = search_results;\r\n }else{\r\n var n_pre = const_.find_max_results_half - (replace_is_showing ? 1 : 0);\r\n var n_post = const_.find_max_results_half;\r\n if(search_current_match_idx < n_pre){\r\n search_results_sub = search_results_sub.concat(search_results.slice(search_current_match_idx - n_pre));\r\n search_results_sub = search_results_sub.concat(search_results.slice(0, search_current_match_idx));\r\n } else {\r\n search_results_sub = search_results_sub.concat(search_results.slice(search_current_match_idx - n_pre, search_current_match_idx));\r\n }\r\n search_results_sub.push(search_results[search_current_match_idx]); \r\n if(search_current_match_idx + n_post >= search_results.length){\r\n search_results_sub = search_results_sub.concat(search_results.slice(search_current_match_idx + 1));\r\n search_results_sub = search_results_sub.concat(search_results.slice(0, n_post + 1 - (search_results.length - search_current_match_idx)));\r\n } else {\r\n search_results_sub = search_results_sub.concat(search_results.slice(search_current_match_idx + 1, search_current_match_idx + n_post + 1));\r\n }\r\n }\r\n\r\n // Now lets build the html to show the subset of search_results in the widget\r\n var show_replace_buttons = dn.g_settings.get('find_replace');\r\n var html = \"\";\r\n for(var ii=0; ii<search_results_sub.length; ii++){\r\n var row = search_results_sub[ii].range.start.row;\r\n var col = search_results_sub[ii].range.start.column;\r\n var prefix_range = new AceRange(row, Math.max(0, col-const_.find_max_prefix_chars), row, col);\r\n var pre_ellipses = col > const_.find_max_prefix_chars; //TODO: deal with indent better\r\n row = search_results_sub[ii].range.end.row;\r\n col = search_results_sub[ii].range.end.column;\r\n var suffix_range = new AceRange(row, col, row, col+const_.find_max_suffix_chars);\r\n html += \"<div class='find_result_item\" + (search_results_sub[ii].idx==search_current_match_idx? \" find_result_current\" : \"\") + \"'>\" +\r\n \"<div class='find_result_line_num'>\" + (row+1) + \"</div>\" +\r\n \"<div class='find_result_text'>\" +\r\n \"<div class='find_result_text_inner'>\" +\r\n (pre_ellipses ? \"…\" : \"\") + escape_str(session.getTextRange(prefix_range)) +\r\n \"<span class='find_result_match'>\" + escape_str(session.getTextRange(search_results_sub[ii].range)) + \"</span>\" +\r\n escape_str(session.getTextRange(suffix_range)) +\r\n \"</div>\" +\r\n \"</div>\" +\r\n (show_replace_buttons ? \"<div class='button inline_button replace_single_result' title='replace'>r</div>\" : \"\") + \r\n \"</div>\";\r\n }\r\n el.search_results.innerHTML = html;\r\n var els = el.search_results.getElementsByClassName('find_result_item');\r\n for(var ii=0; ii<els.length; ii++) if(search_results_sub[ii].idx !== search_current_match_idx)\r\n els[ii].addEventListener('click', search_result_click(search_results_sub[ii].idx));\r\n if(show_replace_buttons){\r\n var els = el.search_results.getElementsByClassName('replace_single_result')\r\n for(var ii=0; ii<els.length; ii++)\r\n els[ii].addEventListener('click', search_replace_result_click(search_results_sub[ii].idx));\r\n }\r\n\r\n if(search_results.length > max_search_results)\r\n el.info_overflow.textContent = \"... and \" + (search_results.length - max_search_results) + \" more matches\";\r\n else\r\n el.info_overflow.textContent = \"\";\r\n\r\n // do the special marker for the current selection and actually select it\r\n search_marker_current = session.addMarker(search_results[search_current_match_idx].range, \"find_current_match_marker\", \"find_current_match_marker\", false);\r\n dn.editor.selection.setSelectionRange(search_results[search_current_match_idx].range, false);\r\n dn.editor.renderer.scrollSelectionIntoView();\r\n}\r\n\r\nvar settings_changed = function(){\r\n if(search_inputs_have_focus || \r\n (dn.g_settings.get('pane') === 'pane_find' && dn.g_settings.get('pane_open') && el.find_input.value))\r\n perform_search();\r\n}\r\n\r\nvar search_result_click = function(ii){\r\n // this can only be called while find input has the focus\r\n return function(e){select_search_result_idx(ii);};\r\n}\r\n\r\nvar search_replace_result_click = function(ii){\r\n return function(e){\r\n replace_result_idx(ii);\r\n e.stopPropagation(); // prevent selecting item\r\n }\r\n}\r\n\r\nvar find_input_keyup = function(e){ \r\n //we need keyup here in order that the val has the new character or new backspace\r\n if(e.which == WHICH.ENTER || e.which == WHICH.ESC || e.which == WHICH.UP || e.which == WHICH.DOWN)\r\n return; \r\n if(search_str == el.find_input.value)\r\n return;\r\n perform_search();\r\n update_search_history();\r\n}\r\n\r\nvar find_input_keydown = function(e){ \r\n // we want keydown here so that we can get repeated firing with keydown (i think on most browsers)\r\n\r\n if ((e.which == WHICH.ENTER && !e.shiftKey) || (!e.ctrlKey && e.which == WHICH.DOWN)){\r\n //find next\r\n select_search_result_idx(search_current_match_idx + 1 < search_results.length ? \r\n search_current_match_idx + 1 \r\n : 0);\r\n e.preventDefault();\r\n return;\r\n }else if((e.which == WHICH.ENTER && e.shiftKey) || (!e.ctrlKey && e.which == WHICH.UP)){\r\n //find previous\r\n select_search_result_idx(search_current_match_idx - 1 < 0 ? \r\n search_results.length -1 \r\n : search_current_match_idx - 1);\r\n e.preventDefault();\r\n return;\r\n }\r\n\r\n if(e.which == WHICH.ESC){\r\n dn.g_settings.set('pane_open', false); // blurs the find_input\r\n dn.focus_editor();\r\n e.preventDefault();\r\n e.stopPropagation();\r\n return; \r\n }\r\n\r\n if(e.ctrlKey && dn.g_find_history && (e.which == WHICH.DOWN || e.which == WHICH.UP)){\r\n dn.g_atomic_exec(function(){\r\n if(e.which == WHICH.UP) // up means go to more recent item\r\n search_history_idx = Math.max(-1, search_history_idx-1);\r\n else // down means move further into the past\r\n search_history_idx++;\r\n search_history_idx = Math.min(search_history_idx, dn.g_find_history.length-1);\r\n if(search_history_idx == -1){\r\n el.find_input.value = search_history_left_behind_str;\r\n }else{\r\n el.find_input.value = dn.g_find_history.get(search_history_idx);\r\n }\r\n el.find_input.setSelectionRange(el.find_input.value.length, el.find_input.value.length+10);\r\n });\r\n perform_search();\r\n e.preventDefault();\r\n }\r\n\r\n}\r\n\r\nvar replace_input_keydown = function(e){\r\n if(e.which == WHICH.ENTER){\r\n if(e.ctrlKey || e.shiftKey)\r\n replace_all();\r\n else\r\n replace_result_idx(search_current_match_idx);\r\n e.preventDefault();\r\n }else{\r\n find_input_keydown(e); // up, down search_results and esc\r\n }\r\n}\r\n\r\nvar replace_all = function(e){\r\n try{\r\n var options = build_search_options();\r\n } catch (e) {\r\n dn.show_error(e.message);\r\n return;\r\n }\r\n dn.editor.replaceAll(el.replace_input.value, options);\r\n dn.focus_editor();\r\n}\r\n\r\nvar replace_result_idx = function(idx){\r\n var range = search_results[idx].range;\r\n // we use undocumented ACE API to avoid messing around tryinng to force it to use the exact range we wanted\r\n dn.editor.$search.set(build_search_options()); //this is needed so that $tryReplace knows what to do with regex'es\r\n dn.editor.$tryReplace(range, el.replace_input.value) // returns true on success, but do we care?\r\n perform_search();\r\n}\r\n\r\n\r\n\r\n\r\n\r\nreturn {\r\n focus_on_input: focus_on_input,\r\n on_document_ready: on_document_ready,\r\n on_find_shortcut: find_shortcut_used,\r\n on_replace_shortcut: replace_shortcut_used,\r\n on_goto_shortcut: goto_shortcut_used\r\n}\r\n\r\n})(dn.const_);","\"use strict\";\r\n\r\n\r\n\r\ndn.esc_pressed = function(e){\r\n dn.g_settings.set('pane_open', !dn.g_settings.get('pane_open'));\r\n\r\n if(dn.g_settings.get('pane_open') && dn.g_settings.get('pane') == 'pane_find'){\r\n dn.find_pane.focus_on_input();\r\n }else{\r\n dn.focus_editor();\r\n }\r\n e.preventDefault();\r\n}\r\n\r\ndn.make_keyboard_shortcuts = function(){\r\n //perviously was using ace for handling these shorcuts because it neater (and efficient?) but it was\r\n //annoying trying to ensure the editor always had focus, and not clear what to do when the editor wasn't showing.\r\n \r\n //we have to delete the default ace commands linked to the keys we care about\r\n dn.editor.commands.removeCommands([\r\n \"find\",\"findprevious\",\"findnext\",\"replace\",\"jumptomatching\",\"sortlines\",\"selecttomatching\",\"gotoline\"]);\r\n\r\n //then add new commands on to the document using keymaster.js...\r\n key('command+s, ctrl+s, ctrl+alt+s, command+alt+s', dn.file_pane.on_save_shorcut);\r\n key('command+p, ctrl+p, ctrl+alt+p, command+alt+p', dn.file_pane.do_print_shorcut);\r\n key('command+o, ctrl+o, ctrl+alt+o, command+alt+o', dn.do_open);\r\n key('command+n, ctrl+n, ctrl+alt+n, command+alt+n', dn.do_new);\r\n key('command+l, ctrl+l, ctrl+alt+l, command+alt+l', dn.find_pane.on_goto_shortcut);\r\n key('command+f, ctrl+f, ctrl+alt+f, command+alt+f', dn.find_pane.on_find_shortcut); \r\n key('command+r, ctrl+r, ctrl+alt+r, command+alt+r' + \r\n ', command+g, ctrl+g, ctrl+alt+g, command+alt+g', dn.find_pane.on_replace_shortcut);\r\n key('command+h, ctrl+h, ctrl+alt+h, command+alt+h', dn.file_pane.do_history);\r\n key('esc', dn.esc_pressed);\r\n key.filter = function(){return 1;}\r\n\r\n // it seems like the clipboard history cycling only works the old way, i.e. using ace....\r\n var HashHandler = require(\"ace/keyboard/hash_handler\").HashHandler\r\n var extraKeyEvents = new HashHandler([\r\n {bindKey: {win: \"Ctrl-Left\",mac: \"Command-Left\"}, descr: \"Clipboard cyle back on paste\", exec: dn.clipboard_tool.on_left},\r\n {bindKey: {win: \"Ctrl-Down\",mac: \"Command-Down\"}, descr: \"Clipboard cyle back on paste\", exec: dn.clipboard_tool.on_left},\r\n {bindKey: {win: \"Ctrl-Right\",mac:\"Command-Right\"}, descr: \"Clipboard cyle forward on paste\", exec: dn.clipboard_tool.on_right},\r\n {bindKey: {win: \"Ctrl-Up\",mac:\"Command-Up\"}, descr: \"Clipboard cyle forward on paste\", exec: dn.clipboard_tool.on_right}\r\n ]);\r\n dn.editor.keyBinding.addKeyboardHandler(extraKeyEvents);\r\n\r\n // Change \"ctrl\" to \"cmd\" if on Mac\r\n dn.ctrl_key = \"crtl\"\r\n if(dn.platform == 'Mac'){\r\n dn.ctrl_key = 'cmd';\r\n var els = document.getElementsByClassName('ctrl_key');\r\n for(var ii=0; ii<els.length; ii++)\r\n els[ii].textContent = 'cmd'\r\n }\r\n}\r\n","\"use strict\";\r\n// DRIVE NOTEPAD 2016\r\n// by DM\r\n\r\ndn.version_str = '2016a';\r\n\r\n// ############################\r\n// Constants and defaults, see alsp info.js\r\n// ############################\r\n\r\ndn.can_show_drag_drop_error = true;\r\ndn.save_undo_id = 0;\r\n\r\ndn.status = {\r\n\r\n file_body: 1, // 0 while getting, 1 when done or irrelevant, -1 if failed\r\n file_meta: 1, // 0 while getting, 1 when done or irrelevant, -1 if failed\r\n file_new: 1, // 0 while creating a new file, 1 when done or irrelevant, -1 if failed\r\n\r\n file_sharing: 0, // after launching the sharing dialog this is set to -1 for everafter\r\n\r\n authentication: 0, // 0 while authenticating, 1 when done\r\n\r\n popup_active: 0, // 0 or 1, i.e. true or false\r\n local_settings: 0, // 1 when local settings have been loaded\r\n realtime_settings: 0, // 1 when realtime settings have been loaded\r\n\r\n // 1: success/no save active, \r\n // 0: in progress\r\n // -1: failure, and abandonded further attempts (never used)\r\n save_body: 1, \r\n save_title: 1,\r\n save_other: 1,\r\n\r\n unsaved_changes: 0, // 1 true, 0 false\r\n user_wants_file: 0, // 1 when page loads with open request, or when users initially saves a new file, 0 otherwise\r\n warned_read_only: 0 // if file is read-only this is set to 1 when user first tries editing the document body\r\n}\r\n\r\ndn.the_file = new dn.FileModel();\r\n\r\ndn.change_line_history = [];\r\ndn.last_change = null;\r\ndn.change_line_classes =(function(rootStr,trueN,factor){\r\n var x = [''];\r\n for(var i=trueN;i;i--)for(var k=0;k<factor;k++)\r\n x.push(rootStr + i);\r\n return x;\r\n})('recent_line_',8,5)\r\ndn.change_line_classes_rm =(function(rootStr,trueN,factor){\r\n var x = [''];\r\n for(var i=trueN;i;i--)for(var k=0;k<factor;k++)\r\n x.push(rootStr + i);\r\n return x;\r\n})('recent_line_rm',8,5)\r\n\r\n\r\ndn.el = dn.el || {};\r\n\r\ndn.show_status = function(){\r\n // TODO: drag-drop from disk\r\n var s = ''\r\n\r\n if(!dn.status.user_wants_file){\r\n if(dn.status.unsaved_changes)\r\n s = \"unsaved file\";\r\n else\r\n s = \"ex nihilo omnia.\";\r\n } else if (dn.status.file_new === 1 && dn.status.file_meta === 1 && dn.status.file_body === 1){\r\n s = \"\" + dn.the_file.title;\r\n var extra = [];\r\n if(dn.the_file.is_read_only)\r\n extra.push(\"read-only\");\r\n if(dn.the_file.is_shared)\r\n extra.push(\"shared\");\r\n if(dn.status.file_sharing == -1)\r\n extra.push(\"sharing status unknown\");\r\n if(dn.status.unsaved_changes)\r\n extra.push(\"unsaved changes\");\r\n if(dn.status.save_body == 0){\r\n extra.push(\"saving document\"); // this means that *at least* the body is being saved, possibly more\r\n } else {\r\n if(dn.status.save_title == 0)\r\n extra.push(\"updating title\");\r\n if(dn.status.save_other == 0)\r\n extra.push(\"updating file properties\")\r\n } \r\n if(extra.length)\r\n s += \"\\n[\" + extra.join(', ') + \"]\"; \r\n }else if(dn.status.file_new === 0)\r\n s = \"Creating new file\";\r\n else if(dn.status.file_new === -1)\r\n s = \"Failed to create new file\";\r\n else if(dn.status.file_meta === 0 && dn.status.file_body === 0)\r\n s = \"Loading file:\\n\" + dn.the_file.file_id;\r\n else if(dn.status.file_meta === 1 && dn.status.file_body === 0)\r\n s = \"Loading \" + (dn.the_file.is_read_only? 'read-only ' : '' ) + \r\n \"file:\\n\" + dn.the_file.title;\r\n else if(dn.status.file_meta === 0 && dn.status.file_body === 1)\r\n s = \"Loading metadata for file:\\n\" + dn.the_file.file_id;\r\n else if(dn.status.file_meta === 1) // and -1\r\n s = \"Failed to download \" + (dn.the_file.is_read_only? 'read-only ' : '' )\r\n + \"file:\\n\" + dn.the_file.title;\r\n else if(dn.status.file_body === 1) // and -1\r\n s = \"Failed to download metadata for file:\\n\" + dn.the_file.file_id;\r\n else // file_body and file_meta both -1\r\n s = \"Failed to load file:\\n\" + dn.the_file.file_id;\r\n \r\n\r\n if(dn.status.authentication != 1){\r\n // auth in progress or failed\r\n if (s)\r\n s += \"\\n\";\r\n if(dn.status.authorization == -1)\r\n s += \"Authorization required...\";\r\n else if(dn.status.popup_active)\r\n s += \"Login/authenticate with popup...\";\r\n else\r\n s += \"Authenticating...\";\r\n }\r\n\r\n text_multi(dn.el.widget_text, s, true);\r\n\r\n if(dn.status.save_body == 0 || dn.status.save_title == 0 || dn.status.save_other == 0)\r\n dn.el.widget_pending.style.display = '';\r\n else\r\n dn.el.widget_pending.style.display = 'none';\r\n}\r\n\r\ndn.show_error = function(message){\r\n console.log(message); //it's just useful to do this too\r\n text_multi(dn.el.widget_error_text, message,true);\r\n dn.el.widget_error.style.display = '';\r\n css_animation(dn.el.the_widget, 'shake', function(){\r\n dn.el.widget_error.style.display = 'none';\r\n }, dn.const_.error_delay_ms);\r\n}\r\n\r\n\r\ndn.toggle_permission = function(state){\r\n var el = dn.el.pane_permissions;\r\n if(state){\r\n if(!dn.status.permissions_showing){\r\n dn.status.permissions_showing = 1;\r\n el.style.display = '';\r\n dn.g_settings.set('pane', 'pane_help');\r\n dn.g_settings.set('pane_open', true);\r\n css_animation(dn.el.the_widget, 'shake', function(){}, dn.const_.error_delay_ms);\r\n }\r\n } else {\r\n dn.status.permissions_showing = 0;\r\n el.style.display = 'none';\r\n }\r\n}\r\n\r\ndn.show_pane = function(id){\r\n if(id === \"pane_permissions\")\r\n return dn.toggle_permission(true);\r\n if(id !== \"pane_file\") // we could check if it was open, but who cares\r\n dn.file_pane.on_close_pane();\r\n\r\n var el = document.getElementById(id);\r\n\r\n // el can be undefined/null to hide everything\r\n for(var ii=0; ii < dn.el.widget_content.children.length; ii++)\r\n if(dn.el.widget_content.children[ii] !== el && dn.el.widget_content.children[ii] !== dn.el.pane_permissions){\r\n dn.el.widget_content.children[ii].style.display = 'none';\r\n var el_icon = dn.menu_icon_from_pane_id[dn.el.widget_content.children[ii].id];\r\n if(el_icon)\r\n el_icon.classList.remove('icon_selected');\r\n }\r\n\r\n if(el){\r\n el.style.display = '';\r\n var el_icon = dn.menu_icon_from_pane_id[el.id];\r\n if(el_icon)\r\n el_icon.classList.add('icon_selected')\r\n }else{\r\n dn.g_settings.set('pane_open', false);\r\n }\r\n}\r\n\r\ndn.widget_mouse_down = function(e){\r\n dn.widget_mouse_down_info = {\r\n off_left: -e.clientX,\r\n off_top: -e.clientY,\r\n start_time: Date.now(),\r\n is_dragging: e.button !== 0};\r\n e.preventDefault();\r\n document.addEventListener('mousemove', dn.document_mouse_move_widget);\r\n document.addEventListener('mouseup', dn.document_mouse_up_widget);\r\n}\r\n\r\ndn.document_mouse_move_widget = function(e){\r\n var x = e.clientX+dn.widget_mouse_down_info.off_left;\r\n var y = e.clientY+dn.widget_mouse_down_info.off_top;\r\n if(!dn.widget_mouse_down_info.is_dragging){\r\n dn.widget_mouse_down_info.is_dragging = (Date.now() - dn.widget_mouse_down_info.start_time > dn.const_.drag_delay_ms)\r\n || (x*x + y*y > dn.const_.drag_shift_px * dn.const_.drag_shift_px);\r\n }\r\n if(dn.widget_mouse_down_info.is_dragging)\r\n translate(dn.el.the_widget, x, y);\r\n e.stopPropagation();\r\n\r\n};\r\n\r\ndn.document_mouse_up_widget = function(e){\r\n document.removeEventListener('mousemove', dn.document_mouse_move_widget);\r\n document.removeEventListener('mouseup', dn.document_mouse_up_widget);\r\n\r\n if(dn.widget_mouse_down_info.is_dragging){\r\n var pos = dn.el.the_widget.getBoundingClientRect();\r\n translate(dn.el.the_widget, 0, 0);\r\n \r\n //work out what widget_anchor should be\r\n var widget_w = dn.el.the_widget.offsetWidth;\r\n var widget_h = dn.el.the_widget.offsetHeight;\r\n var window_w = window.innerWidth;\r\n var window_h = window.innerHeight;\r\n var anchor = []\r\n if(pos.left < window_w - (pos.left + widget_w)){\r\n anchor[0] = 'l'; //anchor left side by window width percentage\r\n anchor[1] = Math.max(0,pos.left/window_w * 100);\r\n }else{\r\n anchor[0] = 'r'; //anchor right side by window width percentage\r\n anchor[1] = Math.max(0,(window_w - (pos.left + widget_w))/window_w * 100);\r\n }\r\n if(pos.top < window_h - (pos.top+ widget_h)){\r\n anchor[2] = 't'; //anchor top side by window height percentage\r\n anchor[3] = Math.max(0,pos.top/window_h * 100);\r\n }else{\r\n anchor[2] = 'b'; //anchor bottom side by window height percentage\r\n anchor[3] = Math.max(0,(window_h - (pos.top + widget_h))/window_h * 100);\r\n }\r\n\r\n if(dn.g_settings)\r\n dn.g_settings.set(\"widget_anchor\",anchor); \r\n\r\n }else{\r\n dn.g_settings.set('pane_open', !dn.g_settings.get('pane_open'));\r\n }\r\n dn.widget_mouse_down_info = undefined;\r\n};\r\n\r\ndn.widget_apply_anchor = function(anchor){\r\n anchor = Array.isArray(anchor) ? anchor : dn.g_settings.get('widget_anchor');\r\n var widget_w = dn.el.the_widget.offsetWidth;\r\n var widget_h = dn.el.the_widget.offsetHeight;\r\n var window_w = window.innerWidth;\r\n var window_h = window.innerHeight;\r\n\r\n if(anchor[0] == 'l'){\r\n // horizontal position is anchored to a fixed percentage of window width on left of widget\r\n if(window_w * anchor[1]/100 + widget_w > window_w){\r\n dn.el.the_widget.style.left = 'inherit';\r\n dn.el.the_widget.style.right = '0px'; //if the widget would overlap the right edge, then instead put it precisely on the right edge\r\n }else{\r\n dn.el.the_widget.style.left = anchor[1] + '%';\r\n dn.el.the_widget.style.right = ''; //use the anchor exactly\r\n }\r\n\r\n // set toolbar position\r\n dn.el.widget_menu.classList.add('flipped');\r\n dn.el.widget_content.classList.add('flipped');\r\n var els = document.getElementsByClassName('widget_menu_icon');\r\n for(var ii=0; ii<els.length; ii++)\r\n els[ii].classList.add('flipped');\r\n\r\n }else{\r\n // horizontal position is anchored to a fixed percentage of window width on right of widget\r\n if( window_w * anchor[1]/100 + widget_w > window_w){\r\n dn.el.the_widget.style.left = '0px';\r\n dn.el.the_widget.style.right = ''; //if the widget would overlap the left edge, then instead put it precisely on the left edge\r\n }else{\r\n dn.el.the_widget.style.left = 'inherit';\r\n dn.el.the_widget.style.right = anchor[1] + '%'; //use the anchor exactly\r\n }\r\n\r\n // set toolbar position\r\n dn.el.widget_menu.classList.remove('flipped');\r\n dn.el.widget_content.classList.remove('flipped');\r\n var els = document.getElementsByClassName('widget_menu_icon');\r\n for(var ii=0; ii<els.length; ii++)\r\n els[ii].classList.remove('flipped');\r\n }\r\n\r\n if(anchor[2] == 't'){\r\n // vertical position is anchored to a fixed percentage of window height on top of widget\r\n if(window_h * anchor[3]/100 + widget_h > window_h){\r\n dn.el.the_widget.style.top = 'inherit';\r\n dn.el.the_widget.style.bottom = '0px'; \r\n }else{\r\n dn.el.the_widget.style.top = anchor[3] + '%';\r\n dn.el.the_widget.style.bottom = ''; \r\n }\r\n }else{\r\n // vertical position is anchored to a fixed percentage of window height on bottom of widget\r\n if(window_h * anchor[3]/100 + widget_h > window_h){\r\n dn.el.the_widget.style.top = '0px';\r\n dn.el.the_widget.style.bottom = ''; \r\n }else{\r\n dn.el.the_widget.style.top = 'inherit';\r\n dn.el.the_widget.style.bottom = anchor[3] + '%'; \r\n }\r\n }\r\n\r\n\r\n\r\n}\r\n\r\ndn.toggle_widget = function(state){\r\n // provide argument \"true\" to open widget, \"false\" to close\r\n if(state){\r\n dn.el.widget_menu.style.display = '';\r\n dn.el.widget_content.style.display = '';\r\n }else{\r\n dn.el.widget_menu.style.display = 'none';\r\n dn.el.widget_content.style.display = 'none';\r\n dn.file_pane.on_close_pane(); // we could check if it file pane was open, but who cares\r\n dn.focus_editor();\r\n }\r\n}\r\n\r\ndn.check_unsaved = function(){\r\n /* called:\r\n (a) before issuing save-body requests, at which point we set dn.save_undo_id to Nan, and\r\n record (in the SaveRequest instance) the current UndoManager.getCurrentId() value for \r\n later use if and when the save completes.\r\n (b) after all pending saves are completed, when we read the undo_id value for the last saved\r\n body version and set dn.save_undo_id to that.\r\n (c) in some kind of regular async manner in response to editor input\r\n\r\n Importantly, note we have monkey-patched the UndoManager class in patch_ace.js. This is what\r\n gives us the concept of an undo_id and the ability to query .getCurrentId().\r\n */\r\n if(dn.save_undo_id === dn.editor.getSession().getUndoManager().getCurrentId()){\r\n // changes match what we know is on the server\r\n dn.status.unsaved_changes = false;\r\n dn.render_document_title();\r\n dn.show_status();\r\n }else if (!dn.status.unsaved_changes){\r\n // changes no longer match the server\r\n dn.status.unsaved_changes = true;\r\n dn.render_document_title();\r\n dn.show_status();\r\n } // else, we already there were unsaved changes\r\n}\r\n\r\n\r\n\r\n// ############################\r\n// Settings stuff\r\n// ############################\r\n\r\ndn.g_settings = (function(){ \r\n // This acts as a mock realtime model to be used until the real model is initialised\r\n var ob = {};\r\n var keeps = {};\r\n var change_listeners = [];\r\n return {\r\n get: function(k){\r\n return ob[k]\r\n }, set: function(k,v){\r\n if(ob[k] === v) return;\r\n ob[k] = v;\r\n for(var ii=0;ii<change_listeners.length;ii++)\r\n change_listeners[ii]({property: k, newValue: v});\r\n }, keep: function(k){\r\n keeps[k] = true\r\n }, get_keeps: function(){\r\n return keeps;\r\n }, addEventListener: function(flag, callback){\r\n if(flag !== \"VALUE_CHANGED\") throw \"only VALUE_CHANGED\"\r\n change_listeners.push(callback);\r\n }, transfer_to_true_model: function(real_model){\r\n // issue changes due to differences in the real and mock models\r\n for(var k in ob)if(ob.hasOwnProperty(k) && !keeps[k])\r\n if(real_model.get(k) !== null && real_model.get(k) !== undefined\r\n && JSON.stringify(ob[k]) !== JSON.stringify(real_model.get(k)))\r\n this.set(k, real_model.get(k)); // will call listeners\r\n // and then register the listeners on the new model\r\n while(change_listeners.length)\r\n real_model.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED, change_listeners.shift());\r\n }\r\n }; \r\n})();\r\n\r\ndn.load_default_settings = function(){\r\n //Lets show the user either the defualt settings or the \r\n //ones last used on this browser (restricted to impersonal settings only)\r\n dn.status.local_settings = 0;\r\n try{\r\n console.log('Loading default/localStorage settings...');\r\n for(var s in dn.default_settings)\r\n if(dn.impersonal_settings_keys.indexOf(s) == -1 || !localStorage || !localStorage[\"g_settings_\" +s])\r\n dn.g_settings.set(s, dn.default_settings[s]);\r\n else\r\n dn.g_settings.set(s, JSON.parse(localStorage[\"g_settings_\" + s]));\r\n }catch(err){\r\n if(localStorage) \r\n localStorage.clear();\r\n console.log(\"Failed to load defaults/localStorage settings. Have cleared localStorage cache.\")\r\n }\r\n dn.status.local_settings = 1;\r\n}\r\n\r\n\r\ndn.show_app_data_document = function(doc){\r\n // build a wrapper for executing functions atomically on g_settings/g_*_history\r\n // TODO: we may need to use this more widely than is currently done.\r\n dn.g_atomic_exec = function(foo){\r\n var result;\r\n try{\r\n doc.getModel().beginCompoundOperation();\r\n result = foo();\r\n }catch(e){\r\n console.log(\"error in atomic update:\\n\"+ e);\r\n }finally{\r\n doc.getModel().endCompoundOperation();\r\n }\r\n return result;\r\n }\r\n\r\n var old_temp_g_settings = dn.g_settings;\r\n dn.g_settings = doc.getModel().getRoot();\r\n\r\n // some settings we want to override the cloud values with changes we made locally,\r\n // other settings may have been missing in the cloud entirely.\r\n console.log(\"Transfering to realtime model for settings.\")\r\n old_temp_g_settings.transfer_to_true_model(dn.g_settings);\r\n var existing_cloud_keys = dn.g_settings.keys();\r\n for(var s in dn.default_settings)\r\n if(s in old_temp_g_settings.get_keeps() || existing_cloud_keys.indexOf(s) == -1)\r\n dn.g_settings.set(s, old_temp_g_settings.get(s));\r\n\r\n dn.g_clipboard = dn.g_settings.get('clipboard');\r\n if(!dn.g_clipboard){\r\n dn.g_settings.set('clipboard', doc.getModel().createList());\r\n dn.g_clipboard = dn.g_settings.get('clipboard');\r\n }if(dn.g_clipboard.length > dn.const_.clipboard_max_length){\r\n // trim clipboard to current length limit, note the oldest stuff is at the 0-end\r\n dn.g_clipboard.removeRange(0, dn.g_clipboard.length-dn.const_.clipboard_max_length);\r\n }\r\n\r\n dn.g_find_history = dn.g_settings.get('findHistory');\r\n if(!dn.g_find_history){\r\n dn.g_settings.set('findHistory', doc.getModel().createList());\r\n dn.g_find_history = dn.g_settings.get('findHistory');\r\n }else if(dn.g_find_history.length > dn.const_.find_history_max_len){\r\n // trim find history to current length limit, the oldest stuff is at the non-zero end.\r\n dn.g_find_history.removeRange(dn.const_.find_history_max_len, dn.g_find_history.length);\r\n }\r\n \r\n //Check lastDNVersionUsed at this point - by default it's blank, bust could also have an out-of-date value\r\n var last_version = dn.g_settings.get('lastDNVersionUsed') \r\n if(last_version != dn.version_str){\r\n if (last_version.length > 0 && parseInt(last_version) !== 2016){\r\n // from this point onwards during this page's lifetime, change the tips \r\n // section to show the update message rather than the tips.\r\n document.getElementById('tips_old_user').style.display = '';\r\n document.getElementById('tips_general').style.display = 'none';\r\n }\r\n dn.g_settings.set('help_inner', 'tips');\r\n dn.g_settings.set('pane', 'pane_help');\r\n dn.g_settings.set('pane_open', 'true');\r\n dn.g_settings.set('lastDNVersionUsed', dn.version_str);\r\n }\r\n\r\n dn.status.realtime_settings = 1;\r\n}\r\n\r\n\r\ndn.settings_changed = function(e){\r\n var new_value = e.newValue;\r\n console.log(\"[user settings] \" + e.property +\": \" + new_value);\r\n if(dn.impersonal_settings_keys.indexOf(e.property)>-1 && localStorage){\r\n localStorage[\"g_settings_\" + e.property] = JSON.stringify(new_value);\r\n }\r\n try{\r\n switch(e.property){\r\n case \"widget_anchor\":\r\n dn.widget_apply_anchor(new_value);\r\n break;\r\n\r\n case \"theme\":\r\n dn.editor.setTheme('ace/theme/' + new_value);\r\n break;\r\n\r\n case \"fontSize\":\r\n var scrollLine = dn.get_scroll_line();\r\n dn.editor.setFontSize(new_value + 'em') \r\n dn.editor.scrollToLine(scrollLine);\r\n break;\r\n\r\n case \"wordWrap\":\r\n var s = dn.editor.getSession();\r\n var scrollLine = dn.get_scroll_line();\r\n s.setUseWrapMode(new_value[0]);\r\n s.setWrapLimitRange(new_value[1],new_value[2]);\r\n dn.editor.scrollToLine(scrollLine);\r\n break;\r\n\r\n case \"wordWrapAt\":\r\n var curWrap = dn.g_settings.get('wordWrap');\r\n if(curWrap[1] && curWrap[1] != new_value)\r\n dn.g_settings.set('wordWrap',[1,new_value,new_value]);\r\n dn.editor.setPrintMarginColumn(new_value);\r\n break;\r\n\r\n case \"showGutterHistory\":\r\n var s = dn.editor.getSession(); \r\n if(!new_value){\r\n var h = dn.change_line_history;\r\n for(var i=0;i<h.length;i++)if(h[i])\r\n s.removeGutterDecoration(i,h[i]<0 ? dn.change_line_classes_rm[-h[i]] : dn.change_line_classes[h[i]]);\r\n dn.change_line_history = []; \r\n }\r\n break;\r\n\r\n case \"newLineDefault\":\r\n if(dn.the_file.loaded_body)\r\n dn.the_file.compute_newline();\r\n break;\r\n\r\n case \"softTabN\":\r\n case \"tabIsHard\": \r\n if(dn.the_file.loaded_body)\r\n dn.the_file.compute_newline();\r\n break;\r\n\r\n case 'pane_open':\r\n if(dn.clipboard_tool.is_active())\r\n break;\r\n dn.toggle_widget(new_value)\r\n if(dn.g_settings.keep)\r\n dn.g_settings.keep('pane_open');\r\n break;\r\n\r\n case 'pane':\r\n if(dn.clipboard_tool.is_active())\r\n break;\r\n dn.show_pane(new_value);\r\n if(dn.g_settings.keep)\r\n dn.g_settings.keep('pane');\r\n if(new_value !== 'pane_help')\r\n dn.g_settings.set('help_inner', 'main');\r\n break; \r\n }\r\n }catch(err){\r\n console.log(\"Error while uptating new settings value.\")\r\n console.dir(e);\r\n console.dir(err);\r\n }\r\n}\r\n\r\ndn.get_scroll_line = function(){\r\n return dn.editor.getSession().screenToDocumentPosition(dn.editor.renderer.getScrollTopRow(),0).row;\r\n}\r\n\r\n\r\n// ############################\r\n// Load stuff\r\n// ############################\r\n\r\n\r\n\r\ndn.show_file_meta = function(resp) {\r\n // this is called both by file loading and by creation of new file\r\n if (resp.error)\r\n throw Error(resp.error);\r\n dn.the_file.file_id = resp.result.id;\r\n var props = {is_read_only: !resp.result.capabilities.canEdit,\r\n is_shared: resp.result.shared};\r\n\r\n // if we are loading meta of an existing file we want to set all the\r\n // properties in our local model of meta. But when creating a new file,\r\n // we don't want to set anything here, because we may have already\r\n // made changes to the local model, and have those changes waiting\r\n // to be saved to the server (they're waiting for the file_id).\r\n if(dn.status.file_meta === 0){ \r\n props.title = resp.result.name;\r\n props.description = resp.result.description || '';\r\n props.loaded_mime_type = resp.result.mimeType;\r\n if(resp.result.properties){\r\n if(resp.result.properties.aceMode !== undefined)\r\n props.syntax = resp.result.properties.aceMode;\r\n if(resp.result.properties.newline !== undefined)\r\n props.newline = resp.result.properties.newline;\r\n if(resp.result.properties.tabs !== undefined)\r\n props.tabs = resp.result.properties.tabs;\r\n }\r\n }\r\n dn.the_file.set(props);\r\n if(resp.result.parents && resp.result.parents.length){\r\n dn.the_file.folder_id = resp.result.parents[0];\r\n dn.set_drive_link_to_folder();\r\n }\r\n\r\n // set the url to match the file\r\n history.replaceState({}, dn.the_file.title, '//' + location.host + location.pathname + \"?\"\r\n + \"state=\" + JSON.stringify({action: \"open\", ids: [dn.the_file.file_id]}));\r\n\r\n //whether we were creating a new file or loading meta for existing, neither is still in progress \r\n dn.status.file_meta = 1; \r\n dn.status.file_new = 1;\r\n dn.show_status();\r\n} \r\n\r\ndn.show_file_body = function(resp){\r\n resp.body = decode_body(resp.body); // fix utf-8 issues\r\n dn.setting_session_value = true;\r\n dn.the_file.loaded_body = resp.body; //this gets used for newline and tab detection, i.e. we don't want the editor to mangle it in any way\r\n dn.editor.session.setValue(resp.body);\r\n dn.setting_session_value = false;\r\n dn.status.file_body = 1;\r\n dn.show_status();\r\n dn.editor.setReadOnly(false);\r\n}\r\n\r\n\r\n// ############################\r\n// Change/history stuff\r\n// ############################\r\n\r\ndn.on_editor_change = function(e){\r\n //console.dir(e);\r\n\r\n if(!e.start || !e.end || dn.setting_session_value)\r\n return;\r\n\r\n if(dn.the_file.is_read_only && dn.status.warned_read_only === 0){\r\n dn.show_error(\"Warning: you cannot save changes. File loaded as read-only.\")\r\n dn.status.warned_read_only = 1;\r\n }\r\n\r\n if(!dn.g_settings.get('showGutterHistory'))\r\n return;\r\n\r\n /* We maintain an array, dn.change_line_history, which has 0 for inactive lines,\r\n a negative number for lines that recently had a deleted, and a positive number\r\n for lines that had a recent insertion. When the change is first made it is\r\n recorded as +-n_classes. Then, each time we make changes to a new line\r\n we decrement the magnitude of previous changes, so that evetunally they hit zero\r\n and are considered \"inactive\". */\r\n var n_classes = dn.change_line_classes.length-1;\r\n var h = dn.change_line_history;\r\n var s = dn.editor.getSession(); \r\n\r\n var start_row = e.start.row;\r\n var end_row = e.end.row;\r\n\r\n // e is of the form {action: \"insert\"| \"delete\", start: {row: #, column: #}, end: {row: #, column: #}, line: []}\r\n\r\n // TODO: test for move based on seeing insert after a remove with both having the same lines[] content\r\n if(dn.last_change && dn.last_change.start_row == start_row && dn.last_change.end_row == end_row && start_row == end_row){\r\n //if this change and the last change were both on the same single lines with action (insert|remove)...\r\n if(dn.last_change.action === e.action){\r\n return; //same action as last time\r\n } else if(e.action === \"remove\"){ // new action is remove, old action was insert\r\n s.removeGutterDecoration(start_row, dn.change_line_classes[n_classes]);\r\n s.addGutterDecoration(start_row, dn.change_line_classes_rm[n_classes]);\r\n h[start_row] = -n_classes;\r\n dn.last_change.action = \"remove\";\r\n return;\r\n } else {// new action is insert, old action was remove\r\n s.removeGutterDecoration(start_row, dn.change_line_classes_rm[n_classes]);\r\n s.addGutterDecoration(start_row, dn.change_line_classes[n_classes]);\r\n h[start_row] = n_classes;\r\n dn.last_change.action = \"insert\";\r\n return;\r\n } \r\n } else {\r\n // otherwise we have an \"acutal\" new change\r\n dn.last_change = {start_row: start_row,\r\n end_row: end_row, \r\n action: e.action}; \r\n }\r\n\r\n\r\n //remove all visible decorations and update the changeLineHistory values (we'll add in the new classes at the end)\r\n for(var ii=0; ii<h.length; ii++)if(h[ii])\r\n s.removeGutterDecoration(ii, h[ii] < 0 ? \r\n dn.change_line_classes_rm[-h[ii]++] : \r\n dn.change_line_classes[h[ii]--]);\r\n\r\n //Update the changeLineHistory relating to the current changed lines\r\n if(e.action === \"remove\"){\r\n if(e.lines.length > 1)\r\n h.splice(start_row, e.lines.length-1); \r\n h[start_row] = -n_classes;\r\n }else{\r\n h[start_row] = n_classes;\r\n if(e.lines.length > 1){\r\n var args_for_splice = [start_row, 0];\r\n for(var ii=0; ii< e.lines.length-1; ii++)\r\n args_for_splice.push(n_classes);\r\n h.splice.apply(h, args_for_splice);\r\n }\r\n }\r\n\r\n for(var ii=0; ii<h.length; ii++)if(h[ii])\r\n s.addGutterDecoration(ii, h[ii]<0 ?\r\n dn.change_line_classes_rm[-h[ii]] :\r\n dn.change_line_classes[h[ii]]);\r\n} \r\n\r\ndn.query_unload = function(){\r\n if(dn.status.unsaved_changes)\r\n return \"If you leave the page now you will loose the unsaved \" + \r\n ( dn.status.user_wants_file && dn.status.file_new === 1 && dn.status.file_body === 1 ?\r\n \"changes to \" : \"new \") +\r\n \"file '\" + dn.the_file.title + \"'.\"\r\n}\r\n\r\ndn.set_drive_link_to_folder = function(){\r\n var els = document.getElementsByClassName('link_drive');\r\n var href = dn.the_file.folder_id ? \r\n 'https://drive.google.com/#folders/' + dn.the_file.folder_id \r\n : 'https://drive.google.com';\r\n for(var ii=0; ii<els.length; ii++)\r\n els[ii].href = href;\r\n // TODO: set new links to have this folder too\r\n}\r\n\r\ndn.show_user_info = function(a){\r\n dn.user_info = a.result;\r\n dn.help_pane.on_user_name_change(a.result.name);\r\n}\r\n\r\ndn.render_document_title = function(){\r\n document.title = (dn.status.unsaved_changes ? \"*\" : \"\") + dn.the_file.title;\r\n}\r\n\r\ndn.set_editor_newline = function(){\r\n // view for dn.the_file model\r\n dn.editor.session.setNewLineMode(dn.the_file.properties_chosen.newline);\r\n}\r\n\r\ndn.set_editor_tabs = function(){\r\n // view for dn.the_file model\r\n var val = dn.the_file.properties_chosen.tabs;\r\n if(val.val === \"hard\"){\r\n dn.editor.session.setUseSoftTabs(false);\r\n }else{\r\n dn.editor.session.setUseSoftTabs(true);\r\n dn.editor.session.setTabSize(val.n);\r\n }\r\n}\r\n\r\ndn.set_editor_syntax = function(){\r\n // view for dn.the_file model\r\n var mode_str = dn.the_file.properties_chosen.syntax;\r\n var modes_array = require(\"ace/ext/modelist\").modes;\r\n for(var ii=0; ii<modes_array.length;ii++)if(modes_array[ii].caption === mode_str){\r\n dn.editor.getSession().setMode(modes_array[ii].mode);\r\n return;\r\n } \r\n dn.show_error(\"unrecognised syntax mode requested\");\r\n}\r\n\r\n\r\ndn.create_file = function(){\r\n // called by first dn.save if a file wasn't loaded.\r\n // the job here is only to save the title of the file,\r\n // anything else that was to be saved will have to wait until\r\n // this request compeltes.\r\n\r\n dn.status.user_wants_file = 1;\r\n dn.status.file_new = 0;\r\n dn.show_status();\r\n\r\n until_success(function(succ, fail){\r\n Promise.resolve(dn.pr_auth)\r\n .then(dn.request_new(dn.new_in_folder, dn.the_file.title))\r\n .then(dn.show_file_meta)\r\n .then(succ, fail);\r\n }).before_retry(dn.filter_api_errors)\r\n .then(function(result){\r\n console.log(\"suceeded creating file\")\r\n dn.pr_file_loaded.resolve();\r\n }).catch(function(err){\r\n console.log(\"failed to create new file\");\r\n console.dir(err);\r\n dn.show_error(dn.api_error_to_string(err));\r\n document.title = \"Drive Notepad\";\r\n dn.status.file_new = -1;\r\n dn.show_status();\r\n dn.g_settings.set('pane', 'pane_help');\r\n dn.g_settings.set('pane_open', true);\r\n console.dir(err);\r\n });\r\n}\r\n\r\ndn.document_ready = function(e){\r\n\r\n // widget :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n dn.el.the_widget = document.getElementById('the_widget');\r\n dn.el.widget_text = document.getElementById('widget_text');\r\n dn.el.widget_error_text = document.getElementById('widget_error_text');\r\n dn.el.widget_error = document.getElementById('widget_error');\r\n dn.el.widget_content = document.getElementById('widget_content');\r\n dn.el.widget_pending = document.getElementById('widget_pending');\r\n dn.el.the_widget.addEventListener('mousedown', dn.widget_mouse_down);\r\n translate(dn.el.the_widget, 0, 0);\r\n dn.el.the_widget.style.display = '';\r\n dn.el.widget_error.style.display = 'none';\r\n dn.el.widget_content.addEventListener('mousedown', prevent_default_and_stop_propagation);\r\n var els = dn.el.widget_content.getElementsByTagName('input');\r\n for(var ii=0; ii<els.length; ii++)\r\n els[ii].addEventListener('mousedown', stop_propagation); // prevents propagation to preventDefault, installed above.\r\n var els = dn.el.widget_content.getElementsByTagName('textarea');\r\n for(var ii=0; ii<els.length; ii++)\r\n els[ii].addEventListener('mousedown', stop_propagation); // prevents propagation to preventDefault, installed above.\r\n\r\n // editor :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n dn.el.editor = document.getElementById('the_editor');\r\n dn.el.editor.innerHTML = '';\r\n dn.el.editor.addEventListener('contextmenu', function(e){\r\n dn.show_error(\"See the list of keyboard shortcuts for copy/paste, select-all, and undo/redo.\")\r\n });\r\n dn.editor = ace.edit(\"the_editor\");\r\n dn.editor.setHighlightSelectedWord(true);\r\n dn.editor.getSession().addEventListener(\"change\", dn.on_editor_change);\r\n dn.editor.addEventListener(\"input\", dn.check_unsaved);\r\n dn.focus_editor = dn.editor.focus.bind(dn.editor);\r\n dn.focus_editor();\r\n dn.editor.setAnimatedScroll(true);\r\n ace.require(\"ace/ext/language_tools\");\r\n dn.editor.setOptions({ \r\n enableBasicAutocompletion: true,\r\n enableLiveAutocompletion: false\r\n });\r\n dn.editor.$blockScrolling = Infinity; // disables scrolling message\r\n dn.clipboard_tool.on_document_ready();\r\n\r\n // widget menu ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n dn.el.widget_menu = document.getElementById('widget_menu');\r\n dn.el.menu_open = document.getElementById('menu_open');\r\n dn.el.menu_find = document.getElementById('menu_find');\r\n dn.el.menu_help = document.getElementById('menu_help');\r\n dn.el.menu_file = document.getElementById('menu_file');\r\n dn.el.menu_general_settings = document.getElementById('menu_general_settings');\r\n dn.el.widget_menu.addEventListener('mousedown', prevent_default_and_stop_propagation);\r\n dn.menu_icon_from_pane_id = {}\r\n var els = dn.el.widget_menu.getElementsByClassName('widget_menu_icon');\r\n for(var ii=0; ii<els.length; ii++){\r\n els[ii].title = dn.menu_id_to_caption[els[ii].id];\r\n dn.menu_icon_from_pane_id['pane_' + els[ii].id.substr(5)] = els[ii];\r\n }\r\n\r\n dn.el.pane_clipboard = document.getElementById('pane_clipboard');\r\n dn.el.pane_permissions = document.getElementById('pane_permissions');\r\n document.getElementById('button_auth').addEventListener('click', dn.reauth_manual);\r\n\r\n // widget panes ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n\r\n // pane file \r\n dn.el.pane_file = document.getElementById('pane_file');\r\n dn.file_pane.on_document_ready();\r\n dn.el.menu_file.addEventListener('click', function(){\r\n dn.g_settings.set('pane', 'pane_file');\r\n })\r\n\r\n // pane general settings\r\n dn.el.pane_general_settings = document.getElementById('pane_general_settings');\r\n dn.settings_pane.on_document_ready();\r\n dn.el.menu_general_settings.addEventListener('click', function(){\r\n dn.g_settings.set('pane', 'pane_general_settings');\r\n })\r\n\r\n // pane help \r\n dn.el.pane_help = document.getElementById('pane_help');\r\n dn.help_pane.on_document_ready();\r\n dn.el.menu_help.addEventListener('click', function(){\r\n dn.g_settings.set('pane', 'pane_help');\r\n })\r\n\r\n // pane find\r\n dn.el.pane_find = document.getElementById('pane_find');\r\n dn.find_pane.on_document_ready();\r\n dn.el.menu_find.addEventListener('click', function(){\r\n dn.g_settings.set('pane', 'pane_find');\r\n dn.find_pane.focus_on_input();\r\n });\r\n\r\n // pane open\r\n dn.el.pane_open = document.getElementById('pane_open');\r\n dn.open_pane.on_document_ready();\r\n dn.el.menu_open.addEventListener('click', function(){ \r\n dn.g_settings.set('pane', 'pane_open');\r\n });\r\n \r\n // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\r\n dn.pr_file_loaded = new SpecialPromise();\r\n dn.g_settings.addEventListener(\"VALUE_CHANGED\", dn.settings_changed);\r\n dn.make_keyboard_shortcuts();\r\n dn.load_default_settings();\r\n document.addEventListener('contextmenu', prevent_default);\r\n window.addEventListener('resize', dn.widget_apply_anchor);\r\n window.onbeforeunload = dn.query_unload;\r\n\r\n //work out whether a fileid was specified in page load, and if not, whether a folderid was.\r\n var params = window_location_to_params_object(); \r\n dn.new_in_folder = undefined;\r\n if(params['state']){\r\n try{\r\n state = params['state'];\r\n state = state.replace(/,\\s*}\\s*$/,\"}\"); // some users have a trailing comma for some reason\r\n var state = JSON.parse(state); \r\n if(state.action && state.action == \"open\" && state.ids && state.ids.length > 0)\r\n dn.the_file.file_id = state.ids[0];\r\n else if (state.folderId)\r\n dn.new_in_folder = state.folderId; // could be invalid nonsense\r\n }catch(e){\r\n dn.show_error(\"Bad URL. This will be treated as a new file.\");\r\n }\r\n }\r\n\r\n dn.the_file.addEventListener(\"change\", function(e){\r\n switch(e.property){\r\n case \"title\":\r\n dn.render_document_title();\r\n break;\r\n\r\n case \"syntax\":\r\n dn.set_editor_syntax();\r\n break;\r\n\r\n case \"newline\":\r\n dn.set_editor_newline();\r\n break;\r\n\r\n case \"tabs\":\r\n dn.set_editor_tabs();\r\n break;\r\n } \r\n });\r\n\r\n // The auth promise can be rejected and resolved multiple times during the lifetime of the app.\r\n // These two handlers will always be called for those events.\r\n dn.pr_auth.on_error(dn.handle_auth_error); \r\n dn.pr_auth.on_success(function(){\r\n // reset some things, could be no-ops...\r\n dn.reauth_auto_delay = 0;\r\n dn.toggle_permission(false);\r\n dn.status.popup_active = 0;\r\n\r\n // and show the good news...\r\n dn.status.authentication = 1;\r\n dn.show_status(); \r\n })\r\n\r\n // if we ever find that we have gone offline, we have to call offline_simple.commence_testing,\r\n // that will then trigger the following event when the connection is restored.\r\n offline_simple.addEventListener('online', dn.pr_auth.resolve.bind(dn.pr_auth)); \r\n\r\n // get user info...\r\n until_success(function(succ, fail){\r\n Promise.resolve(dn.pr_auth)\r\n .then(dn.request_user_info)\r\n .then(dn.show_user_info)\r\n .then(succ, fail);\r\n }).before_retry(dn.filter_api_errors)\r\n .then(function(){\r\n console.log('succeeded getting user info.')\r\n }).catch(function(err){\r\n console.log(\"failed to load user info\")\r\n console.dir(err);\r\n dn.show_error(dn.api_error_to_string(err));\r\n });\r\n \r\n if(dn.the_file.file_id){\r\n // load existing file :::::::::::::::::::::::::::::::::::::::::::::::::::\r\n dn.status.file_meta = 0;\r\n dn.status.file_body = 0;\r\n dn.status.user_wants_file = 1;\r\n\r\n dn.show_status();\r\n dn.editor.setReadOnly(true);\r\n // metadata...\r\n var pr_meta =\r\n until_success(function(succ, fail){\r\n Promise.resolve(dn.pr_auth)\r\n .then(dn.request_file_meta)\r\n .then(dn.show_file_meta)\r\n .then(succ, fail);\r\n }).before_retry(dn.filter_api_errors)\r\n .catch(function(err){\r\n dn.status.file_meta = -1;\r\n dn.show_status();\r\n throw err;\r\n });\r\n\r\n // body...\r\n var pr_body = \r\n until_success(function(succ, fail){\r\n Promise.resolve(dn.pr_auth)\r\n .then(dn.request_file_body)\r\n .then(dn.show_file_body)\r\n .then(succ, fail);\r\n }).before_retry(dn.filter_api_errors)\r\n .catch(function(err){\r\n dn.status.file_body = -1;\r\n dn.show_status();\r\n throw err;\r\n });\r\n\r\n // wait for both meta data and body...\r\n Promise.all([pr_meta, pr_body])\r\n .then(function(vals){\r\n console.log(\"succeeded loading file body and metadata.\");\r\n dn.the_file.set({is_loaded: true});\r\n dn.pr_file_loaded.resolve(); \r\n dn.show_status();\r\n }).catch(function(err){\r\n console.log(\"failed to load file properly..\");\r\n console.dir(err);\r\n dn.show_error(dn.api_error_to_string(err));\r\n document.title = \"Drive Notepad\";\r\n dn.g_settings.set('pane', 'pane_help');\r\n dn.g_settings.set('pane_open', true);\r\n });\r\n\r\n } else {\r\n\r\n // create new file :::::::::::::::::::::::::::::::::::::::::::::::::::\r\n // or rather, wait for the first save action before creating.\r\n dn.show_status();\r\n dn.the_file.set({title: \"untitled.txt\", is_loaded: true}); // there's nothing to load for this model\r\n dn.g_settings.set('pane', 'pane_file');\r\n dn.g_settings.set('pane_open', true);\r\n }\r\n \r\n // load cloud settings ::::::::::::::::::::::::::::::::::::::::::::::::\r\n until_success(function(succ, fail){ \r\n Promise.all([dn.pr_auth, dn.pr_realtime_loaded])\r\n .then(dn.request_app_data_document)\r\n .then(dn.show_app_data_document)\r\n .then(succ, fail)\r\n }).before_retry(dn.filter_api_errors)\r\n .then(function(){\r\n console.log('succeeded loading settings');\r\n }).catch(function(err){\r\n console.log(\"failed to load realtime settings.\")\r\n console.dir(err);\r\n dn.show_error(dn.api_error_to_string(err));\r\n });\r\n\r\n\r\n // load ads at some point in future...\r\n //setTimeout(load_script_async, dn.const_.ad_initial_wait, 'js/banner_ads.js');\r\n}\r\n\r\nif (document.readyState != 'loading' && document.getElementById('the_widget')){ //second test is hack for IEi\r\n dn.document_ready();\r\n}else{\r\n document.addEventListener('DOMContentLoaded', dn.document_ready);\r\n}\r\n"]}