Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
<<courseAdminPanel>>/%
|Автор |Елена Викторовна Батаева|
|Аудитория |9-11 класс|
|Картинка в шапке |./inorganic/chem_header.jpg|
|courseId |inorganic_chemistry|
!!!Описание
<p>Химия — экспериментальная наука. В этом курсе все объяснения строятся на основе химического эксперимента (видеоопытов). Эксперимент дополнен объяснениями и иллюстрациями.</p>
<p>Курс предназначен для учащихся 9-11 классов, изучающих неорганическую химию и стремящихся систематизировать эмпирический материал во всём его многообразии.</p>
<img style="float:right; width: 200px; margin-left: 15px;" src="inorganic/author_200x256.jpg">
<p><b>Елена Викторовна Батаева</b></p>
<p>Кандидат педагогических наук (специальность — методика преподавания химии). Доцент кафедры общей химии МГУ. Преподаватель и заведующая кафедрой химии школы «Интеллектуал».</p>
<p><a href="https://www.youtube.com/embed/EaV5sqh2tiI?rel=0" target="_blank">Лекция. Новые возможности школьного эксперимента.</a></p>
!!!In title
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Аллотропный переход: красный фосфор – белый фосфор" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/1 allotropy/1 - Allotropy of Phosphorus-01.jpg" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Взаимоусиливающийся гидролиз железа (III) и карбоната" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/6%20Iron%20hydrolysis/6 - Iron hydrolysis mutually (III) and carbonate.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Гидролиз солей аммония" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/7%20hydrolysis/7 - Hydrolysis of ammonium salts.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Гидролиз хлорида аммония" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/pager_11/pager_11.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Димеризация оксида азота (IV) и смещение равновесия в этой реакции" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/4%20dimerization/4 - Dimerization of nitric oxide IV and the shift in the reaction equilibrium.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Окислительно-восстановительные процессы 1" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/8 redox/8 - Redox processes.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Окислительно-восстановительные свойства нитритов" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/12%20nitrites/12 - Redox properties of nitrites.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Основные свойства аммиака" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/16%20basic%20ammonia/16 - The basic properties of ammonia.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Отношение солей аммония к нагреванию" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/5 ammonia/5 - Ammonia and heating-03.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Получение и свойства аммиака" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/2 preparation ammonia/2 - Preparation and properties of ammonia.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Получение и свойства оксида азота (II)" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/15%20Receive%20NO/15%20-%20Receive%20NO.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Разложение нитратов" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/3%20nitrate/3 - Nitrate Decomposition.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
|visibleName|Реакции с участием газов|
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
|visibleName|Сравнение окислительно-восстановительной способности нитратов и нитритов|
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Сравнения окислительно-восстановительной способности нитратов и нитритов" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/pager_13/pager_13.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
<img tiddlylink="Фосфаты бария" onclick="onClickTiddlerLink(event)" src="inorganic/pagers/22 phosphates/22 - Phosphates barium.png" class="chem_page_preview" />
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
<<lessonAdminPanel>>/%
!!!Описание
!%/
|ссылка на материал|https://www.youtube.com/embed/eRksvbLO8QY?rel=0|
|ссылка на материал|https://www.youtube.com/embed/pvnNeIR3OvM?rel=0|
|ссылка на материал|https://www.youtube.com/embed/60UK8DMK18Y?rel=0|
|тип шага|pager|
|ссылка на контент шага|./inorganic/pagers/1 allotropy/allo_pager_draft.html|
|ссылка на материал|./inorganic/pagers/1 - allotropy of phosphorus.pdf|
|занимает памяти|22 Мб|
|ссылка на материал|https://www.youtube.com/embed/-ZEiBuoXW6o?rel=0|
|ссылка на материал|https://www.youtube.com/embed/lXk20NsiwTE?rel=0|
|ссылка на материал|https://www.youtube.com/embed/O2HXmWRpLHg?rel=0|
|ссылка на материал|https://www.youtube.com/embed/JCgByl_PMVU?rel=0|
|ссылка на материал|https://www.youtube.com/embed/vNJY4TmIcA8?rel=0|
|ссылка на материал|https://www.youtube.com/embed/EJCUWon4vpo?rel=0|
|ссылка на контент шага|./inorganic/pagers/6%20Iron%20hydrolysis/hydro_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/6%20-%20Iron%20hydrolysis%20mutually%20(III)%20and%20carbonate.pdf|
|занимает памяти|3,1 Мб|
|ссылка на материал|https://www.youtube.com/embed/latFvZClpZA?rel=0|
|ссылка на материал|https://www.youtube.com/embed/DQejC9eUtiA?rel=0|
|ссылка на материал|https://www.youtube.com/embed/moFSdBhcK3k?rel=0|
|ссылка на материал|https://www.youtube.com/embed/D3SF786JEK0?rel=0|
|ссылка на материал|https://www.youtube.com/embed/YWqZvlaEKQA?rel=0|
|ссылка на материал|https://www.youtube.com/embed/29VmQghiy-4?rel=0|
|ссылка на материал|https://www.youtube.com/embed/zXwptl0bK5Q?rel=0|
|ссылка на материал|https://www.youtube.com/embed/IYZblX_9XM4?rel=0|
|ссылка на материал|https://www.youtube.com/embed/Ma1_q_SGaLU?rel=0|
|ссылка на материал|https://www.youtube.com/embed/fbkGTiZbltA?rel=0|
|ссылка на материал|https://www.youtube.com/embed/WZDkV2gjR-w?rel=0|
|ссылка на материал|https://www.youtube.com/embed/NaA7UOkOSo8?rel=0|
|ссылка на материал|https://www.youtube.com/embed/KyI44XQd7A0?rel=0|
|ссылка на материал|https://www.youtube.com/embed/6KZlUhg7AC8?rel=0|
|ссылка на материал|https://www.youtube.com/embed/dHiFCiA1a0g?rel=0|
|ссылка на контент шага|./inorganic/pagers/7%20hydrolysis/hydrolysis_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/7%20-%20Hydrolysis%20of%20ammonium%20salts.pdf|
|занимает памяти|1,9 Мб|
|ссылка на материал|https://youtube.com/embed/GQMtulWbEm4?rel=0|
|ссылка на материал|https://youtube.com/embed/bed1fhz-Tlw?rel=0|
|ссылка на материал|https://youtube.com/embed/DMv_aOSsIP0?rel=0|
|ссылка на материал|https://youtube.com/embed/wprARm0Aawk?rel=0|
|ссылка на материал|https://youtube.com/embed/oaZlIiGSyGE?rel=0|
|ссылка на материал|https://www.youtube.com/embed/vJI7ltsjToQ?rel=0|
|ссылка на материал|https://www.youtube.com/embed/RqeSEMI_cLo?rel=0|
|visibleName||
|ссылка на материал|https://www.youtube.com/embed/b2xApxW-rHE?rel=0|
|ссылка на контент шага|./inorganic/pagers/pager_11/index.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/pager_11/Гидролиз_хлорида_аммония.pdf|
|занимает памяти|1,8 Мб|
|ссылка на материал|https://www.youtube.com/embed/yBqMtBAQeK4?rel=0|
|ссылка на контент шага|./inorganic/pagers/4%20dimerization/dimerization_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/4%20-%20Dimerization%20of%20nitric%20oxide%20IV%20and%20the%20shift%20in%20the%20reaction%20equilibrium.pdf|
|занимает памяти|14,1 Мб|
|ссылка на материал|https://www.youtube.com/embed/_xxR2-98MWI?rel=0|
|ссылка на материал|https://www.youtube.com/embed/VFcTA8dbtBQ?rel=0|
|ссылка на материал|https://www.youtube.com/embed/7l6jRFTG680?rel=0|
|ссылка на материал|https://www.youtube.com/embed/Ik6E9AzbJ7g?rel=0|
|ссылка на материал|https://www.youtube.com/embed/MLCCpflQ5aE?rel=0|
|ссылка на материал|https://www.youtube.com/embed/iJ9OK2ZFsqI?rel=0|
|ссылка на материал|https://youtube.com/embed/UAvMI9BcfvQ?rel=0|
|ссылка на материал|https://www.youtube.com/embed/piHpg43KSq4?rel=0|
|ссылка на материал|https://www.youtube.com/embed/M7JTK3u1Yb8?rel=0|
|ссылка на материал|https://www.youtube.com/embed/vSQKbXs13r8?rel=0|
|ссылка на материал|https://www.youtube.com/embed/RsdpKMXO6c8?rel=0|
|ссылка на материал|https://www.youtube.com/embed/UTPnJKhRvtk?rel=0|
|ссылка на материал|https://www.youtube.com/embed/1hiRJIC9Yks?rel=0|
|ссылка на контент шага|inorganic/pagers/8 redox/redox_pager_draft.html|
|тип шага|pager|
|visibleName||
|ссылка на материал|https://www.youtube.com/embed/H_Loh8rwOCk?rel=0|
|ссылка на материал|https://www.youtube.com/embed/DCuVyKpCmE4?rel=0|
|ссылка на материал|https://www.youtube.com/embed/K0n7V32IIMU?rel=0|
|ссылка на материал|https://www.youtube.com/embed/RyvJ5QBfeT0?rel=0|
|ссылка на материал|https://www.youtube.com/embed/LHQ_c5g3Sos?rel=0|
|ссылка на контент шага|./inorganic/pagers/12%20nitrites/nitrites_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/12%20-%20Redox%20properties%20of%20nitrites.pdf|
|занимает памяти|3,1 Мб|
|ссылка на материал|https://www.youtube.com/embed/Q_yOVm0H6FA?rel=0|
|ссылка на материал|https://www.youtube.com/embed/kPsZE-MIyUg?rel=0|
|ссылка на материал|https://www.youtube.com/embed/dg-LMZBeXXk?rel=0|
|ссылка на материал|https://www.youtube.com/embed/gCNs1AZYnis?rel=0|
|ссылка на материал|https://www.youtube.com/embed/zyiUfZcPDeg?rel=0|
|ссылка на материал|https://www.youtube.com/embed/x9EzVt4Y-Co?rel=0|
|ссылка на материал|https://www.youtube.com/embed/jv6378BCZzY?rel=0|
|ссылка на материал|https://www.youtube.com/embed/0u1Yl0Dj6N4?rel=0|
|ссылка на контент шага|./inorganic/pagers/16%20basic%20ammonia/basic_ammonia_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/16%20-%20The%20basic%20properties%20of%20ammonia.pdf|
|занимает памяти|7 Мб|
|ссылка на материал|https://www.youtube.com/embed/opaWDkVODew?rel=0|
|ссылка на материал|https://www.youtube.com/embed/T3edIzsD3Hw?rel=0|
|ссылка на контент шага|./inorganic/pagers/5 ammonia/ammo_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/5%20-%20ammonia%20and%20heating.pdf|
|занимает памяти|1,3 Мб|
|ссылка на материал|https://www.youtube.com/embed/fJRMeK-pUbQ?rel=0|
|ссылка на материал|https://www.youtube.com/embed/2tP_lZs6xdg?rel=0|
|ссылка на контент шага|./inorganic/pagers/2%20preparation%20ammonia/preparation_ammonia_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/2%20-%20Preparation%20and%20properties%20of%20ammonia.pdf|
|занимает памяти|10,5 Мб|
|ссылка на контент шага|./inorganic/pagers/15%20Receive%20NO/receive_no_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/15%20-%20Receive%20NO.pdf|
|занимает памяти|1 Мб|
|ссылка на материал|https://youtube.com/embed/2aJflzmFidg?rel=0|
|ссылка на материал|https://www.youtube.com/embed/69mn1lgbkC0?rel=0|
|ссылка на материал|https://www.youtube.com/embed/P2_1NGp9OhA?rel=0|
|ссылка на материал|https://www.youtube.com/embed/Rs5b2ZeQd-4?rel=0|
|ссылка на контент шага|./inorganic/pagers/3%20nitrate/nitrate_pager_draft.html|
|тип шага|pager|
|занимает памяти|10,5 Мб|
|ссылка на материал|./inorganic/pagers/3%20-%20Nitrate%20Decomposition.pdf|
|ссылка на материал|https://www.youtube.com/embed/nNVZA0bjKqc?rel=0|
|ссылка на материал|https://www.youtube.com/embed/2s5a4Ciou5M?rel=0|
|ссылка на материал|https://www.youtube.com/embed/XJB8E8OoYIY?rel=0|
|ссылка на материал|https://www.youtube.com/embed/nx8hobwcxzo?rel=0|
|ссылка на контент шага|./inorganic/pagers/pager_13/index.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/pager_13/Сравнение_окислительно-восстановительной_способности_нитрат-иона_и_нитрит-иона.pdf|
|занимает памяти|648 Кб|
|ссылка на материал|https://youtube.com/embed/UnqPIz_ecJw?rel=0|
|ссылка на материал|https://youtube.com/embed/JWrTnzWn6Lo?rel=0|
|ссылка на материал|https://youtube.com/embed/WCRTsH1hFNo?rel=0|
|ссылка на материал|https://youtube.com/embed/G3YvawOqWdA?rel=0|
|ссылка на контент шага|./inorganic/pagers/22 phosphates/phosphates_pager_draft.html|
|тип шага|pager|
|ссылка на материал|./inorganic/pagers/22 - Phosphates barium.pdf|
|занимает памяти|1,4 Мб|
|ссылка на материал|https://www.youtube.com/embed/1fcrGGM4oFY?rel=0|
/***
|Version|1.0|
|Short status|<<insertEditable container:"@stateComment" size:max cell>>|
tests: [[BRP 1]], [[BRP 2]], [[BRP 3]]
***/
//{{{
var orig_BRP_changed = Tiddler.prototype.changed;
// this recalcs links according to config.textPrimitives.tiddlerAnyLinkRegExp and
// config.textPrimitives.tiddlerForcedLinkRegExp , so temporarily hijack them
Tiddler.prototype.changed = function()
{
var brackettedLinkRE = config.textPrimitives.brackettedLink,
// titledBrackettedLinkRE = config.textPrimitives.titledBrackettedLink,
sectionOrSliceAddition =
"(?:(?:(?:"+config.textPrimitives.sliceSeparator+"[^\\|\\n\\]]+)|"+ //::
"(?:"+config.textPrimitives.sectionSeparator+"[^\\n\\]]+))?)", //##
tiddlerForcedLinkRegExp = config.textPrimitives.tiddlerForcedLinkRegExp,
tiddlerAnyLinkRegExp = config.textPrimitives.tiddlerAnyLinkRegExp;
// hijack REs
config.textPrimitives.brackettedLink = "\\[\\[([^\\]]+?)"+ // extra "?" is important here
sectionOrSliceAddition+
"\\]\\]";
// core definition: "\\[\\[([^\\]]+)\\]\\]";
// config.textPrimitives.titledBrackettedLink = "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+?)"+
// sectionOrSliceAddition+
// "\\]\\]";
// core definition: "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]";
// recalc, as in the core:
config.textPrimitives.tiddlerForcedLinkRegExp = new RegExp("(?:" +
config.textPrimitives.titledBrackettedLink + ")|(?:" +
config.textPrimitives.brackettedLink + ")|(?:" +
config.textPrimitives.urlPattern + ")","mg");
config.textPrimitives.tiddlerAnyLinkRegExp = new RegExp("("+
config.textPrimitives.wikiLink + ")|(?:" +
config.textPrimitives.titledBrackettedLink + ")|(?:" +
config.textPrimitives.brackettedLink + ")|(?:" +
config.textPrimitives.urlPattern + ")","mg");
var result = orig_BRP_changed.apply(this,arguments);
// unhijack REs
config.textPrimitives.brackettedLink = brackettedLinkRE;
// config.textPrimitives.titledBrackettedLink = titledBrackettedLinkRE;
// recalc again
config.textPrimitives.tiddlerForcedLinkRegExp = new RegExp("(?:" +
config.textPrimitives.titledBrackettedLink + ")|(?:" +
config.textPrimitives.brackettedLink + ")|(?:" +
config.textPrimitives.urlPattern + ")","mg");
config.textPrimitives.tiddlerAnyLinkRegExp = new RegExp("("+
config.textPrimitives.wikiLink + ")|(?:" +
config.textPrimitives.titledBrackettedLink + ")|(?:" +
config.textPrimitives.brackettedLink + ")|(?:" +
config.textPrimitives.urlPattern + ")","mg");
return result; // in fact, there's no result, this is for possible future extensions
};
//}}}
/***
|Description|This plugin fixes a couple of macro params issues:<br>1) fixes macro error in some cases when a named param has {{{{{}}}-containing value;<br>2) makes "escaped" ' and " in macro params be really escaped (examples: {{{"some \"value\""}}} is parsed as {{{some "value"}}} and {{{'that\'s nice'}}} becomes {{{that's nice}}})|
|Version|1.0|
|Short status|<<insertEditable container:"@stateComment" size:max cell>>|
|Author|Yakov Litvin|
***/
//{{{
// fix the error rising for macros with '{{'-containing named param's value
String.prototype.readMacroParams = function(notAllowEval)
{
// YL tweak: don't use "noNames"
var p = this.parseParams("_default",null,!notAllowEval);
var t, n = [];
for(t = 1; t < p.length; t++)
n.push(p[t].value);
return n;
};
// implement escaping of ' and " in macro params
String.prototype.parseParams = function(defaultName,defaultValue,allowEval,noNames,cascadeDefaults)
{
var parseToken = function(match,p) {
var n;
if(match[p]) // Double quoted
// YL tweak: substitute escaped \" with "
n = match[p].replace(/\\"/g,'"');
else if(match[p+1]) // Single quoted
// YL tweak: substitute escaped \' with '
n = match[p+1].replace(/\\'/g,"'");
else if(match[p+2]) // Double-square-bracket quoted
n = match[p+2];
else if(match[p+3]) // Double-brace quoted
try {
n = match[p+3];
if(allowEval && config.evaluateMacroParameters != "none") {
if(config.evaluateMacroParameters == "restricted") {
if(window.restrictedEval)
n = window.restrictedEval(n);
} else
n = window.eval(n);
}
} catch(ex) {
throw "Unable to evaluate {{" + match[p+3] + "}}: " + exceptionText(ex);
}
else if(match[p+4]) // Unquoted
n = match[p+4];
else if(match[p+5]) // empty quote
n = "";
return n;
};
var r = [{}];
var dblQuote = "(?:\"((?:(?:\\\\\")|[^\"])+)\")";
var sngQuote = "(?:'((?:(?:\\\\\')|[^'])+)')";
var dblSquare = "(?:\\[\\[((?:\\s|\\S)*?)\\]\\])";
var dblBrace = "(?:\\{\\{((?:\\s|\\S)*?)\\}\\})";
var unQuoted = noNames ? "([^\"'\\s]\\S*)" : "([^\"':\\s][^\\s:]*)";
var emptyQuote = "((?:\"\")|(?:''))";
var skipSpace = "(?:\\s*)";
var token = "(?:" + dblQuote + "|" + sngQuote + "|" + dblSquare + "|" + dblBrace + "|" + unQuoted + "|" + emptyQuote + ")";
var re = noNames ? new RegExp(token,"mg") : new RegExp(skipSpace + token + skipSpace + "(?:(\\:)" + skipSpace + token + ")?","mg");
var match;
do {
match = re.exec(this);
if(match) {
var n = parseToken(match,1);
if(noNames) {
r.push({ name:"", value:n });
} else {
var v = parseToken(match,8);
if(v == null && defaultName) {
v = n;
n = defaultName;
} else if(v == null && defaultValue) {
v = defaultValue;
}
r.push({ name:n, value:v });
if(cascadeDefaults) {
defaultName = n;
defaultValue = v;
}
}
}
} while(match);
// Summarise parameters into first element
var t;
for(t = 1; t < r.length; t++)
if(r[0][r[t].name])
r[0][r[t].name].push(r[t].value);
else
r[0][r[t].name] = [r[t].value];
return r;
};
//}}}
//{{{
// --- theme switching -------------------------------------
var usedOnline = window.location.protocol != "file:";
var usedWithBackEnd = !!window.saveOnlineChanges;
var visitorThemeName = "WebTheme";
var authorThemeName = "AuthorTheme";
readOnly = usedOnline && !usedWithBackEnd;
// theme setting helpers
story.setVisitorTheme = function() {
story.switchTheme(visitorThemeName);
//# test (online auto-setting, including web config.options.txtTheme is saved)
};
story.setAuthorTheme = function() {
story.switchTheme(authorThemeName);
//# test (online auto-setting, including web config.options.txtTheme is saved)
};
story.toggleRoleTheme = function() {
if(config.options.txtTheme == visitorThemeName)
story.setAuthorTheme();
else
story.setVisitorTheme();
};
// set theme on startup
if(usedOnline && !usedWithBackEnd) {
var ensureTheme = function(){
if(config.options.txtTheme != visitorThemeName)
story.setVisitorTheme();
}
setInterval(ensureTheme,100);
} else {
var ensureTheme = function(){
if(config.options.txtTheme != authorThemeName)
story.setAuthorTheme();
}
story.setAuthorTheme();
//# dirty hacky way:
setTimeout(ensureTheme,100);
setTimeout(ensureTheme,200);
setTimeout(ensureTheme,300);
setTimeout(ensureTheme,400);
setTimeout(ensureTheme,500);
setTimeout(ensureTheme,600);
}
// enable theme switching by pressing ctrl+shift+t
jQuery(document).on('keydown',function(e){
if(usedOnline && !usedWithBackEnd) return;
if((e.which == 222 /*'*/ || e.which == 0) && e.ctrlKey && e.shiftKey) {
story.toggleRoleTheme();
if(e.preventDefault)
e.preventDefault();
return false;
}
});
// display different tiddlers for an author and a visitor:
story.orig_displayDefaultTiddlers = story.displayDefaultTiddlers;
story.displayDefaultTiddlers = function()
{
if(usedOnline && !usedWithBackEnd)
this.displayTiddlers(null, store.filterTiddlers(store.getTiddlerText("WebDefaultTiddlers")||""));
else
this.orig_displayDefaultTiddlers();
};
// disable including for visitors (prevent error message to appear)
config.options.chkUseInclude = !usedOnline;// || usedWithBackEnd;
// --- helpers ---------------------------------------------
function updateQueryParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i");
if (uri.match(re))
return uri.replace(re, '$1' + key + "=" + value + '$2');
else {
var hash = '';
if( uri.indexOf('#') !== -1 ){
hash = uri.replace(/.*#/, '#');
uri = uri.replace(/#.*/, '');
}
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
return uri + separator + key + "=" + value + hash;
}
};
Tiddler.prototype.getVisibleName = function(sliceName,anotherDefault)
{
return this.getSlice(sliceName || "visibleName") || anotherDefault || this.title;
};
//
if(config.options.txtUnitStep === undefined)
config.options.txtUnitStep = 0;
if(config.options.txtLessonNumber === undefined)
config.options.txtLessonNumber = 0;
// --- unit step macros ------------------------------------
config.macros.unitStep =
{
getUnitSteps: function(tiddler) {
var tag = tiddler.title,
steps = store.filterTiddlers("set: tag["+tag+"] AND tag[unitStep]");
return config.macros.itemMenu.sortByCounter(steps/*, fieldName*/);
},
handler: function(place,macroName,params,wikifier,paramString,tiddler)
{
// lesson steps and current step
var steps = this.getUnitSteps(tiddler);
// header (navigation)
var header = createTiddlyElement(place,"div","","lessonNavigation","",{role:'navigation'});
var hrefToMain = "";
var linkToMain = hrefToMain ? createExternalLink(header,hrefToMain) :
jQuery('<a class="noLink"></a>').appendTo(header)[0];
createTiddlyElement(linkToMain,"div","","logo-sign");
// link to course contents (if not available, doesn't do anything)
var i, tag, theCourse;
for(i = 0; i < tiddler.tags.length; i++) {
tag = store.fetchTiddler(tiddler.tags[i]);
if(tag && tag.tags.contains("course"))
theCourse = tag;
}
var title = tiddler.getVisibleName();
if(theCourse) {
var linkToContents = createTiddlyLink(header,theCourse.title);
jQuery(linkToContents).html(title).addClass("linkToContents");
} else
jQuery("<a class='noLinkToContents'>"+title+"</a>")
.appendTo(header);
var navLink, type;
if(steps.length > 1)
for(let j = 0; j < steps.length; j++) // not compatible with elder browsers
{
navLink = createTiddlyElement(header,"a","","stepLink");
jQuery(navLink).on('click',function(){
config.options.txtUnitStep = j;
refreshStep();
});
if(type = steps[j].getSlice("тип шага"))
createTiddlyElement(navLink,"div","",type);
else
createTiddlyText(navLink,"шаг "+j);
}
// wrapper, 3 colomns and buttons (backward/forward)
var wrapper = createTiddlyElement(place,"div","","unitStep"),
leftColomn = createTiddlyElement(wrapper,"div","","goPrevContainer"),
contentColomn = createTiddlyElement(wrapper,"div","", "unitStepContentContainer"),
rightColomn = createTiddlyElement(wrapper,"div","","goNextContainer");
if(steps.length == 0)
return;
//# display something indicating that the lesson is empty for now
var backContainer = createTiddlyElement(leftColomn,"div","","backContainer");
var backButton = createTiddlyElement(backContainer,"div","","backward");
jQuery(leftColomn).on('click',function(){
config.options.txtUnitStep--;
refreshStep();
});
var forthContainer = createTiddlyElement(rightColomn,"div","","forthContainer");
var forwardButton = createTiddlyElement(forthContainer,"div","","forward");
jQuery(rightColomn).on('click',function(){
config.options.txtUnitStep++;
refreshStep();
});
var refreshStep = function()
{
// refresh content
jQuery(contentColomn).empty();
var step = steps[config.options.txtUnitStep];
var contentUrl = step ? step.getSlice("ссылка на контент шага") : "";
var specifiedHeight = step.getSlice("contentHeight");
if(specifiedHeight) specifiedHeight = parseInt(specifiedHeight);
if(contentUrl) {
var isImage = /\.(png|jpg|jpeg|gif)(\?.*)?$/i.exec(contentUrl);
var isVideo = /(?:youtube\.com)|(?:youtu\.be)|(?:^[-\w]+$)/i.exec(contentUrl)
|| step.getSlice("тип шага") == "video";
if(isVideo) {
/* deal with the following urls:
*
* https://www.youtube.com/watch?v=34c2GNgBpfE
* https://www.youtube.com/embed/34c2GNgBpfE <- canonical one, turn them into this form
* https://youtu.be/34c2GNgBpfE
* 34c2GNgBpfE
*/
var youtubeIdRE = /((?:youtube\.com\/watch\?v=)|(?:youtube\.com\/embed\/)|(?:youtu\.be\/))?([-\w]+)((\?.*)|(\&.*)|$)/,
youtubeIdMatch = youtubeIdRE.exec(contentUrl),
youtubeId = youtubeIdMatch ? youtubeIdMatch[2]:"";
if(youtubeId)
contentUrl = "https://www.youtube.com/embed/"+ youtubeId;
// disable autoplay, remove "related" from YouTube videos
contentUrl = updateQueryParameter(contentUrl, "autoplay", 0);
contentUrl = updateQueryParameter(contentUrl,"rel",0);
}
if(isImage)
jQuery("<img src='"+contentUrl+"' />")
.addClass("contentImage")
.appendTo(contentColomn);
else {
var iframe = createTiddlyElement(contentColomn,"iframe","", "contentIframe","",{
src: contentUrl,
frameborder: 0,
scrolling: "no",
was_reloaded: false
});
if(/\.html$/.exec(contentUrl))
iframe.onload = function(){
this.height = specifiedHeight || (this.contentWindow.document.body.offsetHeight +50);
if(!this.was_reloaded) //optional?
{
this.was_reloaded = true;
try {
this.contentDocument.location.reload();
}catch(ex){}
}
}
// +50 is a dirty hack; no idea why needed
else
// for video mostly
iframe.height = iframe.offsetWidth * 9/16;
}
}
//contentColomn.heigh = contentColomn.firstChild.offsetHeight; //# set via CSS instead
//# implement ?? for no-contentUrl case
// refresh navigation arrows
if(config.options.txtUnitStep == 0)
jQuery(backContainer).hide();
else
jQuery(backContainer).show();
if(config.options.txtUnitStep == steps.length-1)
jQuery(forthContainer).hide();
else
jQuery(forthContainer).show();
//# highlight the link to the opened step in the nav bar
jQuery(".currentStep").removeClass("currentStep");
jQuery(".stepLink:eq("+config.options.txtUnitStep+")") .addClass("currentStep");
}
refreshStep();
},
};
config.macros.lesson =
{
getAttachments: function(tiddler) {
var tag = tiddler.title,
atts = store.filterTiddlers("set: tag["+tag+"] AND tag[attachment]");
return config.macros.itemMenu.sortByCounter(atts/*, fieldName*/);
}
};
config.macros.unitStepFooter =
{
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
//# implement
}
};
config.macros.lessonAdminPanel =
{
handler: function(place,macroName,params,wikifier,paramString,tiddler)
{
// parametric transclusion is useful for more fluid development
wikify('<<tiddler [[LessonAdminPanel]] with:[['+tiddler.title+']] noedit>>',place,null,tiddler);
}
};
// --- course macros ------------------------------------
config.macros.fillCourseHeader = {
handler: function(place,macroName,params,wikifier,paramString,tiddler)
{
var imgUrl = tiddler.getSlice("Картинка в шапке","");
if(imgUrl)
jQuery('#course-header').css("background",
'linear-gradient(to right,rgba(0,0,0,0.4), rgba(0,0,0,0) 80%) no-repeat left, url("'+imgUrl+'") no-repeat center');
jQuery("#main_content #course-header")
.empty()
.append(
'<h2 id="course-name">'+ tiddler.getVisibleName() +'</h2>'+
'<h4 id="course-author">'+ tiddler.getSlice("Автор","") +'</h4>'+
'<h4 id="course-audience">'+ tiddler.getSlice("Аудитория","")+'</h4>'+
(tiddler.getSection("In title",""))
);
}
};
config.macros.fillCourseContents = {
getCourseContents: function(course)
{
if(!course) return null;
//# may be add getting course tiddler if course is the title or courseId
var tids = store.filterTiddlers("[tag["+course.title+"]]"),
courseId = course.getSlice("courseId","");
return config.macros.itemMenu.sortByCounter(tids, courseId);
},
getCourseLessons: function(course)
{
var contents = this.getCourseContents(course), i;
if(!contents) return null;
for(i = 0; i < contents.length; i++)
if(!contents[i].tags.contains("unit"))
contents.splice(i--,1);
return contents;
},
handler: function(place,macroName,params,wikifier,paramString,tiddler)
{
var lessons = this.getCourseLessons(tiddler),
contents = this.getCourseContents(tiddler);
var getIndentIndex = function(itemTiddler) {
if(itemTiddler.tags.contains("unit")) return 0;
if(itemTiddler.tags.contains("заголовок 1 надуровня")) return 1;
if(itemTiddler.tags.contains("заголовок 2 надуровня")) return 2;
},
maxIndentIndex = 0;
for(n = 0; n < contents.length; n++)
if(getIndentIndex(contents[n]) > maxIndentIndex)
maxIndentIndex = getIndentIndex(contents[n]);
var $courseContentsColomn = jQuery("#lessons-list"),
$lessonContentsColomn = jQuery("#lesson-content");
$courseContentsColomn.empty();
// add the "about course" link (implement in refresher)
jQuery('<a class="lesson-name h4">О курсе</a>')
.on('click',function(){
config.options.txtLessonNumber = 0;
selectLesson();
}).appendTo($courseContentsColomn)
.wrap('<div class="lesson" />');
// add per lesson links
for(let i = 0; i < contents.length; i++) {
let item = contents[i], isLesson = item.tags.contains("unit");
let mute = isLesson && !store.getTaggedTiddlers(item.title).length && !item.getSection("Описание");
levelClass = isLesson ? 'h4' :
(item.tags.contains("заголовок 1 надуровня")? 'h3' : 'h2');
indentClass = "indent-"+(maxIndentIndex - getIndentIndex(item));
jQuery('<a class="lesson-name '+levelClass+' '+indentClass+(mute ? ' mute' : '')+'">'
+contents[i].getVisibleName()+'</a>')
.on('click',function(){
if(!isLesson || mute) return;
config.options.txtLessonNumber = lessons.indexOf(item)+1;
selectLesson();
}).appendTo($courseContentsColomn)
.wrap('<div class="lesson" />');
}
var selectLesson = function() {
// (re)set selection
jQuery('.lesson-active').removeClass("lesson-active");
var lessonNumber = config.options.txtLessonNumber-1,
lessonNumberAmongContents = lessonNumber == -1 ? 0 :
contents.indexOf(lessons[lessonNumber])+1;
jQuery(".lesson-name").eq(lessonNumberAmongContents).addClass("lesson-active");
$lessonContentsColomn.empty();
var $lessonContentsWrapper = jQuery('<div>').appendTo($lessonContentsColomn);
window.elementToKeepIntoView = $lessonContentsWrapper[0];
jQuery(window).scroll();
if(config.options.txtLessonNumber == 0) {
// show "about course"
let description = tiddler.getSection("Описание");
if(description)
$lessonContentsWrapper.append('<p>'+description+ '</p>');
/*if(lessons.length)
jQuery('<a class="btn btn-primary">Начать курс</a>')
.on('click',function(){
config.options.txtUnitStep = 0;
story.displayTiddler(this,lessons[0]);
})
.appendTo($lessonContentsWrapper)
*/
//# hr and teacher description
} else {
// show lesson
var lessonNumber = config.options.txtLessonNumber - 1;
if(lessonNumber >= lessons.length) lessonNumber = 0; // fixes a bug taking place when we jump from a course to another one that has fewer lessons
var lesson = lessons[lessonNumber],
title = lesson.title,
visibleTitle = lesson.getVisibleName(),
lessonDescription = lesson.getSection("Описание"),
goLabel = config.macros.unitStep.getUnitSteps(lesson).length > 1 ? "Пройти занятие" : "Посмотреть";
$lessonContentsWrapper
.append('<h2>'+visibleTitle+'</h2>')
//# number in h2/"Занятие #" as h5
.append('<p>'+lessonDescription+'</p>')
.append(config.macros.unitStep.getUnitSteps(lesson).length ?
jQuery('<a class="btn btn-primary">'+goLabel+'</a>')
.on('click',function(){
config.options.txtUnitStep = 0;
story.displayTiddler(this,title);
})
: '')
.append('<ol id="lesson-steps"/>')
var steps = config.macros.unitStep.getUnitSteps(lesson),
ruTypes = {
pager: "Конспект",
task: "Задание",
test: "Тест",
video: "Видео",
};
if(steps.length > 1)
for(let i = 0; i < steps.length; i++) {
let type = steps[i].getSlice("тип шага"),
ruType = ruTypes[type];
jQuery('<a>')
.appendTo("#lesson-steps")
.wrap('<li>').wrap('<p>')
.on('click',function(){
config.options.txtUnitStep = i;
story.displayTiddler(this,title);
})
//.append('<div class="pull-left '+type+'"/>')
.append(jQuery('<img/>',{
class: "pull-left",
src: "images/"+(type=="pager" ? "text" : type)+".svg", // типы, исп-ные до того, отл-ся от тех, что у Виктора
width: "24px",
height: "24px"
}))
.append('<span class="lesson-label">'+steps[i].getVisibleName()+'</span><br>'+
'<small>'+ruType+'</small>')
//# " - 5:99" (video length)
}
var attachments = config.macros.lesson.getAttachments( lesson ),
attName, attUrl, isPdf, attSize;
for(let i = 0; i < attachments.length; i++)
{
attName = attachments[i].getVisibleName();
attUrl = attachments[i].getSlice("ссылка на материал");
isPdf = /.pdf/i.exec(attUrl);
attSize = attachments[i].getSlice("занимает памяти");
jQuery('<a href="'+attUrl+'" target="_blank" />')
.appendTo($lessonContentsWrapper)
.wrap('<p>')
.append('<img src="images/dwnld_solid.svg" class="attachment-icon">'+
'<span class="attachment-label">'+attName+'</span>' +
(isPdf ? ' <img src="images/pdf.svg" class="pdf-attachment-icon">' : '') +
(!attSize ? '' : (isPdf ? ' <span class="file-size">'+attSize+'</span>' : ' (<span class="file-size">'+attSize+'</span>)'))
);
}
}
};
// pick the step (by default "about course")
selectLesson();
}
};
window.prevScroll = 0;
jQuery(window).scroll(function()
{
var menuEl = window.elementToKeepIntoView;
if(!menuEl) return;
var container = menuEl.parentElement;
if(!container) return;
var height = menuEl.offsetHeight,
windowHeight = findWindowHeight(),
scrollDown = window.prevScroll < findScrollY(),
scrollUp = window.prevScroll > findScrollY();
menuEl.style.position = "relative";
var topLimitByContainer = 0, topLimitByWindow = findScrollY() - findPosY(container) -50,
//# get rid of magic value: it's the container's padding-top in px
bottomLimitByContainer = container.offsetHeight -80, //jQuery(container).innerHeight() ?
//# get rid of magic value: it's the container's padding-top + padding-bottom in px
bottomLimitByWindow = topLimitByWindow + findWindowHeight() -20,
//# get rid of magic value: presumably, it's the header's margin-top in px
//re = /(\-?\d+(?:\.\d+)?)\s?px/i,
getPixels = function(value) {
if(!value) return 0;
//var match = re.exec(value);
//if(!match) return parseInt(value);
return parseInt(value);//match[1]); //test with non-px values (are they stored in .style.top?)
},
menuElTopCss = getPixels(menuEl.style.top);
if(!scrollDown && !scrollUp)
menuEl.style.top = topLimitByWindow + "px"; //attach top to window top
if(scrollDown) {
if(height < windowHeight) {
if(menuElTopCss < topLimitByWindow) // top edge is higher than that of window
menuEl.style.top = topLimitByWindow + "px"; //top to top
} else
if(menuElTopCss + height < bottomLimitByWindow) // bottom edge higher than that of window
menuEl.style.top = (bottomLimitByWindow - height) + "px"; //bottom to bottom
}
if(scrollUp) {
if(height < windowHeight)
menuEl.style.top = topLimitByWindow + "px"; //attach top to window top
else
if(menuElTopCss > topLimitByWindow) // top edge lower than that of window
menuEl.style.top = topLimitByWindow + "px"; //attach top to window top
}
//# deal with selectLesson 46 (ends up below the bottom of the container)
// somehow in the menuElTopCss + height > bottomLimitByContainer check below height == 0
// that's true for each selectLesson firing scroll: height == 0
// ensure we're inside the container
menuElTopCss = getPixels(menuEl.style.top);
if(menuElTopCss < topLimitByContainer)
menuEl.style.top = topLimitByContainer + "px";
console.log("height: "+height);
if(menuElTopCss + height > bottomLimitByContainer)
menuEl.style.top = (bottomLimitByContainer - height) + "px";
//# make scrolling smoother
window.prevScroll = findScrollY();
});
config.macros.courseAdminPanel = {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
if(!tiddler) return;
// parametric transclusion is useful for more fluid development
wikify('<<tiddler [[CourseAdminPanel]] with:[['+tiddler.title+']] noedit>>',place,null,tiddler);
}
};
// --- common macros ------------------------------------
// make common topLineMenu and footer? use config.macros.siteTopMenu?
//}}}
/***
|''Name''|DashesFormattersPlugin|
|''Version''|0.1|
|Short status|<<insertEditable container:"@stateComment" size:max cell>>|
test: a -- b, c --- d, --ef--
----
gh —
***/
//{{{
for(var i = 0; i < config.formatters.length; i++)
if(config.formatters[i].name == "mdash") {
config.formatters[i].name = "ndash";
config.formatters[i].handler = function(w) {
createTiddlyElement(w.output,"span").innerHTML = "–";
};
};
/*config.formatters.splice(i,0,{
name: "mdash",
match: "---",
handler: function(w)
{
createTiddlyElement(w.output,"span").innerHTML = "—";
}
});*/
//}}}
/***
|Version|1.4|
{{PoGc{дописать метаданные!}}} Пока у плагина нет документации и т.п., он базируется в репозитории напару с ~GridPlugin
* в версии 1.2 исправлен тот факт, что ":" включался в slice name
* в версии 1.3 изменено поведение в отношении начальных/конечных пробелов/табуляций вокруг slice name
* в версии 1.4 исправлено поведение, когда пробелы в конце "второго столбца" добавляются в slice value
* когда пробел обязательно заменять на \x20? можно ли тут обойтись без этого?
***/
//{{{
TiddlyWiki.prototype.slicesRE = /(?:^([\'\/]{0,2})~?([\.\w]+)\:\1[\t\x20]*([^\n]+)[\t\x20]*$)|(?:^\|\x20?([\'\/]{0,2})~?([^\|\s\:\~\'\/]|(?:[^\|\s~\'\/][^\|\n\f\r]*[^\|\s\:\'\/]))\:?\4[\x20\t]*\|[\t\x20]*([^\n\t\x20](?:[^\n]*[^\n\t\x20])?)[\t\x20]*\|$)/gm;
store.slices = {};
//}}}
/***
|''Version''|1.4|
|''Requires''|UpToDateFiltersPlugin|
|~|requires http://yakovl.bplaced.net/TW/ExtraFilters.html#UpToDateFiltersPlugin only if TW core version is 2.6.1 or below|
|''Source''|http://yakovl.bplaced.net/TW/ExtraFilters.html#ExtraFiltersPlugin|
|''Documentation''|http://yakovl.bplaced.net/TW/ExtraFilters.html#ExtraFiltersPluginInfo|
|''Author''|Yakov Litvin|
|''Licence''|[[BSD-like open source license|http://yakovl.bplaced.net/TW/ExtraFilters.html#%5B%5BYakov%20Litvin%20Public%20Licence%5D%5D]] |
***/
//{{{
if(!config.filters.all)
config.filters.all = function(results,match) { // v1.0
this.forEachTiddler(function(tName,tiddler){
results.pushUnique(tiddler);
});
return results;
};
config.filters.and = function(results,match) { // v1.0
// parse the argument as "filterName[filterParam"
var dividingRE = /([^\[\]]+)\[([^\]]*)/,
filterParts = dividingRE.exec(match[3]);
if(filterParts) {
var filterName = filterParts[1],
filterParam = filterParts[2];
} else
throw("\"and\" filter: wrong syntax");
// create the set of filtered tiddlers
var filter = "[" + filterName + "[" + filterParam + "]]",
tids = this.filterTiddlers(filter),
newResult = [];
// collect tiddlers present among both "results" and filtered tiddlers
for(var i = 0; i < results.length; i++)
for(var j = 0; j < tids.length; j++)
if(results[i] == tids[j])
newResult.push(tids[j]);
return newResult;
};
config.filters.not = function(results,match) { // v1.0
// parse the argument as "filterName[filterParam"
var dividingRE = /([^\[\]]*)\[([^\]]*)/,
filterParts = dividingRE.exec(match[3]);
if(filterParts) {
var filterName = filterParts[1],
filterParam = filterParts[2];
} else
throw("\"not\" filter: wrong syntax");
// create the set of filtered tiddlers
var filter = "[" + filterName + "[" + filterParam + "]]",
tids = this.filterTiddlers(filter);
// collect tiddlers present among "results", but not among filtered tiddlers
for(var i = 0; i < results.length; i++)
for(var j = 0; j < tids.length; j++)
if(results[i] == tids[j]) {
results.splice(i,1);
i--;
tids.splice(j,1);
break;
}
return results;
};
config.filters.tagTree = function(results, match)
{
results = results || [];
var depthRE = /^(\d),(.+)$/, depthMatch = depthRE.exec(match[3]),
depth = depthMatch ? parseInt(depthMatch[1]) : -1, currentDepth = 0,
root = depthMatch ? depthMatch[2] : match[3], tags = [root], prevLength,
i, tagTags, j;
var rootTid = store.fetchTiddler(root);
if(rootTid) results.pushUnique(rootTid);
// get tags, tags of tags etc ;
// for optimization, push to results inline
do {
prevLength = tags.length;
for(i = 0; i < prevLength; i++) //may be optimized by starting from i = ..
{
tagTags = store.getTaggedTiddlers(tags[i]);
for(j = 0; j < tagTags.length; j++) {
tags.pushUnique(tagTags[j].title);
// optimized place to push:
results.pushUnique(tagTags[j]);
}
}
currentDepth++;
} while (tags.length > prevLength && currentDepth != depth);
return results;
};
config.filters.unclassified = function(results,match) { // v1.0
var category = match[3],
instances = this.getTaggedTiddlers(category);
// filter out tiddlers tagged with instances
for(var i = 0; i < results.length; i++)
for(var j = 0; j < instances.length; j++)
if(results[i].isTagged(instances[j].title)) {
results.splice(i,1);
i--;
break;
}
return results;
};
config.filters.taggedOnly =
config.filters.oTag = function(results, match) { // v1.0
// parse param
var add = true, arg = match[3], i;
switch(arg.substr(0,1)) {
case "+":
// "add" is "true" already
arg = arg.substr(1);
break;
case "-":
add = false;
arg = arg.substr(1);
break;
}
var isTaggedOnly = function(tiddler,arg) {
return (tiddler.tags.length == 1) && (!arg || arg == tiddler.tags[0])
};
if(add) {
var tiddlers = this.reverseLookup();
for(i = 0; i < tiddlers.length; i++)
if(isTaggedOnly(tiddlers[i],arg))
results.pushUnique(tiddlers[i]);
} else {
for(i = 0; i < results.length; i++)
if(!isTaggedOnly(results[i],arg))
results.splice(i--,1);
}
return results;
};
config.filters.hasPart = function (results, match) { // v1.1
// parse the argument
var arg = match[3], reText, re, type, isBad, title;
switch(arg.substr(0,2)) {
case "##":
case "::":
isBad = function(title) {
return store.getTiddlerText(title + arg) ? false : true;
};
break
case "@@":
isBad = function(title) {
return store.getValue(title, arg.substr(2)) ? false : true;
};
break
case "r@": // regExp (for tiddler.text) mode
case "R@":
case "t@": // title mode
case "T@":
reText = store.getTiddlerText(arg.substr(2));
type = arg.substr(0,1);
if(!reText)
if(type == "r" || type == "t")
return results; // "forgiving mode", nothing is filtered out in this case
else
throw("RegExp for filtering is not found in " + arg.substr(2));
// no break here
case "r[":
case "R[":
case "t[":
case "T[":
if(!reText) {
reText = arg.substr(2);
type = arg.substr(0,1);
}
if(type == "r" || type == "t") {
try {
re = new RegExp(reText);
} catch(e) {
return results; // "forgiving mode"
}
} else
re = new RegExp(reText);
if(type == "r" || type == "R")
isBad = function(title) {
return results[i].text.match(re) ? false : true;
};
else
isBad = function(title) {
return title.match(re) ? false : true;
};
break
default:
return results;
}
// filter out corresponding tiddlers
for(var i = 0; i < results.length; i++) {
title = results[i].title;
if(isBad(title)) {
results.splice(i,1);
i--;
}
};
return results;
};
config.filters.sortByText = function (results, match) { // v1.1
// parse the argument
var arg = match[3],
ascending = +1;
switch(arg.substr(0,1)) {
case "-":
ascending = -1;
arg = arg.substr(1);
break;
case "+":
arg = arg.substr(1);
break;
}
// use the rest of the argument to get corresponding section/slice
var partSuffix = (arg.substr(0,2) == "::" || arg.substr(0,2) == "##") ?
arg : "";
var self = this;
var compareText = function(t1,t2) {
var text1 = self.getTiddlerText(t1.title + partSuffix),
text2 = self.getTiddlerText(t2.title + partSuffix);
if(text1 && text2)
return text1.localeCompare(text2);
if(text1)
return -1;
if(text2)
return 1;
return 0;
};
return results.sort(compareText);
};
orig_sortFilter = config.filters.sort;
config.filters.sort = function(results,match) { // sort: random, v1.0
if(match[3] === "*random") {
var auxiliaryArray = [],
size = results.length;
var swap = function(i, j) {
var tmp1 = auxiliaryArray[i];
auxiliaryArray[i] = auxiliaryArray[j];
auxiliaryArray[j] = tmp1;
var tmp2 = results[i];
results[i] = results[j];
results[j] = tmp2;
};
for(var i = 0; i < size; i++)
auxiliaryArray.push(Math.random());
for(var j = 0; j < size; j++)
for(var i = 0; i < size - j; i++)
if(auxiliaryArray[i] < auxiliaryArray[i+1])
swap(i,i+1);
return results;
} else
return orig_sortFilter.apply(this, arguments);
};
config.filters.from = function(results,match) { // v1.0
var filter = this.getTiddlerText(match[3],""),
tiddlers = this.filterTiddlers(filter);
for(var i = 0; i < tiddlers.length; i++)
results.pushUnique(tiddlers[i]);
return results;
};
//}}}
/***
|Description|Makes ctrl+tab work for tab changing (when focused on an editarea) in ~FireFox (instead of inserting a tab symbol)|
|Version|1.0|
|Short status|<<insertEditable container:"@stateComment" size:max cell>>|
|Author|Yakov Litvin|
keep overwriting in mind! (hope this will move to the core soon)
***/
//{{{
Story.prototype.onTiddlerKeyPress = function(ev)
{
var e = ev || window.event;
clearMessage();
var consume = false;
var title = this.getAttribute("tiddler");
var target = resolveTarget(e);
switch(e.keyCode) {
case 9: // Tab
var ed = story.getTiddlerField(title,"text");
if(target.tagName.toLowerCase() == "input" && ed.value == config.views.editor.defaultText.format([title])) {
// moving from input field and editor still contains default text, so select it
ed.focus();
ed.select();
consume = true;
}
if(config.options.chkInsertTabs && !e.ctrlKey && target.tagName.toLowerCase() == "textarea") {
replaceSelection(target,String.fromCharCode(9));
consume = true;
}
if(config.isOpera)
target.onblur = function() {
this.focus();
this.onblur = null;
};
break;
case 13: // Ctrl-Enter
case 10: // Ctrl-Enter on IE PC
case 77: // Ctrl-Enter is "M" on some platforms
if(e.ctrlKey) {
blurElement(this);
config.macros.toolbar.invokeCommand(this,"defaultCommand",e);
consume = true;
}
break;
case 27: // Escape
blurElement(this);
config.macros.toolbar.invokeCommand(this,"cancelCommand",e);
consume = true;
break;
}
e.cancelBubble = consume;
if(consume) {
if(e.stopPropagation) e.stopPropagation(); // Stop Propagation
e.returnValue = true; // Cancel The Event in IE
if(e.preventDefault ) e.preventDefault(); // Cancel The Event in Moz
}
return !consume;
};
//}}}
/***
|Version|1.0|
{{DDnc{should be based elsewhere}}}
***/
//{{{
jQuery(window).on("scroll",function(){
var menuElement = document.getElementById("mainMenu");
if(!menuElement) return;
var header = document.getElementsByClassName("header")[0],
headerBottom = header.offsetTop + header.offsetHeight - findScrollY(),
position = findScrollY() + Math.max(headerBottom,0)
menuElement.style.top = position+"px";
});
//}}}
/***
|Description |adds toolbar buttons that allow to "fold" tiddlers|
|Version |1.0.5|
|Author |Yakov Litvin|
|Forked from |[[CollapseTiddlersPlugin|http://www.TiddlyTools.com/#CollapseTiddlersPlugin]] by Eric Shulman and previously Bradley Meck|
|Overwrites |{{{Story.prototype.permaView}}}|
|~CoreVersion? |{{DDn{??, >=2.1}}}|
***/
//{{{
config.shadowTiddlers.CollapsedTemplate =
"<!--{{{-->\
<div class='toolbar' macro='toolbar [[CollapsedToolbarCommands]]'></div>\
<div class='title' macro='view title'></div>\
<!--}}}-->";
config.shadowTiddlers.CollapsedToolbarCommands =
"closeTiddler closeOthers expandTiddler collapseOthers +editTiddler "+
"jump > fields permalink references deleteTiddler";
// hijack config.macros.toolbar.handler to add collapseTiddler and collapseOthers
config.options.chkAddFoldingButtons = (config.options.chkAddFoldingButtons === undefined) ? true : config.options.chkAddFoldingButtons;
config.foldTiddlers_orig_toolbarHandler = config.macros.toolbar.handler;
if(config.options.chkAddFoldingButtons)
config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
// warning: paramString is not changed as /currently/ it's not used by config.macros.toolbar.handler
var i, doAdd = true,
mainCommandRegExp = /closeOthers/,
foldCommandRegExp = /collapseTiddler/,
unfoldCommandRegExp = /expandTiddler/;
// don't add in the folded condition (if expandTiddler is present)
// or if collapseTiddler is already present (manually added to toolbar)
for(i = 0; i < params.length; i++)
if(unfoldCommandRegExp.exec(params[i]) ||
foldCommandRegExp.exec(params[i])) {
doAdd = false;
break;
}
if(!doAdd)
return config.foldTiddlers_orig_toolbarHandler.apply(this,arguments);
for(i = 0; i < params.length; i++)
if(mainCommandRegExp.exec(params[i])) { // locate the "edit" command
params.splice(i+1,0,"collapseTiddler","collapseOthers"); // add after "edit"
break;
}
config.foldTiddlers_orig_toolbarHandler.apply(this,arguments);
};
//}}}
//{{{
config.commands.collapseTiddler = {
text: "fold",
tooltip: "Collapse this tiddler",
collapsedTemplate: "CollapsedTemplate",
webCollapsedTemplate: "WebCollapsedTemplate",
handler: function(event,src,title) {
var e = story.findContainingTiddler(src); if (!e) return false;
// don't fold tiddlers that are being edited!
if(story.isDirty(e.getAttribute("tiddler"))) return false;
var t = config.commands.collapseTiddler.getCollapsedTemplate();
config.commands.collapseTiddler.saveTemplate(e);
config.commands.collapseTiddler.display(title,t);
e.setAttribute("folded","true");
return false;
},
getCollapsedTemplate: function() {
return (readOnly && store.tiddlerExists(this.webCollapsedTemplate)) ?
this.webCollapsedTemplate :
this.collapsedTemplate
},
saveTemplate: function(e) {
if (e.getAttribute("savedTemplate") == undefined)
e.setAttribute("savedTemplate", e.getAttribute("template"));
},
// fold/unfold tiddler with suspend/resume of single/top/bottom-of-page mode
display: function(title,t) {
var opt = config.options;
var saveSPM = opt.chkSinglePageMode; opt.chkSinglePageMode = false;
var saveTPM = opt.chkTopOfPageMode; opt.chkTopOfPageMode = false;
var saveBPM = opt.chkBottomOfPageMode; opt.chkBottomOfPageMode = false;
story.displayTiddler(null,title,t);
opt.chkBottomOfPageMode = saveBPM;
opt.chkTopOfPageMode = saveTPM;
opt.chkSinglePageMode = saveSPM;
}
}
config.commands.expandTiddler = {
text: "unfold",
tooltip: "Expand this tiddler",
handler: function(event,src,title)
{
var e = story.findContainingTiddler(src); if (!e) return false;
var t = e.getAttribute("savedTemplate");
config.commands.collapseTiddler.display(title,t);
e.setAttribute("folded","false");
return false;
}
}
config.macros.collapseAll = {
text: "collapse all",
tooltip: "Collapse all tiddlers",
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,this.text,this.tooltip,function(){
story.forEachTiddler(function(title,tiddler)
{
if(story.isDirty(title)) return;
var t = config.commands.collapseTiddler.getCollapsedTemplate();
config.commands.collapseTiddler.saveTemplate(tiddler);
config.commands.collapseTiddler.display(title,t);
tiddler.folded = true;
});
return false;
})
}
}
config.macros.expandAll = {
text: "expand all",
tooltip: "Expand all tiddlers",
handler: function(place,macroName,params,wikifier,paramString,tiddler){
createTiddlyButton(place,this.text,this.tooltip,function(){
story.forEachTiddler(function(title,tiddler){
var t = config.commands.collapseTiddler.getCollapsedTemplate();
if(tiddler.getAttribute("template")!=t) return; // re-display only if collapsed
var t = tiddler.getAttribute("savedTemplate");
config.commands.collapseTiddler.display(title,t);
tiddler.folded = false;
});
return false;
})
}
}
config.commands.collapseOthers = {
text: "focus",
tooltip: "Expand this tiddler and collapse all others",
handler: function(event,src,title) {
var e = story.findContainingTiddler(src); if (!e) return false;
story.forEachTiddler(function(title,tiddler) {
if(story.isDirty(title)) return;
var t = config.commands.collapseTiddler.getCollapsedTemplate();
if (e == tiddler) t = e.getAttribute("savedTemplate");
config.commands.collapseTiddler.saveTemplate(tiddler);
config.commands.collapseTiddler.display(title,t);
tiddler.folded = (e != tiddler);
})
return false;
}
}
// {{{<<foldFirst>>}}} macro forces tiddler to be folded when *initially* displayed.
// Subsequent re-render does NOT re-fold tiddler, but closing/re-opening tiddler DOES cause it to fold first again.
config.macros.foldFirst = {
handler: function(place,macroName,params,wikifier,paramString,tiddler) {
var e = story.findContainingTiddler(place);
if (e.getAttribute("foldedFirst") == "true") return; // already been folded once
var title = e.getAttribute("tiddler")
var t = config.commands.collapseTiddler.getCollapsedTemplate();
config.commands.collapseTiddler.saveTemplate(e);
config.commands.collapseTiddler.display(title,t);
e.setAttribute("folded","true");
e.setAttribute("foldedFirst","true"); // only when tiddler is first rendered
return false;
}
}
//}}}
//{{{
// [showFolded[n]] adds .openFolded = true to the last n tiddlers among results
config.filters.showFolded = function(results,match) {
var number = parseInt(match[3]); // if NaN, the loop below just is not executed
for(var i = 0; (i < number) && (results.length-1-i >= 0); i++)
results[results.length-1-i].openFolded = true;
return results;
}
// hijack chooseTemplateForTiddler to open tiddlers with .openFolded folded
config.foldTiddlers_orig_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler;
Story.prototype.chooseTemplateForTiddler = function(title,template) {
var t = store.fetchTiddler(title);
if(t && t.openFolded)
{
t.openFolded = false
return "CollapsedTemplate";
}
return config.foldTiddlers_orig_chooseTemplateForTiddler.apply(this,arguments);
}
//# optionally change fold/unfold ~commands so that they change openFolded (the state is remembered during the session)
Story.prototype.isOpenedFolded = function(title) {
var tiddlerElem = story.getTiddler(title);
if(!tiddlerElem)
return false;
return tiddlerElem.getAttribute("template") == "CollapsedTemplate";
}
//# overwrite permaview to save which tiddlers are folded
// use "filter" paramifier
Story.prototype.permaView = function()
{
var links = [];
this.forEachTiddler(function(title,element) {
links.push(String.encodeTiddlyLink(title) +
(story.isOpenedFolded(title) ? " [showFolded[1]]" : ""));
});
var t = links.join(" ");
t = t.replace(/\\/gm,"\\\\").replace(/"/gm,'\\"');
if(t == "")
t = "#";
else
t = encodeURIComponent('filter:"'+t+'"');
if(window.location.hash != t)
window.location.hash = t;
};
// unescape \" and \\ back..
var _unescape = function(value) {
if(typeof value == "string")
return value.replace(/\\"/gm,'"').replace(/\\\\/,'\\');
return value;
};
// ..by hijacking invokeParamifier (certain paramifiers may be hijacked instead - probably enough to hijack only the "filter" one)
config.extensions.ftp_orig_invokeParamifier = invokeParamifier;
invokeParamifier = function(params,handler) {
if(!params)
return config.extensions.ftp_orig_invokeParamifier.apply(this,arguments);
var paramifiers = params[0], name, i;
for(name in paramifiers)
for(i = 0; i < paramifiers[name].length; i++)
paramifiers[name][i] = _unescape(paramifiers[name][i]);
for(i = 1; i < params.length; i++)
params[i].value = _unescape(params[i].value);
return config.extensions.ftp_orig_invokeParamifier.apply(this,arguments);
};
//}}}
/***
|''Name''|ForEachTiddlerPlugin|
|''Version''|1.3.1|
|''Forked from''|[[abego.ForEachTiddlerPlugin|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin]], by Udo Borkowski|
|''Author''|Yakov Litvin|
|''CoreVersion''|2.6.2|
|~|Although