Pređi na sadržaj

Razgovor o Medijavikiju:FileUploadWizard.js/Arhiva 1

Sadržaj stranice nije podržan na drugim jezicima
S Vikipedije, slobodne enciklopedije
Arhiva 1 Arhiva 2

Popravke

Trebalo bi ispraviti sljedeće:

  • primaknutu crtu zameniti sa odmaknutom jer se ne povezuje npr. „Autorstvo—Dijeliti” (ovo dvoje nema nikakve međusobne veze) nego se razdvaja „Krijejtiv komons Autorstvo” i ostatak s desne strane
  • „Autorstvo” bi trebalo da bude malim početnim slovom, ne znam koji je razlog za veliko jer „Attribution” ne označava nikakvu vlastitu imenicu nego je ono engl. isticanje svih riječi velikim početnim slovom osim veznika i dr., mada može se posmatrati i kao izdvojeni dio ali ja ne znam da li to ili ovo prvo (ako je ustaljeno dosad bilo pisanje velikim slovom, pa čak i pisanje s primaknutom crtom, onda se ne isplati mijenjati na hiljadu mjesta [dole udnu stoji „Tekst je dostupan pod licencom Krijejtiv komons Autorstvo—Deliti pod istim uslovima”] — razlog više za ekavicu a manje za ispravljanje crte i razmišljanje o ovom velikom slovu)
  • „posvjećivanje” je sigurno „posvećivanje” i na ijekavici i na ekavici (a trebaće ja mislim sve prebaciti na ekavicu, i onaj obrazac i ovo, jer softver je cijeli koliko znam na ekavici pa ne bi trebalo praviti izuzetak sa ovim obrascem)
  • „Krijejtiv komons-nula” zamijeniti sa „KK-nula”; u stvari taj red bih ja stavio da bude „Predavanje u univerzalno javno vlasništvo (cc-0)” jer je tako dosljedno
  • „dole” je „dolje” na ijekavici; bolje je zamijeniti ovo sa „ispod”
  • „Javnom vlasništvo” treba da bude ili „Javnom vlasništvu” ili „Javno vlasništvo”
  • „Stavka” i „predmet” promijeniti u „Djelo”

Ovdje ću dodati još stvari za ispraviti kako budem pregledao onaj obrazac i ovaj Medijaviki...  Obsuser 13:07, 27. oktobar 2016. (CEST)[odgovori]

Prevodi

<b>No</b>, I want to upload this file here on this wiki only.<br/>" + 
          "<small>This way it can be used only on the English Wikipedia. However, somebody " +
          "else might still decide to copy it to Commons or use it elsewhere later. If you " +
          "do not want your file to be copied to Commons and deleted locally, consider adding " +
          "{{tl|Keep local}}.</small>") :
         "Upload this file.";
   fuwGet('SubmitButton').value = validForCommons ? "Upload locally" : "Upload";
<b>Не</b>, желим да ову датотеку отпремим овдје, само на ову Википедију.<br/>" + 
          "<small>Овако ће се датотека моћи користити само на Википедији на српском језику. Међутим, неко " +
          "други би могао да је копира на Оставу и потом је користи негдје друго. Ако Ви " +
          "не желите да се ова датотека копира на Оставу а потом обрише овдје, додајте " +
          "{{tl|keep local}}.</small>") :
         "Отпреми ову датотеку.";
   fuwGet('SubmitButton').value = validForCommons ? "Отпреми локално" : "Отпреми";

 Obsuser 13:26, 27. oktobar 2016. (CEST)[odgovori]

@Obsuser: Ako imaš vremena da prevedeš, zamolio bih te da to uradiš u nekom svom imenskom prostoru, a ja ću to onda prenjeti ovdje. —Ranko Nikolić (razgovor) 13:40, 27. oktobar 2016. (CEST)[odgovori]
Pokušaću.  Obsuser 14:42, 27. oktobar 2016. (CEST)[odgovori]
/*
* ===============================================================
*                    FileUploadWizard.js
* Script for uploading files through a dynamic questionnaire.
* This is the code to accompany [[Wikipedia:File Upload Wizard]].
* ===============================================================
*/

var fuwTesting = false;
var fuwDefaultTextboxLength = 60;
var fuwDefaultTextareaWidth = '90%';
var fuwDefaultTextareaLines = 3;

// ================================================================
// Constructor function of global fuw (= File Upload Wizard) object
// ================================================================
function fuwGlobal() {

   // Loading the accompanying .css
   mw.loader.load( mw.config.get('wgServer') + mw.config.get('wgScriptPath') +
      '/index.php?title=MediaWiki:FileUploadWizard.css&action=raw&ctype=text/css', 
      'text/css'  );

   // see if user is logged in, autoconfirmed, experienced etc.
   this.getUserStatus();

   fuwSetVisible('warningLoggedOut', (this.userStatus == 'anon'));
   fuwSetVisible('warningNotConfirmed', (this.userStatus == 'notAutoconfirmed'));
   if ((this.userStatus == 'anon') || (this.userStatus == 'notAutoconfirmed')) {
      return;
   }
   fuwSetVisible('fuwStartScriptLink', false);

   // create the form element to wrap the main ScriptForm area
   // containing input elements of Step2 and Step3
   var frm = fuwGet('fuwScriptForm');
   if (! frm) {
      frm = document.createElement('form');
      frm.id = "fuwScriptForm";
      var area = fuwGet('placeholderScriptForm');
      var parent = area.parentNode;
      parent.insertBefore(frm, area);
      parent.removeChild(area);
      frm.appendChild(area);
   }
   this.ScriptForm = frm;

   // create the TargetForm element that contains the filename
   // input box, together with hidden input controls.
   // This is the form that is actually submitted to the api.php.
   frm = fuwGet('TargetForm');
   if (! frm) {
      frm = document.createElement('form');
      frm.id = "TargetForm";
      frm.method = "post";
      frm.enctype = "multipart/form-data";
      // "enctype" doesn't work properly on IE; need "encoding" instead:
      frm.encoding = "multipart/form-data"; 
      // we'll submit via api.php, not index.php, mainly because that
      // allows us to use a proper edit summary different from the page content
      frm.action = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php';

      // However, since api.php sends back a response page that humans won't want to read,
      // we'll have to channel that response away and discard it. We'll use a hidden iframe
      // for that purpose.
      // Unfortunately, it doesn't seem possible to submit file upload content through an 
      // Xmlhtml object via Ajax.
 
      frm.target = "TargetIFrame";
      //testing:
      //frm.target = "_blank";
      var area = fuwGet('placeholderTargetForm');
      var parent = area.parentNode;
      parent.insertBefore(frm, area);
      parent.removeChild(area);
      frm.appendChild(area);
   }
   this.TargetForm = frm;

   // For the testing version, create a third form that will display
   // the contents to be submitted, at the bottom of the page
   if (fuwTesting) {
      frm = fuwGet('fuwTestForm');
      if (! frm) {
         frm = document.createElement('form');
         frm.id = "fuwTestForm";
         var area = fuwGet('placeholderTestForm');
         var parent = area.parentNode;
         parent.insertBefore(frm, area);
         parent.removeChild(area);
         frm.appendChild(area);
      }
      this.TestForm = frm;
   }

   // objects to hold cached results during validation and processing
   this.opts = { };
   this.warn = { };

   // create the input filename box
   var filebox  = document.createElement('input');
   filebox.id   = 'file';
   filebox.name = 'file';
   filebox.type = 'file';
   filebox.size = fuwDefaultTextboxLength;
   filebox.onchange = fuwValidateFile;
   filebox.accept = 'image/png,image/jpeg,image/gif,image/svg+xml,image/tiff,image/x-xcf,application/pdf,image/vnd.djvu,audio/ogg,video/ogg,audio/rtp-midi';
   fuwAppendInput('file', filebox);

   // create hidden controls for sending the remaining API parameters:
   fuwMakeHiddenfield('action', 'upload', 'apiAction');
   fuwMakeHiddenfield('format', 'xml', 'apiFormat');
   fuwMakeHiddenfield('filename', '', 'apiFilename');
   fuwMakeHiddenfield('text', '', 'apiText');
   fuwMakeHiddenfield('comment', '', 'apiComment');
   fuwMakeHiddenfield('token', mw.user.tokens.get('editToken'), 'apiToken');
   fuwMakeHiddenfield('ignorewarnings', 1, 'apiIgnorewarnings');
   fuwMakeHiddenfield('watch', 1, 'apiWatch');

   if (fuwTesting) {
      fuwMakeHiddenfield('title', mw.config.get('wgPageName') + "/sandbox", 'SandboxTitle');
      fuwMakeHiddenfield('token', mw.user.tokens.get('editToken'), 'SandboxToken');
      fuwMakeHiddenfield('recreate', 1, 'SandboxRecreate');
   }

   // create a hidden IFrame to send the api.php response to
   var ifr = document.createElement('iframe');
   ifr.id   = "TargetIFrame";
   ifr.name = "TargetIFrame";
   //ifr.setAttribute('style', 'float:right;width:150px;height:150px;');
   ifr.style.display = "празно";
   ifr.src = "";

   fuwAppendInput('TargetIFrame', ifr);

   if (fuwTesting) {

      // create the sandbox submit button
      btn = document.createElement('input');
      btn.id = 'SandboxButton';
      btn.value = 'Пијесак';
      btn.name  = 'Sandbox';
      btn.disabled = true;
      btn.type = 'button';
      btn.style.width = '12em';
      btn.onclick = fuwSubmitSandbox;
      fuwAppendInput('SandboxButton', btn);

   }

   // create the real submit button
   btn = document.createElement('input');
   btn.id = "SubmitButton";
   btn.value = "Отпреми";
   btn.name = "Upload";
   btn.disabled = true;
   btn.type = "button";
   btn.onclick = fuwSubmitUpload;
   btn.style.width = '12em';
   fuwAppendInput('SubmitButton', btn);

   // create the Commons submit button
   btn = document.createElement('input');
   btn.id = "CommonsButton";
   btn.value = "Отпреми на Оставу";
   btn.name  = "Upload_on_Commons";
   btn.disabled = true;
   btn.type = "button";
   btn.onclick = fuwSubmitCommons;
   btn.style.width = '12em';
   fuwAppendInput('CommonsButton', btn);

   // create reset buttons
   for (i = 1; i<=2; i++) {
      btn = document.createElement('input');
      btn.id = 'ResetButton' + i;
      btn.value = "Ресетуј образац";
      btn.name  = "Reset form";
      btn.type  = "button";
      btn.onclick = fuwReset;
      btn.style.width = '12em';
      fuwAppendInput('ResetButton' + i, btn);
   }

   // names of radio button fields
   var optionRadioButtons = {
      // top-level copyright status choice
      'FreeOrNonFree' : ['OptionFree','OptionNonFree','OptionNoGood'],
      // main subsections under OptionFree
      'FreeOptions'   : ['OptionOwnWork', 'OptionThirdParty', 'OptionFreeWebsite',
                         'OptionPDOld', 'OptionPDOther'],
      // main subsections under OptionNonFree
      'NonFreeOptions': ['OptionNFSubject','OptionNF3D','OptionNFExcerpt',
                         'OptionNFCover','OptionNFLogo','OptionNFPortrait',
                         'OptionNFMisc'],
      // response options inside warningFileExists
      'FileExistsOptions': 
                        ['NoOverwrite','OverwriteSame','OverwriteDifferent'],
      // choice of evidence in OptionThirdParty subsection
      'ThirdPartyEvidenceOptions' : 
                        ['ThirdPartyEvidenceOptionLink',
                         'ThirdPartyEvidenceOptionOTRS',
                         'ThirdPartyEvidenceOptionOTRSForthcoming',
                         'ThirdPartyEvidenceOptionNone'],
      // choice of PD status in OptionPDOld subsection
      'PDOldOptions'  : ['PDUS1923','PDURAA','PDFormality','PDOldOther'],
      // choice of PD status in OptionPDOther subsection
      'PDOtherOptions': ['PDOtherUSGov','PDOtherOfficial','PDOtherSimple',
                         'PDOtherOther'],
      // whether target article is wholly or only partly dedicated to discussing non-free work:
      'NFSubjectCheck': ['NFSubjectCheckDedicated','NFSubjectCheckDiscussed'],
      'NF3DCheck'     : ['NF3DCheckDedicated','NF3DCheckDiscussed'],
      // choice about copyright status of photograph in OptionNF3D
      'NF3DOptions'   : ['NF3DOptionFree','NF3DOptionSame']
   };
   for (var group in optionRadioButtons) {
      var op = optionRadioButtons[group];
      for (i=0; i<op.length; i++) {
         fuwMakeRadiobutton(group, op[i]);
      }
   }
   this.ScriptForm.NoOverwrite.checked = true;
   
   // input fields that trigger special
   // onchange() event handlers for validation:
   fuwMakeTextfield('InputName', fuwValidateFilename);
   fuwMakeTextfield('NFArticle', fuwValidateNFArticle);

   // names of input fields that trigger normal
   // validation event handler
   var activeTextfields = [
      'Artist3D','Country3D',
      'Date','OwnWorkCreation','OwnWorkPublication',
      'Author','Source',
      'Permission','ThirdPartyOtherLicense',
      'ThirdPartyEvidenceLink','ThirdPartyOTRSTicket',
      'FreeWebsiteOtherLicense',
      'PDOldAuthorLifetime','Publication',
      'PDOldCountry','PDOldPermission',
      'PDOfficialPermission','PDOtherPermission',
      'NFSubjectPurpose', 'NF3DOrigDate', 'NF3DPurpose',
      'NF3DCreator',
      'NFPortraitDeceased',
      'EditSummary'
   ];
   for (i=0; i<activeTextfields.length; i++) {
      fuwMakeTextfield(activeTextfields[i]);
   }

   // names of multiline textareas
   var activeTextareas = [
      'InputDesc','NF3DPermission',
      'NFCommercial','NFPurpose','NFReplaceableText',
      'NFReplaceable','NFCommercial','NFMinimality','AnyOther'
   ];
   for (i=0; i<activeTextareas.length; i++) {
      fuwMakeTextarea(activeTextareas[i]);
   };

   var checkboxes = [
      'NFCoverCheckDedicated','NFLogoCheckDedicated','NFPortraitCheckDedicated'
   ];
   for (i=0; i<checkboxes.length; i++) {
      fuwMakeCheckbox(checkboxes[i]);
   };

   var licenseLists = {
      'OwnWorkLicense' : 
        // array structure as expected for input to fuwMakeSelection() function.
        // any entry that is a two-element array will be turned into an option
        // (first element is the value, second element is the display string).
        // Entries that are one-element arrays will be the label of an option group.
        // Zero-element arrays mark the end of an option group.
        [
        ['Допуштате свима употребу док Вас наводе као аутора и дијеле под сличним условима'],
        ['self|GFDL|cc-by-sa-4.0|migration=redundant', 
         'Кријејтив комонс Ауторство—Дијелити под истим условима 4.0 + ГНУ-ова лиценца за слободну документацију (препоручено)',
         true],
        ['self|cc-by-sa-4.0',
         'Кријејтив комонс Ауторство—Дијелити под истим условима 4.0'],
        [],
        ['Допуштате свима употребу док Вас наводе као аутора'],
        ['self|cc-by-4.0',
         'Кријејтив комонс Ауторство 4.0'],
        [],
        ['Без задржавања права'],
        ['cc-zero',
         'Предавање у универзално јавно власништво (cc-0)'],
        []
        ],   
      'ThirdPartyLicense' :
        [
        ['', 'изаберите једну од опција...'],
        ['Слободне лиценце:'],
        ['cc-by-sa-4.0', 'Кријејтив комонс Ауторство—Дијелити под истим условима (cc-by-sa-4.0)'],
        ['cc-by-4.0', 'Кријејтив комонс Ауторство (cc-by-4.0)'],
        ['GFDL', 'ГНУ-ова лиценца за слободну документацију (GFDL)'],
        [],
        ['Без задржавања права:'],
        ['PD-author', 'Јавно власништво'],
        [],
        ['Остало (погледајте испод)'],
        []
        ],   
      'FreeWebsiteLicense' :
        [
        ['', 'изаберите једну од опција...'],
        ['Слободне лиценце:'],
        ['cc-by-sa-4.0', 'Кријејтив комонс Ауторство—Дијелити под истим условима (cc-by-sa-4.0)'],
        ['cc-by-4.0', 'Кријејтив комонс Ауторство (cc-by-4.0)'],
        ['GFDL', 'ГНУ-ова лиценца за слободну документацију (GFDL)'],
        [],
        ['Без задржавања права:'],
        ['PD-author', 'Јавно власништво'],
        [],
        ['Остало (погледајте испод)'],
        []
        ],   
      'USGovLicense' :
       [
       ['PD-USGov', 'Федерална влада САД'],
       ['PD-USGov-NASA','НАСА'],
       ['PD-USGov-Military-Navy','Ратна морнарица САД'],
       ['PD-USGov-NOAA','Национална океанска и атмосферска администрација'],
       ['PD-USGov-Military-Air_Force','Ратно ваздухопловство САД'],
       ['PD-USGov-Military-Army','Армија САД'],
       ['PD-USGov-CIA-WF','CIA World Factbook'],
       ['PD-USGov-USGS','Геолошки топографски институт САД']
       ],
      'IneligibleLicense' :
       [
       ['', 'изаберите једну од опција...'],
       ['PD-shape','Дјело се састоји искључиво од једноставних геометријских облика'],
       ['PD-text','Дјело се састоји само од неколико појединачних ријечи или слова'],
       ['PD-textlogo','Лого или слично дјело које се састоји искључиво од слова и једноставних геометријских облика'],
       ['PD-chem','Хемијска структурална формула'],
       ['PD-ineligible','Друга врста дјела које не садржи оригинално ауторство']
       ],
      'NFSubjectLicense' :
       [
       ['', 'изаберите једну од опција...'],
       ['Non-free 2D art', '2-димензионално умјетничко дјело (слика, цртеж итд.)'], 
       ['Non-free historic image', 'Јединствена историјска фотографија'], 
       ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)']
       ],
      'NF3DLicense' :
       [
       ['', 'изаберите једну од опција...'],
       ['Non-free architectural work', 'Архитектонско дјело'], 
       ['Non-free 3D art', 'Друго 3-димензионално креативно дјело (скулптура итд.)']
       ],
      'NFCoverLicense' :
         [
         ['', 'изаберите једну од опција...'],
         ['Non-free book cover', 'Корица књиге'], 
         ['Non-free album cover', 'Омот звучног записа (албум, сингл, пјесма, ЦД)'], 
         ['Non-free game cover', 'Омот видео/рачунарске игре'], 
         ['Non-free magazine cover', 'Насловна страна часописа'], 
         ['Non-free video cover', 'Омот видео-траке'], 
         ['Non-free software cover', 'Омот софтверског производа'], 
         ['Non-free product cover', 'Омот неког комерцијалног производа'], 
         ['Non-free title-card', 'Уводна шпица ТВ програма'], 
         ['Non-free movie poster', 'Филмски постер'], 
         ['Non-free poster', 'Званични постер догађаја'], 
         ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)']
         ],
      'NFExcerptLicense' :
         [
         ['', 'изаберите једну од опција...'],
         ['Non-free television screenshot', 'Снимак екрана ТВ програма'], 
         ['Non-free film screenshot', 'Снимак екрана филма'], 
         ['Non-free game screenshot', 'Снимак екрана игре'], 
         ['Non-free video screenshot', 'Снимак екрана видеа'], 
         ['Non-free music video screenshot', 'Снимак екрана музичког видеа'], 
         ['Non-free software screenshot', 'Снимак екрана софтвера'], 
         ['Non-free web screenshot', 'Снимак екрана веб-сајта'], 
         ['Non-free speech', 'Аудио-исјечак говора'], 
         ['Non-free audio sample', 'Звучни одломак аудио-снимка'], 
         ['Non-free video sample', 'Исјечак видеа'], 
         ['Non-free sheet music', 'Ноте које представљају музичко дјело'], 
         ['Non-free comic', 'Дио стрипа, графички роман, манга итд.'], 
         ['Non-free computer icon', 'Рачунарска икона'], 
         ['Non-free newspaper image', 'Страница новина'], 
         ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)']
         ],      
      'NFLogoLicense' :
         [
         ['Non-free logo', 'Лого компаније, организације итд.'], 
         ['Non-free seal', 'Званични печат, грб итд.'], 
         ['Non-free symbol', 'Други званични симбол']
         ],
      'NFMiscLicense' :
         [
         ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)'], 
         ['Non-free historic image', 'Историјска фотографија'], 
         ['Non-free 2D art', '2-димензионално умјетничко дјело (слика, цртеж итд.)'], 
         ['Non-free currency', 'Депикција валуте (новчанице, кованице итд.)'], 
         ['Non-free architectural work', 'Архитектонско дјело'], 
         ['Non-free 3D art', 'Друго 3-димензионално креативно дјело (скулптура итд.)'], 
         ['Non-free book cover', 'Корица књиге'], 
         ['Non-free album cover', 'Омот звучног записа (албум, сингл, пјесма, ЦД)'], 
         ['Non-free game cover', 'Омот видео/рачунарске игре'], 
         ['Non-free magazine cover', 'Насловна страна часописа'], 
         ['Non-free video cover', 'Омот видео-траке'], 
         ['Non-free software cover', 'Омот софтверског производа'], 
         ['Non-free product cover', 'Омот неког комерцијалног производа'], 
         ['Non-free title-card', 'Уводна шпица ТВ програма'], 
         ['Non-free movie poster', 'Филмски постер'], 
         ['Non-free poster', 'Званични постер догађаја'], 
         ['Non-free television screenshot', 'Снимак екрана ТВ програма'], 
         ['Non-free film screenshot', 'Снимак екрана филма'], 
         ['Non-free game screenshot', 'Снимак екрана игре'], 
         ['Non-free video screenshot', 'Снимак екрана видеа'], 
         ['Non-free music video screenshot', 'Снимак екрана музичког видеа'], 
         ['Non-free software screenshot', 'Снимак екрана софтвера'], 
         ['Non-free web screenshot', 'Снимак екрана веб-сајта'], 
         ['Non-free speech', 'Аудио-исјечак говора'], 
         ['Non-free audio sample', 'Звучни одломак аудио-снимка'], 
         ['Non-free video sample', 'Исјечак видеа'], 
         ['Non-free sheet music', 'Ноте које представљају музичко дјело'], 
         ['Non-free comic', 'Дио стрипа, графички роман, манга итд.'], 
         ['Non-free computer icon', 'Рачунарска икона'], 
         ['Non-free newspaper image', 'Страница новина'], 
         ['Non-free logo', 'Лого компаније, организације итд.'], 
         ['Non-free seal', 'Званични печат, грб итд.'], 
         ['Non-free symbol', 'Други званични симбол'], 
         ['Non-free sports uniform', 'Спортска униформа'], 
         ['Non-free stamp', 'Поштанска марка'] 
         ],
      'NFExtraLicense' :
         [
         ['', 'none'],
         ['Ауторска права Круне и други владини извори'],
         ['Non-free Crown copyright', 'Ауторско право Круне УК'],
         ['Non-free New Zealand Crown Copyright', 'Ауторско право Круне НЗ'],
         ['Non-free Canadian Crown Copyright', 'Ауторско право Круне Канаде'],
         ['Non-free AUSPIC', 'AUSPIC (Сликовна база података Аустралијског парламента)'],
         ['Non-free Philippines government', 'Филипинска влада'],
         ['Non-free Finnish Defence Forces', 'Финске одбрамбене снаге'],
         [],
         ['Остали појединачни извори'],
         ['Non-free Denver Public Library', 'Денверска јавна библиотека'],
         ['Non-free ESA media', 'ЕСА (Европска свемирска агенција)'],
         [],
         ['Могуће јавно власништво у другим земљама'],
         ['Non-free Old-50', 'Аутор умро прије више од 50 година'],
         ['Non-free Old-70', 'Аутор умро прије више од 70 година'],
         [],
         ['Неке дозволе дате, али није потпуно слободно'],
         ['Non-free promotional', 'Из промотивног прес-кита'],
         ['Non-free with NC', 'Дозвола дата, али само за образовне и/или некомерцијалне сврхе'],
         ['Non-free with ND', 'Дозвола дата, али прерађивање дјела није дозвољено'],
         ['Non-free with permission', 'Дозвола дата, али само за Википедију'],
         []
         ]
   };
   for (var group in licenseLists) {
      fuwMakeSelection(group, licenseLists[group]);
   }


   this.knownCommonsLicenses = {
      'self|GFDL|cc-by-sa-all|migration=redundant' : 1,
      'self|Cc-zero' : 1,
      'PD-self' : 1,
      'self|GFDL|cc-by-sa-4.0|migration=redundant' : 1,
      'self|GFDL|cc-by-4.0|migration=redundant' : 1,
      'self|GFDL|cc-by-sa-3.0|migration=redundant' : 1,
      'self|GFDL|cc-by-3.0|migration=redundant' : 1,
      'self|cc-by-sa-4.0' : 1,
      'self|cc-by-sa-3.0' : 1,
      'cc-by-sa-4.0' : 1,
      'cc-by-sa-3.0' : 1,
      'cc-by-sa-2.5' : 1,
      'cc-by-4.0' : 1,
      'cc-by-3.0' : 1,
      'cc-by-2.5' : 1,
      'FAL' : 1,
      'PD-old-100' : 1,
      'PD-old' : 1,
      'PD-Art' : 1,
      'PD-US' : 1,
      'PD-USGov' : 1,
      'PD-USGov-NASA' : 1,
      'PD-USGov-Military-Navy' : 1,
      'PD-ineligible' : 1,
      'attribution' : 1,
      'copyrighted free use' : 1
   };


   // textfields that don't react directly
   // to user input and are used only for assembling stuff:
   if (fuwTesting) {
      fuwMakeTextfield('SandboxSummary', function(){void(0);});
      fuwMakeTextarea('SandboxText', function(){void(0);});
      fuwGet('SandboxSummary').disabled="онемогућено";
      fuwGet('SandboxText').disabled="онемогућено";
      fuwGet('SandboxText').rows = 12;
   }

   // set links to "_blank" target, so we don't accidentally leave the page,
   // because on some browsers that would destroy all the input the user has already entered
   $('.fuwOutLink a').each(function() {
      this.target = '_blank';
   });

   // make main area visible
   fuwSetVisible('UploadScriptArea', true);

}
// ====================================== 
// end of fuwGlobal constructor function
// ======================================



