Virtonomica:Notes

Система добавления и показа оповещений

当前为 2016-10-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Virtonomica:Notes
  3. // @namespace Virtonomica
  4. // @description Система добавления и показа оповещений
  5. // @version 0.23
  6. // @include https://*virtonomic*.*/*/main/unit/view/*
  7. // @include https://*virtonomic*.*/*/main/company/view/*/unit_list
  8. // @include https://*irtonomic*.*/*/main/politics/president/*
  9. // @include https://*virtonomic*.*/*/main/politics/governor/*
  10. // @include https://*virtonomic*.*/*/main/politics/mayor/*
  11. // ==/UserScript==
  12. var run = function() {
  13. var win = (typeof(unsafeWindow) != 'undefined' ? unsafeWindow : top.window);
  14. $ = win.$;
  15.  
  16. var loc_storage = function(){
  17. return({
  18. 'save': function (name, val){
  19. try {
  20. window.localStorage.setItem( name, JSON.stringify( val ) );
  21. } catch(e) {
  22. out = "Ошибка добавления в локальное хранилище";
  23. //console.log(out);
  24. }
  25. },
  26. 'load': function(name){
  27. obj = JSON.parse( window.localStorage.getItem(name) );
  28. if ( obj == null ) obj = new Object();
  29. return obj;
  30. }
  31. });
  32. }
  33. var LS = new loc_storage();
  34.  
  35. // определяем интерфейс
  36. // autodefined language interface
  37. var lang = 'undef';
  38. var bt_logout = $("li[class='icon menulogout']");
  39. var logout_string = bt_logout.attr('title');
  40. if (logout_string == 'Выход') {
  41. lang = 'Ru';
  42. } else if(logout_string == 'Logout') {
  43. lang = 'En';
  44. }
  45. console.log(lang);
  46. if ( lang == 'undef') {
  47. alert('Unsupported language for userscript "Notes"');
  48. return;
  49. }
  50.  
  51. // Строки зависимые от языка
  52. // language definitions
  53. var LangMsg = new Object();
  54. LangMsg['Ru'] = new Object();
  55. LangMsg['En'] = new Object();
  56.  
  57. LangMsg['Ru']['governor'] = "Губернатор";
  58. LangMsg['En']['governor'] = "Governor";
  59. LangMsg['Ru']['president'] = "Президент";
  60. LangMsg['En']['president'] = "President";
  61. LangMsg['Ru']['mayor'] = "Мэр";
  62. LangMsg['En']['mayor'] = "Mayor";
  63.  
  64. LangMsg['Ru']['notes'] = "Напоминание";
  65. LangMsg['En']['notes'] = "Notes";
  66.  
  67. LangMsg['Ru']['save'] = "Сохранить";
  68. LangMsg['En']['save'] = "Save";
  69. LangMsg['Ru']['del'] = "Удалить";
  70. LangMsg['En']['del'] = "Delete";
  71.  
  72. LangMsg['Ru']['add_notes'] = "Добавить напоминание";
  73. LangMsg['En']['add_notes'] = "Add Notes";
  74.  
  75. LangMsg['Ru']['export'] = "Окно экспорта/импорта";
  76. LangMsg['En']['export'] = "Windwow export/import";
  77. LangMsg['Ru']['import'] = "Импортировать данные из окна";
  78. LangMsg['En']['import'] = "Importing data from textarea";
  79. LangMsg['Ru']['data_export'] = "Данные экспорта";
  80. LangMsg['En']['data_export'] = "Data exporting";
  81. // --- virtonomica user interface
  82. LangMsg['Ru']['comp'] = "компании";
  83. LangMsg['En']['comp'] = "of a company";
  84. //console.log( LangMsg );
  85. /**
  86. * записать данные в локальнео хранилище, с проверкой ошибок
  87. */
  88. function ToStorage(name, val)
  89. {
  90. try {
  91. window.localStorage.setItem( name, JSON.stringify( val ) );
  92. } catch(e) {
  93. out = "Ошибка добавления в локальное хранилище";
  94. //console.log(out);
  95. }
  96. }
  97.  
  98. function getFromStorage(obj, id_shop)
  99. {
  100. if (obj[id_shop] == null) return '';
  101. return JSON.stringify(obj[id_shop]);
  102. }
  103.  
  104. /**
  105. * Добавить заметку к текущему предприятию
  106. * следует вызывать на страницах где одно подраздление, ИД которого виден в url
  107. *
  108. * @param msg текст сообщения, можно использовать html теги
  109. */
  110. function addNotes( msg ){
  111. // объект для хранения сообщений
  112. notes = JSON.parse( window.localStorage.getItem('notes') );
  113. if ( notes == null ) notes = new Object();
  114.  
  115. // Идентификатор подразделения
  116. var id = /(\d+)/.exec(location.href)[0];
  117. var head = $("#headerInfo");
  118. var title = $("h1", head).text();
  119.  
  120. head = $("div.officePlace");
  121. var type = head.text();
  122. var nn = type.indexOf("компании");
  123. if (nn > 0){
  124. type = type.substring(0, nn);
  125. var ptrn = /\s*((\S+\s*)*)/;
  126. type = type.replace(ptrn, "$1");
  127. ptrn = /((\s*\S+)*)\s*/;
  128. type = type.replace(ptrn, "$1");
  129. } else {
  130. type = '';
  131. }
  132.  
  133. if ( notes[id] == null ) notes[id] = new Object();
  134.  
  135. var d = new Date();
  136.  
  137. if ( notes[id]['text'] != null) {
  138. // сообщение для этого подраздления уже есть
  139. msg = notes[id]['text'] + "<br>" + msg;
  140. }
  141.  
  142. notes[id]['text'] = msg;
  143. // Количество миллисекунд
  144. notes[id]['time'] = d.getTime();
  145. notes[id]['name'] = title;
  146. notes[id]['type'] = type;
  147.  
  148. ToStorage('notes', notes);
  149. }
  150.  
  151. var txt = "<table><tr><td><td><table width=100%><tr><td align=rigth id=notes_title><td align=center><h3>" + LangMsg[ lang ]['notes'] + "</h3><div id=notes_link style='color:grey'></div></table><td>&nbsp;";
  152. txt+= "";
  153. txt+= "<tr><td>&nbsp;<td align=center id=notes_form>&nbsp;<td>&nbsp;" + "<tr><td colspan=3></table>";
  154. var div_form = "<div id=notes style='background: none repeat scroll 0% 0% rgb(223, 223, 223); z-index: 1002; position: absolute; border: 1px solid rgb(0, 0, 0); display: none;'>" + txt + "</div>";
  155.  
  156. var div_export = "<div id=notes_export style='background: none repeat scroll 0% 0% rgb(223, 223, 223); z-index: 1003; position: absolute; border: 1px solid rgb(0, 0, 0); display: none;'>"
  157. + "<h3 style='margin:4px'>" + LangMsg[ lang ]['data_export'] + "</h3>"
  158. + "<table><tr><td>&nbsp;<td>"
  159. + "<textarea name=export_text id=export_text rows=10 cols=64></textarea>"
  160. + "<br><center><span id=export_load></span></center>"
  161. + "</table>";
  162. + "</div>";
  163.  
  164. var tu = $("table.unit-list-2014");
  165. if (tu.length == 1) {
  166. // Это у нас список подразделений - рисуем кнопку отображения отчета со сылками
  167. // Оповещения
  168. notes = JSON.parse( window.localStorage.getItem('notes') );
  169. if ( notes == null ) notes = new Object();
  170. var len = 0;
  171.  
  172. // проверить, какие оповещения отразить как актуальные
  173. for (key in notes){
  174. len++;
  175. }
  176.  
  177. // http://cdn1.iconfinder.com/data/icons/Upojenie_by_SoundForge/Icons/Notes.png
  178. // http://www.iconsearch.ru/uploads/icons/crystalclear/24x24/kedit.png
  179.  
  180. var wc = $("<li><div id=main_notes style='float:left;cursor:pointer; color: white;'> <img alt='Список напоминаний' src=http://cdn1.iconfinder.com/data/icons/humano2/32x32/apps/gnome-sticky-notes-applet.png> <span id=all_notes> ("+ len+")</span></div>").click( function() {
  181. $("#notes").toggle();
  182. if( $('#notes').is(':visible') ) {
  183. // код для visible
  184. // Оповещения
  185. notes = JSON.parse( window.localStorage.getItem('notes') );
  186. if ( notes == null ) notes = new Object();
  187.  
  188. // Формируем ссылку на торговый зал
  189. var url = /^https:\/\/virtonomic[as]\.(\w+)\/\w+\//.exec(location.href)[0];
  190. console.log(url);
  191.  
  192. var all_count = 0;
  193. $("#notes_form").html('');
  194. var out = $("<table>");
  195. for (key in notes){
  196. if (notes[key] == null) continue;
  197. if (notes[key]['time'] == null) continue;
  198.  
  199. // подсчитываем сколько у нас оповещениий
  200. // TODO - учитывать только акутальные
  201. all_count++;
  202.  
  203. var d = new Date();
  204. d.setTime(notes[key]['time']);
  205.  
  206. link = "<a href=" + url + "main/unit/view/" + key + ">" + notes[key]['name'] + "</a>";
  207. if ( notes[key]['link'] != null ) {
  208. link = "<a href=" + notes[key]['link'] + ">" + notes[key]['name'] + "</a>";
  209. }
  210. span = $("<span name=" + key + " style='cursor:pointer;' title='del'><font color=red><b>Х</b></font></span>").click(
  211. function(){
  212. idp = $(this).attr('name');
  213. //alert('del = ' + idp);
  214. delete notes[idp];
  215. ToStorage('notes', notes);
  216. $(this).parent().css("text-decoration","line-through").css("color","grey");
  217. //$("#main_notes").click().click();
  218. });
  219.  
  220. out_tr = $("<tr>");
  221. out_tr.append("<td>" + d.toLocaleDateString())
  222. .append("<td>" + link)
  223. .append("<td>(" + notes[key]['type'] + ")")
  224. .append("<td style='border: 1px solid gray; border-radius: 4px 4px 4px 4px; box-shadow: 0 1px 3px 0 #999999; display: block; float: left; margin-top: 4px; overflow: hidden; padding: 2px 4px; text-align:left'>" + notes[key]['text'])
  225. .append("<td>").append(span);
  226. out.append(out_tr);
  227. str = "(" + all_count +")";
  228. if (all_count == 0) str = '';
  229. $("#all_notes").html("(" + all_count +")");
  230. }
  231. $("#notes_form").html( out );
  232.  
  233. }
  234. });
  235.  
  236. // http://cdn1.iconfinder.com/data/icons/basicset/save_32.png
  237. // http://www.iconsearch.ru/uploads/icons/ultimategnome/48x48/stock_export.png
  238. var wc_export = $("<span id=main_notes_export style='cursor:pointer; color: white;'><img src=http://cdn1.iconfinder.com/data/icons/basicset/save_32.png title='" + LangMsg[ lang]['export']+ "' alt='О" + LangMsg[ lang]['export']+ "'></span>").click( function() {
  239. $("#export_text").val( JSON.stringify( notes ) );
  240. $("#notes_export").toggle();
  241. });
  242.  
  243. // http://cdn1.iconfinder.com/data/icons/freeapplication/png/24x24/Load.png
  244. // http://www.iconsearch.ru/uploads/icons/freeapplication/24x24/load.png
  245. var wc_load = $("<img src=http://cdn1.iconfinder.com/data/icons/freeapplication/png/24x24/Load.png title='" + LangMsg[ lang ]['import'] + "' alt='" + LangMsg[ lang ]['import'] + "'>").click( function() {
  246. //alert("Load");
  247. var text = $("#export_text").val() ;
  248. try {
  249. notes = JSON.parse( text );
  250. ToStorage('notes', notes);
  251. $("#notes_export").hide();
  252. $("#main_notes").click().click();
  253. } catch(e) {
  254. alert("Неверные данным для импорта");
  255. }
  256. });
  257.  
  258. var container = $('ul.tabu');
  259. container.append( wc );
  260.  
  261. $("table.unit-top").before ( div_form);
  262. //container.append( div_form );
  263. //var container = $('#topblock');
  264. //container.append( $('<table><tr><td>').append(wc) );
  265. //container.append( div_form );
  266. $("#notes_title").append(wc_export).append( div_export );
  267. $("#export_load").append(wc_load);
  268.  
  269.  
  270. return;
  271. }
  272.  
  273. // Идентификатор подразделения
  274. var id = /(\d+)/.exec(location.href)[0];
  275. console.log("id=" + id);
  276. // тип подразделения
  277. var type = '';
  278. // название подразделения
  279. var title = '';
  280. var pos = location.href.indexOf("politics");
  281. // проверяем на объект политики
  282. if (pos > 0) {
  283. console.log("politics");
  284. // вычитываем название объекта политики
  285. var polit_name = "";
  286. var el = $("#headerInfoCenter h1");
  287. var el2 = $("a", el);
  288. if (el2.length > 0 ) {
  289. polit_name = el2.text();
  290. } else {
  291. polit_name = el.text();
  292. }
  293. if ( location.href.indexOf("president") > 0 ) {
  294. type = LangMsg[ lang ]['president'];
  295. }
  296. if ( location.href.indexOf("governor") > 0 ) {
  297. type = LangMsg[ lang ]['governor'] ;
  298. }
  299. if ( location.href.indexOf("mayor") > 0 ) {
  300. type = LangMsg[ lang ]['mayor'] ;
  301. polit_name = el.html();
  302. pos = polit_name.indexOf("<img");
  303. polit_name = $.trim( polit_name.substr(0, pos) );
  304. }
  305. console.log( polit_name );
  306. title = polit_name;
  307. console.log( type );
  308. } else {
  309. // обработка обыных юнитов (units)
  310. var head = $("#headerInfo");
  311. var title = $("h1", head).text();
  312.  
  313. head = $("div.officePlace");
  314. var type = head.text();
  315. var nn = type.indexOf( LangMsg[ lang ]['comp'] );
  316. if (nn > 0){
  317. type = type.substring(0, nn);
  318. var ptrn = /\s*((\S+\s*)*)/;
  319. type = type.replace(ptrn, "$1");
  320. ptrn = /((\s*\S+)*)\s*/;
  321. type = type.replace(ptrn, "$1");
  322. } else {
  323. type = '';
  324. }
  325. }
  326. // Оповещения
  327. notes = JSON.parse( window.localStorage.getItem('notes') );
  328. if ( notes == null ) notes = new Object();
  329. if ( notes[id] == null) notes[id] = new Object();
  330.  
  331. notes_html = "";
  332. if ( notes[id]['text'] != null) notes_html = notes[id]['text'];
  333.  
  334. var form = "";
  335. form += "<span id=notes_error style='color:red;'></span><br>";
  336. form += "<div id=notes_preview style='border: 1px solid gray; border-radius: 4px 4px 4px 4px; box-shadow: 0 1px 3px 0 #999999; display: block; float: left; margin-top: 4px; margin-right: 4px; overflow: hidden; padding: 2px 4px; text-align:left'>" + notes_html +"</div>";
  337. form += " <textarea name=notes_txt id=notes_txt rows=5 cols=48>";
  338. form += notes_html;
  339. form+= "</textarea><br>";
  340.  
  341. var form_button = $("<button id=notes_btn style='cursor:pointer'>" +LangMsg[ lang ]['save'] + "</button>").click( function() {
  342. $("#notes_error").text('');
  343. var text = $("#notes_txt").val() ;
  344. $("#notes_preview").html( text );
  345. if (text == '') {
  346. $("#notes_error").text('Ошибка - нет описания');
  347. return;
  348. }
  349.  
  350. var d = new Date();
  351. // Оповещения
  352. notes = JSON.parse( window.localStorage.getItem('notes') );
  353. if ( notes == null ) notes = new Object();
  354.  
  355. if ( notes[id] == null) notes[id] = new Object();
  356.  
  357. notes[id]['text'] = text;
  358. notes[id]['time'] = d.getTime();
  359. notes[id]['name'] = title;
  360. notes[id]['type'] = type;
  361. notes[id]['link'] = location.href;
  362.  
  363. ToStorage('notes', notes);
  364. $("#notes").toggle();
  365. });
  366.  
  367. var form_button_del = $(" <button style='cursor:pointer'>" +LangMsg[ lang ]['del'] + "</button>").click( function() {
  368. // Оповещения
  369. notes = JSON.parse( window.localStorage.getItem('notes') );
  370. if ( notes == null ) notes = new Object();
  371.  
  372. if ( notes[id] == null) notes[id] = new Object();
  373.  
  374. $("#notes_txt").val("");
  375. $("#notes_preview").html( "" );
  376. delete notes[id];
  377. ToStorage('notes', notes);
  378. });
  379.  
  380. // http://cdn1.iconfinder.com/data/icons/oxygen/32x32/actions/document-new.png
  381. // http://www.iconsearch.ru/uploads/icons/ull_icons/24x24/message_add.png
  382. var wc = $("<li style='cursor:pointer; color: white;'><img alt='"+ LangMsg[ lang ]['add_notes'] + "' src=http://cdn1.iconfinder.com/data/icons/oxygen/32x32/actions/document-new.png title='"+ LangMsg[ lang ]['add_notes'] + "'> </li>").click( function() {
  383. $("#notes").toggle();
  384. // Обновить зампетку
  385. notes = JSON.parse( window.localStorage.getItem('notes') );
  386. if ( notes == null ) notes = new Object();
  387. if ( notes[id] == null) notes[id] = new Object();
  388.  
  389. $("#notes_txt").change(function() {
  390. console.log('change ' + $("#notes_txt").val() );
  391. $("#notes_preview").html( $("#notes_txt").val() );
  392. });
  393. if ( notes[id]['text'] == null ) return;
  394. $("#notes_txt").val( notes[id]['text'] );
  395. $("#notes_preview").html( notes[id]['text'] );
  396. if (notes[id]['link'] != null) {
  397. $("#notes_link").html( notes[id]['link'] );
  398. }
  399. });
  400. //var container = $('#topblock');
  401. var container = $('#topblock').next();
  402.  
  403. if (tu.length == 0) {
  404. container = $("li:last", container).prev().parent();
  405. container.append(wc) ;
  406. //container.append( $('<table><tr><td>').append(wc) );
  407. $("#childMenu").before ( div_form);
  408.  
  409. $("#notes_form").append(form).append(form_button).append(form_button_del);
  410. }
  411. }
  412.  
  413. if(window.top == window) {
  414. var script = document.createElement("script");
  415. script.textContent = '(' + run.toString() + ')();';
  416. document.documentElement.appendChild(script);
  417. }