function fuwRadioClick(e) {
   var ev = e || event;
   var src = ev.target || ev.srcElement;
   //alert('onclick event from ' + src + ' (' + src.value + ')');
   fuwUpdateOptions();
   return true;
}

/* 
* =============================================================
* function fuwUpdateOptions
* =============================================================
* This is the onchange event handler for most of the input
* elements in the main form. It changes visibility and disabled
* status for the various sections of the input form in response
* to which options are chosen.
*/
function fuwUpdateOptions() {

   var fuw = window.fuw;
   var warn = fuw.warn;
   var opts = fuw.opts = { };
   opts.InputFilename = $('#TargetForm input#file').val();

   var widgets = fuw.ScriptForm.elements;
   for (i = 0; i < widgets.length; i++) {
      var w = widgets[i];
      if (w.type == "radio") {
         var nm = w.name;
         var id = w.id;
         var vl = w.checked && !w.disabled && fuwIsVisible(w);
         opts[id] = vl;
         if (vl) opts[nm] = id;
      }
      else {
         var id = w.id;
         var active = !w.disabled && fuwIsVisible(w);
         if (active) {
            var value = ((type == 'checkbox') ? w.checked : w.value);
            opts[id] = value;         
         }
      }
   };
   opts.MainOption = opts.FreeOptions || opts.NonFreeOptions;
   
   // some parts of the input form are re-used across sections
   // and must be moved into the currently active input section:

   // minimality section is shared between all NF sections
   fuwMove('NFMinimalitySection', 'detailsNFSubject', (opts.OptionNFSubject)) ||
   fuwMove('NFMinimalitySection', 'detailsNF3D', (opts.OptionNF3D)) ||
   fuwMove('NFMinimalitySection', 'detailsNFExcerpt', (opts.OptionNFExcerpt)) ||
   fuwMove('NFMinimalitySection', 'detailsNFCover', (opts.OptionNFCover)) ||
   fuwMove('NFMinimalitySection', 'detailsNFLogo', (opts.OptionNFLogo)) ||
   fuwMove('NFMinimalitySection', 'detailsNFPortrait', (opts.OptionNFPortrait)) ||
   fuwMove('NFMinimalitySection', 'detailsNFMisc', true);

   // AnyOtherInfo section is shared between all
   fuwMove('AnyOtherInfo', 'detailsOwnWork', opts.OptionOwnWork) ||
   fuwMove('AnyOtherInfo', 'detailsThirdParty', opts.OptionThirdParty) ||
   fuwMove('AnyOtherInfo', 'detailsFreeWebsite', opts.OptionFreeWebsite) ||
   fuwMove('AnyOtherInfo', 'detailsPDOld', opts.OptionPDOld) ||
   fuwMove('AnyOtherInfo', 'detailsPDOther', opts.OptionPDOther) ||
   fuwMove('AnyOtherInfo', 'detailsNFSubject', opts.OptionNFSubject) ||
   fuwMove('AnyOtherInfo', 'detailsNF3D', opts.OptionNF3D) ||
   fuwMove('AnyOtherInfo', 'detailsNFExcerpt', opts.OptionNFExcerpt) ||
   fuwMove('AnyOtherInfo', 'detailsNFCover', opts.OptionNFCover) ||
   fuwMove('AnyOtherInfo', 'detailsNFLogo', opts.OptionNFLogo) ||
   fuwMove('AnyOtherInfo', 'detailsNFPortrait', opts.OptionNFPortrait) ||
   fuwMove('AnyOtherInfo', 'detailsNFMisc', opts.OptionNFMisc);

   // author input field is shared between all sections except "Own Work".
   // (will serve for the immediate/photographic author, in those cases where there
   // are two author fields)
   fuwMove('Author', 'placeholderFreeWebsiteAuthor', (opts.OptionFreeWebsite)) ||
   fuwMove('Author', 'placeholderPDOldAuthor', (opts.OptionPDOld)) ||
   fuwMove('Author', 'placeholderPDOtherAuthor', (opts.OptionPDOther)) ||
   fuwMove('Author', 'placeholderNFSubjectAuthor', (opts.OptionNFSubject)) ||
   fuwMove('Author', 'placeholderNF3DAuthor', (opts.OptionNF3D)) ||
   fuwMove('Author', 'placeholderNFExcerptAuthor', (opts.OptionNFExcerpt)) ||
   fuwMove('Author', 'placeholderNFCoverAuthor', (opts.OptionNFCover)) ||
   fuwMove('Author', 'placeholderNFPortraitAuthor', (opts.OptionNFPortrait)) ||
   fuwMove('Author', 'placeholderNFMiscAuthor', (opts.OptionNFMisc)) ||
   fuwMove('Author', 'placeholderAuthor', true);

   // source input field is shared between all sections except "Own Work".
   // (will serve for immediate/web source, in those cases where there are two
   // source fields involved)
   fuwMove('Source', 'placeholderFreeWebsiteSource', (opts.OptionFreeWebsite)) ||
   fuwMove('Source', 'placeholderPDOldSource', (opts.OptionPDOld)) ||
   fuwMove('Source', 'placeholderPDOtherSource', (opts.OptionPDOther)) ||
   fuwMove('Source', 'placeholderNFSubjectSource', (opts.OptionNFSubject)) ||
   fuwMove('Source', 'placeholderNF3DSource', (opts.OptionNF3D)) ||
   fuwMove('Source', 'placeholderNFExcerptSource', (opts.OptionNFExcerpt)) ||
   fuwMove('Source', 'placeholderNFCoverSource', (opts.OptionNFCover)) ||
   fuwMove('Source', 'placeholderNFLogoSource', (opts.OptionNFLogo)) ||
   fuwMove('Source', 'placeholderNFPortraitSource', (opts.OptionNFPortrait)) ||
   fuwMove('Source', 'placeholderNFMiscSource', (opts.OptionNFMisc)) ||
   fuwMove('Source', 'placeholderSource', true);

   // date input field is shared between all sections except "Logo", which doesn't need it.
   // will serve for derived/photographic date in the case of 3D items
   fuwMove('Date', 'placeholderFreeWebsiteDate', (opts.OptionFreeWebsite)) ||
   fuwMove('Date', 'placeholderThirdPartyDate', (opts.OptionThirdParty)) ||
   fuwMove('Date', 'placeholderPDOldDate', (opts.OptionPDOld)) ||
   fuwMove('Date', 'placeholderPDOtherDate', (opts.OptionPDOther)) ||
   fuwMove('Date', 'placeholderNFSubjectDate', (opts.OptionNFSubject)) ||
   fuwMove('Date', 'placeholderNF3DDate', (opts.OptionNF3D)) ||
   fuwMove('Date', 'placeholderNFExcerptDate', (opts.OptionNFExcerpt)) ||
   fuwMove('Date', 'placeholderNFCoverDate', (opts.OptionNFCover)) ||
   fuwMove('Date', 'placeholderNFPortraitDate', (opts.OptionNFPortrait)) ||
   fuwMove('Date', 'placeholderNFMiscDate', (opts.OptionNFMisc)) ||
   fuwMove('Date', 'placeholderDate', true);
   
   // permission field is shared between ThirdParty and FreeWebsite sections
   fuwMove('Permission', 'placeholderFreeWebsitePermission', (opts.OptionFreeWebsite)) ||
   fuwMove('Permission', 'placeholderPermission', true);

   // publication field is shared between PDOld, NFPortrait and NFMisc
   fuwMove('Publication', 'placeholderNFPortraitPublication', (opts.OptionNFPortrait)) ||
   fuwMove('Publication', 'placeholderNFMiscPublication', (opts.OptionNFMisc)) ||
   fuwMove('Publication', 'placeholderPublication', true);

   // Purpose, Commercial, Replaceable and ReplaceableText FUR fields are shared
   // between some but not all of the non-free sections
   fuwMove('NFPurpose', 'placeholderNFExcerptPurpose', (opts.OptionNFExcerpt)) ||
   fuwMove('NFPurpose', 'placeholderNFPurpose');
   fuwMove('NFCommercial', 'placeholderNFPortraitCommercial', (opts.OptionNFPortrait)) ||
   fuwMove('NFCommercial', 'placeholderNFCommercial');
   fuwMove('NFReplaceable', 'placeholderNFPortraitReplaceable', (opts.OptionNFPortrait)) ||
   fuwMove('NFReplaceable', 'placeholderNFReplaceable');
   fuwMove('NFReplaceableText', 'placeholderNFExcerptReplaceable', (opts.OptionNFExcerpt)) ||
   fuwMove('NFReplaceableText', 'placeholderNFReplaceableText', true);

   // submit button goes to Step1 if user has chosen a plain overwrite of an existing file,
   // and to the active section of Step3 if otherwise
   fuwMove('fuwSubmit', 'UploadScriptStep1', (warn.ImageExists && opts.OverwriteSame)) ||
   fuwMove('fuwSubmit', 'detailsOwnWork', opts.OptionOwnWork) ||
   fuwMove('fuwSubmit', 'detailsThirdParty', opts.OptionThirdParty) ||
   fuwMove('fuwSubmit', 'detailsFreeWebsite', opts.OptionFreeWebsite) ||
   fuwMove('fuwSubmit', 'detailsPDOld', opts.OptionPDOld) ||
   fuwMove('fuwSubmit', 'detailsPDOther', opts.OptionPDOther) ||
   fuwMove('fuwSubmit', 'detailsNFSubject', opts.OptionNFSubject) ||
   fuwMove('fuwSubmit', 'detailsNF3D', opts.OptionNF3D) ||
   fuwMove('fuwSubmit', 'detailsNFExcerpt', opts.OptionNFExcerpt) ||
   fuwMove('fuwSubmit', 'detailsNFCover', opts.OptionNFCover) ||
   fuwMove('fuwSubmit', 'detailsNFLogo', opts.OptionNFLogo) ||
   fuwMove('fuwSubmit', 'detailsNFPortrait', opts.OptionNFPortrait) ||
   fuwMove('fuwSubmit', 'fuwSubmitHost', true);


   // Show and hide warnings:

   // filename-related warnings:
   fuwSetVisible('warningIllegalChars', warn.IllegalChars);
   fuwSetVisible('warningBadFilename',  warn.BadFilename);
   fuwSetVisible('warningImageOnCommons', warn.ImageOnCommons);
   fuwSetVisible('warningImageExists', warn.ImageExists);
   fuwMove('warningImageThumb', 'warningImageOnCommons', warn.ImageOnCommons, true) ||
   fuwMove('warningImageThumb', 'warningImageExists', true, true);


   // notices related to the top-level options:
   fuwSetVisible('warningWhyNotCommons', opts.OptionFree);
   fuwSetVisible('warningNF', opts.OptionNonFree);
   fuwSetVisible('warningNoGood', opts.OptionNoGood);

   // warnings related to non-free "used in" article
   fuwSetVisible('warningNFArticleNotFound', warn.NFArticleNotFound);
   fuwSetVisible('warningNFArticleNotMainspace', warn.NFArticleNotMainspace);
   fuwSetVisible('warningUserspaceDraft', warn.UserspaceDraft);
   fuwSetVisible('warningNFArticleDab', warn.NFArticleDab);
   fuwSetVisible('NFArticleOK', warn.NFArticleOK);

   // warnings depending on user status:
   if (fuw.userStatus.match(/problem|newbie|notAutoconfirmed/)) {
      fuwSetVisible('warningFreeWebsite', opts.OptionFreeWebsite);
      fuwSetVisible('warningOwnWork', opts.OptionOwnWork);
      fuwSetVisible('warningPDOther', opts.OptionPDOther);
      fuwSetVisible('warningNFSubject', opts.OptionNFSubject);
   }

   // hide main sections in case of intended plain overwrite:   
   fuwSetVisible('UploadScriptStep2', !(warn.ImageExists && opts.OverwriteSame));
   fuwSetVisible('UploadScriptStep3', !(warn.ImageExists && opts.OverwriteSame));

   // show/hide top-level options
   fuwSetVisible('detailsFreeStatus', opts.OptionFree);
   fuwSetVisible('sendToCommons', opts.OptionFree);

   // show/hide details sections
   fuwSetVisible('detailsNFArticle', opts.OptionNonFree);
   fuwSetVisible('detailsNFWorkType', opts.OptionNonFree);
   fuwSetVisible('detailsOwnWork', opts.OptionOwnWork);
   fuwSetVisible('detailsThirdParty', opts.OptionThirdParty);
   fuwSetVisible('detailsFreeWebsite', opts.OptionFreeWebsite);
   fuwSetVisible('detailsPDOld', opts.OptionPDOld);
   fuwSetVisible('detailsPDOther', opts.OptionPDOther);
   fuwSetVisible('detailsNFSubject', opts.OptionNFSubject);
   fuwSetVisible('detailsNF3D', opts.OptionNF3D);
   fuwSetVisible('detailsNFExcerpt', opts.OptionNFExcerpt);
   fuwSetVisible('detailsNFCover', opts.OptionNFCover);
   fuwSetVisible('detailsNFLogo', opts.OptionNFLogo);
   fuwSetVisible('detailsNFPortrait', opts.OptionNFPortrait);
   fuwSetVisible('detailsNFMisc', opts.OptionNFMisc);

   fuwSetVisible('EditSummaryDiv', opts.OverwriteSame || opts.OverwriteDifferent);

   // set enabled/disabled
   // It might be useful to adapt this to be more liberal about
   // the order of input, at least for experienced users.

   //fuwSetEnabled('Artist3D', opts.PD3D);
   //fuwSetEnabled('Country3D', opts.FOP3D);
   fuwSetEnabled('ThirdPartyEvidenceLink', opts.ThirdPartyEvidenceOptionLink);
   fuwSetEnabled('ThirdPartyOTRSTicket', opts.ThirdPartyEvidenceOptionOTRS);
   fuwSetEnabled('NFSubjectPurpose', opts.NFSubjectCheckDiscussed);
   fuwSetEnabled('NF3DPurpose', opts.NF3DCheckDiscussed);
   fuwSetEnabled('NF3DPermission', opts.NF3DOptionFree);
   fuwSetEnabled('USGovLicense', opts.PDOtherUSGov);
   fuwSetEnabled('PDOfficialPermission', opts.PDOtherOfficial);
   fuwSetEnabled('IneligibleLicense', opts.PDOtherSimple);
   fuwSetEnabled('PDOtherPermission', opts.PDOtherOther);
   fuwSetEnabled('AnyOther', true);

   // need to re-collect the remaining (non-radiobutton) input into the opts object again,
   // preparing for validation:
   for (i = 0; i < widgets.length; i++) {
      var w = widgets[i];
      var type = w.type;

      if (type != "radio") {
         var id = w.id;
         var active = !w.disabled && fuwIsVisible(w);
         if (active) {
            var value = ((type == 'checkbox') ? w.checked : w.value);
            opts[id] = value;         
         }
      }
   };

   // final step of validation: check if input is sufficient for
   // setting the submit buttons active
   var valid = fuw.validateInput();
   var validForCommons = valid && opts.OptionFree && !(opts.OverwriteSame || opts.OverwriteDifferent)
         && !opts.ThirdPartyEvidenceOptionNone;
   fuwSetVisible('sendToCommons', opts.OptionFree);
   fuwSetEnabled('CommonsButton', validForCommons);
   fuwGet('fuwSubmitText').innerHTML = opts.OptionFree ? 
         ("<b>Не</b>, желим да ову датотеку отпремим овдје, само на ову Википедију.<br/>" + 
          "<small>Овако ће се датотека моћи користити само на Википедији на српском језику. Међутим, неко " +
          "други би могао да је копира на Оставу и потом је користи негдје друго. Ако Ви " +
          "не желите да се ова датотека копира на Оставу а потом обрише овдје, додајте " +
          "{{tl|keep local}}.</small>") :
         "Отпреми ову датотеку.";
   fuwGet('SubmitButton').value = validForCommons ? "Отпреми локално" : "Отпреми";   
   fuwSetEnabled('EditSummary', true);
   fuwSetEnabled('SubmitButton', valid && (fuw.userStatus != 'notAutoconfirmed'));
   if (fuwTesting) {
      fuwSetEnabled('SandboxButton', valid);
   }

   // if we're in testing mode, update the Sandbox display fields
   // after each input change. In normal mode, collectInput() will
   // only be needed on submit.
   if (fuwTesting) {
      fuw.collectInput();
      fuw.formatOutput(false);
      fuwSetVisible('placeholderTestForm', true);
   }  
}

// ============================================================
// methods of the global fuw object
// ============================================================

// ============================================================
// report validation status of filename information
// ============================================================
// This is called from within fuw.validateInput(), i.e. every
// time anything in the whole form is changed. It only reports
// results that have previously been cached in the opts and warn
// objects. The actual checking is done in the event handler
// of the file input boxes.
fuwGlobal.prototype.hasValidFilename = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid =   
      opts.InputName &&
      opts.InputFilename &&
      !warn.BadFilename &&
      !warn.ImageOnCommons &&
      // if image exists on enwiki, accept only if user has confirmed overwrite:
      !(warn.ImageExists && !(opts.OverwriteSame || opts.OverwriteDifferent));
   //alert("HasValidFilename: " + valid);
   return valid;
};

// ============================================================
// validation status for common input elements for all free
// options
// ============================================================
fuwGlobal.prototype.hasValidCommonFreeInput = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid = opts.InputDesc;
   //alert("HasValidCommonFreeInput: " + valid);
   return valid;
};
// ============================================================
// validation status for common input elements for all non-free
// options
// ============================================================
fuwGlobal.prototype.hasValidCommonNFInput = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid =
      opts.OptionNonFree &&
      opts.InputDesc && 
      opts.NFArticle &&
      opts.Source &&
      opts.NFMinimality &&
      !warn.NFArticleNotFound &&
      !warn.NFArticleNotMainspace &&
      !warn.NFArticleDab;
   //alert("hasValidCommonNFInput: " + valid);
   return valid;
};
// ============================================================
// Main validation routine. Modify this to tweak which fields
// are to be considered obligatory for each case group
// ============================================================
fuwGlobal.prototype.validateInput = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid = (
      this.hasValidFilename()
      &&
      (! (opts.OverwriteDifferent && ! opts.EditSummary))
      &&
      (
       ( // overwriting is okay if there is an edit summary
        opts.OverwriteSame && opts.EditSummary
       )
       ||
       ( // free options
         this.hasValidCommonFreeInput() &&
         (
          (opts.OptionOwnWork &&
           opts.Date &&
           opts.OwnWorkLicense)
          ||
          (opts.OptionThirdParty &&
           opts.Author &&
           opts.Source &&
           opts.Permission &&
           (opts.ThirdPartyOtherLicense || opts.ThirdPartyLicense) &&
           ((opts.ThirdPartyEvidenceOptionLink && opts.ThirdPartyEvidenceLink) ||
            opts.ThirdPartyEvidenceOptionOTRS ||
            opts.ThirdPartyEvidenceOptionOTRSForthcoming ||
            opts.ThirdPartyEvidenceOptionNone))
          ||
          (opts.OptionFreeWebsite &&
           opts.Author &&
           opts.Source &&
           (opts.FreeWebsiteOtherLicense || opts.FreeWebsiteLicense) &&
           opts.Permission)
          ||
          (opts.OptionPDOld &&
           opts.Author &&
           opts.PDOldAuthorLifetime &&
           opts.Publication &&
           opts.Date &&
           opts.Source &&
           opts.PDOldOptions && 
           (! (opts.PDOldOther && ! opts.PDOldPermission)))
          ||
          (opts.OptionPDOther &&
           opts.Author &&
           opts.Source &&
           ((opts.PDOtherUSGov && opts.USGovLicense) ||
            (opts.PDOtherOfficial && opts.PDOfficialPermission) ||
            (opts.PDOtherSimple && opts.IneligibleLicense) ||
            (opts.PDOtherOther && opts.PDOtherPermission)))
        )
       ) // end of free options
       ||
       ( // non-free options
         this.hasValidCommonNFInput() &&
         (
          (opts.OptionNFSubject &&
           opts.NFSubjectLicense &&
           opts.Author &&
           (opts.NFSubjectCheckDedicated ||
           (opts.NFSubjectCheckDiscussed && opts.NFSubjectPurpose)))
          ||
          (opts.OptionNF3D &&
           opts.NF3DLicense &&
           opts.NF3DCreator &&
           opts.Author &&
           (opts.NF3DOptionSame ||
           (opts.NF3DOptionFree || opts.NF3DPermission)) && 
           (opts.NF3DCheckDedicated ||
            (opts.NF3DCheckDiscussed && opts.NF3DPurpose)))
          ||
          (opts.OptionNFExcerpt &&
           opts.NFExcerptLicense &&
           opts.Author &&
           opts.NFPurpose)
          ||
          (opts.OptionNFCover &&
           opts.NFCoverLicense &&
           opts.Author &&
           opts.NFCoverCheckDedicated 
          )
          ||
          (opts.OptionNFLogo &&
           opts.NFLogoLicense &&
           opts.NFLogoCheckDedicated
          )
          ||
          (opts.OptionNFPortrait &&
           opts.Publication &&
           opts.NFPortraitDeceased &&
           opts.Author &&
           opts.NFPortraitCheckDedicated &&
           opts.NFReplaceable &&
           opts.NFCommercial)
          ||
          (opts.OptionNFMisc &&
           opts.NFMiscLicense &&
           opts.Author &&
           opts.Publication &&
           opts.NFPurpose &&
           opts.NFReplaceableText &&
           opts.NFReplaceable &&
           opts.NFCommercial)
         )
       ) // end of non-free options
      )
   );
   return valid;
};

// =============================================================
// return which template name will be used as the main
// description template
// =============================================================
fuwGlobal.prototype.getDescriptionTemplateName = function() {
   // standard "Information" template for free files:
   if (this.opts.OptionFree) return "Information";
   // experimental new version of fair-use rationale template,
   // designed to fit the fields used in the wizard
   else if (this.opts.OptionNonFree) return "Non-free use rationale 2";
   return undefined;
};

// =============================================================
// get the license tag code from the appropriate input element
// =============================================================

fuwGlobal.prototype.getStandardLicense = function() {
   var opts = this.opts;
   
}

fuwGlobal.prototype.getLicense = function() {
   var opts = this.opts;
      // ThirdParty and FreeWebsite have alternative input fields
      // for manual entry of other licenses:
   var license = {};
   if (opts.PDOtherOther || opts.PDOldOther) {
      license.special = opts.PDOtherOther ? opts.PDOtherPermission : opts.PDOldPermission;
      if (! (license.special.match(/^\s*\{\{.+\}\}\s*$/))) {
         license.special = '{{PD-because|' + license.special + '}}';
      }
   }
   else {
      license.special = 
         opts.ThirdPartyOtherLicense || 
         opts.FreeWebsiteOtherLicense ||
         (opts.PDOtherOfficial ? ('{{PD-because|званично дјело правно изузето од ауторских права у земљи свог поријекла}}') : null) ||
         (opts.OptionNFPortrait ? ('{{non-free biog-pic|' + opts.NFArticle + '}}') : null);
   }   
   if (! license.special) {
      // standard, non-parametrized tag licenses from dropdownbox.
      var simpleLicense = (opts.OptionOwnWork ? opts.OwnWorkLicense : null) ||
          (opts.OptionThirdParty ? opts.ThirdPartyLicense : null) ||
          (opts.OptionFreeWebsite ? opts.FreeWebsiteLicense : null) ||
          (opts.OptionNFSubject ? opts.NFSubjectLicense : null) ||
          (opts.OptionNF3D ? opts.NF3DLicense : null) ||
          (opts.OptionNFExcerpt ? opts.NFExcerptLicense : null) ||
          (opts.OptionNFCover ? opts.NFCoverLicense : null) ||
          (opts.OptionNFLogo ? opts.NFLogoLicense : null) ||
          (opts.OptionNFMisc ? opts.NFMiscLicense : null) ||
          (opts.PDOtherUSGov ? opts.USGovLicense : null) ||
          (opts.PDOtherSimple ? opts.IneligibleLicense : null) ||
          (opts.PDUS1923 ? 'PD-US-1923' : null) ||
          (opts.PDURAA   ? 'PD-URAA' : null) ||
          (opts.PDFormality ? 'PD-US' : null);

       // "PD-author" needs parameter, at least on Commons
       if (simpleLicense == 'PD-author') {
          license.special = '{{PD-author|' + opts.Author + '}}';
       }
       else if (this.knownCommonsLicenses[simpleLicense]) {
       // make sure we send only those licenses as "standard" licenses
       // that exist in the Commons license dropdown box
          license.standard = simpleLicense;
       }
       else {
          license.special = '\{\{' + simpleLicense + '\}\}';
       }
   }
   return license;
};

function fuwSubst(template) {
   return '{{subst:' + template + '}}';
}

// ===================================================================
// Produce code for local tracking categories
// ===================================================================
fuwGlobal.prototype.getTrackingCategory = function() {
   var opts = this.opts;
   var cat = "";
   if (opts.OptionFreeWebsite) { cat = "Датотеке из слободно лиценцираних спољашњих извора"; }
   else if (opts.OptionThirdParty) { cat = "Датотеке лиценциране од стране трећих лица"; }
   else if (opts.PDOtherOther || opts.PDOldOther) { cat = "Датотеке са нестандардним изјавама јавног власништва"; }
   else if (opts.OptionNFSubject || opts.OptionNF3D) { cat = "Неслободне датотеке отпремљене за сврху коментара"; }
   if (cat) {
      cat = "\n\{\{category ordered by date|" + cat + "|" + 
      fuwSubst("CURRENTYEAR") + "|" + fuwSubst("CURRENTMONTH") + "|" + fuwSubst("CURRENTDAY2") + "\}\}";
   }
   return cat;
};

// ===================================================================
// Get or create an edit summary for the upload
// ===================================================================
// Note: if we work with the api.php interface, we can have separate
// data for the edit summary and the description page, which is far
// better than the way the index.php interface does it.
// TO DO: need to actually define an input element for a manually
// entered edit summary. Must be obligatory when overwriting files.
// In other cases we'll use an automatic edit summary.
// ===================================================================
fuwGlobal.prototype.getEditSummary = function() {
   var opts = this.opts;
   return (
      (opts.EditSummary ? (opts.EditSummary + ' ([[' + mw.config.get('wgPageName') + '|Чаробњак за отпремање]])') : null)||
      ("отпремање " +
       (
        (opts.OptionOwnWork ? 'личне датотеке ' : false) ||
        (opts.OptionThirdParty ? 'слободне датотеке некога другог ' : false) ||
        (opts.OptionFreeWebsite ? 'датотеке из слободно објављеног извора ' : false) ||
        (opts.OptionPDOld       ? 'старог дјела у јавном власништву ' : false) ||
        (opts.OptionPDOther     ? 'дјела у јавном власништву ' : false) ||
        (opts.OptionNFSubject   ? 'неслободног дјела као предмета расправе ' : false) ||
        (opts.OptionNF3D        ? 'депикције неслободног 3Д дјела ' : false) ||
        (opts.OptionNFExcerpt   ? 'исјечка неслободног дјела ' : false) ||
        (opts.OptionNFCover     ? 'неслободног омота ' : false) ||
        (opts.OptionNFLogo      ? 'неслободног логоа ' : false) ||
        (opts.OptionNFPortrait    ? 'неслободног историјског портрета ' : false) ||
        (opts.OptionNFMisc      ? 'неслободне датотеке ' : "")
       )
       + 
       ("путем [[" + mw.config.get('wgPageName') + "|Чаробњака за отпремање]]")
      ));
};


function fuwPackInfo(text, forCommons) {
   if (forCommons) {
      // reformat wikilinks embedded in description fields to adapt them for Commons
      text = text.replace(/\[\[([^\]]+)\]\]/g, 
         function(str, p1, offset, s) {

            // mark File links as local
            if (p1.match(/^:(File|Image|Датотека|Слика|Datoteka|Slika):/)) {
               return "[[:sr" + p1 + "]]";
            }      
            // leave prefixed links unchanged:
            else if (p1.match(/^:[\w\-]+:/)) {
               return str;
            }
            // if the link is piped, add a prefix only
            else if (p1.match(/.+\|/)) {
               return "[[:sr:" + p1 + "]]";
            }
            // introduce a pipe
            else {
               return "[[:sr:" + p1 + "|" + p1 + "]]";
            }
         }
      );
      return "{{sr|" + text + "}}";
   } else return text;
}

// ================================================================
// This is the main method called by the event handler for the 
// (experimental) submit button. Its main task is to collect the 
// input into a single string of wikitext for the description page.
// ================================================================
fuwGlobal.prototype.collectInput = function() {
   var opts = this.opts;

   // object representing template fields for filling in
   // the description template. Pre-loaded with some
   // standard settings:
   var descFields = this.descFields = { 
      'Description' : opts.InputDesc,
      'Author'      : opts.Author,
      'Date'        : opts.Date,
      'Source'      : opts.Source
   };
   // "other information" (outside the template)
   this.otherInfo = null;
   
   if (opts.OptionNonFree) {
      descFields.Article = opts.NFArticle;
   }
   
   // add/modify option-specific fields:
   switch (opts.MainOption) {
      case 'OptionOwnWork':
      
         // use standard "source" field for optional "how created?" and 
         // "previously published" input fields.
         descFields.Source = fuwAppendLines([
            (opts.OwnWorkCreation || "{{own}}"), 
            "<br/>\n", 
            fuwSurroundString("'''Претходно објављено:''' ", opts.OwnWorkPublication)]);
         var username = mw.user.getName();
         descFields.Author = '[[User:' + username + '|' + username + ']]';
         break;

      case 'OptionThirdParty':
      
         // use standard "permission" field for a compilation of the
         // "permission" input field and the various "evidence" options
         var evidence = (
            opts.ThirdPartyEvidenceOptionLink ? 
               ("Изјава о лиценци може се пронаћи онлајн на: " + opts.ThirdPartyEvidenceLink) :
               (opts.ThirdPartyEvidenceOptionOTRS ? 
               ("Споразум о лиценци прослијеђен је на [[Википедија:OTRS|OTRS]]." + 
                  fuwSurroundString(" Тикет: ", opts.ThirdPartyOTRSTicket) + "\{\{OTRS pending|year=" + fuwSubst("CURRENTYEAR") + 
                                                                              "|month=" + fuwSubst("CURRENTMONTH") + 
                                                                              "|day=" + fuwSubst("CURRENTDAY2") + "\}\}") :
               (opts.ThirdPartyEvidenceOptionOTRSForthcoming ? 
               "Споразум о лиценци биће ускоро прослијеђен на [[Википедија:OTRS|OTRS]]. \{\{OTRS pending|year=" + fuwSubst("CURRENTYEAR") + 
                                                                              "|month=" + fuwSubst("CURRENTMONTH") + 
                                                                              "|day=" + fuwSubst("CURRENTDAY2") + "\}\}" :
               (opts.ThirdPartyEvidenceOptionNone ?
               "Биће обезбијеђено на захтјев." : null))));
         descFields.Permission = fuwAppendLines([
            opts.ThirdPartyPermission,
            "<br/>\n",
            fuwSurroundString("'''Доказ:''' ", evidence)]);
         break;
         
      case 'OptionFreeWebsite':
         descFields.Permission = opts.Permission;
         break;
         
      case 'OptionPDOld':
         // add "lifetime" input to "author" field
         descFields.Author = fuwAppendLines([
            opts.Author,
            "<br/>\n",
            fuwSurroundString("(Животни вијек: ", opts.PDOldAuthorLifetime, ")")
         ]);
         
         // combine original and direct source into standard "source" field: 
         descFields.Source = fuwAppendLines([
            fuwSurroundString("'''Оригинално објављивање''': ", opts.Publication),
            "<br/>\n",
            fuwSurroundString("'''Непосредни извор''': ", opts.Source)
         ]);
         
         // no standard tag available for "lack-of-registration" PD-US. Need
         // to put this into the "permission" field
         if (opts.PDFormality) 
            descFields.Permission = 
               "Ауторска права су истекла јер је дјело објављено без напомене " +
               "о истима и/или без неопходне регистрације истих.";
      
         // add optional "explanation" input to "permission" field
         if (opts.PDOldPermission) {
            descFields.Permission = fuwAppendLines([
               descFields.Permission,
               "\n\n",
               opts.PDOldPermission
            ]);
         }
         break;
         
      case 'OptionPDOther':
         // Need "permission" field in case of "official item" option
         if (opts.PDOtherOfficial) 
            descFields.Permission = opts.PDOfficialPermission;
         break; 

      case 'OptionNFSubject':
         // most FUR elements can be automatically provided:
         descFields.Purpose = (
            opts.NFSubjectCheckDedicated ? 
             ("За визуелну идентификацију објекта чланка. " +
              "Чланак у цјелини посвећен је баш расправи о овом дјелу.") :
            (opts.NFSubjectCheckDiscussed ?
             ("Да се подржи енциклопедијска расправа о овом дјелу у чланку у питању. " +
              "Илустрација је неопходна да подржи сљедећи специфични навод: " +
              "<br/>\n" + opts.NFSubjectPurpose) : null)
         );
         // I hate FURs filled with trivial/predictable/redundant verbiage,
         // so we'll just cut it short. And don't anybody dare complain that
         // that's not a valid FUR.
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;

      case 'OptionNF3D':
         // complex case: we need to assemble attribution and FUR both for the 
         // original 3D work and for the photographic depiction. Both might be 
         // non-free.
         descFields.Author = fuwAppendLines([
            fuwSurroundString("'''Оригинално дјело:''' ", opts.NF3DCreator),
            "<br/>\n",
            fuwSurroundString("'''Депикција:''' ", opts.Author)
         ]);
         descFields.Date = fuwAppendLines([
            fuwSurroundString("'''Оригинално дјело:''' ", opts.NF3DOrigDate),
            "<br/>\n",
            fuwSurroundString("'''Депикција:''' ", opts.Date)
         ]);
         descFields.Purpose = (
            opts.NF3DCheckDedicated ? 
             ("За визуелну идентификацију објекта чланка. " +
              "Чланак у цјелини посвећен је баш расправи о овом дјелу.") :
            (opts.NF3DCheckDiscussed ? 
             ("Да се подржи енциклопедијска расправа о овом дјелу у чланку у питању. " +
              "Илустрација је неопходна да подржи сљедећи специфични навод: " +
              "<br/>\n" + opts.NF3DPurpose) : null)
         );
         descFields.Replaceability = "Н/Д";
         descFields.Commercial    = "Н/Д";
         descFields["Other information"] = (
            opts.NF3DOptionSame ?
            ("Слику је направио и објавио исти аутор који посједује " +
             "ауторска права за оригинално дјело (објекат) и није " +
             "могуће сврсисходно створити алтернативни приказ.") :
            ("Аутор слике објавио је фотографско дјело под " +
             "слободном лиценцом, или је иста у јавном власништву: " + opts.NF3DPermission)
         );
         break; 
         
      case 'OptionNFExcerpt':
         // FURs for screenshots etc. don't normally need to bother
         // about replaceability (with free images) and with commercial role,
         // but do need to bother about purpose and about replaceability with text.
         descFields.Purpose        = opts.NFPurpose;
         descFields.Replaceability_text = opts.NFReplaceableText;
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;
         
      case 'OptionNFCover':
         // cover art gets standard rationales.
         descFields.Purpose = 
            "да служи као примарно средство визуелне идентификације " +
            "при врху чланка посвећеног дјелу у питању.";
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;
 
      case 'OptionNFLogo':
         // logos get standard rationales.
         descFields.Purpose = 
            "да служи као примарно средство визуелне идентификације " +
            "при врху чланка посвећеног ентитету у питању.";
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;

      case 'OptionNFPortrait':
         // as with other historic photographs, it is useful to have both
         // original publication and direct source
         descFields.Source = fuwAppendLines([
            fuwSurroundString("'''Оригинално објављивање''': ", opts.Publication),
            "<br/>\n",
            fuwSurroundString("'''Непосредни извор''': ", opts.Source)
         ]);   
         descFields.Purpose = 
            "за визуелну идентификацију особе у питању, " +
            "при врху његовог/њеног биографског чланка";
         descFields.Replaceability = opts.NFReplaceable;
         descFields.Commercial = opts.NFCommercial;
         descFields['Other information'] = 
            "Субјекат на фотографији је покојник/ца од: " + opts.NFPortraitDeceased;
         break;
         
      case 'OptionNFMisc':
         descFields.Source = fuwAppendLines([
            fuwSurroundString(
               "'''Оригинално објављивање''': ", 
               opts.Publication,
               "<br/>\n'''Непосредни извор:''' "),
            "",
            opts.Source
         ]);   
         descFields.Purpose = opts.NFPurpose;
         descFields.Replaceability = opts.NFReplaceable;
         descFields.Replaceability_text = opts.NFReplaceable_text;
         descFields.Commercial = opts.NFCommercial; 
         break;     
   };

   if (opts.OptionNonFree) {
      // common stuff for all non-free files:
      
      // Minimality field (same for all NF options):
      descFields.Minimality = opts.NFMinimality;
      
      // append optional "extra license" selector and "AnyOther" fields
      // to "Other information" field:
      descFields['Other information'] = fuwAppendLines([
         descFields['Other information'],
         "<br/>\n",
         fuwSurroundString('\{\{', opts.NFExtraLicense, '\}\}'),
         "<br/>\n",
         opts.AnyOther
      ]);
   }
   else {
      // common stuff for all free files:
      descFields.Other_versions = ''
      this.otherInfo = fuwAppendLines([this.otherInfo, "\n\n", opts.AnyOther]);
   
   }

};

fuwGlobal.prototype.formatOutput = function(forCommons) {
   var baseForm = this.ScriptForm;
   var targetForm = this.TargetForm;
   if (fuwTesting) {
      var testForm   = this.TestForm;
   }
   var opts = this.opts;
   var otherInfo = this.otherInfo;
   var descFields = this.descFields;

   var summary = "{{" + this.getDescriptionTemplateName();

   // assemble all fields into the wikitext of the description page:
   var fieldOrder = [
      'Source', 'Date', 'Author', 'Permission', 'Other_versions',
      'Article', 'Purpose', 'Replaceability', 'Replaceability_text', 
      'Minimality', 'Commercial', 'Other information'
   ];
   summary += "\n|Description = " + fuwPackInfo(descFields['Description'], forCommons);
   for (var i = 0; i < fieldOrder.length; i++) {
      if (descFields[fieldOrder[i]]) {
         summary += "\n|" + fieldOrder[i] + " = " + descFields[fieldOrder[i]];
      }
   }
   summary += "\n}}\n";
   if (otherInfo) {
      summary += "\n;Other information:\n" + fuwPackInfo(otherInfo, forCommons) + "\n";
   }

   var editSummary = this.getEditSummary();
   
   var license = this.getLicense();
   
   if (forCommons) {
      // pack our description info into an url pointing to the 
      // standard Commons Special:Upload
      // with pre-loaded description fields

      summary = fuwSubst("Ознаку отпремања је додао ЧО sr.wp") + "\n" + summary;
      summary = summary.replace(/\{\{OTRS pending\}\}/g, fuwSubst("OP"));

      if (license.special) {
         // manually format the whole description page including the license tag, if it
         // isn't one of the bare standard licenses in the dropdown box. Otherwise,
         // submit description summary and license as two separate url parameters.
         summary = summary + "\n\n" + license.special;
      }
      return (fuwGetCommonsURL() +
         "?title=Special:Upload" +
         "&wpUploadDescription=" +
         encodeURIComponent(summary) +
         (license.standard ? 
          ("&wpLicense=" + encodeURIComponent(license.standard)) : '') +
         "&wpDestFile=" + 
         encodeURIComponent(opts.InputName));
   }
   else {
      // pack all description into a single "text" parameter to be submitted
      // to the local api.php upload.
      summary = "==Опис==\n" + 
         summary + 
         "\n==Лиценцирање==\n" + 
         (license.standard ? ("\{\{" + license.standard + "\}\}") : license.special) +
         this.getTrackingCategory();
         
      if (fuwTesting) {
         // Testing mode: show our data in the dummy form
         // at the bottom of the page.
         fuwGet('placeholderSandboxFilename').innerHTML = opts.InputName;
         this.TestForm.SandboxSummary.value = editSummary;
         this.TestForm.SandboxText.value = summary;
         fuwSetVisible('placeholderTestForm', true);
      }
      // write output parameters into target form
      // I can't believe IE7 is too stupid to simply understand "this.TargetForm.filename.value".
      ($('#TargetForm [name="filename"]')[0]).value = opts.InputName;
      ($('#TargetForm [name="text"]'    )[0]).value = summary;
      ($('#TargetForm [name="comment"]' )[0]).value = editSummary;
      ($('#TargetForm [name="token"]'   )[0]).value = mw.user.tokens.get('editToken');

   }
   
};

function fuwHasUserGroup(group) {
   // workaround because old IE versions don't have array.indexOf :-(
   for (i = 0; i < mw.config.get('wgUserGroups').length; i++) {
      if (mw.config.get('wgUserGroups')[i] == group) {
         return true;
      }
   }
   return false
}

fuwGlobal.prototype.getUserStatus = function() {
   // function to determine the experience status and userrights of the current user:
   // 'anon': not logged in; can't use script.
   // 'notAutoconfirmed': can't use local upload, but may use script to prepare upload for Commons
   // 'newbie': autoconfirmed but editcount < 100 
   //    (may be used in future to adapt instructions more to newbie needs)
   // 'problem': autoconfirmed but has 3 or more image-related warnings or deletion notifications among recent user talk entries
   //    (may be used in future to produce more strongly worded instructions)
   // 'autoconfirmed': regular user
   // 'sysop'

   if (mw.config.get('wgUserName')) {
      if (fuwHasUserGroup('sysop')) {
         this.userStatus = 'sysop';
      }
      else if (fuwHasUserGroup('autoconfirmed') || fuwHasUserGroup('confirmed')) {
         this.userStatus = 'autoconfirmed';
         $.ajax({
            url     : mw.util.wikiScript( 'api' ),
            type    : 'GET',
            dataType: 'xml',
            traditional : true,
            data:   {
                     format: 'xml',
                     action: 'query',
                     meta  : 'userinfo',
                     uiprop: 'editcount',
                     prop  : 'revisions',
                     titles: 'User talk' + mw.config.get('wgUserName'),
                     rvprop: 'comment|user',
                     rvlimit: 30
                    },      
            success: function(data) {
            // callback func     
               var fuw = window.fuw;
               if (data) {
                  var ui = data.getElementsByTagName('userinfo');
                  if (ui) {
                     var editcount = ui[0].getAttribute('editcount');
                     if (editcount < 100) {
                        fuw.userStatus = 'newbie';
                     }
                  }
                  var revs = data.getElementsByTagName('rev');
                  var countWarn = 0;
                  for (i = 0; i < revs.length; i++) {
                     var rev = revs[i];
                     var usr = rev.getAttribute('user');
                     var cmt = rev.getAttribute('comment');
                     if ((usr == 'ImageTaggingBot') ||
                         (cmt.search(/(означавање за брисање \[\[Датотека)|(недостају датотеке за отпремање)|(Датотека (извор и )?проблем са лиценцирањем ауторских права)|(Номиновање за брзо брисање \[\[Датотека)|(Обавјештење: стављање на списак \[\[могуће неслободне датотеке)/) >= 0)) {
                        countWarn += 1;   
                     }
                  }
                  if (countWarn >= 3) {
                     fuw.userStatus = 'problem';
                  }
               }
            }
         });
      }
      else {
         this.userStatus = 'notAutoconfirmed';
      }
   }
   else {
      this.userStatus = 'anon';
   }
};

// =================================================================
// Convenience function for getting the regular index.php
// interface of Commons. Not very elegant.
// =================================================================
function fuwGetCommonsURL() {
   if (document.URL.match(/^https:/)) 
      return "https://commons.wikimedia.org/w/index.php";
   else
      return "http://commons.wikimedia.org/w/index.php";
}  

// ==================================================================
// functions for building form elements
// ==================================================================
fuwMakeRadiobutton = function(group, option, checked, event) {
   // Stupid IE7 doesn't get "value" attribute unless it's created in this convoluted way.
   // Annoying.   
   var node = $('<input type="radio" id="' + option + '" name="' + group + '" value="' + option + '"></input>')[0];
   if (checked) node.checked = true;
   node.onclick = event || fuwRadioClick;
   node.onclick = event || fuwRadioClick;
   fuwAppendInput(option, node);
};
fuwMakeTextfield = function(label, event) {
   var node  = document.createElement('input');
   node.type = 'text';
   node.name = label;
   node.size = fuwDefaultTextboxLength;
   node.onchange = event || fuwUpdateOptions;
   // only for testing:
   //node.value = label;
   fuwAppendInput(label, node);
};
fuwMakeTextarea = function(label, event) {
   var node  = document.createElement('textarea');
   node.name = label;
   node.rows = fuwDefaultTextareaLines;
   node.style.width = fuwDefaultTextareaWidth;
   node.onchange = event || fuwUpdateOptions;
   //only for testing:
   //node.innerHTML = label;
   fuwAppendInput(label, node);
};
fuwMakeCheckbox = function(label, checked, event) {
   var node  = document.createElement('input');
   node.name = label;
   node.type = 'checkbox';
   //only for testing:
   //node.title= label;
   node.checked = checked;
   node.onchange = event || fuwUpdateOptions;
   fuwAppendInput(label, node);
}
fuwMakeHiddenfield = function(name, value, id) {
   var node   = document.createElement('input');
   node.name  = name;
   node.type  = 'hidden';
   node.value = value;
   fuwAppendInput((id || name), node);
};
fuwMakeAnchor = function(label, href, content) {
   var node   = document.createElement('a');
   node.name  = label;
   node.target= "_blank";
   node.href  = href;
   node.innerHTML = content;
   fuwAppendInput(label, node);
};
fuwMakeSelection = function(name, values) {
   var root = document.createElement('select');
   var current = root;
   try {
      for (i=0; i<values.length; i++) {
         var line = values[i];
         var entry;
         if (line.length == 0) {
            current = root;
         }
         else if (line.length == 1) {
            entry = document.createElement('optgroup');
            entry.setAttribute('label', line[0]);
            root.appendChild(entry);
            current = entry;
         }
         else {
            entry = document.createElement('option');
            entry.setAttribute('value', line[0]);
            entry.setAttribute('title', '{{' + line[0] + '}}');
            entry.innerHTML = line[1];
            if (line.length > 2) {
               entry.setAttribute('selected', 'selected');
            } 
            current.appendChild(entry);
         }
      }
   } catch (e) { alert("Назив: " + name + ", i=" + i); }
   root.name = name;
   root.onchange = fuwUpdateOptions;
   fuwAppendInput(name, root);
};
function fuwMakeWikilink(place, target, redlink, display) {
   
   place = fuwGet(place);
   var id = place.id;
   var anchor;
   if (place.tagName == 'A') {
      anchor = place;
   }
   else {
      anchor = document.createElement('a');
      place.appendChild(anchor);
   }
   anchor.href = mw.util.getUrl(target);
   anchor.title = target;
   anchor.innerHTML = target;
   anchor.className = (redlink ? 'new' : null);
}

function fuwAppendInput(label, content) {
   // append a newly created input element to an existing
   // span element marked as id="placeholderXYZ"
   var node = fuwGet('placeholder' + label);
   var old  = fuwGet(label);
   if (old) {
      old.parentNode.removeChild(old);
   }
   content.id = content.id || label;
   if (node) {
      while (node.hasChildNodes()) {
         node.removeChild(node.firstChild);
      }
      node.appendChild(content);
   }
}

// ======================================================
// move an element away from its current position
// and append it to a target element if condition is true
// ======================================================
function fuwMove(mv, tg, condition, toStart) {
   if (condition) {
      move   = fuwGet(mv);
      target = fuwGet(tg);
      if (move && target) {
         var parent = move.parentNode;
         if (! (target===parent)) {
            parent.removeChild(move);
            if (toStart) {
               target.insertBefore(move, target.firstChild);
            }
            else {
               target.appendChild(move);
            }
         }
      }
      else {
         alert("Непронађени елементи: move=" + mv + "(" + move + "), target=" + tg + "(" + target + ")");
      } 
   }
   return condition;
}

// ===================================================
// make an element visible/invisible
// ===================================================
function fuwSetVisible(tg, condition) {
   target = fuwGet(tg);
   if (target) {
      if (condition) {
         $(target).show();
      }
      else {
         $(target).hide();
      }
   }
   else {
      alert("Непронађени елемент: " +  (tg.nodeType ? tg.id : tg));
   }
}

// ===================================================
// set enabled/disabled status for an element and/or
// all input controls contained in it.
// ===================================================
function fuwSetEnabled(tg, condition) {
   target = fuwGet(tg);
   try {
      var elements = (target.tagName.match(/^(input|textarea|select|button|a)$/i) ? 
         [target] :
         $('#' + target.id + ' *'));
      for (i = 0; i<elements.length; i++) {
         if (elements[i].tagName.match(/^(input|textarea|select|button|a)$/i)) {
            elements[i].disabled = (condition ? null : "онемогућено");
         }
      }
   } catch (e) { alert("Непронађени елемент: " +  (tg.nodeType ? tg.id : tg)); }
}

// ===================================================
// convenience function to check whether a given
// element is currenly visible. Needs to check display
// property of the element and its ancestors
// ===================================================
function fuwIsVisible(el) {
   element = fuwGet(el);
   if (!element) return false;
   el = element.id;
   
   var visible = true;
   while (! (element === document.body)) {
      if (element.style.display == "празно") {
         visible = false;
         break;
      }
      element = element.parentNode;
   }
   return visible;
}

// ===================================================
// cleanup filename
// ===================================================
function fuwCleanFilename() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var oldname = name = $.trim(nameBox.value);

   if (name) {
      // strip accidentally added [[   ]] or [[:  ]] brackets
      name = name.replace(/(^\[\[:?)|(\]\]$)/g, "");
      // strip accidentally added "File:" prefix
      name = name.replace(/^(File|Image|Датотека|Слика|Datoteka|Slika):/, "");
      // replace underscores with spaces
      name = name.replace(/_/g, " ");
      // uppercase first letter
      name = name.charAt( 0 ).toUpperCase() + name.slice(1);
   }
   if (oldname != name) {
      nameBox.value = name;
   }
   // always return true so the next validation step will proceed:
   return true;
}


// ==================================================
// check filename for technically illegal 
// characters, trying to fix them automatically
// ==================================================
function fuwCheckLegalFilename() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var oldname = name = $.trim(nameBox.value);

   if (name) {
      // resolve accidentally entered html entities and URI-encoded %XX character codes
      name = name.replace(/\&[a-z]+;/g, fuwHtmlEntityDecode);
      name = name.replace(/(\%[A-F0-9]{2,2})/g, decodeURI);
      // remove illegal characters # < > [ ] | { } /:
      // using a best guess for an acceptable replacement
      name = name.replace(/[<\[\{]/g, "(");
      name = name.replace(/[>\]\}]/g, ")");
      name = name.replace(/[#:\|]/g,  ",");
      name = name.replace(/\//g, "-");
      // remove sequences of tildes
      name = name.replace(/\~{3,}/g, "---");
      // remove initial slash
      name = name.replace(/^\//, "");
   }
   
   if (oldname != name) {
      window.fuw.warn.IllegalChars = true;
      nameBox.value = name;
      return false;
   }
   else {
      window.fuw.warn.IllegalChars = false;
      return true;
   }
}
function fuwHtmlEntityDecode(str) {
   // hack to translate accidentally entered html entity code
   // into actual characters
   var ta=document.createElement('textarea');
   ta.innerHTML=str.replace(/</g,'<').replace(/>/g,'>');
   return ta.value;
}

// =======================================================
// Check against various common patterns of poorly chosen
// filenames (too short / too generic)
// =======================================================
function fuwCheckPoorFilename() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var name = $.trim(nameBox.value);
	name = name.replace(/\.(png|gif|jpg|jpeg|xcf|pdf|mid|ogg|ogv|svg|djvu|tiff|tif|oga)$/i, "");

   // name should be at least 10 characters long, excluding file type extension
   var tooShort = (name.length < 10);
   
   // common generic filename patterns: 
   // IMG......jpg
   // Image....jpg
   // DSC......jpg
   // Picture......jpg
   // Pic..........jpg
   // anything that has fewer than 3 alphabetic letters and then just numbers
   var pattern = /^(img|image|dsc|picture|pic)?(\\s*|\\_*|[a-z]{,3})?\\d+$/i;
   var auto = name.match(pattern);

   window.fuw.warn.BadFilename = (tooShort || auto);
   return !tooShort && !auto;
}

// =======================================================
// check if file extensions match between local filename
// and target filename input box. Automatically append 
// appropriate extension to target filename if they don't.
// =======================================================
function fuwCheckFileExtension() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var name = $.trim(nameBox.value);
   var fileBox = window.fuw.TargetForm.file;
   var file = fileBox.value;
   
   // cancel check if no filename has been provided yet
   if (!file || !name) return true;
   
   var extensions = /.+\.(png|gif|jpg|jpeg|xcf|pdf|mid|ogg|ogv|svg|djvu|tiff|tif|oga)$/i;
   var mimetypes = {
      "png"  : "image/png",
      "gif"  : "image/gif",
      "jpg"  : "image/jpeg",
      "jpeg" : "image/jpeg",
      "xcf"  : "image/x-xcf",
      "pdf"  : "application/pdf",
      "mid"  : "audio/rtp-midi",
      "ogg"  : "audio/ogg",
      "ogv"  : "video/ogg",
      "svg"  : "image/svg+xml",
      "djvu" : "image/vnd.djvu",
      "tiff" : "image/tiff",
      "tif"  : "image/tiff",
      "oga"  : "video/ogg"
   };   

   var found = extensions.exec(file);
   var fileExt = found ? found[1].toLowerCase() : "";
   found = extensions.exec(name);
   var nameExt = found ? found[1].toLowerCase() : "";
   var mime = mimetypes[fileExt]; 
   
   if (fileExt && mime && (mimetypes[nameExt] != mime)) {
      nameBox.value = name.replace(/\.?$/, ('.' + fileExt));
   }
   return true;
}

// ============================================================
// Check if a file under the chosen name already exists,
// either locally or on Commons.
// Store results in the fuw.warn object, so warnings will
// be displayed on the next fuwUpdateOptions() call
// ============================================================
function fuwCheckFileExists() {
   // this is an asynchronous AJAX function.
   // results won't yet be present when this function returns.

   var nameBox = window.fuw.ScriptForm.InputName;
   var name = $.trim(nameBox.value);

   // using the jQuery wrapper for the Ajax functionality:
   $.ajax({
      url     : mw.util.wikiScript( 'api' ),
      type    : 'GET',
      dataType: 'xml',
      traditional : true,
      data:   {
               format: 'xml',
               action: 'query',
               titles: 'File:' + name,
               prop  : 'imageinfo',
               iiprop: 'url|user',
               iiurlwidth: 120
              },      
      success: function(resp) {
      // callback function, called when API query has succeeded:
         // see if the request has returned info from an existing image:
         var foundlist = resp.getElementsByTagName('ii');
         var exists = (foundlist.length >= 1);
         var isCommons = false;
         if (exists) {

            // extract description data from http response.
            // see https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii 
            // for structure of API response
            var foundImg = foundlist[0];
            isCommons = (foundImg.parentNode.parentNode.getAttribute('imagerepository')=='shared');

            // need this data for creating our own image thumb link
            var width = foundImg.getAttribute('thumbwidth');
            var height = foundImg.getAttribute('thumbheight');
            var thumbURL = foundImg.getAttribute('thumburl');
            var lastUser = foundImg.getAttribute('user');
            var descURL = foundImg.getAttribute('descriptionurl');

            // API returns link to local description page even for Commons images.
            // However, we want a direct link to Commons.
            if (isCommons) {
               descURL = descURL.replace(/sr\.wikipedia\.org/, "commons.wikimedia.org");
               descURL = descURL.replace(/\/\/secure\.wikimedia\.org\/wikipedia\/sr/, "commons.wikimedia.org");
            }

            // build the image info into the warning section of our page:
            thumbDiv = fuwGet('warningImageThumb');
            if (thumbDiv) {
            
               // make all links point to description page:
               var thumbA = thumbDiv.getElementsByTagName('a');
               for (i = 0; i<thumbA.length; i++) {
                  thumbA[i].setAttribute('href', descURL);
               }
               // insert the image itself:
               var thumbImg = thumbDiv.getElementsByTagName('img');
               if (thumbImg.length > 0) {
                  thumbImg = thumbImg[0];
                  thumbImg.setAttribute('src', thumbURL);
                  thumbImg.setAttribute('width', width);
                  thumbImg.setAttribute('height', height);
               }
               // insert the name of the last uploader:
               var thumbSpan = fuwGet('existingImageUploader');
               // TO DO: turn this into a proper link
               if (thumbSpan) thumbSpan.innerHTML = lastUser;
            }

            
         }
         warn = window.fuw.warn;
         warn.ImageOnCommons = exists && isCommons;
         warn.ImageExists    = exists && !isCommons;

         fuwUpdateOptions();
      }
   });
}

// ===========================================================
// onchange event handler for the local filename box
// ===========================================================
fuwValidateFile = function() {
   fuwCheckFileExtension();
   fuwUpdateOptions();
}

// ===========================================================
// onchange event handler for the name input box
// ===========================================================
fuwValidateFilename = function() {
   fuwCleanFilename();
   if (
      fuwCheckLegalFilename() &&
      fuwCheckPoorFilename() &&
      fuwCheckFileExtension()) {
      // after fuwCheckFileExists(),
      // fuwUpdateOptions will be triggered
      // by the callback function after Ajax completion
      fuwCheckFileExists();
   }
   else {
      // if there's been no Ajax call.
      fuwUpdateOptions();
   }
};

// ==========================================================
// function fuwValidateNFArticle()
// ==========================================================
// This is the validation routine for the obligatory
// article-to-be-used-in field for non-free files. It queries
// api.php about the target article through an Ajax call.
// It will store error info in the fuw.warn object,
// triggering the following error on the next updateOptions():
// * warningNFArticleNotFound : target page doesn't exist.
// * warningNFArticleNotMainspace : target is not an article. 
// * warningNFArticleDab : target is a disambiguation page.
// Redirects will automatically be substituted.
// ==========================================================
fuwValidateNFArticle = function() {
   
   var nameBox = window.fuw.ScriptForm.NFArticle;
   oldname = name = nameBox.value;
   
   // cleanup article name:
   // automatically fix accidentally added [[ ... ]] and
   // regularize underscores
   name = $.trim(name);
   name = name.replace(/(^\[\[)|(\]\]$)/g, "");
   // automatically fix article names entered as full urls:
   name = name.replace(/^https?:\/\/sr\.wikipedia\.org\/wiki\//, "");
   name = name.replace(/^https?:\/\/sr\.wikipedia\.org\/w\/index\.php\?title=/, "");
   name = name.replace(/_/g, " ");
   if (name != oldname) nameBox.value = name;
   
   // do nothing more if field was blank
   if (!name) return;

   // using the jQuery wrapper for the Ajax functionality:
   $.ajax({
      url     : mw.util.wikiScript( 'api' ),
      type    : 'GET',
      dataType: 'xml',
      traditional : true,
      data:   {
               format: 'xml',
               action: 'query',
               titles: name,
               prop  : 'info|categories|links'
              },      
      success: function(resp) {
      // callback function, called when API query has succeeded:
         var errorType = 0;
         var pg = resp.getElementsByTagName('page')[0];
         var title = pg.getAttribute('title');
         var target = title;
         if (pg.getAttribute('missing') != null) {
            // no page found under this title.
            errorType = 1;
         }           
         else {
            var userspace = false;
            var ns = pg.getAttribute('ns');
            var rd = pg.getAttribute('redirect');
            if (ns != 0) {
               // not a mainspace page!
               errorType = 2;

               // try to detect if the target might be a user space draft:               
               if (title.match(new RegExp("User( talk)?:" + mw.config.get('wgUserName')))) {
                  userspace = true;
               }
            }
            else if (rd != null) {
               // redirect page
               // API returns an empty redirect="" attribute if
               // the page is a redirect
               var targets = pg.getElementsByTagName('pl');
               for (i=0; i<targets.length; i++) {
                  var link = targets[i];
                  if (link.getAttribute('ns')==0) {
                     target = link.getAttribute('title');
                     errorType = 3;
                     break;
                  }
               }
            }
            else {
               // check for disambiguation categories
               var cats = pg.getElementsByTagName('cl');
               for (i=0; i<cats.length; i++) {
                  var cat = cats[i];
                  if (cat.getAttribute('title') == "Категорија:Вишезначна одредница") {
                     errorType = 4;
                     break;
                  }
               }  
            }
         }
         warn = window.fuw.warn;
         warn.NFArticleNotFound = (errorType==1);
         warn.NFArticleNotMainspace = (errorType==2);
         warn.UserspaceDraft = ((errorType==2) && userspace);
         warn.NFArticleDab = (errorType==4);
         warn.NFArticleOK  = (errorType==0);

         // fix links in error messages:
         if (warn.NFArticleNotFound) {
            fuwMakeWikilink(fuwGet('warningNFArticleNotFound').getElementsByTagName('A')[0], target, true);
         }
         else if (warn.NFArticleNotMainspace) {
            fuwMakeWikilink(fuwGet('warningNFArticleNotMainspace').getElementsByTagName('A')[0], target);
         }
         else if (warn.NFArticleDab) {
            fuwMakeWikilink(fuwGet('warningNFArticleDab').getElementsByTagName('A')[0], target);
         }
         else if (warn.NFArticleOK) {
            fuwMakeWikilink(fuwGet('NFArticleOK').getElementsByTagName('A')[0], target);
         }
                       
         if (errorType==3) {
            // automatically replace title with redirect target
            window.fuw.ScriptForm.NFArticle.value = target;
            // need to recursively call validation again now
            //if (confirm(name + " је преусмјерење. Пратите га до " + target + "?")) {
               fuwValidateNFArticle();
            //}
         }
         else {
            fuwUpdateOptions();
         }          
      }
   });
};

// ================================================
// manually reload script (just for testing)
// ================================================
function fuwReload() {
   mw.loader.load( 'http://localhost/script/uploadscript.js' );
   fuwReset();
}

// ================================================
// reset forms
// TO DO: add a button that actually triggers this.
// ================================================
function fuwReset() {
   var forms = mw.util.$content[0].getElementsByTagName('form');
   for (i = 0; i < forms.length; i++) {
      forms[i].reset();
      window.fuw.warn = { };
      window.fuw.opts = { };
   }
   fuwSetVisible('UploadScriptArea', true);
   fuwSetVisible('fuwSuccess', false);
   fuwSetVisible('fuwWaiting', false);
   fuwUpdateOptions();
}

// ===============================================
// convenience functions for string handling
// ===============================================
function fuwAppendLines(parts) {
   // assemble a string from an array of strings.
   // treat every second element as a conditional
   // separator that will be included only if 
   // surrounding elements are non-empty.
   var build = "";
   for (var i = 0; i < parts.length; i += 2) {
      if (parts[i]) {
         if (build) build += parts[i - 1];
         build += parts[i];
      }
   }
   return build;
}
function fuwSurroundString(prefix, content, suffix) {
   // put a prefix and a suffix on a string, 
   // if the input string is non-empty.
   if (content) 
      return (prefix ? prefix : "") + content + (suffix ? suffix : ""); 
   else return "";
}

// ========================================================
// convenience function for accessing the contents of the
// dummy TargetIFrame
// ========================================================
function fuwGetDocumentFromIFrame(iframe) {
   var doc = (iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document);
   if (doc.XMLDocument) {
      doc = doc.XMLDocument;
   }
   return doc;
}
// ========================================================
// event handler for the dummy TargetIFrame's onload event.
// TO DO: expand stub to add real notification of success,
// link to new file page, instructions about how to include
// file in articles, etc.
// ========================================================
function fuwUploadCompleted() {
   var doc = fuwGetDocumentFromIFrame(fuwGet('TargetIFrame'));
   if (doc) {
      //alert(doc);
      fuwSetVisible('successThumb', false);

      var fuw = window.fuw;
      var name = fuw.opts.InputName;

      var uploads = doc.getElementsByTagName('upload');
      var success = false;
      for (i = uploads.length-1; i>=0; i--) {
         if (uploads[i].getAttribute('result') == 'Success') {
            success = true;
            // need to get the real resulting filename here; might be different from the requested one in some cases.
            name = uploads[i].getAttribute('filename');
            break;
         }
      }
      if (success) {

         // need another ajax call to check the file is actually there,
         // and to retrieve its direct thumb img url:
         $.ajax({
            url     : mw.util.wikiScript( 'api' ),
            type    : 'GET',
            dataType: 'xml',
            traditional : true,
            data:   {
                     format: 'xml',
                     action: 'query',
                     titles: 'File:' + name,
                     prop  : 'imageinfo',
                     iiprop: 'url',
                     iiurlwidth: 120
                    },      
            success: function(resp) {
               // callback function, called when API query has succeeded:
               // see if the request has returned info from an existing image:

               var foundImg = resp.getElementsByTagName('ii')[0];
               if (foundImg) {

                  // need this data for creating our own image thumb link
                  var width = foundImg.getAttribute('thumbwidth');
                  var height = foundImg.getAttribute('thumbheight');
                  var thumbURL = foundImg.getAttribute('thumburl');
                  var lastUser = foundImg.getAttribute('user');
                  var descURL = foundImg.getAttribute('descriptionurl');

                  // build the thumbnail in the success message:
                  thumbDiv = fuwGet('successThumb');
                  
                  // make link point to description page:
                  var thumbA = thumbDiv.getElementsByTagName('a')[0];
                  thumbA.href = descURL;

                  // insert the image itself:
                  var thumbImg = thumbDiv.getElementsByTagName('img')[0];
                  thumbImg.setAttribute('src', thumbURL);
                  thumbImg.setAttribute('width', width);
                  thumbImg.setAttribute('height', height);
                  
                  fuwSetVisible(thumbDiv, true);
               }
            }
         });
         fuwMakeWikilink(
            fuwGet('fuwSuccessLink2').getElementsByTagName('a')[0],
            'File:' + name);
         fuwGet('placeholderExFilename1').innerHTML = name;
         fuwGet('placeholderExFilename2').innerHTML = name;
         fuwSetVisible('fuwSuccess', true);
         fuwSetVisible('fuwWaiting', false);
      }
      else {
         var err = doc.getElementsByTagName('error');
         if (err) {
            var info = err[0].getAttribute('info');
            var details = err[0].getElementsByTagName('detail');
            var add = "";
            for (i = 0; i < details.length; i++) {
               if (add.length > 0) add += ", ";
               add += details[i].textContent;
            }
            if (add) {
               info = info + " (" + add + ")";
            }
            alert("Отпремање није успјело: " + info);
         }
         else {
            alert("Непозната грешка: Отпремање можда није успјело.");
         }
      }
   }
}

// ========================================================
// clean out dummy IFrame before submitting a request
// ========================================================
function fuwResetTargetIFrame() {
   var doc = fuwGetDocumentFromIFrame(fuwGet('TargetIFrame'));
   if (doc) {
      while (doc.hasChildNodes()) {
         doc.removeChild(doc.firstChild);
      }
   }
}

// ========================================================
// Event handler for the real submit button
// ========================================================
function fuwSubmitUpload() {
   
   var fuw = window.fuw;
   var frm = fuw.TargetForm;

   fuw.collectInput();
   fuw.formatOutput(false);

   // we will use the iframe's onload event to trigger a function that
   // adds success notification etc.
   fuwResetTargetIFrame();
   var ifr = fuwGet('TargetIFrame');
   if (ifr.attachEvent) {
      // workaround for IE, according to 
      // http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/
      ifr.attachEvent("onload", fuwUploadCompleted);
   }
   else {
      // all other browsers
      ifr.onload = fuwUploadCompleted;
   }

   if (fuwTesting) {
      fuwSetVisible('placeholderTestForm', false);
   }
   fuwSetVisible('UploadScriptArea', false);

   fuwMakeWikilink(
     fuwGet('fuwSuccessLink').getElementsByTagName('a')[0], 'File:' + fuw.opts.InputName);
   fuwSetVisible('fuwWaiting', true);

   frm.submit();
   var opts = window.fuw.opts;
   // the API won't overwrite the description page text while overwriting
   // a file, which is really, really, really annoying and stupid.
   // So in the opts.OverwriteDifferent scenario, we need to edit
   // the description page through a separate ajax call. Dang.
   if (opts.OverwriteDifferent) {
      $.ajax({
         url   : mw.util.wikiScript('api'),
         type  : 'POST',
         dataType : 'xml',
         data  : {
                  format : 'xml',
                  action : 'edit',
                  title  : 'File:' + opts.InputName,
                  token  : mw.user.tokens.get('editToken'),
                  summary : opts.EditSummary,
                  text   : ($('#TargetForm .[name="text"]')[0]).value

                 }
      });
   }
}

// =======================================================
// Event handler for the Commons submit button
// =======================================================
function fuwSubmitCommons() {
   var fuw = window.fuw;
   fuw.collectInput();
   var url = fuw.formatOutput(true);
   alert("Сада ћете бити преусмјерени на Оставу. \nКористите образац за отпремање на Остави да бисте додали категорије у опис датотеке коју отпремате, а потом завршите отпремање.");
   window.location = url;
}

// =======================================================
// Event handler for the test submit button
// (write description string to sandbox only)
// =======================================================
function fuwSubmitSandbox() {
   var frm = window.fuw.TestForm;
   $.ajax({
      url     : mw.util.wikiScript( 'api' ),
      type    : 'POST',
      dataType: 'xml',
      data:   {
               format: 'xml',
               action: 'edit',
               title : mw.config.get('wgPageName') + "/sandbox",
               token : mw.user.tokens.get('editToken'),
               recreate : 1,
               summary  : frm.SandboxSummary.value,
               text     : frm.SandboxText.value
              },      
      success: function(resp) {
         alert("Уређена страница пијеска!");
      }
   });
}



// ========================================================
// convenience wrapper function to replace calls to
// document.getElementById() 
// to avoid browser incompatibility
// ========================================================
function fuwGet(target) {
   if (target && target.nodeType) return target;
   else {
      var found = $('#' + target);
      if (found) return found[0];
   }
   return undefined;
}

// ========================================================
// onload hook function, loading this script
// ========================================================
$(function() { 
   if (fuwGet('UploadScriptArea')) {
      window.fuw = new fuwGlobal();
      fuwUpdateOptions();
   }
});

Evo preveo sam ovde šta je trebalo a i šta možda nije (ne znam da li opisi kao što je fuwSurroundString("'''Непосредни извор''': " služe za imena koja će se generisati ovde ili za Ostavu, ali lako je taj dio prekopirati kakav je bio nepreveden pa uporediti izmjene i eventualno ponovo prevesti na srpski u tom vraćenom originalnom dijelu na engleskom jeziku ono što treba stvarno da bude na srpskom.

Treba još nekoliko puta pročitati i uskladiti sa šablonom za obrazac koji je trenutno u pijesku i revidiran prvi put.  Obsuser 18:39, 27. oktobar 2016. (CEST)[odgovori]

Potrebno ispraviti: opremanja → otpremanja, Obajveštenje → Obavještenje, < → &lt; i > → &gt; te          (vidjeti za ovo posljednje/razmake u kodu na ovoj SZR šta je između tagova za kod i noviki tagova pošto se nije prikazalo).  Obsuser 19:09, 27. oktobar 2016. (CEST)[odgovori]
Gdje izvršiti ove posljednje tri promjene primjene? —Ranko Nikolić (razgovor) 19:14, 27. oktobar 2016. (CEST)[odgovori]
U ovom Medijavijiju; ova posljednja je manje bitna a &lt; i &gt; su se vjerovatno pretvorili u < i > redom u kodu (koji si direktno kopirao sa ove stranice Razgovora o Medijavikiju a ne iz samog njenog koda).
Ovo se vidi da se promijenilo pri usporedbi izmjena: ovdje (podebljane oznake Red 1.806 i Red 1.817).  Obsuser 20:25, 27. oktobar 2016. (CEST)[odgovori]

Nastavak

@Ranko Nikolić i Srdjan m: Šta mislite o ijekavici? Ja sam da se sve prebaci u ekavicu jer je softver inače na ekavici; eventualno, ako je izvodljivo, da se doda u podešavanjima opcija u kojoj će se izabrati izgovor i zavisno od toga da se koristi ekavski Medijaviki i onaj obrazac i ijekavski Medijaviki i onaj obrazac (ali nije na meni da odlučujem o ovome, a i komplikovano je i pominjao sam ovo još jednom — i za ćirilicu/latinicu takođe takođe, da budu četiri verzije u zavisnosti od odabira pisma i izgovora — pa nije bilo ništa).

Još bolje rješenje je pitati na Trgu u vezi sa ijekavicom u obrascu za otpremanje i da se više korisnika izjasni (osim ako nešto meni promiče pa treba zaista na ijekavici).

Pošto su ijekavica i ekavica potpuno ravnoprave u srpskom jeziku nema potrebe za bilo kakvim prebacivanjem. —Ranko Nikolić (razgovor) 20:17, 27. oktobar 2016. (CEST)[odgovori]
Jesu potpuno ravnopravni izgovori ali ide se previše na štetu dosljednosti. Da li ima ijedan drugi dio interfejsa da je na ijekavici?
Ako nema, mislim da je bolje pitati na Trgu. Sugerisao sam još sad i neću više jer nije od ključnog značaja...
Takođe, ne znam gdje treba prevesti famozno dugme „Choose File” i tekst „No file chosen” (i možda ima još povezanog teksta) — jer ovo se sve do danas zadržalo neprevedeno u trenutnom (starom) obrascu (desno od „Naziv izvorne datoteke”).  Obsuser 20:25, 27. oktobar 2016. (CEST)[odgovori]
Pa ako se budemo uvijek oslanjali na dosljednost nikada neće ni biti dijela interfejsa na ijekavici. Možda ti je najbolje da engleze pitaš u čemu je problem. —Ranko Nikolić (razgovor) 20:50, 27. oktobar 2016. (CEST)[odgovori]
Ako možeš kopiraj samo kod iz ovog odjeljka Prevodi (direktno iz odjeljka nakon klika na Uredi), sada sam popravio sitnice, i toliko od mene sad-zasad (vi revidirajte ponovo, a ako mogu još negdje pomoći kažite).
Moguće je da sam nešto preveo što nije trebalo, ali cijeli novi sistem treba dobro istestirati i vidjeti gdje se šta generiše pa doraditi (obratiti pažnju npr. na File|Image|Datoteka itd., onda spajanje rečenica, kategorije, ispis poruka o greškama, opise izmjena, šablone za licence — a takođe i slanje na Ostavu odavde koje bi moglo da bude problematično).
Takođe ovo „Životni vijek” mi je čudno [nepovezano] ako tu ide datum smrti (ili ne ide uvijek? unosi se 100 [životni vijek] ili 1916 [godina smrti]?), te pominjanje neke „rasprave” u članku a misli se na sadržaj/dio/dijelove članka gdje se nešto govori o datoteci (kako sam ja shvatio).
Ja sam predložio četiri verzije: sr-ec-ek, sr-ec-ijek, sr-el-ek, sr-el-ijek i nazvao ih snovima; ako se ikad ostvare (a nije nemoguće), tada će se cijeli interfejs koji je sada na ekavici morati prevesti na ijekavicu i dodati u podešavanja (i padajući meni gdje su sad samo za pisma) i opcije za izgovor. To je samo teorija, možda je i neizvodljiva, ali nema veze, neka ostane zabilježena kao teorija...
„Choose File” i dr. vidim sada da nije izgleda prevedeno ni na jednoj Viki, ali sada nema veze (može ih se naravno i pitati, Engleze, ako će ostati u starom obrascu a nekome smetati neprevedeno)... Obsuser 01:01, 28. oktobar 2016. (CEST)[odgovori]
Trebaće popraviti ovo sa none/празно i možda онемогућено odnosno napraviti da se prikazuje tekst „prazno” umjesto „none” a ukloniti kutiju koja se sada prikazuje u 1. koraku ('none' je možda trebalo prevesti)...  Obsuser 01:49, 28. oktobar 2016. (CEST)[odgovori]
Ovaj posljednji none što si preveo je pravi, a jedan ili oba moja празно valjda utiču na prikaz one kutije u prvom koraku koje inače nema pa treba taj jedan ili oba vratiti u none.  Obsuser 02:26, 31. oktobar 2016. (CET)[odgovori]
Ako se možda koristi u ovom Medijavikiju i ispisuje negdje (ne znam napamet gdje bi to moglo biti po samom kodu Medijavikija) „File:” i sl., zamijeniti to sa „Datoteka:” i sl. da se ispisuje preveden oblik.  Obsuser 11:59, 31. oktobar 2016. (CET)[odgovori]
Možda tako nešto ima ovdje. —Ranko Nikolić (razgovor) 12:59, 31. oktobar 2016. (CET)[odgovori]
@Obsuser: Koliko ja znam, to dugme/tekst u potpunosti zavisi od preglednika (možda i od sistema). Na primjer, na Firefox-u mi uopšte ne piše „Choose File”, već „Browse...” a pored „No file selected” jer su mi preglednik i sistem na engleskom. Ako imaš instaliran Chrome, možeš lako prebaciti jezik i provjeriti /pod „Change the language of your Chrome browser (Windows & Chromebook only)” (ja ne mogu, jer ne radi na macOS-u)/. Ako se ne promijeni, onda zavisi od jezika sistema. – Srdjan m (razgovor) 19:12, 31. oktobar 2016. (CET)[odgovori]
@Srdjan m: U pravu si, probao sam prije nekoliko sati i bilo je prevedeno kada sam u Chrome-u promijenio jezik u srpski.
Ali koji je smisao toga? Zar nije svaki veb-sajt „za sebe” odnosno sam tekst koji ispisuje ne bi trebalo da uopšte zavisi od pretraživača nego od samog sajta (jedino da pretraživač utiče na neka formatiranja odnosno CSS i sl.). Mislim veoma je čudno, ali možda su morali tako jer se pristupa računaru da se uzme slika pa je sigurnije kroz pretraživač i to...
Nego ako možeš, ti pogledaj nedostaje li šta i prevedi na Translejt vikiju šta je povezano za onaj Čarobnjak, a usput molim te pogledaj i ono što sam ja prevodio ovde i u pijesku (moguće je da ima u ovom Medijavikiju neko „File:” koje treba zamijeniti sa „Datoteka:” da se ispisuje prevedeno i sl.; obratiti pažnju i na File|Image|Datoteka itd., onda spajanje rečenica, kategorije, ispis poruka o greškama, opise izmjena, šablone za licence — a takođe i slanje na Ostavu; ponavljam: takođe ovo „Životni vijek” mi je čudno [nepovezano] ako tu ide datum smrti (ili ne ide uvijek? unosi se 100 [životni vijek] ili 1916 [godina smrti]?), te pominjanje neke „rasprave” u članku a misli se na sadržaj/dio/dijelove članka gdje se nešto govori o temi tog članka a povezano s datotekom koja je za to neophodna).  Obsuser 05:17, 1. novembar 2016. (CET)[odgovori]
Na sajtu Translatewiki sve je u redu, a vidjeću ostatak u pijesku. Čarobnjak bi valjalo/trebalo temeljno testirati, samo što ne znam kako to izvesti bez da se potpuno spamuju skorašnje izmjene... – Srdjan m (razgovor) 07:58, 1. novembar 2016. (CET)[odgovori]

Dorada

@Ranko Nikolić: Sitnica, treba zamijeniti "|Водич за отпремање]]") sa "|Водича за отпремање]]").  Obsuser 17:50, 29. april 2017. (CEST)[odgovori]

  Urađeno . — Ranko   Niko lić   18:54, 29. april 2017. (CEST)[odgovori]

Ispraviti i „Non-free Denver Public Library” u „Non-free Denver Public Library image”.  Obsuser 20:14, 18. maj 2017. (CEST)[odgovori]

  Urađeno . — Ranko   Niko lić   21:01, 18. maj 2017. (CEST)[odgovori]

@Ranko Nikolić: Treba zamijeniti додајте  sa у поље за другу лиценцу додајте  i {{tl|keep local}} sa „&#123;&#123;keep local&#125;&#125;”.  Obsuser 22:26, 24. maj 2017. (CEST)[odgovori]

Zamijenio i dodao nove licence. — Ranko   Niko lić   22:34, 24. maj 2017. (CEST)[odgovori]
Stavi i navodnike, a ovo se trenutno nalazi u „Ovo je neslobodno djelo zaštićeno autorskim pravima, ali vjerujem da spada pod poštenu upotrebu.” > „neka druga vrsta neslobodnog djela” > „Poseban izvor i uslovi licenciranja (neobavezno)”.
Da bi one za državne akte bile među slobodnima, pokušaj kopirati ovdje sve što je vezano za „USGovLicense” odnosno na VP:Vodič za otpremanje što je vezano za „Djelo stvorila agencija Federalne vlade SAD.” (za ovo može da piše „Djelo stvorila agencija vlade, vlada ili neki državni organ druge zemlje.”). Cija i Državni akti SAD ne treba (već ima dodato), samo one za državne akte Srbije i Crne Gore. Ako ne bude radilo (trebalo bi da doda jednu opciju), onda vratiti i smisliti nešto drugo.  Obsuser 22:51, 24. maj 2017. (CEST)[odgovori]
@Ranko Nikolić: Takođe treba prevesti \n;Other information u \n;Остале информације i zamijeniti:
  • 'File:' + name sa 'Датотека:' + name (više pojavljivanja)
  • 'File:' + fuw.opts.InputName sa 'Датотека:' + fuw.opts.InputName
  • 'File:' + opts.InputName sa 'Датотека:' + opts.InputName
(Mislim da se zbog ovog prvog nije ispisivala poruka o uspešnom otpremanju.)  Obsuser 13:37, 27. maj 2017. (CEST)[odgovori]

@Ranko Nikolić: Evo, pokušaj:

/*
* ===============================================================
*                    FileUploadWizard.js
* Script for uploading files through a dynamic questionnaire.
* This is the code to accompany [[Wikipedia:File Upload Wizard]].
* ===============================================================
*/

var fuwTesting = false;
var fuwDefaultTextboxLength = 60;
var fuwDefaultTextareaWidth = '90%';
var fuwDefaultTextareaLines = 3;

// ================================================================
// Constructor function of global fuw (= File Upload Wizard) object
// ================================================================
function fuwGlobal() {

   // Loading the accompanying .css
   mw.loader.load( mw.config.get('wgServer') + mw.config.get('wgScriptPath') +
      '/index.php?title=MediaWiki:FileUploadWizard.css&action=raw&ctype=text/css', 
      'text/css'  );

   // see if user is logged in, autoconfirmed, experienced etc.
   this.getUserStatus();

   fuwSetVisible('warningLoggedOut', (this.userStatus == 'anon'));
   fuwSetVisible('warningNotConfirmed', (this.userStatus == 'notAutoconfirmed'));
   if ((this.userStatus == 'anon') || (this.userStatus == 'notAutoconfirmed')) {
      return;
   }
   fuwSetVisible('fuwStartScriptLink', false);

   // create the form element to wrap the main ScriptForm area
   // containing input elements of Step2 and Step3
   var frm = fuwGet('fuwScriptForm');
   if (! frm) {
      frm = document.createElement('form');
      frm.id = "fuwScriptForm";
      var area = fuwGet('placeholderScriptForm');
      var parent = area.parentNode;
      parent.insertBefore(frm, area);
      parent.removeChild(area);
      frm.appendChild(area);
   }
   this.ScriptForm = frm;

   // create the TargetForm element that contains the filename
   // input box, together with hidden input controls.
   // This is the form that is actually submitted to the api.php.
   frm = fuwGet('TargetForm');
   if (! frm) {
      frm = document.createElement('form');
      frm.id = "TargetForm";
      frm.method = "post";
      frm.enctype = "multipart/form-data";
      // "enctype" doesn't work properly on IE; need "encoding" instead:
      frm.encoding = "multipart/form-data"; 
      // we'll submit via api.php, not index.php, mainly because that
      // allows us to use a proper edit summary different from the page content
      frm.action = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php';

      // However, since api.php sends back a response page that humans won't want to read,
      // we'll have to channel that response away and discard it. We'll use a hidden iframe
      // for that purpose.
      // Unfortunately, it doesn't seem possible to submit file upload content through an 
      // Xmlhtml object via Ajax.
 
      frm.target = "TargetIFrame";
      //testing:
      //frm.target = "_blank";
      var area = fuwGet('placeholderTargetForm');
      var parent = area.parentNode;
      parent.insertBefore(frm, area);
      parent.removeChild(area);
      frm.appendChild(area);
   }
   this.TargetForm = frm;

   // For the testing version, create a third form that will display
   // the contents to be submitted, at the bottom of the page
   if (fuwTesting) {
      frm = fuwGet('fuwTestForm');
      if (! frm) {
         frm = document.createElement('form');
         frm.id = "fuwTestForm";
         var area = fuwGet('placeholderTestForm');
         var parent = area.parentNode;
         parent.insertBefore(frm, area);
         parent.removeChild(area);
         frm.appendChild(area);
      }
      this.TestForm = frm;
   }

   // objects to hold cached results during validation and processing
   this.opts = { };
   this.warn = { };

   // create the input filename box
   var filebox  = document.createElement('input');
   filebox.id   = 'file';
   filebox.name = 'file';
   filebox.type = 'file';
   filebox.size = fuwDefaultTextboxLength;
   filebox.onchange = fuwValidateFile;
   filebox.accept = 'image/png,image/jpeg,image/gif,image/svg+xml,image/tiff,image/x-xcf,application/pdf,image/vnd.djvu,audio/ogg,video/ogg,audio/rtp-midi';
   fuwAppendInput('file', filebox);

   // create hidden controls for sending the remaining API parameters:
   fuwMakeHiddenfield('action', 'upload', 'apiAction');
   fuwMakeHiddenfield('format', 'xml', 'apiFormat');
   fuwMakeHiddenfield('filename', '', 'apiFilename');
   fuwMakeHiddenfield('text', '', 'apiText');
   fuwMakeHiddenfield('comment', '', 'apiComment');
   fuwMakeHiddenfield('token', mw.user.tokens.get('editToken'), 'apiToken');
   fuwMakeHiddenfield('ignorewarnings', 1, 'apiIgnorewarnings');
   fuwMakeHiddenfield('watch', 1, 'apiWatch');

   if (fuwTesting) {
      fuwMakeHiddenfield('title', mw.config.get('wgPageName') + "/sandbox", 'SandboxTitle');
      fuwMakeHiddenfield('token', mw.user.tokens.get('editToken'), 'SandboxToken');
      fuwMakeHiddenfield('recreate', 1, 'SandboxRecreate');
   }

   // create a hidden IFrame to send the api.php response to
   var ifr = document.createElement('iframe');
   ifr.id   = "TargetIFrame";
   ifr.name = "TargetIFrame";
   //ifr.setAttribute('style', 'float:right;width:150px;height:150px;');
   ifr.style.display = "none";
   ifr.src = "";

   fuwAppendInput('TargetIFrame', ifr);

   if (fuwTesting) {

      // create the sandbox submit button
      btn = document.createElement('input');
      btn.id = 'SandboxButton';
      btn.value = 'Пијесак';
      btn.name  = 'Sandbox';
      btn.disabled = true;
      btn.type = 'button';
      btn.style.width = '12em';
      btn.onclick = fuwSubmitSandbox;
      fuwAppendInput('SandboxButton', btn);

   }

   // create the real submit button
   btn = document.createElement('input');
   btn.id = "SubmitButton";
   btn.value = "Отпреми";
   btn.name = "Upload";
   btn.disabled = true;
   btn.type = "button";
   btn.onclick = fuwSubmitUpload;
   btn.style.width = '12em';
   fuwAppendInput('SubmitButton', btn);

   // create the Commons submit button
   btn = document.createElement('input');
   btn.id = "CommonsButton";
   btn.value = "Отпреми на Оставу";
   btn.name  = "Upload_on_Commons";
   btn.disabled = true;
   btn.type = "button";
   btn.onclick = fuwSubmitCommons;
   btn.style.width = '12em';
   fuwAppendInput('CommonsButton', btn);

   // create reset buttons
   for (i = 1; i<=2; i++) {
      btn = document.createElement('input');
      btn.id = 'ResetButton' + i;
      btn.value = "Ресетуј образац";
      btn.name  = "Reset form";
      btn.type  = "button";
      btn.onclick = fuwReset;
      btn.style.width = '12em';
      fuwAppendInput('ResetButton' + i, btn);
   }

   // names of radio button fields
   var optionRadioButtons = {
      // top-level copyright status choice
      'FreeOrNonFree' : ['OptionFree','OptionNonFree','OptionNoGood'],
      // main subsections under OptionFree
      'FreeOptions'   : ['OptionOwnWork', 'OptionThirdParty', 'OptionFreeWebsite',
                         'OptionPDOld', 'OptionPDOther'],
      // main subsections under OptionNonFree
      'NonFreeOptions': ['OptionNFSubject','OptionNF3D','OptionNFExcerpt',
                         'OptionNFCover','OptionNFLogo','OptionNFPortrait',
                         'OptionNFMisc'],
      // response options inside warningFileExists
      'FileExistsOptions': 
                        ['NoOverwrite','OverwriteSame','OverwriteDifferent'],
      // choice of evidence in OptionThirdParty subsection
      'ThirdPartyEvidenceOptions' : 
                        ['ThirdPartyEvidenceOptionLink',
                         'ThirdPartyEvidenceOptionOTRS',
                         'ThirdPartyEvidenceOptionOTRSForthcoming',
                         'ThirdPartyEvidenceOptionNone'],
      // choice of PD status in OptionPDOld subsection
      'PDOldOptions'  : ['PDUS1923','PDURAA','PDFormality','PDOldOther'],
      // choice of PD status in OptionPDOther subsection
      'PDOtherOptions': ['PDOtherUSGov','PDOtherGov','PDOtherOfficial','PDOtherSimple',
                         'PDOtherOther'],
      // whether target article is wholly or only partly dedicated to discussing non-free work:
      'NFSubjectCheck': ['NFSubjectCheckDedicated','NFSubjectCheckDiscussed'],
      'NF3DCheck'     : ['NF3DCheckDedicated','NF3DCheckDiscussed'],
      // choice about copyright status of photograph in OptionNF3D
      'NF3DOptions'   : ['NF3DOptionFree','NF3DOptionSame']
   };
   for (var group in optionRadioButtons) {
      var op = optionRadioButtons[group];
      for (i=0; i<op.length; i++) {
         fuwMakeRadiobutton(group, op[i]);
      }
   }
   this.ScriptForm.NoOverwrite.checked = true;
   
   // input fields that trigger special
   // onchange() event handlers for validation:
   fuwMakeTextfield('InputName', fuwValidateFilename);
   fuwMakeTextfield('NFArticle', fuwValidateNFArticle);

   // names of input fields that trigger normal
   // validation event handler
   var activeTextfields = [
      'Artist3D','Country3D',
      'Date','OwnWorkCreation','OwnWorkPublication',
      'Author','Source',
      'Permission','ThirdPartyOtherLicense',
      'ThirdPartyEvidenceLink','ThirdPartyOTRSTicket',
      'FreeWebsiteOtherLicense',
      'PDOldAuthorLifetime','Publication',
      'PDOldCountry','PDOldPermission',
      'PDOfficialPermission','PDOtherPermission',
      'NFSubjectPurpose', 'NF3DOrigDate', 'NF3DPurpose',
      'NF3DCreator',
      'NFPortraitDeceased',
      'EditSummary'
   ];
   for (i=0; i<activeTextfields.length; i++) {
      fuwMakeTextfield(activeTextfields[i]);
   }

   // names of multiline textareas
   var activeTextareas = [
      'InputDesc','NF3DPermission',
      'NFCommercial','NFPurpose','NFReplaceableText',
      'NFReplaceable','NFCommercial','NFMinimality','AnyOther'
   ];
   for (i=0; i<activeTextareas.length; i++) {
      fuwMakeTextarea(activeTextareas[i]);
   };

   var checkboxes = [
      'NFCoverCheckDedicated','NFLogoCheckDedicated','NFPortraitCheckDedicated'
   ];
   for (i=0; i<checkboxes.length; i++) {
      fuwMakeCheckbox(checkboxes[i]);
   };

   var licenseLists = {
      'OwnWorkLicense' : 
        // array structure as expected for input to fuwMakeSelection() function.
        // any entry that is a two-element array will be turned into an option
        // (first element is the value, second element is the display string).
        // Entries that are one-element arrays will be the label of an option group.
        // Zero-element arrays mark the end of an option group.
        [
        ['Допуштате свима употребу док Вас наводе као аутора и дијеле под сличним условима'],
        ['self|GFDL|cc-by-sa-4.0|migration=redundant', 
         'Кријејтив комонс Ауторство—Дијелити под истим условима 4.0 и ГНУ-ова лиценца за слободну документацију (препоручено)',
         true],
        ['self|cc-by-sa-4.0',
         'Кријејтив комонс Ауторство—Дијелити под истим условима 4.0'],
        [],
        ['Допуштате свима употребу док Вас наводе као аутора'],
        ['self|cc-by-4.0',
         'Кријејтив комонс Ауторство 4.0'],
        [],
        ['Без задржавања права'],
        ['cc-zero',
         'Предавање у универзално јавно власништво (cc-0)'],
        []
        ],   
      'ThirdPartyLicense' :
        [
        ['', 'изаберите једну од опција...'],
        ['Слободне лиценце:'],
        ['cc-by-sa-4.0', 'Кријејтив комонс Ауторство—Дијелити под истим условима (cc-by-sa-4.0)'],
        ['cc-by-4.0', 'Кријејтив комонс Ауторство (cc-by-4.0)'],
        ['GFDL', 'ГНУ-ова лиценца за слободну документацију (GFDL)'],
        [],
        ['Без задржавања права:'],
        ['PD-author', 'Јавно власништво'],
        [],
        ['Остало (погледајте испод)'],
        []
        ],   
      'FreeWebsiteLicense' :
        [
        ['', 'изаберите једну од опција...'],
        ['Слободне лиценце:'],
        ['cc-by-sa-4.0', 'Кријејтив комонс Ауторство—Дијелити под истим условима (cc-by-sa-4.0)'],
        ['cc-by-4.0', 'Кријејтив комонс Ауторство (cc-by-4.0)'],
        ['GFDL', 'ГНУ-ова лиценца за слободну документацију (GFDL)'],
        [],
        ['Без задржавања права:'],
        ['PD-author', 'Јавно власништво'],
        [],
        ['Остало (погледајте испод)'],
        []
        ],   
      'USGovLicense' :
       [
       ['PD-USGov', 'Федерална влада САД'],
       ['PD-USGov-NASA','НАСА'],
       ['PD-USGov-Military-Navy','Ратна морнарица САД'],
       ['PD-USGov-NOAA','Национална океанска и атмосферска администрација'],
       ['PD-USGov-Military-Air_Force','Ратно ваздухопловство САД'],
       ['PD-USGov-Military-Army','Армија САД'],
       ['PD-USGov-CIA-WF','CIA World Factbook'],
       ['PD-USGov-USGS','Геолошки топографски институт САД']
       ],
      'OtherGovLicense' :
       [
       ['ЈВ-акти Србије', 'Државни акти Србије'],
       ['ЈВ-акти Црне Горе', 'Државни акти Црне Горе']
       ],
      'IneligibleLicense' :
       [
       ['', 'изаберите једну од опција...'],
       ['PD-shape','Дјело се састоји искључиво од једноставних геометријских облика'],
       ['PD-text','Дјело се састоји само од неколико појединачних ријечи или слова'],
       ['PD-textlogo','Лого или слично дјело које се састоји искључиво од слова и једноставних геометријских облика'],
       ['PD-chem','Хемијска структурална формула'],
       ['PD-ineligible','Друга врста дјела које не садржи оригинално ауторство']
       ],
      'NFSubjectLicense' :
       [
       ['', 'изаберите једну од опција...'],
       ['Non-free 2D art', '2-димензионално умјетничко дјело (слика, цртеж итд.)'], 
       ['Non-free historic image', 'Јединствена историјска фотографија'], 
       ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)']
       ],
      'NF3DLicense' :
       [
       ['', 'изаберите једну од опција...'],
       ['Non-free architectural work', 'Архитектонско дјело'], 
       ['Non-free 3D art', 'Друго 3-димензионално креативно дјело (скулптура итд.)']
       ],
      'NFCoverLicense' :
         [
         ['', 'изаберите једну од опција...'],
         ['Non-free book cover', 'Корица књиге'], 
         ['Non-free album cover', 'Омот звучног записа (албум, сингл, пјесма, ЦД)'], 
         ['Non-free game cover', 'Омот видео/рачунарске игре'], 
         ['Non-free magazine cover', 'Насловна страна часописа'], 
         ['Non-free video cover', 'Омот видео-траке'], 
         ['Non-free software cover', 'Омот софтверског производа'], 
         ['Non-free product cover', 'Омот неког комерцијалног производа'], 
         ['Non-free title-card', 'Уводна шпица ТВ програма'], 
         ['Non-free movie poster', 'Филмски постер'], 
         ['Non-free poster', 'Званични постер догађаја'], 
         ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)']
         ],
      'NFExcerptLicense' :
         [
         ['', 'изаберите једну од опција...'],
         ['Non-free television screenshot', 'Снимак екрана ТВ програма'], 
         ['Non-free film screenshot', 'Снимак екрана филма'], 
         ['Non-free game screenshot', 'Снимак екрана игре'], 
         ['Non-free video screenshot', 'Снимак екрана видеа'], 
         ['Non-free music video screenshot', 'Снимак екрана музичког видеа'], 
         ['Non-free software screenshot', 'Снимак екрана софтвера'], 
         ['Non-free web screenshot', 'Снимак екрана веб-сајта'], 
         ['Non-free speech', 'Аудио-исјечак говора'], 
         ['Non-free audio sample', 'Звучни одломак аудио-снимка'], 
         ['Non-free video sample', 'Исјечак видеа'], 
         ['Non-free sheet music', 'Ноте које представљају музичко дјело'], 
         ['Non-free comic', 'Дио стрипа, графички роман, манга итд.'], 
         ['Non-free computer icon', 'Рачунарска икона'], 
         ['Non-free newspaper image', 'Страница новина'], 
         ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)']
         ],      
      'NFLogoLicense' :
         [
         ['Non-free logo', 'Лого компаније, организације итд.'], 
         ['Non-free seal', 'Званични печат, грб итд.'], 
         ['Non-free symbol', 'Други званични симбол']
         ],
      'NFMiscLicense' :
         [
         ['Non-free fair use in', 'нешто друго (опишите у пољу за кратак опис 2. корака изнад)'], 
         ['Non-free historic image', 'Историјска фотографија'], 
         ['Non-free 2D art', '2-димензионално умјетничко дјело (слика, цртеж итд.)'], 
         ['Non-free currency', 'Депикција валуте (новчанице, кованице итд.)'], 
         ['Non-free architectural work', 'Архитектонско дјело'], 
         ['Non-free 3D art', 'Друго 3-димензионално креативно дјело (скулптура итд.)'], 
         ['Non-free book cover', 'Корица књиге'], 
         ['Non-free album cover', 'Омот звучног записа (албум, сингл, пјесма, ЦД)'], 
         ['Non-free game cover', 'Омот видео/рачунарске игре'], 
         ['Non-free magazine cover', 'Насловна страна часописа'], 
         ['Non-free video cover', 'Омот видео-траке'], 
         ['Non-free software cover', 'Омот софтверског производа'], 
         ['Non-free product cover', 'Омот неког комерцијалног производа'], 
         ['Non-free title-card', 'Уводна шпица ТВ програма'], 
         ['Non-free movie poster', 'Филмски постер'], 
         ['Non-free poster', 'Званични постер догађаја'], 
         ['Non-free television screenshot', 'Снимак екрана ТВ програма'], 
         ['Non-free film screenshot', 'Снимак екрана филма'], 
         ['Non-free game screenshot', 'Снимак екрана игре'], 
         ['Non-free video screenshot', 'Снимак екрана видеа'], 
         ['Non-free music video screenshot', 'Снимак екрана музичког видеа'], 
         ['Non-free software screenshot', 'Снимак екрана софтвера'], 
         ['Non-free web screenshot', 'Снимак екрана веб-сајта'], 
         ['Non-free speech', 'Аудио-исјечак говора'], 
         ['Non-free audio sample', 'Звучни одломак аудио-снимка'], 
         ['Non-free video sample', 'Исјечак видеа'], 
         ['Non-free sheet music', 'Ноте које представљају музичко дјело'], 
         ['Non-free comic', 'Дио стрипа, графички роман, манга итд.'], 
         ['Non-free computer icon', 'Рачунарска икона'], 
         ['Non-free newspaper image', 'Страница новина'], 
         ['Non-free logo', 'Лого компаније, организације итд.'], 
         ['Non-free seal', 'Званични печат, грб итд.'], 
         ['Non-free symbol', 'Други званични симбол'], 
         ['Non-free sports uniform', 'Спортска униформа'], 
         ['Non-free stamp', 'Поштанска марка'] 
         ],
      'NFExtraLicense' :
         [
         ['', 'празно'],
         ['Ауторска права Круне и други владини извори'],
         ['Non-free Crown copyright', 'Ауторско право Круне УК'],
         ['Non-free New Zealand Crown Copyright', 'Ауторско право Круне НЗ'],
         ['Non-free Canadian Crown Copyright', 'Ауторско право Круне Канаде'],
         ['Non-free AUSPIC', 'AUSPIC (Сликовна база података Аустралијског парламента)'],
         ['Non-free Philippines government', 'Филипинска влада'],
         ['Non-free Finnish Defence Forces', 'Финске одбрамбене снаге'],
         [],
         ['Остали појединачни извори'],
         ['Non-free Denver Public Library image', 'Денверска јавна библиотека'],
         ['Non-free ESA media', 'ЕСА (Европска свемирска агенција)'],
         [],
         ['Могуће јавно власништво у другим земљама'],
         ['Non-free Old-50', 'Аутор умро прије више од 50 година'],
         ['Non-free Old-70', 'Аутор умро прије више од 70 година'],
         ['ЈВ-Босна и Херцеговина', 'Босна и Херцеговина'],
         ['ЈВ-Босна и Херцеговина-изузетак', 'Босна и Херцеговина (изузетак)'],
         ['ЈВ-Израел', 'Израел'],
         ['ЈВ-Италија', 'Италија'],
         ['ЈВ-Пољска', 'Пољска'],
         ['ЈВ-Русија', 'Русија'],
         ['ЈВ-САД', 'САД'],
         ['ЈВ-САД-1923-иностранство', 'САД (иностранство 1923)'],
         ['ЈВ-САД пре 1978.', 'САД (пре 1978)'],
         ['ЈВ-Србија', 'Србија'],
         ['ЈВ-Хрватска', 'Хрватска'],
         ['ЈВ-Хрватска-изузетак', 'Хрватска (изузетак)'],
         ['ЈВ-Црна Гора', 'Црна Гора'],
         [],
         ['Неке дозволе дате, али није потпуно слободно'],
         ['Non-free promotional', 'Из промотивног прес-кита'],
         ['Non-free with NC', 'Дозвола дата, али само за образовне и/или некомерцијалне сврхе'],
         ['Non-free with ND', 'Дозвола дата, али прерађивање дјела није дозвољено'],
         ['Non-free with permission', 'Дозвола дата, али само за Википедију'],
         []
         ]
   };
   for (var group in licenseLists) {
      fuwMakeSelection(group, licenseLists[group]);
   }


   this.knownCommonsLicenses = {
      'self|GFDL|cc-by-sa-all|migration=redundant' : 1,
      'self|Cc-zero' : 1,
      'PD-self' : 1,
      'self|GFDL|cc-by-sa-4.0|migration=redundant' : 1,
      'self|GFDL|cc-by-4.0|migration=redundant' : 1,
      'self|GFDL|cc-by-sa-3.0|migration=redundant' : 1,
      'self|GFDL|cc-by-3.0|migration=redundant' : 1,
      'self|cc-by-sa-4.0' : 1,
      'self|cc-by-sa-3.0' : 1,
      'cc-by-sa-4.0' : 1,
      'cc-by-sa-3.0' : 1,
      'cc-by-sa-2.5' : 1,
      'cc-by-4.0' : 1,
      'cc-by-3.0' : 1,
      'cc-by-2.5' : 1,
      'FAL' : 1,
      'PD-old-100' : 1,
      'PD-old' : 1,
      'PD-Art' : 1,
      'PD-US' : 1,
      'PD-USGov' : 1,
      'PD-USGov-NASA' : 1,
      'PD-USGov-Military-Navy' : 1,
      'PD-ineligible' : 1,
      'attribution' : 1,
      'copyrighted free use' : 1
   };


   // textfields that don't react directly
   // to user input and are used only for assembling stuff:
   if (fuwTesting) {
      fuwMakeTextfield('SandboxSummary', function(){void(0);});
      fuwMakeTextarea('SandboxText', function(){void(0);});
      fuwGet('SandboxSummary').disabled="онемогућено";
      fuwGet('SandboxText').disabled="онемогућено";
      fuwGet('SandboxText').rows = 12;
   }

   // set links to "_blank" target, so we don't accidentally leave the page,
   // because on some browsers that would destroy all the input the user has already entered
   $('.fuwOutLink a').each(function() {
      this.target = '_blank';
   });

   // make main area visible
   fuwSetVisible('UploadScriptArea', true);

}
// ====================================== 
// end of fuwGlobal constructor function
// ======================================



function fuwRadioClick(e) {
   var ev = e || event;
   var src = ev.target || ev.srcElement;
   //alert('onclick event from ' + src + ' (' + src.value + ')');
   fuwUpdateOptions();
   return true;
}

/* 
* =============================================================
* function fuwUpdateOptions
* =============================================================
* This is the onchange event handler for most of the input
* elements in the main form. It changes visibility and disabled
* status for the various sections of the input form in response
* to which options are chosen.
*/
function fuwUpdateOptions() {

   var fuw = window.fuw;
   var warn = fuw.warn;
   var opts = fuw.opts = { };
   opts.InputFilename = $('#TargetForm input#file').val();

   var widgets = fuw.ScriptForm.elements;
   for (i = 0; i < widgets.length; i++) {
      var w = widgets[i];
      if (w.type == "radio") {
         var nm = w.name;
         var id = w.id;
         var vl = w.checked && !w.disabled && fuwIsVisible(w);
         opts[id] = vl;
         if (vl) opts[nm] = id;
      }
      else {
         var id = w.id;
         var active = !w.disabled && fuwIsVisible(w);
         if (active) {
            var value = ((type == 'checkbox') ? w.checked : w.value);
            opts[id] = value;         
         }
      }
   };
   opts.MainOption = opts.FreeOptions || opts.NonFreeOptions;
   
   // some parts of the input form are re-used across sections
   // and must be moved into the currently active input section:

   // minimality section is shared between all NF sections
   fuwMove('NFMinimalitySection', 'detailsNFSubject', (opts.OptionNFSubject)) ||
   fuwMove('NFMinimalitySection', 'detailsNF3D', (opts.OptionNF3D)) ||
   fuwMove('NFMinimalitySection', 'detailsNFExcerpt', (opts.OptionNFExcerpt)) ||
   fuwMove('NFMinimalitySection', 'detailsNFCover', (opts.OptionNFCover)) ||
   fuwMove('NFMinimalitySection', 'detailsNFLogo', (opts.OptionNFLogo)) ||
   fuwMove('NFMinimalitySection', 'detailsNFPortrait', (opts.OptionNFPortrait)) ||
   fuwMove('NFMinimalitySection', 'detailsNFMisc', true);

   // AnyOtherInfo section is shared between all
   fuwMove('AnyOtherInfo', 'detailsOwnWork', opts.OptionOwnWork) ||
   fuwMove('AnyOtherInfo', 'detailsThirdParty', opts.OptionThirdParty) ||
   fuwMove('AnyOtherInfo', 'detailsFreeWebsite', opts.OptionFreeWebsite) ||
   fuwMove('AnyOtherInfo', 'detailsPDOld', opts.OptionPDOld) ||
   fuwMove('AnyOtherInfo', 'detailsPDOther', opts.OptionPDOther) ||
   fuwMove('AnyOtherInfo', 'detailsNFSubject', opts.OptionNFSubject) ||
   fuwMove('AnyOtherInfo', 'detailsNF3D', opts.OptionNF3D) ||
   fuwMove('AnyOtherInfo', 'detailsNFExcerpt', opts.OptionNFExcerpt) ||
   fuwMove('AnyOtherInfo', 'detailsNFCover', opts.OptionNFCover) ||
   fuwMove('AnyOtherInfo', 'detailsNFLogo', opts.OptionNFLogo) ||
   fuwMove('AnyOtherInfo', 'detailsNFPortrait', opts.OptionNFPortrait) ||
   fuwMove('AnyOtherInfo', 'detailsNFMisc', opts.OptionNFMisc);

   // author input field is shared between all sections except "Own Work".
   // (will serve for the immediate/photographic author, in those cases where there
   // are two author fields)
   fuwMove('Author', 'placeholderFreeWebsiteAuthor', (opts.OptionFreeWebsite)) ||
   fuwMove('Author', 'placeholderPDOldAuthor', (opts.OptionPDOld)) ||
   fuwMove('Author', 'placeholderPDOtherAuthor', (opts.OptionPDOther)) ||
   fuwMove('Author', 'placeholderNFSubjectAuthor', (opts.OptionNFSubject)) ||
   fuwMove('Author', 'placeholderNF3DAuthor', (opts.OptionNF3D)) ||
   fuwMove('Author', 'placeholderNFExcerptAuthor', (opts.OptionNFExcerpt)) ||
   fuwMove('Author', 'placeholderNFCoverAuthor', (opts.OptionNFCover)) ||
   fuwMove('Author', 'placeholderNFPortraitAuthor', (opts.OptionNFPortrait)) ||
   fuwMove('Author', 'placeholderNFMiscAuthor', (opts.OptionNFMisc)) ||
   fuwMove('Author', 'placeholderAuthor', true);

   // source input field is shared between all sections except "Own Work".
   // (will serve for immediate/web source, in those cases where there are two
   // source fields involved)
   fuwMove('Source', 'placeholderFreeWebsiteSource', (opts.OptionFreeWebsite)) ||
   fuwMove('Source', 'placeholderPDOldSource', (opts.OptionPDOld)) ||
   fuwMove('Source', 'placeholderPDOtherSource', (opts.OptionPDOther)) ||
   fuwMove('Source', 'placeholderNFSubjectSource', (opts.OptionNFSubject)) ||
   fuwMove('Source', 'placeholderNF3DSource', (opts.OptionNF3D)) ||
   fuwMove('Source', 'placeholderNFExcerptSource', (opts.OptionNFExcerpt)) ||
   fuwMove('Source', 'placeholderNFCoverSource', (opts.OptionNFCover)) ||
   fuwMove('Source', 'placeholderNFLogoSource', (opts.OptionNFLogo)) ||
   fuwMove('Source', 'placeholderNFPortraitSource', (opts.OptionNFPortrait)) ||
   fuwMove('Source', 'placeholderNFMiscSource', (opts.OptionNFMisc)) ||
   fuwMove('Source', 'placeholderSource', true);

   // date input field is shared between all sections except "Logo", which doesn't need it.
   // will serve for derived/photographic date in the case of 3D items
   fuwMove('Date', 'placeholderFreeWebsiteDate', (opts.OptionFreeWebsite)) ||
   fuwMove('Date', 'placeholderThirdPartyDate', (opts.OptionThirdParty)) ||
   fuwMove('Date', 'placeholderPDOldDate', (opts.OptionPDOld)) ||
   fuwMove('Date', 'placeholderPDOtherDate', (opts.OptionPDOther)) ||
   fuwMove('Date', 'placeholderNFSubjectDate', (opts.OptionNFSubject)) ||
   fuwMove('Date', 'placeholderNF3DDate', (opts.OptionNF3D)) ||
   fuwMove('Date', 'placeholderNFExcerptDate', (opts.OptionNFExcerpt)) ||
   fuwMove('Date', 'placeholderNFCoverDate', (opts.OptionNFCover)) ||
   fuwMove('Date', 'placeholderNFPortraitDate', (opts.OptionNFPortrait)) ||
   fuwMove('Date', 'placeholderNFMiscDate', (opts.OptionNFMisc)) ||
   fuwMove('Date', 'placeholderDate', true);
   
   // permission field is shared between ThirdParty and FreeWebsite sections
   fuwMove('Permission', 'placeholderFreeWebsitePermission', (opts.OptionFreeWebsite)) ||
   fuwMove('Permission', 'placeholderPermission', true);

   // publication field is shared between PDOld, NFPortrait and NFMisc
   fuwMove('Publication', 'placeholderNFPortraitPublication', (opts.OptionNFPortrait)) ||
   fuwMove('Publication', 'placeholderNFMiscPublication', (opts.OptionNFMisc)) ||
   fuwMove('Publication', 'placeholderPublication', true);

   // Purpose, Commercial, Replaceable and ReplaceableText FUR fields are shared
   // between some but not all of the non-free sections
   fuwMove('NFPurpose', 'placeholderNFExcerptPurpose', (opts.OptionNFExcerpt)) ||
   fuwMove('NFPurpose', 'placeholderNFPurpose');
   fuwMove('NFCommercial', 'placeholderNFPortraitCommercial', (opts.OptionNFPortrait)) ||
   fuwMove('NFCommercial', 'placeholderNFCommercial');
   fuwMove('NFReplaceable', 'placeholderNFPortraitReplaceable', (opts.OptionNFPortrait)) ||
   fuwMove('NFReplaceable', 'placeholderNFReplaceable');
   fuwMove('NFReplaceableText', 'placeholderNFExcerptReplaceable', (opts.OptionNFExcerpt)) ||
   fuwMove('NFReplaceableText', 'placeholderNFReplaceableText', true);

   // submit button goes to Step1 if user has chosen a plain overwrite of an existing file,
   // and to the active section of Step3 if otherwise
   fuwMove('fuwSubmit', 'UploadScriptStep1', (warn.ImageExists && opts.OverwriteSame)) ||
   fuwMove('fuwSubmit', 'detailsOwnWork', opts.OptionOwnWork) ||
   fuwMove('fuwSubmit', 'detailsThirdParty', opts.OptionThirdParty) ||
   fuwMove('fuwSubmit', 'detailsFreeWebsite', opts.OptionFreeWebsite) ||
   fuwMove('fuwSubmit', 'detailsPDOld', opts.OptionPDOld) ||
   fuwMove('fuwSubmit', 'detailsPDOther', opts.OptionPDOther) ||
   fuwMove('fuwSubmit', 'detailsNFSubject', opts.OptionNFSubject) ||
   fuwMove('fuwSubmit', 'detailsNF3D', opts.OptionNF3D) ||
   fuwMove('fuwSubmit', 'detailsNFExcerpt', opts.OptionNFExcerpt) ||
   fuwMove('fuwSubmit', 'detailsNFCover', opts.OptionNFCover) ||
   fuwMove('fuwSubmit', 'detailsNFLogo', opts.OptionNFLogo) ||
   fuwMove('fuwSubmit', 'detailsNFPortrait', opts.OptionNFPortrait) ||
   fuwMove('fuwSubmit', 'fuwSubmitHost', true);


   // Show and hide warnings:

   // filename-related warnings:
   fuwSetVisible('warningIllegalChars', warn.IllegalChars);
   fuwSetVisible('warningBadFilename',  warn.BadFilename);
   fuwSetVisible('warningImageOnCommons', warn.ImageOnCommons);
   fuwSetVisible('warningImageExists', warn.ImageExists);
   fuwMove('warningImageThumb', 'warningImageOnCommons', warn.ImageOnCommons, true) ||
   fuwMove('warningImageThumb', 'warningImageExists', true, true);


   // notices related to the top-level options:
   fuwSetVisible('warningWhyNotCommons', opts.OptionFree);
   fuwSetVisible('warningNF', opts.OptionNonFree);
   fuwSetVisible('warningNoGood', opts.OptionNoGood);

   // warnings related to non-free "used in" article
   fuwSetVisible('warningNFArticleNotFound', warn.NFArticleNotFound);
   fuwSetVisible('warningNFArticleNotMainspace', warn.NFArticleNotMainspace);
   fuwSetVisible('warningUserspaceDraft', warn.UserspaceDraft);
   fuwSetVisible('warningNFArticleDab', warn.NFArticleDab);
   fuwSetVisible('NFArticleOK', warn.NFArticleOK);

   // warnings depending on user status:
   if (fuw.userStatus.match(/problem|newbie|notAutoconfirmed/)) {
      fuwSetVisible('warningFreeWebsite', opts.OptionFreeWebsite);
      fuwSetVisible('warningOwnWork', opts.OptionOwnWork);
      fuwSetVisible('warningPDOther', opts.OptionPDOther);
      fuwSetVisible('warningNFSubject', opts.OptionNFSubject);
   }

   // hide main sections in case of intended plain overwrite:   
   fuwSetVisible('UploadScriptStep2', !(warn.ImageExists && opts.OverwriteSame));
   fuwSetVisible('UploadScriptStep3', !(warn.ImageExists && opts.OverwriteSame));

   // show/hide top-level options
   fuwSetVisible('detailsFreeStatus', opts.OptionFree);
   fuwSetVisible('sendToCommons', opts.OptionFree);

   // show/hide details sections
   fuwSetVisible('detailsNFArticle', opts.OptionNonFree);
   fuwSetVisible('detailsNFWorkType', opts.OptionNonFree);
   fuwSetVisible('detailsOwnWork', opts.OptionOwnWork);
   fuwSetVisible('detailsThirdParty', opts.OptionThirdParty);
   fuwSetVisible('detailsFreeWebsite', opts.OptionFreeWebsite);
   fuwSetVisible('detailsPDOld', opts.OptionPDOld);
   fuwSetVisible('detailsPDOther', opts.OptionPDOther);
   fuwSetVisible('detailsNFSubject', opts.OptionNFSubject);
   fuwSetVisible('detailsNF3D', opts.OptionNF3D);
   fuwSetVisible('detailsNFExcerpt', opts.OptionNFExcerpt);
   fuwSetVisible('detailsNFCover', opts.OptionNFCover);
   fuwSetVisible('detailsNFLogo', opts.OptionNFLogo);
   fuwSetVisible('detailsNFPortrait', opts.OptionNFPortrait);
   fuwSetVisible('detailsNFMisc', opts.OptionNFMisc);

   fuwSetVisible('EditSummaryDiv', opts.OverwriteSame || opts.OverwriteDifferent);

   // set enabled/disabled
   // It might be useful to adapt this to be more liberal about
   // the order of input, at least for experienced users.

   //fuwSetEnabled('Artist3D', opts.PD3D);
   //fuwSetEnabled('Country3D', opts.FOP3D);
   fuwSetEnabled('ThirdPartyEvidenceLink', opts.ThirdPartyEvidenceOptionLink);
   fuwSetEnabled('ThirdPartyOTRSTicket', opts.ThirdPartyEvidenceOptionOTRS);
   fuwSetEnabled('NFSubjectPurpose', opts.NFSubjectCheckDiscussed);
   fuwSetEnabled('NF3DPurpose', opts.NF3DCheckDiscussed);
   fuwSetEnabled('NF3DPermission', opts.NF3DOptionFree);
   fuwSetEnabled('USGovLicense', opts.PDOtherUSGov);
   fuwSetEnabled('OtherGovLicense', opts.PDOtherGov);
   fuwSetEnabled('PDOfficialPermission', opts.PDOtherOfficial);
   fuwSetEnabled('IneligibleLicense', opts.PDOtherSimple);
   fuwSetEnabled('PDOtherPermission', opts.PDOtherOther);
   fuwSetEnabled('AnyOther', true);

   // need to re-collect the remaining (non-radiobutton) input into the opts object again,
   // preparing for validation:
   for (i = 0; i < widgets.length; i++) {
      var w = widgets[i];
      var type = w.type;

      if (type != "radio") {
         var id = w.id;
         var active = !w.disabled && fuwIsVisible(w);
         if (active) {
            var value = ((type == 'checkbox') ? w.checked : w.value);
            opts[id] = value;         
         }
      }
   };

   // final step of validation: check if input is sufficient for
   // setting the submit buttons active
   var valid = fuw.validateInput();
   var validForCommons = valid && opts.OptionFree && !(opts.OverwriteSame || opts.OverwriteDifferent)
         && !opts.ThirdPartyEvidenceOptionNone;
   fuwSetVisible('sendToCommons', opts.OptionFree);
   fuwSetEnabled('CommonsButton', validForCommons);
   fuwGet('fuwSubmitText').innerHTML = opts.OptionFree ? 
         ("<b>Не</b>, желим да ову датотеку отпремим овдје, само на ову Википедију.<br/>" + 
          "<small>Овако ће се датотека моћи користити само на Википедији на српском језику. Међутим, неко " +
          "други би могао да је копира на Оставу и потом је користи негдје друго. Ако Ви " +
          "не желите да се ова датотека копира на Оставу а потом обрише овдје, у поље за другу лиценцу додајте " +
          "„{{keep local}}”.</small>") :
         "Отпреми ову датотеку.";
   fuwGet('SubmitButton').value = validForCommons ? "Отпреми локално" : "Отпреми";   
   fuwSetEnabled('EditSummary', true);
   fuwSetEnabled('SubmitButton', valid && (fuw.userStatus != 'notAutoconfirmed'));
   if (fuwTesting) {
      fuwSetEnabled('SandboxButton', valid);
   }

   // if we're in testing mode, update the Sandbox display fields
   // after each input change. In normal mode, collectInput() will
   // only be needed on submit.
   if (fuwTesting) {
      fuw.collectInput();
      fuw.formatOutput(false);
      fuwSetVisible('placeholderTestForm', true);
   }  
}

// ============================================================
// methods of the global fuw object
// ============================================================

// ============================================================
// report validation status of filename information
// ============================================================
// This is called from within fuw.validateInput(), i.e. every
// time anything in the whole form is changed. It only reports
// results that have previously been cached in the opts and warn
// objects. The actual checking is done in the event handler
// of the file input boxes.
fuwGlobal.prototype.hasValidFilename = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid =   
      opts.InputName &&
      opts.InputFilename &&
      !warn.BadFilename &&
      !warn.ImageOnCommons &&
      // if image exists on enwiki, accept only if user has confirmed overwrite:
      !(warn.ImageExists && !(opts.OverwriteSame || opts.OverwriteDifferent));
   //alert("HasValidFilename: " + valid);
   return valid;
};

// ============================================================
// validation status for common input elements for all free
// options
// ============================================================
fuwGlobal.prototype.hasValidCommonFreeInput = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid = opts.InputDesc;
   //alert("HasValidCommonFreeInput: " + valid);
   return valid;
};
// ============================================================
// validation status for common input elements for all non-free
// options
// ============================================================
fuwGlobal.prototype.hasValidCommonNFInput = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid =
      opts.OptionNonFree &&
      opts.InputDesc && 
      opts.NFArticle &&
      opts.Source &&
      opts.NFMinimality &&
      !warn.NFArticleNotFound &&
      !warn.NFArticleNotMainspace &&
      !warn.NFArticleDab;
   //alert("hasValidCommonNFInput: " + valid);
   return valid;
};
// ============================================================
// Main validation routine. Modify this to tweak which fields
// are to be considered obligatory for each case group
// ============================================================
fuwGlobal.prototype.validateInput = function() {
   var opts = this.opts;
   var warn = this.warn;
   var valid = (
      this.hasValidFilename()
      &&
      (! (opts.OverwriteDifferent && ! opts.EditSummary))
      &&
      (
       ( // overwriting is okay if there is an edit summary
        opts.OverwriteSame && opts.EditSummary
       )
       ||
       ( // free options
         this.hasValidCommonFreeInput() &&
         (
          (opts.OptionOwnWork &&
           opts.Date &&
           opts.OwnWorkLicense)
          ||
          (opts.OptionThirdParty &&
           opts.Author &&
           opts.Source &&
           opts.Permission &&
           (opts.ThirdPartyOtherLicense || opts.ThirdPartyLicense) &&
           ((opts.ThirdPartyEvidenceOptionLink && opts.ThirdPartyEvidenceLink) ||
            opts.ThirdPartyEvidenceOptionOTRS ||
            opts.ThirdPartyEvidenceOptionOTRSForthcoming ||
            opts.ThirdPartyEvidenceOptionNone))
          ||
          (opts.OptionFreeWebsite &&
           opts.Author &&
           opts.Source &&
           (opts.FreeWebsiteOtherLicense || opts.FreeWebsiteLicense) &&
           opts.Permission)
          ||
          (opts.OptionPDOld &&
           opts.Author &&
           opts.PDOldAuthorLifetime &&
           opts.Publication &&
           opts.Date &&
           opts.Source &&
           opts.PDOldOptions && 
           (! (opts.PDOldOther && ! opts.PDOldPermission)))
          ||
          (opts.OptionPDOther &&
           opts.Author &&
           opts.Source &&
           ((opts.PDOtherUSGov && opts.USGovLicense) ||
            (opts.PDOtherGov && opts.OtherGovLicense) ||
            (opts.PDOtherOfficial && opts.PDOfficialPermission) ||
            (opts.PDOtherSimple && opts.IneligibleLicense) ||
            (opts.PDOtherOther && opts.PDOtherPermission)))
        )
       ) // end of free options
       ||
       ( // non-free options
         this.hasValidCommonNFInput() &&
         (
          (opts.OptionNFSubject &&
           opts.NFSubjectLicense &&
           opts.Author &&
           (opts.NFSubjectCheckDedicated ||
           (opts.NFSubjectCheckDiscussed && opts.NFSubjectPurpose)))
          ||
          (opts.OptionNF3D &&
           opts.NF3DLicense &&
           opts.NF3DCreator &&
           opts.Author &&
           (opts.NF3DOptionSame ||
           (opts.NF3DOptionFree || opts.NF3DPermission)) && 
           (opts.NF3DCheckDedicated ||
            (opts.NF3DCheckDiscussed && opts.NF3DPurpose)))
          ||
          (opts.OptionNFExcerpt &&
           opts.NFExcerptLicense &&
           opts.Author &&
           opts.NFPurpose)
          ||
          (opts.OptionNFCover &&
           opts.NFCoverLicense &&
           opts.Author &&
           opts.NFCoverCheckDedicated 
          )
          ||
          (opts.OptionNFLogo &&
           opts.NFLogoLicense &&
           opts.NFLogoCheckDedicated
          )
          ||
          (opts.OptionNFPortrait &&
           opts.Publication &&
           opts.NFPortraitDeceased &&
           opts.Author &&
           opts.NFPortraitCheckDedicated &&
           opts.NFReplaceable &&
           opts.NFCommercial)
          ||
          (opts.OptionNFMisc &&
           opts.NFMiscLicense &&
           opts.Author &&
           opts.Publication &&
           opts.NFPurpose &&
           opts.NFReplaceableText &&
           opts.NFReplaceable &&
           opts.NFCommercial)
         )
       ) // end of non-free options
      )
   );
   return valid;
};

// =============================================================
// return which template name will be used as the main
// description template
// =============================================================
fuwGlobal.prototype.getDescriptionTemplateName = function() {
   // standard "Information" template for free files:
   if (this.opts.OptionFree) return "Information";
   // experimental new version of fair-use rationale template,
   // designed to fit the fields used in the wizard
   else if (this.opts.OptionNonFree) return "Non-free use rationale 2";
   return undefined;
};

// =============================================================
// get the license tag code from the appropriate input element
// =============================================================

fuwGlobal.prototype.getStandardLicense = function() {
   var opts = this.opts;
   
}

fuwGlobal.prototype.getLicense = function() {
   var opts = this.opts;
      // ThirdParty and FreeWebsite have alternative input fields
      // for manual entry of other licenses:
   var license = {};
   if (opts.PDOtherOther || opts.PDOldOther) {
      license.special = opts.PDOtherOther ? opts.PDOtherPermission : opts.PDOldPermission;
      if (! (license.special.match(/^\s*\{\{.+\}\}\s*$/))) {
         license.special = '{{PD-because|' + license.special + '}}';
      }
   }
   else {
      license.special = 
         opts.ThirdPartyOtherLicense || 
         opts.FreeWebsiteOtherLicense ||
         (opts.PDOtherOfficial ? ('{{PD-because|званично дјело правно изузето од ауторских права у земљи свог поријекла}}') : null) ||
         (opts.OptionNFPortrait ? ('{{non-free biog-pic|' + opts.NFArticle + '}}') : null);
   }   
   if (! license.special) {
      // standard, non-parametrized tag licenses from dropdownbox.
      var simpleLicense = (opts.OptionOwnWork ? opts.OwnWorkLicense : null) ||
          (opts.OptionThirdParty ? opts.ThirdPartyLicense : null) ||
          (opts.OptionFreeWebsite ? opts.FreeWebsiteLicense : null) ||
          (opts.OptionNFSubject ? opts.NFSubjectLicense : null) ||
          (opts.OptionNF3D ? opts.NF3DLicense : null) ||
          (opts.OptionNFExcerpt ? opts.NFExcerptLicense : null) ||
          (opts.OptionNFCover ? opts.NFCoverLicense : null) ||
          (opts.OptionNFLogo ? opts.NFLogoLicense : null) ||
          (opts.OptionNFMisc ? opts.NFMiscLicense : null) ||
          (opts.PDOtherUSGov ? opts.USGovLicense : null) ||
          (opts.PDOtherGov ? opts.OtherGovLicense : null) ||
          (opts.PDOtherSimple ? opts.IneligibleLicense : null) ||
          (opts.PDUS1923 ? 'PD-US-1923' : null) ||
          (opts.PDURAA   ? 'PD-URAA' : null) ||
          (opts.PDFormality ? 'PD-US' : null);

       // "PD-author" needs parameter, at least on Commons
       if (simpleLicense == 'PD-author') {
          license.special = '{{PD-author|' + opts.Author + '}}';
       }
       else if (this.knownCommonsLicenses[simpleLicense]) {
       // make sure we send only those licenses as "standard" licenses
       // that exist in the Commons license dropdown box
          license.standard = simpleLicense;
       }
       else {
          license.special = '\{\{' + simpleLicense + '\}\}';
       }
   }
   return license;
};

function fuwSubst(template) {
   return '{{subst:' + template + '}}';
}

// ===================================================================
// Produce code for local tracking categories
// ===================================================================
fuwGlobal.prototype.getTrackingCategory = function() {
   var opts = this.opts;
   var cat = "";
   if (opts.OptionFreeWebsite) { cat = "Датотеке из слободно лиценцираних спољашњих извора"; }
   else if (opts.OptionThirdParty) { cat = "Датотеке лиценциране од стране трећих лица"; }
   else if (opts.PDOtherOther || opts.PDOldOther) { cat = "Датотеке са нестандардним изјавама јавног власништва"; }
   else if (opts.OptionNFSubject || opts.OptionNF3D) { cat = "Неслободне датотеке отпремљене за сврху коментара"; }
   if (cat) {
      cat = "\n\{\{category ordered by date|" + cat + "|" + 
      fuwSubst("CURRENTYEAR") + "|" + fuwSubst("CURRENTMONTH") + "|" + fuwSubst("CURRENTDAY2") + "\}\}";
   }
   return cat;
};

// ===================================================================
// Get or create an edit summary for the upload
// ===================================================================
// Note: if we work with the api.php interface, we can have separate
// data for the edit summary and the description page, which is far
// better than the way the index.php interface does it.
// TO DO: need to actually define an input element for a manually
// entered edit summary. Must be obligatory when overwriting files.
// In other cases we'll use an automatic edit summary.
// ===================================================================
fuwGlobal.prototype.getEditSummary = function() {
   var opts = this.opts;
   return (
      (opts.EditSummary ? (opts.EditSummary + ' ([[' + mw.config.get('wgPageName') + '|Водич за отпремање]])') : null)||
      ("отпремање " +
       (
        (opts.OptionOwnWork ? 'личне датотеке ' : false) ||
        (opts.OptionThirdParty ? 'слободне датотеке некога другог ' : false) ||
        (opts.OptionFreeWebsite ? 'датотеке из слободно објављеног извора ' : false) ||
        (opts.OptionPDOld       ? 'старог дјела у јавном власништву ' : false) ||
        (opts.OptionPDOther     ? 'дјела у јавном власништву ' : false) ||
        (opts.OptionNFSubject   ? 'неслободног дјела као предмета расправе ' : false) ||
        (opts.OptionNF3D        ? 'депикције неслободног 3Д дјела ' : false) ||
        (opts.OptionNFExcerpt   ? 'исјечка неслободног дјела ' : false) ||
        (opts.OptionNFCover     ? 'неслободног омота ' : false) ||
        (opts.OptionNFLogo      ? 'неслободног логоа ' : false) ||
        (opts.OptionNFPortrait    ? 'неслободног историјског портрета ' : false) ||
        (opts.OptionNFMisc      ? 'неслободне датотеке ' : "")
       )
       + 
       ("путем [[" + mw.config.get('wgPageName') + "|Водича за отпремање]]")
      ));
};


function fuwPackInfo(text, forCommons) {
   if (forCommons) {
      // reformat wikilinks embedded in description fields to adapt them for Commons
      text = text.replace(/\[\[([^\]]+)\]\]/g, 
         function(str, p1, offset, s) {

            // mark File links as local
            if (p1.match(/^:(File|Image|Датотека|Слика|Datoteka|Slika):/)) {
               return "[[:sr" + p1 + "]]";
            }      
            // leave prefixed links unchanged:
            else if (p1.match(/^:[\w\-]+:/)) {
               return str;
            }
            // if the link is piped, add a prefix only
            else if (p1.match(/.+\|/)) {
               return "[[:sr:" + p1 + "]]";
            }
            // introduce a pipe
            else {
               return "[[:sr:" + p1 + "|" + p1 + "]]";
            }
         }
      );
      return "{{sr|" + text + "}}";
   } else return text;
}

// ================================================================
// This is the main method called by the event handler for the 
// (experimental) submit button. Its main task is to collect the 
// input into a single string of wikitext for the description page.
// ================================================================
fuwGlobal.prototype.collectInput = function() {
   var opts = this.opts;

   // object representing template fields for filling in
   // the description template. Pre-loaded with some
   // standard settings:
   var descFields = this.descFields = { 
      'Description' : opts.InputDesc,
      'Author'      : opts.Author,
      'Date'        : opts.Date,
      'Source'      : opts.Source
   };
   // "other information" (outside the template)
   this.otherInfo = null;
   
   if (opts.OptionNonFree) {
      descFields.Article = opts.NFArticle;
   }
   
   // add/modify option-specific fields:
   switch (opts.MainOption) {
      case 'OptionOwnWork':
      
         // use standard "source" field for optional "how created?" and 
         // "previously published" input fields.
         descFields.Source = fuwAppendLines([
            (opts.OwnWorkCreation || "{{own}}"), 
            "<br/>\n", 
            fuwSurroundString("'''Претходно објављено:''' ", opts.OwnWorkPublication)]);
         var username = mw.user.getName();
         descFields.Author = '[[User:' + username + '|' + username + ']]';
         break;

      case 'OptionThirdParty':
      
         // use standard "permission" field for a compilation of the
         // "permission" input field and the various "evidence" options
         var evidence = (
            opts.ThirdPartyEvidenceOptionLink ? 
               ("Изјава о лиценци може се пронаћи онлајн на: " + opts.ThirdPartyEvidenceLink) :
               (opts.ThirdPartyEvidenceOptionOTRS ? 
               ("Споразум о лиценци прослијеђен је на [[Википедија:OTRS|OTRS]]." + 
                  fuwSurroundString(" Тикет: ", opts.ThirdPartyOTRSTicket) + "\{\{OTRS pending|year=" + fuwSubst("CURRENTYEAR") + 
                                                                              "|month=" + fuwSubst("CURRENTMONTH") + 
                                                                              "|day=" + fuwSubst("CURRENTDAY2") + "\}\}") :
               (opts.ThirdPartyEvidenceOptionOTRSForthcoming ? 
               "Споразум о лиценци биће ускоро прослијеђен на [[Википедија:OTRS|OTRS]]. \{\{OTRS pending|year=" + fuwSubst("CURRENTYEAR") + 
                                                                              "|month=" + fuwSubst("CURRENTMONTH") + 
                                                                              "|day=" + fuwSubst("CURRENTDAY2") + "\}\}" :
               (opts.ThirdPartyEvidenceOptionNone ?
               "Биће обезбијеђено на захтјев." : null))));
         descFields.Permission = fuwAppendLines([
            opts.ThirdPartyPermission,
            "<br/>\n",
            fuwSurroundString("'''Доказ:''' ", evidence)]);
         break;
         
      case 'OptionFreeWebsite':
         descFields.Permission = opts.Permission;
         break;
         
      case 'OptionPDOld':
         // add "lifetime" input to "author" field
         descFields.Author = fuwAppendLines([
            opts.Author,
            "<br/>\n",
            fuwSurroundString("(Животни вијек: ", opts.PDOldAuthorLifetime, ")")
         ]);
         
         // combine original and direct source into standard "source" field: 
         descFields.Source = fuwAppendLines([
            fuwSurroundString("'''Оригинално објављивање''': ", opts.Publication),
            "<br/>\n",
            fuwSurroundString("'''Непосредни извор''': ", opts.Source)
         ]);
         
         // no standard tag available for "lack-of-registration" PD-US. Need
         // to put this into the "permission" field
         if (opts.PDFormality) 
            descFields.Permission = 
               "Ауторска права су истекла јер је дјело објављено без напомене " +
               "о истима и/или без неопходне регистрације истих.";
      
         // add optional "explanation" input to "permission" field
         if (opts.PDOldPermission) {
            descFields.Permission = fuwAppendLines([
               descFields.Permission,
               "\n\n",
               opts.PDOldPermission
            ]);
         }
         break;
         
      case 'OptionPDOther':
         // Need "permission" field in case of "official item" option
         if (opts.PDOtherOfficial) 
            descFields.Permission = opts.PDOfficialPermission;
         break; 

      case 'OptionNFSubject':
         // most FUR elements can be automatically provided:
         descFields.Purpose = (
            opts.NFSubjectCheckDedicated ? 
             ("За визуелну идентификацију објекта чланка. " +
              "Чланак у цјелини посвећен је баш расправи о овом дјелу.") :
            (opts.NFSubjectCheckDiscussed ?
             ("Да се подржи енциклопедијска расправа о овом дјелу у чланку у питању. " +
              "Илустрација је неопходна да подржи сљедећи специфични навод: " +
              "<br/>\n" + opts.NFSubjectPurpose) : null)
         );
         // I hate FURs filled with trivial/predictable/redundant verbiage,
         // so we'll just cut it short. And don't anybody dare complain that
         // that's not a valid FUR.
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;

      case 'OptionNF3D':
         // complex case: we need to assemble attribution and FUR both for the 
         // original 3D work and for the photographic depiction. Both might be 
         // non-free.
         descFields.Author = fuwAppendLines([
            fuwSurroundString("'''Оригинално дјело:''' ", opts.NF3DCreator),
            "<br/>\n",
            fuwSurroundString("'''Депикција:''' ", opts.Author)
         ]);
         descFields.Date = fuwAppendLines([
            fuwSurroundString("'''Оригинално дјело:''' ", opts.NF3DOrigDate),
            "<br/>\n",
            fuwSurroundString("'''Депикција:''' ", opts.Date)
         ]);
         descFields.Purpose = (
            opts.NF3DCheckDedicated ? 
             ("За визуелну идентификацију објекта чланка. " +
              "Чланак у цјелини посвећен је баш расправи о овом дјелу.") :
            (opts.NF3DCheckDiscussed ? 
             ("Да се подржи енциклопедијска расправа о овом дјелу у чланку у питању. " +
              "Илустрација је неопходна да подржи сљедећи специфични навод: " +
              "<br/>\n" + opts.NF3DPurpose) : null)
         );
         descFields.Replaceability = "Н/Д";
         descFields.Commercial    = "Н/Д";
         descFields["Other information"] = (
            opts.NF3DOptionSame ?
            ("Слику је направио и објавио исти аутор који посједује " +
             "ауторска права за оригинално дјело (објекат) и није " +
             "могуће сврсисходно створити алтернативни приказ.") :
            ("Аутор слике објавио је фотографско дјело под " +
             "слободном лиценцом, или је иста у јавном власништву: " + opts.NF3DPermission)
         );
         break; 
         
      case 'OptionNFExcerpt':
         // FURs for screenshots etc. don't normally need to bother
         // about replaceability (with free images) and with commercial role,
         // but do need to bother about purpose and about replaceability with text.
         descFields.Purpose        = opts.NFPurpose;
         descFields.Replaceability_text = opts.NFReplaceableText;
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;
         
      case 'OptionNFCover':
         // cover art gets standard rationales.
         descFields.Purpose = 
            "да служи као примарно средство визуелне идентификације " +
            "при врху чланка посвећеног дјелу у питању.";
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;
 
      case 'OptionNFLogo':
         // logos get standard rationales.
         descFields.Purpose = 
            "да служи као примарно средство визуелне идентификације " +
            "при врху чланка посвећеног ентитету у питању.";
         descFields.Replaceability = "Н/Д";
         descFields.Commercial     = "Н/Д";
         break;

      case 'OptionNFPortrait':
         // as with other historic photographs, it is useful to have both
         // original publication and direct source
         descFields.Source = fuwAppendLines([
            fuwSurroundString("'''Оригинално објављивање''': ", opts.Publication),
            "<br/>\n",
            fuwSurroundString("'''Непосредни извор''': ", opts.Source)
         ]);   
         descFields.Purpose = 
            "за визуелну идентификацију особе у питању, " +
            "при врху његовог/њеног биографског чланка";
         descFields.Replaceability = opts.NFReplaceable;
         descFields.Commercial = opts.NFCommercial;
         descFields['Other information'] = 
            "Субјекат на фотографији је покојник/ца од: " + opts.NFPortraitDeceased;
         break;
         
      case 'OptionNFMisc':
         descFields.Source = fuwAppendLines([
            fuwSurroundString(
               "'''Оригинално објављивање''': ", 
               opts.Publication,
               "<br/>\n'''Непосредни извор:''' "),
            "",
            opts.Source
         ]);   
         descFields.Purpose = opts.NFPurpose;
         descFields.Replaceability = opts.NFReplaceable;
         descFields.Replaceability_text = opts.NFReplaceable_text;
         descFields.Commercial = opts.NFCommercial; 
         break;     
   };

   if (opts.OptionNonFree) {
      // common stuff for all non-free files:
      
      // Minimality field (same for all NF options):
      descFields.Minimality = opts.NFMinimality;
      
      // append optional "extra license" selector and "AnyOther" fields
      // to "Other information" field:
      descFields['Other information'] = fuwAppendLines([
         descFields['Other information'],
         "<br/>\n",
         fuwSurroundString('\{\{', opts.NFExtraLicense, '\}\}'),
         "<br/>\n",
         opts.AnyOther
      ]);
   }
   else {
      // common stuff for all free files:
      descFields.Other_versions = ''
      this.otherInfo = fuwAppendLines([this.otherInfo, "\n\n", opts.AnyOther]);
   
   }

};

fuwGlobal.prototype.formatOutput = function(forCommons) {
   var baseForm = this.ScriptForm;
   var targetForm = this.TargetForm;
   if (fuwTesting) {
      var testForm   = this.TestForm;
   }
   var opts = this.opts;
   var otherInfo = this.otherInfo;
   var descFields = this.descFields;

   var summary = "{{" + this.getDescriptionTemplateName();

   // assemble all fields into the wikitext of the description page:
   var fieldOrder = [
      'Source', 'Date', 'Author', 'Permission', 'Other_versions',
      'Article', 'Purpose', 'Replaceability', 'Replaceability_text', 
      'Minimality', 'Commercial', 'Other information'
   ];
   summary += "\n|Description = " + fuwPackInfo(descFields['Description'], forCommons);
   for (var i = 0; i < fieldOrder.length; i++) {
      if (descFields[fieldOrder[i]]) {
         summary += "\n|" + fieldOrder[i] + " = " + descFields[fieldOrder[i]];
      }
   }
   summary += "\n}}\n";
   if (otherInfo) {
      summary += "\n;Остале информације:\n" + fuwPackInfo(otherInfo, forCommons) + "\n";
   }

   var editSummary = this.getEditSummary();
   
   var license = this.getLicense();
   
   if (forCommons) {
      // pack our description info into an url pointing to the 
      // standard Commons Special:Upload
      // with pre-loaded description fields

      summary = fuwSubst("Ознаку отпремања је додао ЧО sr.wp") + "\n" + summary;
      summary = summary.replace(/\{\{OTRS pending\}\}/g, fuwSubst("OP"));

      if (license.special) {
         // manually format the whole description page including the license tag, if it
         // isn't one of the bare standard licenses in the dropdown box. Otherwise,
         // submit description summary and license as two separate url parameters.
         summary = summary + "\n\n" + license.special;
      }
      return (fuwGetCommonsURL() +
         "?title=Special:Upload" +
         "&wpUploadDescription=" +
         encodeURIComponent(summary) +
         (license.standard ? 
          ("&wpLicense=" + encodeURIComponent(license.standard)) : '') +
         "&wpDestFile=" + 
         encodeURIComponent(opts.InputName));
   }
   else {
      // pack all description into a single "text" parameter to be submitted
      // to the local api.php upload.
      summary = "==Опис==\n" + 
         summary + 
         "\n==Лиценцирање==\n" + 
         (license.standard ? ("\{\{" + license.standard + "\}\}") : license.special) +
         this.getTrackingCategory();
         
      if (fuwTesting) {
         // Testing mode: show our data in the dummy form
         // at the bottom of the page.
         fuwGet('placeholderSandboxFilename').innerHTML = opts.InputName;
         this.TestForm.SandboxSummary.value = editSummary;
         this.TestForm.SandboxText.value = summary;
         fuwSetVisible('placeholderTestForm', true);
      }
      // write output parameters into target form
      // I can't believe IE7 is too stupid to simply understand "this.TargetForm.filename.value".
      ($('#TargetForm [name="filename"]')[0]).value = opts.InputName;
      ($('#TargetForm [name="text"]'    )[0]).value = summary;
      ($('#TargetForm [name="comment"]' )[0]).value = editSummary;
      ($('#TargetForm [name="token"]'   )[0]).value = mw.user.tokens.get('editToken');

   }
   
};

function fuwHasUserGroup(group) {
   // workaround because old IE versions don't have array.indexOf :-(
   for (i = 0; i < mw.config.get('wgUserGroups').length; i++) {
      if (mw.config.get('wgUserGroups')[i] == group) {
         return true;
      }
   }
   return false
}

fuwGlobal.prototype.getUserStatus = function() {
   // function to determine the experience status and userrights of the current user:
   // 'anon': not logged in; can't use script.
   // 'notAutoconfirmed': can't use local upload, but may use script to prepare upload for Commons
   // 'newbie': autoconfirmed but editcount < 100 
   //    (may be used in future to adapt instructions more to newbie needs)
   // 'problem': autoconfirmed but has 3 or more image-related warnings or deletion notifications among recent user talk entries
   //    (may be used in future to produce more strongly worded instructions)
   // 'autoconfirmed': regular user
   // 'sysop'

   if (mw.config.get('wgUserName')) {
      if (fuwHasUserGroup('sysop')) {
         this.userStatus = 'sysop';
      }
      else if (fuwHasUserGroup('autoconfirmed') || fuwHasUserGroup('confirmed')) {
         this.userStatus = 'autoconfirmed';
         $.ajax({
            url     : mw.util.wikiScript( 'api' ),
            type    : 'GET',
            dataType: 'xml',
            traditional : true,
            data:   {
                     format: 'xml',
                     action: 'query',
                     meta  : 'userinfo',
                     uiprop: 'editcount',
                     prop  : 'revisions',
                     titles: 'User talk' + mw.config.get('wgUserName'),
                     rvprop: 'comment|user',
                     rvlimit: 30
                    },      
            success: function(data) {
            // callback func     
               var fuw = window.fuw;
               if (data) {
                  var ui = data.getElementsByTagName('userinfo');
                  if (ui) {
                     var editcount = ui[0].getAttribute('editcount');
                     if (editcount < 100) {
                        fuw.userStatus = 'newbie';
                     }
                  }
                  var revs = data.getElementsByTagName('rev');
                  var countWarn = 0;
                  for (i = 0; i < revs.length; i++) {
                     var rev = revs[i];
                     var usr = rev.getAttribute('user');
                     var cmt = rev.getAttribute('comment');
                     if ((usr == 'ImageTaggingBot') ||
                         (cmt.search(/(означавање за брисање \[\[Датотека)|(недостају датотеке за отпремање)|(Датотека (извор и )?проблем са лиценцирањем ауторских права)|(Номиновање за брзо брисање \[\[Датотека)|(Обавјештење: стављање на списак \[\[могуће неслободне датотеке)/) >= 0)) {
                        countWarn += 1;   
                     }
                  }
                  if (countWarn >= 3) {
                     fuw.userStatus = 'problem';
                  }
               }
            }
         });
      }
      else {
         this.userStatus = 'notAutoconfirmed';
      }
   }
   else {
      this.userStatus = 'anon';
   }
};

// =================================================================
// Convenience function for getting the regular index.php
// interface of Commons. Not very elegant.
// =================================================================
function fuwGetCommonsURL() {
   if (document.URL.match(/^https:/)) 
      return "https://commons.wikimedia.org/w/index.php";
   else
      return "http://commons.wikimedia.org/w/index.php";
}  

// ==================================================================
// functions for building form elements
// ==================================================================
fuwMakeRadiobutton = function(group, option, checked, event) {
   // Stupid IE7 doesn't get "value" attribute unless it's created in this convoluted way.
   // Annoying.   
   var node = $('<input type="radio" id="' + option + '" name="' + group + '" value="' + option + '"></input>')[0];
   if (checked) node.checked = true;
   node.onclick = event || fuwRadioClick;
   node.onclick = event || fuwRadioClick;
   fuwAppendInput(option, node);
};
fuwMakeTextfield = function(label, event) {
   var node  = document.createElement('input');
   node.type = 'text';
   node.name = label;
   node.size = fuwDefaultTextboxLength;
   node.onchange = event || fuwUpdateOptions;
   // only for testing:
   //node.value = label;
   fuwAppendInput(label, node);
};
fuwMakeTextarea = function(label, event) {
   var node  = document.createElement('textarea');
   node.name = label;
   node.rows = fuwDefaultTextareaLines;
   node.style.width = fuwDefaultTextareaWidth;
   node.onchange = event || fuwUpdateOptions;
   //only for testing:
   //node.innerHTML = label;
   fuwAppendInput(label, node);
};
fuwMakeCheckbox = function(label, checked, event) {
   var node  = document.createElement('input');
   node.name = label;
   node.type = 'checkbox';
   //only for testing:
   //node.title= label;
   node.checked = checked;
   node.onchange = event || fuwUpdateOptions;
   fuwAppendInput(label, node);
}
fuwMakeHiddenfield = function(name, value, id) {
   var node   = document.createElement('input');
   node.name  = name;
   node.type  = 'hidden';
   node.value = value;
   fuwAppendInput((id || name), node);
};
fuwMakeAnchor = function(label, href, content) {
   var node   = document.createElement('a');
   node.name  = label;
   node.target= "_blank";
   node.href  = href;
   node.innerHTML = content;
   fuwAppendInput(label, node);
};
fuwMakeSelection = function(name, values) {
   var root = document.createElement('select');
   var current = root;
   try {
      for (i=0; i<values.length; i++) {
         var line = values[i];
         var entry;
         if (line.length == 0) {
            current = root;
         }
         else if (line.length == 1) {
            entry = document.createElement('optgroup');
            entry.setAttribute('label', line[0]);
            root.appendChild(entry);
            current = entry;
         }
         else {
            entry = document.createElement('option');
            entry.setAttribute('value', line[0]);
            entry.setAttribute('title', '{{' + line[0] + '}}');
            entry.innerHTML = line[1];
            if (line.length > 2) {
               entry.setAttribute('selected', 'selected');
            } 
            current.appendChild(entry);
         }
      }
   } catch (e) { alert("Назив: " + name + ", i=" + i); }
   root.name = name;
   root.onchange = fuwUpdateOptions;
   fuwAppendInput(name, root);
};
function fuwMakeWikilink(place, target, redlink, display) {
   
   place = fuwGet(place);
   var id = place.id;
   var anchor;
   if (place.tagName == 'A') {
      anchor = place;
   }
   else {
      anchor = document.createElement('a');
      place.appendChild(anchor);
   }
   anchor.href = mw.util.getUrl(target);
   anchor.title = target;
   anchor.innerHTML = target;
   anchor.className = (redlink ? 'new' : null);
}

function fuwAppendInput(label, content) {
   // append a newly created input element to an existing
   // span element marked as id="placeholderXYZ"
   var node = fuwGet('placeholder' + label);
   var old  = fuwGet(label);
   if (old) {
      old.parentNode.removeChild(old);
   }
   content.id = content.id || label;
   if (node) {
      while (node.hasChildNodes()) {
         node.removeChild(node.firstChild);
      }
      node.appendChild(content);
   }
}

// ======================================================
// move an element away from its current position
// and append it to a target element if condition is true
// ======================================================
function fuwMove(mv, tg, condition, toStart) {
   if (condition) {
      move   = fuwGet(mv);
      target = fuwGet(tg);
      if (move && target) {
         var parent = move.parentNode;
         if (! (target===parent)) {
            parent.removeChild(move);
            if (toStart) {
               target.insertBefore(move, target.firstChild);
            }
            else {
               target.appendChild(move);
            }
         }
      }
      else {
         alert("Непронађени елементи: move=" + mv + "(" + move + "), target=" + tg + "(" + target + ")");
      } 
   }
   return condition;
}

// ===================================================
// make an element visible/invisible
// ===================================================
function fuwSetVisible(tg, condition) {
   target = fuwGet(tg);
   if (target) {
      if (condition) {
         $(target).show();
      }
      else {
         $(target).hide();
      }
   }
   else {
      alert("Непронађени елемент: " +  (tg.nodeType ? tg.id : tg));
   }
}

// ===================================================
// set enabled/disabled status for an element and/or
// all input controls contained in it.
// ===================================================
function fuwSetEnabled(tg, condition) {
   target = fuwGet(tg);
   try {
      var elements = (target.tagName.match(/^(input|textarea|select|button|a)$/i) ? 
         [target] :
         $('#' + target.id + ' *'));
      for (i = 0; i<elements.length; i++) {
         if (elements[i].tagName.match(/^(input|textarea|select|button|a)$/i)) {
            elements[i].disabled = (condition ? null : "онемогућено");
         }
      }
   } catch (e) { alert("Непронађени елемент: " +  (tg.nodeType ? tg.id : tg)); }
}

// ===================================================
// convenience function to check whether a given
// element is currenly visible. Needs to check display
// property of the element and its ancestors
// ===================================================
function fuwIsVisible(el) {
   element = fuwGet(el);
   if (!element) return false;
   el = element.id;
   
   var visible = true;
   while (! (element === document.body)) {
      if (element.style.display == "none") {
         visible = false;
         break;
      }
      element = element.parentNode;
   }
   return visible;
}

// ===================================================
// cleanup filename
// ===================================================
function fuwCleanFilename() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var oldname = name = $.trim(nameBox.value);

   if (name) {
      // strip accidentally added [[   ]] or [[:  ]] brackets
      name = name.replace(/(^\[\[:?)|(\]\]$)/g, "");
      // strip accidentally added "File:" prefix
      name = name.replace(/^(File|Image|Датотека|Слика|Datoteka|Slika):/, "");
      // replace underscores with spaces
      name = name.replace(/_/g, " ");
      // uppercase first letter
      name = name.charAt( 0 ).toUpperCase() + name.slice(1);
   }
   if (oldname != name) {
      nameBox.value = name;
   }
   // always return true so the next validation step will proceed:
   return true;
}


// ==================================================
// check filename for technically illegal 
// characters, trying to fix them automatically
// ==================================================
function fuwCheckLegalFilename() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var oldname = name = $.trim(nameBox.value);

   if (name) {
      // resolve accidentally entered html entities and URI-encoded %XX character codes
      name = name.replace(/\&[a-z]+;/g, fuwHtmlEntityDecode);
      name = name.replace(/(\%[A-F0-9]{2,2})/g, decodeURI);
      // remove illegal characters # < > [ ] | { } /:
      // using a best guess for an acceptable replacement
      name = name.replace(/[<\[\{]/g, "(");
      name = name.replace(/[>\]\}]/g, ")");
      name = name.replace(/[#:\|]/g,  ",");
      name = name.replace(/\//g, "-");
      // remove sequences of tildes
      name = name.replace(/\~{3,}/g, "---");
      // remove initial slash
      name = name.replace(/^\//, "");
   }
   
   if (oldname != name) {
      window.fuw.warn.IllegalChars = true;
      nameBox.value = name;
      return false;
   }
   else {
      window.fuw.warn.IllegalChars = false;
      return true;
   }
}
function fuwHtmlEntityDecode(str) {
   // hack to translate accidentally entered html entity code
   // into actual characters
   var ta=document.createElement('textarea');
   ta.innerHTML=str.replace(/</g,'<').replace(/>/g,'>');
   return ta.value;
}

// =======================================================
// Check against various common patterns of poorly chosen
// filenames (too short / too generic)
// =======================================================
function fuwCheckPoorFilename() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var name = $.trim(nameBox.value);
	name = name.replace(/\.(png|gif|jpg|jpeg|xcf|pdf|mid|ogg|ogv|svg|djvu|tiff|tif|oga)$/i, "");

   // name should be at least 10 characters long, excluding file type extension
   var tooShort = (name.length < 10);
   
   // common generic filename patterns: 
   // IMG......jpg
   // Image....jpg
   // DSC......jpg
   // Picture......jpg
   // Pic..........jpg
   // anything that has fewer than 3 alphabetic letters and then just numbers
   var pattern = /^(img|image|dsc|picture|pic)?(\\s*|\\_*|[a-z]{,3})?\\d+$/i;
   var auto = name.match(pattern);

   window.fuw.warn.BadFilename = (tooShort || auto);
   return !tooShort && !auto;
}

// =======================================================
// check if file extensions match between local filename
// and target filename input box. Automatically append 
// appropriate extension to target filename if they don't.
// =======================================================
function fuwCheckFileExtension() {
   var nameBox = window.fuw.ScriptForm.InputName;
   var name = $.trim(nameBox.value);
   var fileBox = window.fuw.TargetForm.file;
   var file = fileBox.value;
   
   // cancel check if no filename has been provided yet
   if (!file || !name) return true;
   
   var extensions = /.+\.(png|gif|jpg|jpeg|xcf|pdf|mid|ogg|ogv|svg|djvu|tiff|tif|oga)$/i;
   var mimetypes = {
      "png"  : "image/png",
      "gif"  : "image/gif",
      "jpg"  : "image/jpeg",
      "jpeg" : "image/jpeg",
      "xcf"  : "image/x-xcf",
      "pdf"  : "application/pdf",
      "mid"  : "audio/rtp-midi",
      "ogg"  : "audio/ogg",
      "ogv"  : "video/ogg",
      "svg"  : "image/svg+xml",
      "djvu" : "image/vnd.djvu",
      "tiff" : "image/tiff",
      "tif"  : "image/tiff",
      "oga"  : "video/ogg"
   };   

   var found = extensions.exec(file);
   var fileExt = found ? found[1].toLowerCase() : "";
   found = extensions.exec(name);
   var nameExt = found ? found[1].toLowerCase() : "";
   var mime = mimetypes[fileExt]; 
   
   if (fileExt && mime && (mimetypes[nameExt] != mime)) {
      nameBox.value = name.replace(/\.?$/, ('.' + fileExt));
   }
   return true;
}

// ============================================================
// Check if a file under the chosen name already exists,
// either locally or on Commons.
// Store results in the fuw.warn object, so warnings will
// be displayed on the next fuwUpdateOptions() call
// ============================================================
function fuwCheckFileExists() {
   // this is an asynchronous AJAX function.
   // results won't yet be present when this function returns.

   var nameBox = window.fuw.ScriptForm.InputName;
   var name = $.trim(nameBox.value);

   // using the jQuery wrapper for the Ajax functionality:
   $.ajax({
      url     : mw.util.wikiScript( 'api' ),
      type    : 'GET',
      dataType: 'xml',
      traditional : true,
      data:   {
               format: 'xml',
               action: 'query',
               titles: 'Датотека:' + name,
               prop  : 'imageinfo',
               iiprop: 'url|user',
               iiurlwidth: 120
              },      
      success: function(resp) {
      // callback function, called when API query has succeeded:
         // see if the request has returned info from an existing image:
         var foundlist = resp.getElementsByTagName('ii');
         var exists = (foundlist.length >= 1);
         var isCommons = false;
         if (exists) {

            // extract description data from http response.
            // see https://www.mediawiki.org/wiki/API:Properties#imageinfo_.2F_ii 
            // for structure of API response
            var foundImg = foundlist[0];
            isCommons = (foundImg.parentNode.parentNode.getAttribute('imagerepository')=='shared');

            // need this data for creating our own image thumb link
            var width = foundImg.getAttribute('thumbwidth');
            var height = foundImg.getAttribute('thumbheight');
            var thumbURL = foundImg.getAttribute('thumburl');
            var lastUser = foundImg.getAttribute('user');
            var descURL = foundImg.getAttribute('descriptionurl');

            // API returns link to local description page even for Commons images.
            // However, we want a direct link to Commons.
            if (isCommons) {
               descURL = descURL.replace(/sr\.wikipedia\.org/, "commons.wikimedia.org");
               descURL = descURL.replace(/\/\/secure\.wikimedia\.org\/wikipedia\/sr/, "commons.wikimedia.org");
            }

            // build the image info into the warning section of our page:
            thumbDiv = fuwGet('warningImageThumb');
            if (thumbDiv) {
            
               // make all links point to description page:
               var thumbA = thumbDiv.getElementsByTagName('a');
               for (i = 0; i<thumbA.length; i++) {
                  thumbA[i].setAttribute('href', descURL);
               }
               // insert the image itself:
               var thumbImg = thumbDiv.getElementsByTagName('img');
               if (thumbImg.length > 0) {
                  thumbImg = thumbImg[0];
                  thumbImg.setAttribute('src', thumbURL);
                  thumbImg.setAttribute('width', width);
                  thumbImg.setAttribute('height', height);
               }
               // insert the name of the last uploader:
               var thumbSpan = fuwGet('existingImageUploader');
               // TO DO: turn this into a proper link
               if (thumbSpan) thumbSpan.innerHTML = lastUser;
            }

            
         }
         warn = window.fuw.warn;
         warn.ImageOnCommons = exists && isCommons;
         warn.ImageExists    = exists && !isCommons;

         fuwUpdateOptions();
      }
   });
}

// ===========================================================
// onchange event handler for the local filename box
// ===========================================================
fuwValidateFile = function() {
   fuwCheckFileExtension();
   fuwUpdateOptions();
}

// ===========================================================
// onchange event handler for the name input box
// ===========================================================
fuwValidateFilename = function() {
   fuwCleanFilename();
   if (
      fuwCheckLegalFilename() &&
      fuwCheckPoorFilename() &&
      fuwCheckFileExtension()) {
      // after fuwCheckFileExists(),
      // fuwUpdateOptions will be triggered
      // by the callback function after Ajax completion
      fuwCheckFileExists();
   }
   else {
      // if there's been no Ajax call.
      fuwUpdateOptions();
   }
};

// ==========================================================
// function fuwValidateNFArticle()
// ==========================================================
// This is the validation routine for the obligatory
// article-to-be-used-in field for non-free files. It queries
// api.php about the target article through an Ajax call.
// It will store error info in the fuw.warn object,
// triggering the following error on the next updateOptions():
// * warningNFArticleNotFound : target page doesn't exist.
// * warningNFArticleNotMainspace : target is not an article. 
// * warningNFArticleDab : target is a disambiguation page.
// Redirects will automatically be substituted.
// ==========================================================
fuwValidateNFArticle = function() {
   
   var nameBox = window.fuw.ScriptForm.NFArticle;
   oldname = name = nameBox.value;
   
   // cleanup article name:
   // automatically fix accidentally added [[ ... ]] and
   // regularize underscores
   name = $.trim(name);
   name = name.replace(/(^\[\[)|(\]\]$)/g, "");
   // automatically fix article names entered as full urls:
   name = name.replace(/^https?:\/\/sr\.wikipedia\.org\/wiki\//, "");
   name = name.replace(/^https?:\/\/sr\.wikipedia\.org\/w\/index\.php\?title=/, "");
   name = name.replace(/_/g, " ");
   if (name != oldname) nameBox.value = name;
   
   // do nothing more if field was blank
   if (!name) return;

   // using the jQuery wrapper for the Ajax functionality:
   $.ajax({
      url     : mw.util.wikiScript( 'api' ),
      type    : 'GET',
      dataType: 'xml',
      traditional : true,
      data:   {
               format: 'xml',
               action: 'query',
               titles: name,
               prop  : 'info|categories|links'
              },      
      success: function(resp) {
      // callback function, called when API query has succeeded:
         var errorType = 0;
         var pg = resp.getElementsByTagName('page')[0];
         var title = pg.getAttribute('title');
         var target = title;
         if (pg.getAttribute('missing') != null) {
            // no page found under this title.
            errorType = 1;
         }           
         else {
            var userspace = false;
            var ns = pg.getAttribute('ns');
            var rd = pg.getAttribute('redirect');
            if (ns != 0) {
               // not a mainspace page!
               errorType = 2;

               // try to detect if the target might be a user space draft:               
               if (title.match(new RegExp("User( talk)?:" + mw.config.get('wgUserName')))) {
                  userspace = true;
               }
            }
            else if (rd != null) {
               // redirect page
               // API returns an empty redirect="" attribute if
               // the page is a redirect
               var targets = pg.getElementsByTagName('pl');
               for (i=0; i<targets.length; i++) {
                  var link = targets[i];
                  if (link.getAttribute('ns')==0) {
                     target = link.getAttribute('title');
                     errorType = 3;
                     break;
                  }
               }
            }
            else {
               // check for disambiguation categories
               var cats = pg.getElementsByTagName('cl');
               for (i=0; i<cats.length; i++) {
                  var cat = cats[i];
                  if (cat.getAttribute('title') == "Категорија:Вишезначна одредница") {
                     errorType = 4;
                     break;
                  }
               }  
            }
         }
         warn = window.fuw.warn;
         warn.NFArticleNotFound = (errorType==1);
         warn.NFArticleNotMainspace = (errorType==2);
         warn.UserspaceDraft = ((errorType==2) && userspace);
         warn.NFArticleDab = (errorType==4);
         warn.NFArticleOK  = (errorType==0);

         // fix links in error messages:
         if (warn.NFArticleNotFound) {
            fuwMakeWikilink(fuwGet('warningNFArticleNotFound').getElementsByTagName('A')[0], target, true);
         }
         else if (warn.NFArticleNotMainspace) {
            fuwMakeWikilink(fuwGet('warningNFArticleNotMainspace').getElementsByTagName('A')[0], target);
         }
         else if (warn.NFArticleDab) {
            fuwMakeWikilink(fuwGet('warningNFArticleDab').getElementsByTagName('A')[0], target);
         }
         else if (warn.NFArticleOK) {
            fuwMakeWikilink(fuwGet('NFArticleOK').getElementsByTagName('A')[0], target);
         }
                       
         if (errorType==3) {
            // automatically replace title with redirect target
            window.fuw.ScriptForm.NFArticle.value = target;
            // need to recursively call validation again now
            //if (confirm(name + " је преусмјерење. Пратите га до " + target + "?")) {
               fuwValidateNFArticle();
            //}
         }
         else {
            fuwUpdateOptions();
         }          
      }
   });
};

// ================================================
// manually reload script (just for testing)
// ================================================
function fuwReload() {
   mw.loader.load( 'http://localhost/script/uploadscript.js' );
   fuwReset();
}

// ================================================
// reset forms
// TO DO: add a button that actually triggers this.
// ================================================
function fuwReset() {
   var forms = mw.util.$content[0].getElementsByTagName('form');
   for (i = 0; i < forms.length; i++) {
      forms[i].reset();
      window.fuw.warn = { };
      window.fuw.opts = { };
   }
   fuwSetVisible('UploadScriptArea', true);
   fuwSetVisible('fuwSuccess', false);
   fuwSetVisible('fuwWaiting', false);
   fuwUpdateOptions();
}

// ===============================================
// convenience functions for string handling
// ===============================================
function fuwAppendLines(parts) {
   // assemble a string from an array of strings.
   // treat every second element as a conditional
   // separator that will be included only if 
   // surrounding elements are non-empty.
   var build = "";
   for (var i = 0; i < parts.length; i += 2) {
      if (parts[i]) {
         if (build) build += parts[i - 1];
         build += parts[i];
      }
   }
   return build;
}
function fuwSurroundString(prefix, content, suffix) {
   // put a prefix and a suffix on a string, 
   // if the input string is non-empty.
   if (content) 
      return (prefix ? prefix : "") + content + (suffix ? suffix : ""); 
   else return "";
}

// ========================================================
// convenience function for accessing the contents of the
// dummy TargetIFrame
// ========================================================
function fuwGetDocumentFromIFrame(iframe) {
   var doc = (iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document);
   if (doc.XMLDocument) {
      doc = doc.XMLDocument;
   }
   return doc;
}
// ========================================================
// event handler for the dummy TargetIFrame's onload event.
// TO DO: expand stub to add real notification of success,
// link to new file page, instructions about how to include
// file in articles, etc.
// ========================================================
function fuwUploadCompleted() {
   var doc = fuwGetDocumentFromIFrame(fuwGet('TargetIFrame'));
   if (doc) {
      //alert(doc);
      fuwSetVisible('successThumb', false);

      var fuw = window.fuw;
      var name = fuw.opts.InputName;

      var uploads = doc.getElementsByTagName('upload');
      var success = false;
      for (i = uploads.length-1; i>=0; i--) {
         if (uploads[i].getAttribute('result') == 'Success') {
            success = true;
            // need to get the real resulting filename here; might be different from the requested one in some cases.
            name = uploads[i].getAttribute('filename');
            break;
         }
      }
      if (success) {

         // need another ajax call to check the file is actually there,
         // and to retrieve its direct thumb img url:
         $.ajax({
            url     : mw.util.wikiScript( 'api' ),
            type    : 'GET',
            dataType: 'xml',
            traditional : true,
            data:   {
                     format: 'xml',
                     action: 'query',
                     titles: 'Датотека:' + name,
                     prop  : 'imageinfo',
                     iiprop: 'url',
                     iiurlwidth: 120
                    },      
            success: function(resp) {
               // callback function, called when API query has succeeded:
               // see if the request has returned info from an existing image:

               var foundImg = resp.getElementsByTagName('ii')[0];
               if (foundImg) {

                  // need this data for creating our own image thumb link
                  var width = foundImg.getAttribute('thumbwidth');
                  var height = foundImg.getAttribute('thumbheight');
                  var thumbURL = foundImg.getAttribute('thumburl');
                  var lastUser = foundImg.getAttribute('user');
                  var descURL = foundImg.getAttribute('descriptionurl');

                  // build the thumbnail in the success message:
                  thumbDiv = fuwGet('successThumb');
                  
                  // make link point to description page:
                  var thumbA = thumbDiv.getElementsByTagName('a')[0];
                  thumbA.href = descURL;

                  // insert the image itself:
                  var thumbImg = thumbDiv.getElementsByTagName('img')[0];
                  thumbImg.setAttribute('src', thumbURL);
                  thumbImg.setAttribute('width', width);
                  thumbImg.setAttribute('height', height);
                  
                  fuwSetVisible(thumbDiv, true);
               }
            }
         });
         fuwMakeWikilink(
            fuwGet('fuwSuccessLink2').getElementsByTagName('a')[0],
            'Датотека:' + name);
         fuwGet('placeholderExFilename1').innerHTML = name;
         fuwGet('placeholderExFilename2').innerHTML = name;
         fuwSetVisible('fuwSuccess', true);
         fuwSetVisible('fuwWaiting', false);
      }
      else {
         var err = doc.getElementsByTagName('error');
         if (err) {
            var info = err[0].getAttribute('info');
            var details = err[0].getElementsByTagName('detail');
            var add = "";
            for (i = 0; i < details.length; i++) {
               if (add.length > 0) add += ", ";
               add += details[i].textContent;
            }
            if (add) {
               info = info + " (" + add + ")";
            }
            alert("Отпремање није успјело: " + info);
         }
         else {
            alert("Непозната грешка: Отпремање можда није успјело.");
         }
      }
   }
}

// ========================================================
// clean out dummy IFrame before submitting a request
// ========================================================
function fuwResetTargetIFrame() {
   var doc = fuwGetDocumentFromIFrame(fuwGet('TargetIFrame'));
   if (doc) {
      while (doc.hasChildNodes()) {
         doc.removeChild(doc.firstChild);
      }
   }
}

// ========================================================
// Event handler for the real submit button
// ========================================================
function fuwSubmitUpload() {
   
   var fuw = window.fuw;
   var frm = fuw.TargetForm;

   fuw.collectInput();
   fuw.formatOutput(false);

   // we will use the iframe's onload event to trigger a function that
   // adds success notification etc.
   fuwResetTargetIFrame();
   var ifr = fuwGet('TargetIFrame');
   if (ifr.attachEvent) {
      // workaround for IE, according to 
      // http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/
      ifr.attachEvent("onload", fuwUploadCompleted);
   }
   else {
      // all other browsers
      ifr.onload = fuwUploadCompleted;
   }

   if (fuwTesting) {
      fuwSetVisible('placeholderTestForm', false);
   }
   fuwSetVisible('UploadScriptArea', false);

   fuwMakeWikilink(
     fuwGet('fuwSuccessLink').getElementsByTagName('a')[0], 'Датотека:' + fuw.opts.InputName);
   fuwSetVisible('fuwWaiting', true);

   frm.submit();
   var opts = window.fuw.opts;
   // the API won't overwrite the description page text while overwriting
   // a file, which is really, really, really annoying and stupid.
   // So in the opts.OverwriteDifferent scenario, we need to edit
   // the description page through a separate ajax call. Dang.
   if (opts.OverwriteDifferent) {
      $.ajax({
         url   : mw.util.wikiScript('api'),
         type  : 'POST',
         dataType : 'xml',
         data  : {
                  format : 'xml',
                  action : 'edit',
                  title  : 'Датотека:' + opts.InputName,
                  token  : mw.user.tokens.get('editToken'),
                  summary : opts.EditSummary,
                  text   : ($('#TargetForm .[name="text"]')[0]).value

                 }
      });
   }
}

// =======================================================
// Event handler for the Commons submit button
// =======================================================
function fuwSubmitCommons() {
   var fuw = window.fuw;
   fuw.collectInput();
   var url = fuw.formatOutput(true);
   alert("Сада ћете бити преусмјерени на Оставу. \nКористите образац за отпремање на Остави да бисте додали категорије у опис датотеке коју отпремате, а потом завршите отпремање.");
   window.location = url;
}

// =======================================================
// Event handler for the test submit button
// (write description string to sandbox only)
// =======================================================
function fuwSubmitSandbox() {
   var frm = window.fuw.TestForm;
   $.ajax({
      url     : mw.util.wikiScript( 'api' ),
      type    : 'POST',
      dataType: 'xml',
      data:   {
               format: 'xml',
               action: 'edit',
               title : mw.config.get('wgPageName') + "/sandbox",
               token : mw.user.tokens.get('editToken'),
               recreate : 1,
               summary  : frm.SandboxSummary.value,
               text     : frm.SandboxText.value
              },      
      success: function(resp) {
         alert("Уређена страница пијеска!");
      }
   });
}



// ========================================================
// convenience wrapper function to replace calls to
// document.getElementById() 
// to avoid browser incompatibility
// ========================================================
function fuwGet(target) {
   if (target && target.nodeType) return target;
   else {
      var found = $('#' + target);
      if (found) return found[0];
   }
   return undefined;
}

// ========================================================
// onload hook function, loading this script
// ========================================================
$(function() { 
   if (fuwGet('UploadScriptArea')) {
      window.fuw = new fuwGlobal();
      fuwUpdateOptions();
   }
});

Ako ne bude radilo pokušaću popraviti.  Obsuser 11:06, 29. maj 2017. (CEST)[odgovori]

@Ranko Nikolić: Možeš li dodati thumbA[i].setAttribute('title', 'Датотека:' .. name); ispod thumbA[i].setAttribute('href', descURL); i thumbA.title = 'Датотека:' .. name; ispod thumbA.href = descURL; neće li se promijeniti onaj hover tekst „Datoteka:Example sr-ijek.svg” definisan u atributu title taga a? Nadam se da ne treba + umjesto ...   Obsuser 03:18, 30. maj 2017. (CEST)[odgovori]
Takođe treba zamijeniti Ознаку отпремања је додао ЧО sr.wp sa Upload marker added by sr.wp UW jer je ovo ime šablona na Ostavi koji sam upravo napravio.  Obsuser 03:03, 3. jun 2017. (CEST)[odgovori]
@Obsuser: Mislim da je sve ovo urađeno. — Ranko   Niko lić   11:46, 19. jul 2017. (CEST)[odgovori]

Dorada 2

@Ranko Nikolić Ako možeš izvrši sledeće zamene:

  • ... image/vnd.djvu,audio/ogg,video/ogg,audio/rtp-midi → ... image/vnd.djvu,audio/ogg,video/ogg,audio/rtp-midi,audio/wav
  • png|gif|jpg|jpeg|xcf|pdf|mid|ogg|ogv|svg|djvu|tiff|tif|ogapng|gif|jpg|jpeg|xcf|pdf|mid|ogg|ogv|svg|djvu|tiff|tif|oga|wav ×2
  • "oga"  : "video/ogg""oga"  : "video/ogg", pa u novom redu "wav"  : "audio/wav" sa onim razmacima iz koda a ne odavde sa SZR

Ovime bi trebalo da se automatski dodaju nastavci i za wav format itd.   Obsuser 05:39, 8. avgust 2017. (CEST)[odgovori]