<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Qlik Sense Extensions - Qlik Sense - Обучение, учебник, онлайн курс</title>
	<atom:link href="https://qliksense.ivan-shamaev.ru/tag/qlik-sense-extensions/feed/" rel="self" type="application/rss+xml" />
	<link>https://qliksense.ivan-shamaev.ru/tag/qlik-sense-extensions/</link>
	<description>Qlik Sense на русском языке. Пошаговые уроки для изучения Клик Сенс</description>
	<lastBuildDate>Fri, 03 Jun 2022 14:39:04 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>

<image>
	<url>https://qliksense.ivan-shamaev.ru/wp-content/uploads/2018/07/QlikSense_ICON2-150x150.png</url>
	<title>Qlik Sense Extensions - Qlik Sense - Обучение, учебник, онлайн курс</title>
	<link>https://qliksense.ivan-shamaev.ru/tag/qlik-sense-extensions/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Создание Extensions с помощью nebula.js &#8211; пример Hello World</title>
		<link>https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/</link>
					<comments>https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 11 Feb 2022 20:33:07 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[Hello World - What is Nebula.js]]></category>
		<category><![CDATA[Hello World nebula.js extension]]></category>
		<category><![CDATA[Making Sense of Qlik APIs – Nebula CLI]]></category>
		<category><![CDATA[nebula.js]]></category>
		<category><![CDATA[nebula.js extension]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[What is Nebula.js]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2684</guid>

					<description><![CDATA[<p>В этом уроке мы создадим расширение HelloWorld, используя nebula.js и Qlik Sense Desktop Видео Hello World Extension &#8211; What is Nebula.js? Making Sense of Qlik APIs – Nebula CLI Создайем расширение HelloWorld, используя nebula.js В этом руководстве вы узнаете, как создать простое расширение, отображающее таблицу с использованием nebula.js. В статье будут<a class="moretag" href="https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/">Создание Extensions с помощью nebula.js &#8211; пример Hello World</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<blockquote><p>В этом уроке мы создадим расширение HelloWorld, используя nebula.js и Qlik Sense Desktop</p></blockquote>
<h1 data-testid="docs-header">Видео</h1>
<h2 data-testid="docs-header">Hello World Extension &#8211; What is Nebula.js?</h2>
<p><iframe title="Hello World - What is Nebula.js?" width="750" height="563" src="https://www.youtube.com/embed/MxQVuorsjVc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h2>Making Sense of Qlik APIs – Nebula CLI</h2>
<p><iframe title="Making Sense of Qlik APIs – Nebula CLI" width="750" height="563" src="https://www.youtube.com/embed/oF68t8DPpsE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h1 data-testid="docs-header" class=""><span>Создайем расширение HelloWorld, используя nebula.js</span></h1>
<p><span>В этом руководстве вы узнаете, как создать простое расширение, отображающее таблицу с использованием </span><code class="language-text">nebula.js</code><span>.</span></p>
<p><span>В статье будут пройдены следующие шаги:</span></p>
<ol>
<li><span>Создание проекта</span></li>
<li><span>Настройка структуры данных</span></li>
<li><span>Данные рендеринга</span></li>
<li><span>Выбор данных</span></li>
<li><span>Создание и загрузка расширения</span></li>
</ol>
<blockquote><p><strong><span>Примечание.</span></strong><span> Чтобы загрузить расширение в Qlik Sense SaaS, вам необходим доступ к тенанту Qlik Sense SaaS и либо права администратора тенанта, либо средства для получения ключа API, сгенерированного для вас. Вы можете </span><a href="https://www.qlik.com/us/trial/qlik-sense-business"><span>подписаться на бесплатную пробную версию</span></a><span> , если у вас нет существующего клиента.</span></p></blockquote>
<h2 id="requirements">Требования</h2>
<p><span>Этот учебник требует, чтобы у вас было следующее:</span></p>
<ul>
<li><a href="https://nodejs.org/en/download/"><span>Node.js</span></a><span> (версия 10 или новее)</span></li>
<li><span>Терминал (например , </span><a href="https://gitforwindows.org/"><span>Git Bash для Windows</span></a><span> или Terminal.app для Mac)</span></li>
<li><span>Современный веб-браузер, например Google Chrome</span></li>
<li><span>Текстовый редактор или IDE по вашему выбору, например Visual Studio Code.</span></li>
<li><span>Существующая </span><a href="https://qlik.dev/basics/authentication-options#web-integrations"><span>веб-интеграция</span></a><span> или возможность ее создания. Или клиент Qlik Sense Desktop.</span></li>
</ul>
<h2 id="create-a-project">Создание проекта</h2>
<p><span>Самый быстрый способ начать работу — использовать </span><code class="language-text">nebula.js</code> <span>интерфейс командной строки:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">npx @nebula.js/cli create hello --picasso none</code></pre>
</div>
<p><span>Параметр </span><code class="language-text">--picasso none</code> <span>указывает команде не создавать шаблон визуализации Пикассо, другие параметры &#8211; </span><code class="language-text">minimal</code><span>и </span><code class="language-text">barchart</code><span>.</span></p>
<p><span>Команда формирует проект в папке </span><code class="language-text">/hello</code> <span>со следующей структурой:</span></p>
<ul>
<li><code class="language-text">/src</code>
<ul>
<li><code class="language-text">index.js</code> <span>&#8211; Основная точка входа этой визуализации</span></li>
<li><code class="language-text">object-properties.js</code> <span>&#8211; Свойства объекта, хранящиеся в приложении</span></li>
<li><code class="language-text">data.js</code> <span>&#8211; Конфигурация данных</span></li>
</ul>
</li>
<li><code class="language-text">/test</code> <span>&#8211; Интеграционные тесты</span></li>
<li><code class="language-text">package.json</code></li>
</ul>
<p><span>Папка содержит несколько дополнительных точечных файлов, обеспечивающих проверку и форматирование кода.</span></p>
<h3 id="start-the-development-server">Запуск сервера разработки</h3>
<p><span>Запустите сервер разработки с помощью команды:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">cd hello<span></span>
npm run start</code></pre>
</div>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension.jpg"><img fetchpriority="high" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension.jpg" alt="" class="aligncenter size-full wp-image-2771" width="1348" height="138" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension.jpg 1348w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension-300x31.jpg 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension-1024x105.jpg 1024w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_development_server_qlik_sense_extension-768x79.jpg 768w" sizes="(max-width: 1348px) 100vw, 1348px" /></a></p>
<p><span>Команда запускает локальный сервер разработки и открывает </span><a href="http://localhost:8080/"><span>http://localhost:8080</span></a><span> в вашем браузере.</span></p>
<p><img decoding="async" src="https://qlik.dev/static/hub-connect-f5711011cb5bed761c101f5dce82214a.png" alt="Подключиться к движку" /></p>
<p><span>Сервер разработки должен подключаться к ассоциативному движку Qlik, работающему в любом развертывании Qlik. Введите URL-адрес WebSocket, соответствующий используемому вами продукту Qlik.</span></p>
<p><strong>Чтобы открыть WebSocket для движка, используйте один из следующих URI:</strong></p>
<ul>
<li><strong>Qlik Sense Enterprise:</strong> <code>wss://server.domain.com:4747/</code> или <code>wss://server.domain.com[/virtual proxy]/</code></li>
<li><strong>Qlik Sense Desktop:</strong> <code>ws://localhost:4848/</code></li>
</ul>
<p><span>Затем выберите приложение для подключения.</span></p>
<p><img decoding="async" src="https://qlik.dev/static/hub-app-275f908203b91a5417c556d5d3b50eeb.png" alt="Подключиться к приложению" /></p>
<p><span>Затем вы будете перенаправлены в основной пользовательский интерфейс разработчика, где сможете увидеть отрендеренную визуализацию:</span></p>
<p><img decoding="async" src="https://qlik.dev/static/hub-dev-21416471f69a21ff6e9ed3f07ac66810.png" alt="Сервер разработки" /></p>
<p><span>Любые обновления </span><code class="language-text">/src/index.js</code><span>, влияющие на вывод, автоматически вызывают обновление визуализации, и вы сразу же видите изменения.</span></p>
<h2 id="configure-data-structure">Настроить структуру данных</h2>
<p><span>Простое </span><code class="language-text">Hello</code><span>сообщение на самом деле не так уж полезно, пора добавить некоторые данные.</span></p>
<p><span>Добавьте </span><code class="language-text">qHyperCubeDef</code> <span>определение в </span><code class="language-text">object-properties.js</code><span>:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">const</span> properties <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">qHyperCubeDef</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">qInitialDataFetch</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">qWidth</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token literal-property property">qHeight</span><span class="token operator">:</span> <span class="token number">10</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Затем добавьте </span><code class="language-text">/qHyperCubeDef</code> <span>в качестве цели данных в </span><code class="language-text">data.js</code><span>:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">targets</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
      <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">'/qHyperCubeDef'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>После этих изменений у вас должна появиться возможность добавлять данные на панели свойств справа:</span></p>
<p><img decoding="async" src="https://qlik.dev/static/tutorial-data-targets-f5fb58c59929b6886ccb25aeac35806b.png" alt="Цели данных" /></p>
<p><span>Добавьте измерение, нажав </span><strong><span>Add dimension</span></strong><span> и выбрав значение в появившемся меню. Затем проделайте то же самое с мерой &#8211; <strong>Add measures</strong>.</span></p>
<h2 id="render-data">Данные рендеринга</h2>
<p><span>Чтобы отобразить данные, вам сначала нужно получить к ним доступ через </span><code class="language-text">useLayout</code> <span>хук:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">import</span> <span class="token punctuation">{</span> useLayout<span class="token punctuation">,</span> useElement<span class="token punctuation">,</span> useEffect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@nebula.js/stardust'</span><span class="token punctuation">;</span><span></span>
<span></span>
<span class="token comment">// ...</span>
<span class="token function">component</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">useLayout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
</div>
<p><span>Затем вы можете </span><code class="language-text">useLayout</code> <span>в сочетании с </span><code class="language-text">useEffect</code> <span>отображать заголовки и строки данных в </span><code class="language-text">qHyperCube</code><span>:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token function">component</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token function">useElement</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> layout <span class="token operator">=</span> <span class="token function">useLayout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
  <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>layout<span class="token punctuation">.</span>qSelectionInfo<span class="token punctuation">.</span>qInSelections<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">// skip rendering when in selection mode</span>
      <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">const</span> hc <span class="token operator">=</span> layout<span class="token punctuation">.</span>qHyperCube<span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// headers</span>
    <span class="token keyword">const</span> columns <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>hc<span class="token punctuation">.</span>qDimensionInfo<span class="token punctuation">,</span> <span class="token operator">...</span>hc<span class="token punctuation">.</span>qMeasureInfo<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">f</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> f<span class="token punctuation">.</span>qFallbackTitle<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> header <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;thead&gt;&lt;tr&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>columns<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">c</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-punctuation string">`</span><span class="token string">&lt;th&gt;</span><span class="token interpolation-punctuation punctuation">${</span>c<span class="token interpolation-punctuation punctuation">}</span><span class="token string">&lt;/th&gt;</span><span class="token template-punctuation string">`</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/tr&gt;&lt;/thead&gt;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// rows</span>
    <span class="token keyword">const</span> rows <span class="token operator">=</span> hc<span class="token punctuation">.</span>qDataPages<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>qMatrix
      <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">row</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;tr&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>row<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">cell</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-punctuation string">`</span><span class="token string">&lt;td&gt;</span><span class="token interpolation-punctuation punctuation">${</span>cell<span class="token punctuation">.</span>qText<span class="token interpolation-punctuation punctuation">}</span><span class="token string">&lt;/td&gt;</span><span class="token template-punctuation string">`</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/tr&gt;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// table</span>
    <span class="token keyword">const</span> table <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;table&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>header<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;tbody&gt;</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rows<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">&lt;/tbody&gt;&lt;/table&gt;</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><span></span>
<span></span>
    <span class="token comment">// output</span>
    element<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> table<span class="token punctuation">;</span><span></span>
<span></span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>element<span class="token punctuation">,</span> layout<span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
</div>
<h3>Выберите данные</h3>
<p><span>Перед выбором данных необходимо добавить метаданные в каждую строку, чтобы значения можно было идентифицировать для выбора:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token comment">// rows</span>
<span class="token keyword">const</span> rows <span class="token operator">=</span> hc<span class="token punctuation">.</span>qDataPages<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>qMatrix
  <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>
    <span class="token punctuation">(</span><span class="token parameter">row<span class="token punctuation">,</span> rowIdx</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;tr data-row="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rowIdx<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"&gt;
        </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>row<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">cell</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token template-punctuation string">`</span><span class="token string">&lt;td&gt;</span><span class="token interpolation-punctuation punctuation">${</span>cell<span class="token punctuation">.</span>qText<span class="token interpolation-punctuation punctuation">}</span><span class="token string">&lt;/td&gt;</span><span class="token template-punctuation string">`</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
      &lt;/tr&gt;</span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Затем добавьте </span><code class="language-text">'click'</code><span>обработчик событий, </span><code class="language-text">element</code><span>который выполняет следующие действия:</span></p>
<ul>
<li><span>Проверяет, что выбранный элемент является </span><code class="language-text">td</code></li>
<li><span>Начинает выбор </span><code class="language-text">/qHyperCubeDef</code><span>, если он еще не активирован</span></li>
<li><span>Извлекает </span><code class="language-text">data-row</code> <span>индекс из</span> <code class="language-text">tr</code></li>
<li><span>Обновления </span><code class="language-text">selectedRows</code> <span>по клику</span> <code class="language-text">data-row</code></li>
</ul>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token function">useElement</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> selections <span class="token operator">=</span> <span class="token function">useSelections</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>selectedRows<span class="token punctuation">,</span> setSelectedRows<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
<span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token function-variable function">listener</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>tagName <span class="token operator">===</span> <span class="token string">'TD'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>selections<span class="token punctuation">.</span><span class="token function">isActive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        selections<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token string">'/qHyperCubeDef'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">const</span> row <span class="token operator">=</span> <span class="token operator">+</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>parentElement<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'data-row'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token function">setSelectedRows</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">prev</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>prev<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> prev<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">v</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> v <span class="token operator">!==</span> row<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token operator">...</span>prev<span class="token punctuation">,</span> row<span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span><span></span>
<span></span>
  element<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> listener<span class="token punctuation">)</span><span class="token punctuation">;</span><span></span>
<span></span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    element<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> listener<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>element<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Затем обновите стиль выбранных строк в таблице всякий раз, когда они изменяются:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>layout<span class="token punctuation">.</span>qSelectionInfo<span class="token punctuation">.</span>qInSelections<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// no need to update when not in selection mode</span>
    <span class="token keyword">return</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  element<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'tbody tr'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">tr</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> idx <span class="token operator">=</span> <span class="token operator">+</span>tr<span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'data-row'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    tr<span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> selectedRows<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>idx<span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token string">'#eee'</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>element<span class="token punctuation">,</span> selectedRows<span class="token punctuation">,</span> layout<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<p><span>Наконец, примените выбранные значения через </span><code class="language-text">selections</code> <span>API:</span></p>
<div class="gatsby-highlight" data-language="js">
<pre class="language-js" tabindex="0"><code class="language-js"><span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>selections<span class="token punctuation">.</span><span class="token function">isActive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>selectedRows<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      selections<span class="token punctuation">.</span><span class="token function">select</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">'selectHyperCubeCells'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'/qHyperCubeDef'</span><span class="token punctuation">,</span> selectedRows<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      selections<span class="token punctuation">.</span><span class="token function">select</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        <span class="token literal-property property">method</span><span class="token operator">:</span> <span class="token string">'resetMadeSelections'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>selectedRows<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">setSelectedRows</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>selections<span class="token punctuation">.</span><span class="token function">isActive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> selectedRows<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</div>
<h2 id="build-and-upload-extension">Создайте и загрузите расширение</h2>
<p><span>До сих пор вы работали в локальной изолированной среде над диаграммой, которая не зависела от какого-либо конкретного продукта Qlik.</span></p>
<p><span>Команда:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">npm run build</code></pre>
</div>
<p><span>генерирует пакет в </span><code class="language-text">/dist</code> <span>папку, и это все, что вам нужно для распространения диаграммы в виде пакета npm.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result.jpg"><img decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result.jpg" alt="" class="aligncenter size-full wp-image-2773" width="619" height="167" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result.jpg 619w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/npm_run_build_result-300x81.jpg 300w" sizes="(max-width: 619px) 100vw, 619px" /></a></p>
<p><span>Однако Qlik Sense требует некоторых дополнительных файлов и немного другого формата для интерпретации диаграммы как расширения. Чтобы сгенерировать эти файлы, вы можете запустить команду:</span></p>
<div class="gatsby-highlight" data-language="bash">
<pre class="language-bash" tabindex="0"><code class="language-bash">npm run sense</code></pre>
</div>
<p><span>Команда создает все файлы в папку </span><code class="language-text">/hello-ext</code><span>, которую затем можно использовать в качестве расширения в Qlik Sense по вашему выбору.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result.jpg"><img decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result.jpg" alt="" class="aligncenter size-full wp-image-2774" width="622" height="169" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result.jpg 622w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2022/02/nebula_npm_run_sense_result-300x82.jpg 300w" sizes="(max-width: 622px) 100vw, 622px" /></a></p>
<p><span>Чтобы загрузить расширение в клиент Qlik Sense SaaS, следуйте инструкциям по </span><a href="https://help.qlik.com/en-US/cloud-services/Subsystems/Hub/Content/Sense_Hub/Admin/mc-extensions.htm"><span>управлению расширениями</span></a><span>.</span></p>
<p><span style="color: #ff6600;"><strong>Важная и неочевидный шаг для использования собранного расширения из директории hello-ext:</strong> </span>Обязательно нужно удалить <strong>&#8220;-ext&#8221;</strong> из директории, иначе экстеншен не будет работать и появится приписка, что экстеншен не найден на сервере. Хотя в списке визуализаций в Qlik Sense он появится.</p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/">Создание Extensions с помощью nebula.js &#8211; пример Hello World</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/build-a-helloworld-extension-using-nebula-js/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>qExt v2.0 &#8211; Extension Development Environment (Qlik Sense)</title>
		<link>https://qliksense.ivan-shamaev.ru/qext-extension-development-environment/</link>
					<comments>https://qliksense.ivan-shamaev.ru/qext-extension-development-environment/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 11 Feb 2022 19:38:31 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[Extension Development Environment]]></category>
		<category><![CDATA[qext]]></category>
		<category><![CDATA[qExt v2.0]]></category>
		<category><![CDATA[qext-scripts]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2672</guid>

					<description><![CDATA[<p>qExt v2.0 Tutorial qExt — это инструмент, помогающий автоматизировать создание и развертывание расширений визуализации Qlik Sense. Он может настроить вас на стандартные среды разработки расширений и более простой метод импорта скомпилированного кода на ваш сервер Qlik, чтобы вам не приходилось каждый раз вручную удалять и импортировать расширение. Посмотреть проект на GitHub Qlik<a class="moretag" href="https://qliksense.ivan-shamaev.ru/qext-extension-development-environment/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qext-extension-development-environment/">qExt v2.0 &#8211; Extension Development Environment (Qlik Sense)</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>qExt v2.0 Tutorial</h1>
<p><span>qExt — это инструмент, помогающий автоматизировать создание и развертывание расширений визуализации Qlik Sense. Он может настроить вас на стандартные среды разработки расширений и более простой метод импорта скомпилированного кода на ваш сервер Qlik, чтобы вам не приходилось каждый раз вручную удалять и импортировать расширение.</span></p>
<p><span>Посмотреть </span><a href="https://github.com/axisgroup/qExt" target="_blank" rel="noopener"><span>проект на GitHub</span></a></p>
<h1>Qlik Sense Extensions &#8211; Расширения Qlik Sense</h1>
<h2>Анатомия Qlik Extension</h2>
<p><span>Расширения Qlik Sense позволяют создавать собственные объекты визуализации и функциональные объекты в приложении Qlik Sense. Расширения обычно используются для расширения возможностей визуализации Qlik для пользователей, использующих приложения Qlik в режиме самообслуживания. Дополнительные сведения об объектах расширения qlik sense можно найти на сайте Qlik </span><a href="https://help.qlik.com/en-US/sense-developer/April2020/Content/Sense_Helpsites/extend-qlik-sense.htm" target="_blank" rel="noopener"><span>здесь .</span></a></p>
<p><span>все файлы расширения должны храниться в одной папке проекта и, как минимум, должны включать </span><a href="https://opensrc.axisgroup.com/qext/qlik-extensions/anatomy.html#qext-file"><span>файл qext</span></a><span> и основной </span><a href="https://opensrc.axisgroup.com/qext/qlik-extensions/anatomy.html#script-file"><span>файл сценария</span></a>.</p>
<h3 id="qext-file"><span>файл qext</span></h3>
<p><span>файл qext в проекте расширения содержит объект json, который определяет метаданные объекта расширения. Имя файла — это уникальное имя, которое Qlik будет использовать для идентификации расширения, и оно должно совпадать с именем файла сценария.</span></p>
<p><span>как минимум, файл qext должен включать свойства имени и типа. (полные свойства qext можно найти </span><a href="https://help.qlik.com/en-US/sense-developer/April2020/Subsystems/Extensions/Content/Sense_Extensions/Overview/qext-file-overview.htm" target="_blank" rel="noopener"><span>здесь</span></a><span> )</span></p>
<p><span>пример файла qext:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">// hello-world.qext
{
    "name": "Hello World",
    "description": "Hello world example",
    "type": "visualization",
    "version": "1.0.0",
    "author": "john bellizzi"
}</pre>
<h3 id="script-file">Script File</h3>
<p><span>файл сценария в проекте расширения — это файл javascript, содержащий всю логику работы вашего расширения. он определяет, как данные поступают в объект, что отображается в объекте, свойства, которые можно установить для объекта, и многое другое. имя файла должно соответствовать вашему файлу qext</span></p>
<p><span>существует множество параметров конфигурации файла скрипта, и большинство из них можно найти в руководстве </span><a href="https://help.qlik.com/en-US/sense-developer/April2020/Subsystems/Extensions/Content/Sense_Extensions/extensions-introduction.htm" target="_blank" rel="noopener"><span>здесь</span></a><span> . базовый сценарий использует функцию определения для загрузки любых необходимых ресурсов и возвращает объект javascript, содержащий функции, которые контролируют данные, проходящие через расширение.</span></p>
<p><span>наиболее распространенным методом, используемым в расширении, является </span><code>paint</code><span>метод, который запускается каждый раз, когда происходит изменение состояния приложения или изменение размера, чтобы мы могли отображать обновления в контейнере объекта расширения. </span></p>
<p><span>Вот пример файла скрипта</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">define(["jquery"], function($) {
    return {
        paint: function($element, layout) {
            var $helloWorld = $(document.createElement("div"))
            $helloWorld.html('Hello World from the extension "SimpleHelloWorld"&lt;br/&gt;')
            $element.append($helloWorld)

            // layout contains the properties and calculated data of our object
            console.log(layout)
        },
    }
})</pre>
<h3>Deployment (Развертывание)</h3>
<p><span>при развертывании расширения на сервере qlik правильным методом является сжатие всего каталога расширения в zip-файл, а затем переход к разделу расширений qmc и импорт заархивированного файла расширения. если расширение с таким именем уже развернуто, его необходимо предварительно удалить с сервера с помощью кнопки удаления в разделе расширений qmc</span></p>
<p><span>в qlik sense desktop проект расширения просто необходимо поместить в папку </span><code>C:\Users\[UserName]\Documents\Qlik\Sense\Extensions\</code><span>. любые изменения в файлах расширения будут отражены в расширении при перезагрузке страницы приложения.</span></p>
<p><span>ознакомьтесь со </span><a href="https://opensrc.axisgroup.com/qext/qlik-extensions/why-qext.html"><span>следующим разделом</span></a><span> , чтобы узнать, как qExt помогает в настройке этих проектов и автоматизации развертывания.</span></p>
<h2>Для чего нужно qExt?</h2>
<p><span>Библиотека qExt была создана по трем основным причинам.</span></p>
<ol>
<li><span>обеспечить лучшую поддержку для компиляции </span><strong><span>javascript следующего поколения</span></strong><span></span></li>
<li><span>упростить процесс </span><strong><span>развертывания</span></strong><span> расширений в средах qlik sense</span></li>
<li><span>сделать инициализацию новых проектов расширений более воспроизводимой с помощью </span><strong><span>стандартных шаблонов кода</span></strong></li>
</ol>
<h3 id="next-gen-javascript"><span>JavaScript следующего поколения</span></h3>
<p><span>скрипт, который вы видели на предыдущей странице (и javascript, который вы увидите во многих расширениях qlik), написан на ванильном javascript, который обычно можно использовать в большинстве современных веб-браузеров. это отличное начало для многих, кто начинает знакомиться с javascript, но многие разработчики хотят использовать более новые версии и возможности javascript, включая импорт модулей, функции стрелок и многое другое.</span></p>
<p><span>существует множество инструментов, помогающих преобразовывать новый код javascript в обратно совместимые форматы. qExt использует babel в координации с webpack для компиляции всего кода в формат, который может использоваться современными браузерами.</span></p>
<h3 id="streamline-deployment"><span>Оптимизация развертывания</span></h3>
<p><span>в последнем разделе упоминался процесс развертывания расширений в наших средах qlik. если вы выполняете серьезную работу по разработке проекта, ручное решение по удалению и повторному импорту кода проекта каждый раз, когда вносятся изменения, вероятно, не подходит. именно поэтому мы встроили интеграцию развертывания в qExt. инструмент может установить прямое соединение с вашим сервером qlik и автоматически удалить старое расширение и развернуть обновленное за считанные секунды с помощью API qrs</span></p>
<h3 id="templates"><span>Шаблоны</span></h3>
<p><span>в примере кода с предыдущей страницы использовался только один из многих методов, доступных в расширениях qlik. обычно при разработке расширений мы используем другие объекты и методы, такие как initialProperties, шаблон, контроллер и другие, чтобы полностью использовать настройки наших расширений. мы обнаружили, что многие из них довольно часто используются в проектах, и вместо того, чтобы переопределять их каждый раз, когда мы создаем новое расширение, мы определили их в шаблонных проектах, которые можно использовать для создания новых проектов расширений из</span></p>
<h1>Введение в qExt Packages (Пакеты qExt)</h1>
<p><span>библиотека qExt на самом деле состоит из двух разных пакетов, которые помогают нам в разработке расширений.</span></p>
<ol>
<li><span>qext-scripts — инструмент, который запускается в нашей среде разработки расширений для компиляции кода и развертывания его в средах qlik sense.</span></li>
<li><span>qext — инструмент cli, который позволяет нам создать новый проект расширения с определенным шаблоном.</span></li>
</ol>
<h2 id="qext-scripts"><span>qext-скрипты</span></h2>
<p><span>если мы оглянемся назад на 3 проблемы, которые qExt решает в </span><a href="https://opensrc.axisgroup.com/qext/qlik-extensions/why-qext.html"><span>разделе почему qExt</span></a><span> , qext-скрипты в основном помогают нам решить первые 2 проблемы. он поддерживает разработку javascript следующего поколения, компилируя наш код в обратно совместимый формат, и упрощает процесс развертывания, автоматически архивируя скомпилированный код и отправляя его в среды, которые нам нужно обновить.</span></p>
<p><span>если у вас уже настроена среда разработки расширений, вы можете легко включить в нее qext-скрипты, установив ее из npm в свой проект расширения.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">$ npm install --save-dev qext-scripts</pre>
<h2 id="qext"><span>qext</span></h2>
<p><span>библиотека qext помогает нам решить третью проблему, которую мы задали в вопросе, почему именно qExt, реализуя шаблоны шаблонного кода. это в первую очередь интерфейс командной строки, который мы можем запускать глобально для создания проекта с указанным шаблоном каталога. он также автоматически установит зависимость qext-scripts</span></p>
<p><span>qext лучше всего устанавливать глобально, чтобы проекты можно было настраивать, откуда бы вы его ни вызывали.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">$ npm install -g qext</pre>
<p>&nbsp;</p>
<h1>Использование</h1>
<h2>Быстрый старт</h2>
<p>прочитайте это, чтобы быстро установить инструменты qext и настроить новый проект</p>
<h3 id="install-qext"><span>Установить QExt</span></h3>
<p><span>установить основной инструмент qext глобально</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">npm install -g qext</pre>
<h3>Создать новое расширение</h3>
<p><span>откройте окно терминала, в котором вы хотите разместить свой проект, и используйте инструмент qext cli для создания и установки нового проекта расширения.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">qext --create-extension my-extension --install
cd my-extension</pre>
<p><em><span>по умолчанию qext установит </span><a href="https://opensrc.axisgroup.com/qext/templates/starter.html"><code>starter</code></a><span>шаблон проекта. другие шаблоны могут быть переданы через флаг шаблона. доступные шаблоны можно найти </span><a href="https://opensrc.axisgroup.com/qext/templates/"><span>здесь</span></a></em></p>
<h3>Build extension (сборка экстеншена)</h3>
<p><span>обновите исходные файлы расширения по мере необходимости, затем запустите</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">npm run build</pre>
<p><span>проект расширения будет скомпилирован и заархивирован в выходной каталог</span></p>
<h3>Просмотр экстеншена</h3>
<p><span>запустите команду qext watch</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">npm run watch</pre>
<p><span>любые изменения, которые вы делаете и сохраняете в своих исходных файлах, будут автоматически перестроены в ваш выходной каталог.</span></p>
<h3>Deploy extension</h3>
<p><span>добавьте следующую конфигурацию развертывания в файл qext.config.json</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
    ...,
    "serverDeploy": {
        "host": "hostname",
        "isSecure": true,
        "windowsAuth": true
    }
}</pre>
<p>затем запустите</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">npm run deploy</pre>
<p><span>окно терминала запросит ваши учетные данные. предоставить учетные данные для пользователя с доступом на запись к расширениям qlik sense, и новое расширение будет развернуто на сервере</span></p>
<p><em><span>конфигурация serverDeploy может потребовать другие параметры в зависимости от конфигурации сервера. проверьте </span><a href="https://opensrc.axisgroup.com/qext/configuration/qext-config-json.html"><span>qExt config</span></a><span> для полных настроек конфигурации</span></em></p>
<p><span>в качестве альтернативы вы можете аутентифицироваться с использованием аутентификации заголовка. проверить использование раздела </span><a href="https://opensrc.axisgroup.com/qext/usage/header-auth.html"><span>аутентификации заголовка для получения дополнительной информации</span></a></p>
<h1>Templates (Шаблоны)</h1>
<p><span>Шаблоны позволяют вам устанавливать предварительно определенные каталоги проектов и настройки при использовании инструмента qext cli. имя используемого шаблона может быть передано через </span><code>-t, --template [type]</code><span>флаг. ниже приведены шаблоны, которые вы можете выбрать</span></p>
<ul>
<li><a href="https://opensrc.axisgroup.com/qext/templates/vanilla-base.html"><span>vanilla-base</span></a><span> — самый простой проект, настроенный для проектов, которые будут написаны с использованием vanilla javascript.</span></li>
<li><a href="https://opensrc.axisgroup.com/qext/templates/base.html"><span>base</span></a><span> — базовый каталог проекта, который устанавливает минимальные исходные файлы, которые будут скомпилированы с использованием webpack и babel.</span></li>
<li><a href="https://opensrc.axisgroup.com/qext/templates/starter.html"><span>starter</span></a><span> — начальный шаблон, включая общие методы расширения и файлы конфигурации</span></li>
</ul>
<h2>Vanilla base</h2>
<p><span>базовый шаблон vanilla — это самый простой шаблон, с которого вы можете начать, используя qExt.</span></p>
<h3 id="project-directory"><span>Каталог проекта</span></h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">├── src
│ ├── qext-template.qext
│ ├── qext-template.js
├── static
├── package.json
├── qext.config.json</pre>
<h3><span>каталог src</span></h3>
<p><span>исходный каталог имеет 2 исходных файла </span><code>qext-template.qext</code><span>и </span><code>qext-template.js</code><span>. эти файлы следует переименовать в имя расширения, поскольку оно должно храниться в Qlik Sense (имя, которое вы видите при просмотре расширений в QMC).</span></p>
<h3 id="qextconfigjson"><span>qext.config.json</span></h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
    "extension": "qext-template",
    "output": "./dist",
    "vanilla": {
        "entry": "./src",
        "static": "./static"
    }
}</pre>
<p><span>файл конфигурации qext настроен с именем расширения, установленным на qext-template, и для сборки в ванильном режиме. </span><span>когда проект построен, файлы будут скопированы из исходного кода в выходной каталог как есть</span></p>
<h2>Base</h2>
<p><span>базовый шаблон — это базовый шаблон, используемый для компиляции исходного кода расширения с помощью babel и webpack.</span></p>
<h2 id="project-directory"><span>Каталог проекта</span></h2>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">├── src
│ ├── index.qext
│ ├── index.js
├── static
├── package.json
├── qext.config.json</pre>
<h3 id="src-directory"><span>каталог src</span></h3>
<p><span>исходный каталог имеет 2 исходных файла, </span><code>index.qext</code><span>и</span><code>index.js</code></p>
<h3 id="qextconfigjson"><span>qext.config.json</span></h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
    "extension": "qext-template",
    "output": "./dist",
    "compile": {
        "entry": "./src/index.js",
        "qext": "./src/index.qext",
        "static": "./static"
    }
}</pre>
<p><span>файл конфигурации qext настроен с именем расширения, установленным на qext-template, и для сборки в режиме компиляции. </span><span>когда проект будет построен, webpack скомпилирует файлы через файл compile.entry и поместит скомпилированные файлы в выходной каталог. </span><span>он также скопирует файл qext в выходной каталог</span></p>
<h2>Starter</h2>
<p><span>начальный шаблон устанавливает каталог вашего проекта с часто используемыми методами расширения</span></p>
<h3 id="project-directory"><span>Каталог проекта</span></h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">├── src
│ ├── index.qext
│ ├── index.js
│ ├── style.css
│ ├── methods
│ │ ├── controller.js
│ │ ├── definition.js
│ │ ├── index.js
│ │ ├── initial-properties.js
│ │ ├── paint.js
│ │ ├── resize.js
│ │ ├── template.html
├── static
├── package.json
├── qext.config.json</pre>
<h3 id="qextconfigjson"><span>qext.config.json</span></h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
    "extension": "qext-template",
    "output": "./dist",
    "compile": {
        "entry": "./src/index.js",
        "qext": "./src/index.qext",
        "static": "./static"
    }
}</pre>
<p><span>файл конфигурации qext настроен с именем расширения, установленным на qext-template, и для сборки в режиме компиляции. </span><span>когда проект будет построен, webpack скомпилирует файлы через файл compile.entry и поместит скомпилированные файлы в выходной каталог. </span><span>он также скопирует файл qext в выходной каталог</span></p>
<h3>src/index.qext</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">{
    "type": "visualization",
    "name": "qExt Template"
}</pre>
<p><span>это метаданные расширения. свойство name должно быть обновлено до имени, которое видит конечный пользователь на панели объектов расширения приложения qlik. файл будет переименован в </span><code>extension</code><span>значение свойства в</span><code>qext.config.json</code></p>
<h3>src/index.js</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">import { initialProperties, template, definition, controller, paint, resize } from "./methods"
import "./style.css"

window.define([], function() {
    return {
        initialProperties,
        template,
        definition,
        controller,
        paint,
        resize,
    }
})</pre>
<h3>src/style.css</h3>
<p><span>это файл css, используемый для определения любых стилей для нашего объекта расширения. обратите внимание, что все классы должны быть предварительно выбраны с именем класса объекта расширения, которое будет в формате</span><extension-name><span>-qv-объект. например, если вы хотите установить цвет фона элемента с классом </span><code>container</code><span>в вашем объекте расширения, а имя вашего расширения — </span><code>my-extension</code><span>, ваш css должен выглядеть так:</span></extension-name></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">.my-extension-qv-object .container {
    background-color: lightblue;
}</pre>
<h3>src/methods/initial-properties.js</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default {
    qHyperCubeDef: {
        qDimensions: [],
        qMeasures: [],
        qInitialDataFetch: [],
    },
}</pre>
<p><span>Initial-properties определяет определение свойств объекта при его первом создании пользователем qlik sense. </span><span>шаблон устанавливает свойства с помощью HyperCubeDef, но это можно изменить на другие определения qlik, такие как ListObjectDef, или пользовательские свойства</span></p>
<h3>src/methods/definition.js</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default {
    type: "items",
    component: "accordion",
    items: {
        settings: {
            uses: "settings",
        },
    },
}</pre>
<p><span>объект определения определяет конфигурацию панели свойств расширения. это основной способ, с помощью которого пользователь, добавляющий расширение на лист qlik, может настраивать и изменять параметры расширения, включая измерения, показатели, цвета и т. д.</span></p>
<p><span>больше о том, как настроить объект определения, можно найти </span><a href="https://help.qlik.com/en-US/sense-developer/April2020/Subsystems/Extensions/Content/Sense_Extensions/extensions-build-properties-panel.htm" target="_blank" rel="noopener"><span>здесь</span></a></p>
<h3>src/methods/paint.js</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default function($element, layout) {
    // ..paint code here
}</pre>
<p><span>функция рисования запускается каждый раз, когда происходит обновление макета нашего объекта расширения. это может быть вызвано изменением состояния выбора приложения qlik sense, а также изменением размера окна. это позволяет «перекрашивать» наше расширение при изменении, чтобы отображаемый вывод отображал самую последнюю версию данных, передаваемых в расширение. </span><code>$element</code><span>содержит ссылку элемента dom на объект расширения, который можно использовать для управления тем, что отображается в dom расширения, а layout содержит рассчитанный макет объекта расширения, включая любые выходные данные гиперкуба и настройки свойств.</span></p>
<h3>src/methods/resize.js</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default function($element, layout) {
    // ..resize code here
}</pre>
<p><span>методы изменения размера дают нам более точный контроль над тем, как наше расширение перерисовывается во время различных типов обновлений. в случаях, когда обновления, необходимые для изменения выбора и изменения размера, отличаются, мы можем разделить изменение размера на функцию метода изменения размера. важно отметить, что если возвращается метод изменения размера, в нашем </span><code>src/index.js</code><span>файле краска не будет запускаться при изменении размера окна.</span></p>
<h3>src/methods/template.html</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">&lt;div class="chart-container"&gt;qExt Template&lt;/div&gt;</pre>
<p><span>файл шаблона определяет исходный html, который отображается в нашем расширении. этот html можно увидеть в </span><code>$element</code><span>dom, который передается функциям рисования и изменения размера.</span></p>
<h3>src/methods/controller.js</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export default [
    "$scope",
    "$element",
    function($scope, $element) {
        // ..controller code here
    },
]</pre>
<p><span>функция контроллера запускается при инициализации расширения. </span><span>это может быть полезно для настройки начальной конфигурации и потоков для расширения, когда оно инициализируется на экране.</span></p>
<h3>src/methods/index.js</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">export { default as initialProperties } from "./initial-properties"
export { default as template } from "./template.html"
export { default as definition } from "./definition"
export { default as controller } from "./controller"
export { default as paint } from "./paint"
export { default as resize } from "./resize"</pre>
<p><span>этот файл экспортирует все модули из </span><code>methods</code><span>каталога</span></p>
<h1>Configuration</h1>
<h2>CLI Flags (<span>Флаги командной строки)</span></h2>
<table style="border-style: solid; border-color: #474747; width: 100%; height: 175px;">
<thead>
<tr style="height: 27px;">
<th style="height: 27px; width: 43.3333%;"><strong>Flag</strong></th>
<th style="height: 27px; width: 35.7333%;"><strong>Description</strong></th>
<th style="height: 27px; width: 10.9333%;"><strong>Required</strong></th>
<th style="height: 27px; width: 9.46667%;"><strong>Default</strong></th>
</tr>
</thead>
<tbody>
<tr style="height: 60px;">
<td style="height: 60px; width: 43.3333%;"><code>-c, --create-extension &lt;name&gt;</code></td>
<td style="height: 60px; width: 35.7333%;">name of extension</td>
<td style="height: 60px; width: 10.9333%;">Yes</td>
<td style="height: 60px; width: 9.46667%;">N/A</td>
</tr>
<tr style="height: 30px;">
<td style="height: 30px; width: 43.3333%;"><code>-t, --template [type]</code></td>
<td style="height: 30px; width: 35.7333%;">name template</td>
<td style="height: 30px; width: 10.9333%;">No</td>
<td style="height: 30px; width: 9.46667%;">starter</td>
</tr>
<tr style="height: 58px;">
<td style="height: 58px; width: 43.3333%;"><code>-i, --install</code></td>
<td style="height: 58px; width: 35.7333%;">if provided, will install qext-scripts</td>
<td style="height: 58px; width: 10.9333%;">No</td>
<td style="height: 58px; width: 9.46667%;">N/A</td>
</tr>
</tbody>
</table>
<h2>qext Config</h2>
<table>
<thead>
<tr>
<th>property</th>
<th>description</th>
<th>type</th>
<th>required</th>
</tr>
</thead>
<tbody>
<tr>
<td>extension</td>
<td>name of extension object</td>
<td>string</td>
<td>yes</td>
</tr>
<tr>
<td>output</td>
<td>directory where output files will be placed</td>
<td>string</td>
<td>yes</td>
</tr>
<tr>
<td>vanilla</td>
<td>configuration of vanilla settings in running in vanilla mode</td>
<td><a href="https://opensrc.axisgroup.com/qext/configuration/qext-config-json.html#vanilla">vanilla</a></td>
<td>yes if compile not defined</td>
</tr>
<tr>
<td>compile</td>
<td>configuration of compile settings in running in compile mode</td>
<td><a href="https://opensrc.axisgroup.com/qext/configuration/qext-config-json.html#compile">compile</a></td>
<td>yes if vanilla not defined</td>
</tr>
<tr>
<td>serverDeploy</td>
<td>configuration of server deployment settings if deploying to server</td>
<td><a href="https://opensrc.axisgroup.com/qext/configuration/qext-config-json.html#serverdeploy">serverDeploy</a></td>
<td>no</td>
</tr>
<tr>
<td>desktopDeploy</td>
<td>configuration of desktop deployment settings if deploying to desktop environment</td>
<td><a href="https://opensrc.axisgroup.com/qext/configuration/qext-config-json.html#desktopdeploy">desktopDeploy</a></td>
<td>no</td>
</tr>
</tbody>
</table>
<h3 id="vanilla">vanilla</h3>
<table>
<thead>
<tr>
<th>property</th>
<th>description</th>
<th>type</th>
<th>required</th>
</tr>
</thead>
<tbody>
<tr>
<td>entry</td>
<td>source directory path to be copied into output</td>
<td>string</td>
<td>yes</td>
</tr>
<tr>
<td>static</td>
<td>static directory path to be copied into output</td>
<td>string</td>
<td>no</td>
</tr>
</tbody>
</table>
<h3 id="compile">compile</h3>
<table>
<thead>
<tr>
<th>property</th>
<th>description</th>
<th>type</th>
<th>required</th>
</tr>
</thead>
<tbody>
<tr>
<td>entry</td>
<td>entry file path to build project from</td>
<td>string</td>
<td>yes</td>
</tr>
<tr>
<td>qext</td>
<td>qext file path to be copied into output directory</td>
<td>string</td>
<td>yes</td>
</tr>
<tr>
<td>static</td>
<td>static directory path to be copied into output</td>
<td>string</td>
<td>no</td>
</tr>
<tr>
<td>webpackComments</td>
<td>set to false to hide webpack compile comments when building</td>
<td>bool</td>
<td>no</td>
</tr>
<tr>
<td>altWebpackConfig</td>
<td>path to alternate webpack.config.js file that should override the default webpack config definition</td>
<td>string</td>
<td>no</td>
</tr>
</tbody>
</table>
<h3 id="serverdeploy">serverDeploy</h3>
<table>
<thead>
<tr>
<th>property</th>
<th>description</th>
<th>type</th>
<th>required</th>
</tr>
</thead>
<tbody>
<tr>
<td>host</td>
<td>host name of qlik server</td>
<td>string</td>
<td>yes</td>
</tr>
<tr>
<td>port</td>
<td>port over which to access qlik server</td>
<td>number</td>
<td>no</td>
</tr>
<tr>
<td>prefix</td>
<td>prefix endpoint where resources are deployed. typically used with header authentication</td>
<td>string</td>
<td>no</td>
</tr>
<tr>
<td>isSecure</td>
<td>whether endpoint should be connected to over ssl</td>
<td>bool</td>
<td>no</td>
</tr>
<tr>
<td>allowSelfSignedSignature</td>
<td>allow connection to qlik server that has a self-signed certificate</td>
<td>bool</td>
<td>no</td>
</tr>
<tr>
<td>hdrAuthUser</td>
<td>name of user as defined in the header authentication virtual proxy</td>
<td>string</td>
<td>no</td>
</tr>
<tr>
<td>hdrAuthHeaderName</td>
<td>name of auth header property as defined in virtual proxy</td>
<td>string</td>
<td>no</td>
</tr>
<tr>
<td>windowsAuth</td>
<td>set to true to use windows authentication to deploy extension</td>
<td>bool</td>
<td>no</td>
</tr>
<tr>
<td>user</td>
<td>username associated with windowsAuth. if defined here, you will not be prompted for credentials in the terminal</td>
<td>string</td>
<td>no</td>
</tr>
<tr>
<td>password</td>
<td>password associated with windowsAuth. if defined here, you will not be prompted for credentials in the terminal</td>
<td>string</td>
<td>no</td>
</tr>
</tbody>
</table>
<h3 id="desktopdeploy">desktopDeploy</h3>
<table>
<thead>
<tr>
<th>property</th>
<th>description</th>
<th>type</th>
<th>required</th>
</tr>
</thead>
<tbody>
<tr>
<td>destination</td>
<td>destination of built extension files.</td>
<td>string</td>
<td>yes</td>
</tr>
</tbody>
</table>
<h1>Использованные источники</h1>
<ol>
<li><a href="https://opensrc.axisgroup.com/qext/" target="_blank" rel="noopener">https://opensrc.axisgroup.com/qext/</a></li>
<li><a href="https://medium.com/@jbellizzi/new-qext-277121a59b93" target="_blank" rel="noopener">https://medium.com/@jbellizzi/new-qext-277121a59b93</a></li>
<li><a href="https://github.com/axisgroup/qExt" target="_blank" rel="noopener">https://github.com/axisgroup/qExt</a></li>
</ol>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qext-extension-development-environment/">qExt v2.0 &#8211; Extension Development Environment (Qlik Sense)</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/qext-extension-development-environment/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Панель свойств расширения или Properties Panel</title>
		<link>https://qliksense.ivan-shamaev.ru/properties-panel-basics-qlik-extension/</link>
					<comments>https://qliksense.ivan-shamaev.ru/properties-panel-basics-qlik-extension/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 12 Feb 2021 20:27:45 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[Building a properties panel]]></category>
		<category><![CDATA[Building visualization extensions]]></category>
		<category><![CDATA[custom properties]]></category>
		<category><![CDATA[extension custom properties]]></category>
		<category><![CDATA[Properties panel basics]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[Reusable Properties]]></category>
		<category><![CDATA[как задать свойства расширения]]></category>
		<category><![CDATA[Настраиваемые свойства Extension]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2580</guid>

					<description><![CDATA[<p>Создание панели свойств Qlik Sense Extension Введение в свойства расширения. Что такое панель свойств? Перед тем, как перейти к разработке Qlik Sense Visualization Extensions, необходимо понять основные принципы определения и использования свойств в Qlik Sense расширениях. Основная идея свойств состоит в том, чтобы предложить пользователям способ настройки поведения расширений визуализации таким же<a class="moretag" href="https://qliksense.ivan-shamaev.ru/properties-panel-basics-qlik-extension/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/properties-panel-basics-qlik-extension/">Панель свойств расширения или Properties Panel</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Создание панели свойств Qlik Sense Extension</h1>
<h2>Введение в свойства расширения. Что такое панель свойств?</h2>
<p>Перед тем, как перейти к разработке Qlik Sense Visualization Extensions, необходимо понять основные принципы определения и использования свойств в Qlik Sense расширениях.</p>
<p><span>Основная идея свойств состоит в том, чтобы предложить пользователям способ настройки поведения </span><em><span>расширений визуализации</span></em><span> таким же образом, как они будут управлять собственными объектами Qlik Sense. Поэтому разработчик расширения может использовать программный интерфейс для определения свойств, которые затем отображаются на правой панели свойств.</span></p>
<h2>Определение панели свойств</h2>
<p><span>Свойства структурированы иерархически (есть еще такой термин, как аккордеон панели свойств):</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Panel_Properties_Customization_Developing.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Panel_Properties_Customization_Developing.png" alt="" width="242" height="481" class="aligncenter size-full wp-image-2583" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Panel_Properties_Customization_Developing.png 242w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Panel_Properties_Customization_Developing-151x300.png 151w" sizes="(max-width: 242px) 100vw, 242px" /></a></p>
<p>A &#8211; Sections<br />
B &#8211; Header<br />
C &#8211; Items</p>
<p>Есть еще одна иллюстрация (с сайта <strong><a href="http://qliksite.io/tutorials/qliksense-visualization-extensions/part-01/06-Introduction-to-Using-Properties/" target="_blank" rel="noopener">http://qliksite.io/tutorials/qliksense-visualization-extensions/part-01/06-Introduction-to-Using-Properties/</a></strong>):</p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Development_Accordion_Concept.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Development_Accordion_Concept.png" alt="" width="582" height="466" class="aligncenter size-full wp-image-2584" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Development_Accordion_Concept.png 582w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Extension_Development_Accordion_Concept-300x240.png 300w" sizes="(max-width: 582px) 100vw, 582px" /></a></p>
<p><strong>Accordion</strong><span></span></p>
<ul>
<li>Accordion<span> </span><strong>sections</strong>
<ul>
<li>Section<span> </span><strong>headers</strong>
<ul>
<li>Property<span> </span><strong>items</strong></li>
</ul>
</li>
</ul>
</li>
</ul>
<p><span>Свойства добавляются путем их </span><span class="syntax"><span>определения в</span></span><span> свойстве <code>definition</code> в файле JavaScript. </span></p>
<p><strong>Есть два способа определения свойств:</strong></p>
<ul>
<li><span>Повторное использование существующих встроенных свойств (</span>Reusing existing, built-in, properties)</li>
<li><span>Создать настраиваемые свойства (custom properties)</span></li>
</ul>
<p><strong>Reusable Properties:</strong></p>
<ul>
<li>Dimensions</li>
<li>Measures</li>
<li>Sorting</li>
<li>Appearance</li>
<li>Add-Ons</li>
</ul>
<h3><madcap:concept term="Building visualization extensions" xmlns:madcap="http://www.madcapsoftware.com/Schemas/MadCap.xsd"><span>Повторное использование существующих свойств</span></madcap:concept></h3>
<p><span>Вот некоторые типичные свойства, используемые для наиболее распространенных встроенных визуализаций </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense</span></span><span>:</span></p>
<ul>
<li><span>Все собственные визуализации имеют раздел </span><span class="ui_item"><span>Внешний вид</span></span><span> с заголовком раздела </span><span class="ui_item"><span>Общие</span></span><span> .</span></li>
<li><span>Большинство встроенных визуализаций позволяют определять </span><span class="ui_item"><span>измерения</span></span><span> и </span><span class="ui_item"><span>меры</span></span><span> .</span></li>
</ul>
<h4 id="anchor-1" tabindex="-1"><span>Определение свойств</span></h4>
<p><span>Если вы создаете расширение визуализации без defining a properties panel, </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense</span></span><span> по умолчанию будет включать раздел <strong>&#8220;</strong></span><strong><span class="ui_item">Внешний вид</span></strong><span><strong>&#8220;</strong> или <strong>&#8220;<span class="ui_item">Appearance</span> section&#8221;</strong>.</span></p>
<p><span>Тот же результат будет достигнут при повторном использовании раздела </span><span class="syntax"><span>настроек</span></span><span>, который является внутренним именем раздела Внешний вид.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [
        'jquery'
    ],
    function ( $ ) {
        'use strict';

        return {

            // Define what the properties panel looks like
            definition: {
                type: "items",
                component: "accordion",
                items: {
                    appearance: {
                        uses: "settings",
                    }
                }
            },
            // Paint/Rendering logic
            paint: function ( $element /*, layout*/ ) {

                $element.empty();
                var $msg = $( document.createElement( 'div' ) );
                $msg.html( 'Just demonstrating default behavior of the property panel"' );
                $element.append( $msg );

            }
        };

    } );</pre>
<p><span>На основе приведенного выше кода вы теперь можете расширить <code><span class="syntax">definition</span></code> </span><span>для повторного использования других встроенных разделов. В этом примере мы также повторно будем использовать разделы измерений, мер и сортировки.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">// Define what the properties panel looks like
definition: {
    type: "items",
    component: "accordion",
    items: {
        dimensions: {
            uses: "dimensions"
        },
        measures: {
            uses: "measures"
        },
        sorting: {
            uses: "sorting"
        },
        appearance: {
            uses: "settings",
        }
    }
},</pre>
<p>В результате мы получим следующую панель свойств:</p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript.jpg"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript.jpg" alt="" width="324" height="368" class="aligncenter size-full wp-image-2585" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript.jpg 324w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript-264x300.jpg 264w" sizes="(max-width: 324px) 100vw, 324px" /></a></p>
<h4 id="anchor-2" tabindex="-1"><span>Ссылка на свойства</span></h4>
<p><span>Параметр макета (layout) передается в метод paint, и он включает текущую область расширения визуализации вместе с определенными свойствами.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">// Paint/Rendering logic
paint: function ( $element, layout ) {

    console.info('paint &gt;&gt; layout &gt;&gt; ', layout);

}</pre>
<p><span>Если вы посмотрите на вывод консоли, например, в Chrome DevTools, вы найдете то, что ищете.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/chrome_devtools_properties_console_log_print.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/chrome_devtools_properties_console_log_print.png" alt="" width="953" height="253" class="aligncenter size-full wp-image-2586" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/chrome_devtools_properties_console_log_print.png 953w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/chrome_devtools_properties_console_log_print-300x80.png 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/chrome_devtools_properties_console_log_print-768x204.png 768w" sizes="(max-width: 953px) 100vw, 953px" /></a></p>
<p><span>С этой информацией теперь вы можете начать выводить некоторые значения в метод <code>paint</code></span><span>.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">// Paint/Rendering logic
paint: function ( $element, layout ) {

    //output values from the property panel
    $element.empty();
    
    //output container
    var $msg = $( document.createElement( 'div' ) );
    
    //variable holding the output
    var html = '&lt;b&gt;Property values:&lt;/b&gt;&lt;br/&gt;';
    html += 'Title: ' + layout.title + '&lt;br/&gt;';
    html += 'Subtitle: ' + layout.subtitle + '&lt;br/&gt;';
    
    //assign the variable to the output container
    $msg.html( html );
    
    //add the output container to the current element
    $element.append( $msg );

}</pre>
<p>Получим следующий результат:</p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript_example2.jpg"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript_example2.jpg" alt="" width="549" height="495" class="aligncenter size-full wp-image-2587" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript_example2.jpg 549w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Qlik_Sense_Custom_Properties_result_of_javascript_example2-300x270.jpg 300w" sizes="(max-width: 549px) 100vw, 549px" /></a></p>
<h3 id="anchor-3" tabindex="-1"><span>Собственные свойства, которые можно использовать повторно</span></h3>
<p><span>В этом разделе перечислены собственные свойства </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense,</span></span><span> которые можно повторно использовать в определении панели свойств.</span></p>
<h4>Dimensions</h4>
<p><span>Когда вы повторно используете раздел</span> Dimensions section, <span>он включает в себя следующее</span>:</p>
<ul>
<li>Add dimension</li>
</ul>
<p><span>После добавления измерения у вас есть следующие свойства по умолчанию</span>:</p>
<ul>
<li>Field</li>
<li>Label</li>
<li>Show null values</li>
<li>Limitation</li>
<li>Show others</li>
<li>Others label</li>
</ul>
<p><strong>Пример: Add Dimensions section</strong></p>
<p><span>В приведенном ниже примере показано, как добавить раздел &#8220;<strong>Dimensions</strong>&#8221; на панель свойств вашего расширения визуализации. </span><span>Обратите внимание, что определено, что расширение визуализации должно иметь ровно одно измерение.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [], function ( ) {
    
    return {
        type: "items",
        component: "accordion",
        items: {
            dimensions: {
                uses: "dimensions",
                min: 1,
                max: 1
            }
        }
    };
 
});</pre>
<h4>Measures</h4>
<p><span>Когда вы повторно используете раздел &#8220;Меры&#8221;, он включает в себя следующее</span>:</p>
<ul>
<li>Add measure</li>
</ul>
<p><span>Когда вы добавили меру, у вас появятся следующие свойства по умолчанию</span>:</p>
<ul>
<li>Label</li>
<li>Expression</li>
<li>Number formatting</li>
</ul>
<p class="example" data-mc-autonum="Example: " data-mc-conditions=""><strong><span class="autonumber">Пример: </span>Add Measures section</strong></p>
<p data-mc-conditions=""><span>В этом примере показано, как мы теперь добавили определение раздела «Меры» на панель свойств нашего расширения визуализации. </span><span>Обратите внимание, что здесь мы также определяем, что расширение визуализации должно иметь ровно одну меру.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">define( [], function ( ) {
    
    return {
        type: "items",
        component: "accordion",
        items: {
            dimensions: {
                uses: "dimensions",
                min: 1,
                max: 1
            },
            measures: {
                uses: "measures",
                min: 1,
                max: 1
            }
        }
    };
 
});</pre>
<h4>Sorting</h4>
<p><span>Когда вы повторно используете раздел сортировки, он включает в себя следующее</span>:</p>
<ul>
<li>Labels of the dimension and measure<span>, используемые в расширении визуализации</span></li>
<li>Sorting option (Auto or Custom)<span>Опция Custom включает в себя следующее:</span>
<ul>
<li>Sort by expression (only available for dimensions)</li>
<li>Sort numerically</li>
<li>Sort alphabetically</li>
<li>Sort by frequency (only available for filter panes)</li>
</ul>
</li>
</ul>
<p class="example" data-mc-autonum="Example: " data-mc-conditions=""><strong><span class="autonumber">Пример: </span>Add Sorting section</strong></p>
<p data-mc-conditions=""><span>В этом примере показано, как мы теперь добавили определение раздела «Сортировка» на панель свойств вашего расширения визуализации. Мы не вносили никаких изменений в раздел «Сортировка», предварительно определенный </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense</span></span><span>.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">define( [], function ( ) {
    
    return {
        type: "items",
        component: "accordion",
        items: {
            dimensions: {
                uses: "dimensions",
                min: 1,
                max: 1
            },
            measures: {
                uses: "measures",
                min: 1,
                max: 1
            },
            sorting: {
                uses: "sorting"
            }
        }
    };
 
});</pre>
<h4>Add-ons (Надстройки)</h4>
<p><span>Когда вы повторно используете раздел надстроек (Add-ons), он включает в себя следующее:</span></p>
<ul>
<li>Data handling</li>
<li>Reference lines</li>
</ul>
<p class="example" data-mc-autonum="Example: " data-mc-conditions=""><strong><span class="autonumber">Пример: </span>Add Add-ons section</strong></p>
<p data-mc-conditions=""><span>В этом примере показано, как мы добавляем определение раздела «Надстройки» на панель свойств вашего расширения визуализации. Мы не вносили никаких изменений в раздел «Надстройки», предварительно определенный </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense</span></span><span>.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [], function ( ) {
    
    return {
        type: "items",
        component: "accordion",
        items: {
            dimensions: {
                uses: "dimensions",
                min: 1,
                max: 1
            },
            measures: {
                uses: "measures",
                min: 1,
                max: 1
            },
            sorting: {
                uses: "sorting"
            },
            addons: {
                uses: "addons"
            }
        }
    };
 
});</pre>
<h4>Appearance (<span class="syntax">settings</span>) &#8211; <span>Внешний вид</span></h4>
<blockquote><p><span>Appearance section называется </span><code><span class="syntax">settings</span></code><span> в коде.</span></p></blockquote>
<p><span>Когда вы повторно используете раздел «Внешний вид», он включает в себя следующее:</span></p>
<ul>
<li>General &#8211; <span>Общий</span><span>Включает настройки для заголовка, подзаголовка и сноски</span></li>
<li>Presentation &#8211; <span>Презентация</span> (<span>доступна только для визуализаций с более чем одним измерением</span>)</li>
<li>Colors and legend &#8211; <span>Цвета и легенда</span> (<span>доступно только в некоторых типах визуализаций</span>)</li>
<li>X-axis &#8211; <span>Ось X</span> (<span>доступна только в некоторых типах визуализаций</span>)</li>
<li>Y-axis &#8211; <span>Ось Y</span> (<span>доступна только в некоторых типах визуализаций</span>)</li>
</ul>
<p class="example" data-mc-autonum="Example: " data-mc-conditions=""><strong><span class="autonumber">Пример: </span>Add Appearance section</strong></p>
<p data-mc-conditions=""><span class="CommonComponentsQlik Sense"><span>В этом примере показано, как мы добавляем определение раздела «Внешний вид» на панель свойств вашего расширения визуализации. Мы не вносили никаких изменений в раздел «Надстройки», предварительно определенный </span><span>Qlik Sense</span><span>.</span></span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [], function ( ) {
    
    return {
        type: "items",
        component: "accordion",
        items: {
            dimensions: {
                uses: "dimensions",
                min: 1,
                max: 1
            },
            measures: {
                uses: "measures",
                min: 1,
                max: 1
            },
            sorting: {
                uses: "sorting"
            },
            addons: {
                uses: "addons"
            },
            settings: {
                uses: "settings"
            }
        }
    };
 
});</pre>
<h3><strong>Добавление дополнительных свойств (</strong><madcap:concept term="Building visualization extensions" xmlns:madcap="http://www.madcapsoftware.com/Schemas/MadCap.xsd">custom properties)</madcap:concept></h3>
<p><span>Вы можете задать <strong>custom properties</strong> для <strong>visualization extension</strong>. </span><span style="color: #339966;"><strong><span class="CommonComponentsQlik Sense">Qlik Sense</span></strong></span><span> автоматически добавляет их на панель свойств и заботится о сохранении. Затем вы найдете выбранные значения в параметре <code>layout</code>.</span></p>
<p><span>Для каждого свойства вы задаете объект JavaScript с разными полями в зависимости от того, какой тип настраиваемого свойства вы определяете.</span></p>
<p><span>Следующие компоненты пользовательского интерфейса могут использоваться для отображения ваших custom properties на панели свойств:</span></p>
<ul>
<li><strong>Button</strong> &#8211; Кнопка</li>
<li><strong>Button group</strong> &#8211; Группа кнопок</li>
<li><strong>Check box</strong> &#8211; Флажок</li>
<li><strong>Color-picker</strong> &#8211; выбор цвета</li>
<li><strong>Drop down list</strong> &#8211; Выпадающий список</li>
<li><strong>Input box / text box</strong> &#8211; <span><span>Поле ввода / текстовое поле</span></span></li>
<li><strong>Link</strong> &#8211; Ссылка</li>
<li><strong>Media</strong></li>
<li><strong>Radio button</strong> &#8211; Переключатель</li>
<li><strong>Range slider</strong> &#8211; Ползунок для выбора диапазона</li>
<li><strong>Slider</strong></li>
<li><strong>Switch</strong> &#8211; Переключатель</li>
<li><strong>Text</strong> &#8211; Текст</li>
<li><strong>Text area</strong> &#8211; Текстовая область</li>
</ul>
<p><span>Их можно сгруппировать в разделы и заголовки на панели свойств. </span><span>Каждый из них предоставляет различные параметры конфигурации для управления их поведением.</span></p>
<h4><strong>Совет: Как улучшить управляемость скриптом Javascript при разработке Extension?</strong></h4>
<p><span>Если у вас есть много разных свойств, определенных в основном файле JavaScript, вы скоро поймете, что размер файла js может стать довольно большим, и его будет трудно читать и поддерживать. Для облегчения работы с js есть разные подходы:</span></p>
<ul>
<li><span>Разделите раздел <code>definition</code> на несколько переменных JavaScript.</span></li>
<li><span>Создайте отдельный файл JavaScript для определения ваших свойств и загрузите этот файл в основной файл сценария расширения визуализации.</span></li>
</ul>
<h5><span>Определение свойств в отдельном файле JavaScript</span></h5>
<p><span>В этом разделе показано, как определить ваши свойства в отдельном файле JavaScript. </span><span>Мы начинаем со следующего кода, определенного в вашем основном файле сценария.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [
        'jquery'
    ],
    function ( $ ) {
        'use strict';

        return {

            // Define what the properties panel looks like
            definition: {
                type: "items",
                component: "accordion",
                items: {
                    dimensions: {
                        uses: "dimensions"
                    },
                    measures: {
                        uses: "measures"
                    },
                    appearance: {
                        uses: "settings",
                    }
                }
            },
            // Paint/Rendering logic
            paint: function ( $element, layout ) {
            // Main rendering logic goes here
            }
        };
    } );</pre>
<p><span>Создайте файл и назовите его <strong>properties.js</strong>. </span><span>Сохраните его в той же папке, где находятся ваши основные файлы расширения визуализации. </span><span>Новый файл <strong>properties.js</strong> должен выглядеть так:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [], function () {
    'use strict';
    // *****************************************************************************
    // Dimensions &amp; Measures
    // *****************************************************************************
    var dimensions = {
        uses: "dimensions",
        min: 0,
        max: 1
    };
    var measures = {
        uses: "measures",
        min: 0,
        max: 1
    };
    // *****************************************************************************
    // Appearance section
    // *****************************************************************************
    var appearanceSection = {
        uses: "settings"
    };
    // *****************************************************************************
    // Main properties panel definition
    // Only what is defined here is returned from properties.js
    // *****************************************************************************
    return {
        type: "items",
        component: "accordion",
        items: {
            dimensions: dimensions,
            measures: measures,
            appearance: appearanceSection
        }
    };
});</pre>
<p><span>Затем вам нужно загрузить внешнее определение свойств в ваш основной файл сценария и назначить <code>definition</code></span><span>.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [
        // Load properties.js using requireJS
        // Note: if you load .js files, omit the file extension
        // otherwise requireJS will not load it correctly
        './properties'
    ],
    function ( props ) {
        'use strict';
        return {
            definition: props,
            // Paint/Rendering logic
            paint: function ( $element, layout ) {
            // Main rendering logic goes here
            }
        };
    } );</pre>
<h4>Добавление basic custom property</h4>
<p><span>В этом разделе мы определим самый простой, но один из наиболее распространенных компонентов &#8211; текстовое поле.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">// Text box definition
var myTextBox = {
    ref: "props.myTextBox",
    label: "My text box",
    type: "string"
};</pre>
<p><span>В определении всех компонентов пользовательского интерфейса есть общие свойства, которые можно установить.</span></p>
<p><code><span class="syntax">type</span></code></p>
<p><span>Используется для всех определений типов настраиваемых свойств. Может быть </span><code><span class="API_syntax_input">string</span></code>,<span> </span><code><span class="API_syntax_input">integer</span></code>,<span> </span><code><span class="API_syntax_input">number</span></code><span> или</span><span> </span><code><span class="API_syntax_input">boolean</span></code>.</p>
<p><code><span class="syntax">ref</span></code></p>
<p><span>Имя или идентификатор, используемый для ссылки на свойство.</span></p>
<p><code><span class="syntax">label</span></code></p>
<p><span>Используется для определения метки, отображаемой на панели свойств.</span></p>
<p><code><span class="syntax">component</span></code></p>
<p><span>Используется для определения того, как свойство отображается на панели свойств.</span></p>
<div class="note"></div>
<blockquote><p><span>В приведенном выше примере <code><span class="syntax">component</span></code> </span><span>не определен. </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense </span></span><span>автоматически по умолчанию использует текстовое поле, если <code><span class="syntax">component</span></code> </span><span>не определен для элементов, <code><span class="syntax">type</span></code> </span><span class="syntax"><span>которых </span></span><span>является <code><span class="API_syntax_input">string</span></code> </span><span>или <code><span class="API_syntax_input">integer</span></code></span><span>.</span></p></blockquote>
<h4 id="anchor-3" tabindex="-1"><span>Добавление определения компонента на панель свойств</span></h4>
<p><span>В этом разделе мы добавим вновь созданное текстовое поле на основе строки в раздел Внешний вид.</span></p>
<p><strong>Перед:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">// Appearance section
var appearanceSection = {
    uses: "settings"
};
// Main properties panel definition
// Only what is defined here is returned from properties.js
return {
    type: "items",
    component: "accordion",
    items: {
        appearance: appearanceSection
    }
};</pre>
<p><strong>После:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">var myTextBox = {
    ref: "props.myTextBox",
    label: "My text box",
    type: "string"
};

// Appearance section
var appearanceSection = {
    uses: "settings",
    items: {
        myTextBox: myTextBox
    }
};

// Main properties panel definition
// Only what is defined here is returned from properties.js
return {
    type: "items",
    component: "accordion",
    items: {
        appearance: appearanceSection
    }
};</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Adding_component_definition_to_properties_panel.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Adding_component_definition_to_properties_panel.png" alt="" width="230" height="208" class="aligncenter size-full wp-image-2592" /></a></p>
<h4 id="anchor-4" tabindex="-1"><span>Добавление собственного заголовка раздела</span></h4>
<p><span>В предыдущем примере вы добавили текстовое поле в новый раздел. В заголовке раздела автоматически повторно использовалась метка компонента. В этом разделе вы добавите собственный заголовок раздела. Для этого вы создаете новый заголовок ( </span><code><span class="syntax"><span>myNewHeader</span></span></code><span> в примере ниже) в существующем разделе «Внешний вид», а затем добавляете туда элементы:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">var appearanceSection = {
    uses: "settings",
    items: {
        // Definition of the custom section header
        myNewHeader: {
            type: "items",
            label: "My header, containing text box",
            items: {
                myTextBox: myTextBox
            }
        }
    }
};

// NOTHING CHANGED HERE ...
// Return overall definition of the property accordion
return {
    type: "items",
    component: "accordion",
    items: {
        appearance: appearanceSection
    }
};</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Adding_component_definition_to_properties_panel_2.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/Adding_component_definition_to_properties_panel_2.png" alt="" width="230" height="205" class="aligncenter size-full wp-image-2593" /></a></p>
<h4 id="anchor-5" tabindex="-1"><span>Добавление настраиваемого раздела</span></h4>
<p><span>Вы также можете создавать совершенно новые разделы аккордеона.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">// Some components
var header1_item1 = {
    ref: "props.section1.item1",
    label: "Section 1 / Item 1",
    type: "string",
    expression: "optional"
};

...
...

// Define a custom section
myCustomSection = {
    // not necessary to define the type, component "expandable-items" will automatically
    // default to "items"
    // type: "items"
    component: "expandable-items",
    label: "My Accordion Section",
    items: {
        header1: {
            type: "items",
            label: "Header 1",
            items: {
                header1_item1: header1_item1,
                header1_item2: header1_item2
            }
        },
        header2: {
            type: "items",
            label: "Header 2",
            items: {
                header2_item1: header2_item1,
                header2_item2: header2_item2
            }
        }

    }
}</pre>
<p><span>Ключ в приведенном выше коде заключается в том, что вы добавляете <code>expandable-items</code></span><span> компонента . Остальной код работает как в предыдущих примерах.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">return {
    type: "items",
    component: "accordion",
    items: {
        appearance: appearanceSection,
        customSection: myCustomSection
    	 }
    };
});</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/qlik_sense_extension_development_tutorial_custom_section.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/qlik_sense_extension_development_tutorial_custom_section.png" alt="" width="248" height="505" class="aligncenter size-full wp-image-2595" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/qlik_sense_extension_development_tutorial_custom_section.png 248w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/02/qlik_sense_extension_development_tutorial_custom_section-147x300.png 147w" sizes="(max-width: 248px) 100vw, 248px" /></a></p>
<h3 id="anchor-6" tabindex="-1"><span>Отображение и сохранение custom (настраиваемых) свойств</span></h3>
<p><span>После того как вы определили </span><strong>custom properties</strong><span>, </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense</span></span><span> позаботится обо всем остальном, а именно:</span></p>
<ul>
<li><span>Отображение <strong>custom properties</strong> вместе со встроенными свойствами</span></li>
<li><span>Сохранение значений свойств. Если значение свойства изменяется, вам не нужно заботиться о сохранении, то есть о сохранении и загрузке значения свойства.</span></li>
</ul>
<h3 id="anchor-7" tabindex="-1"><span>Ссылка на значения настраиваемых свойств</span></h3>
<p><span>Ссылка на значения <strong>custom properties</strong> аналогична ссылке на значения из встроенных свойств, но с одним исключением. Используя </span><code><span class="syntax"><span>ref</span></span></code><span>, вы можете определить, как значения свойств отображаются в дереве объектов. Этот принцип применяется ко всем элементам настраиваемых свойств.</span></p>
<p class="examples" data-mc-autonum="Examples: "><strong><span class="autonumber">Примеры:</span></strong></p>
<p data-mc-autonum="Examples: "><span>Определяем текстовое поле:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">var myTextBox = {
    ref: "myTextBox",
    ...
};</pre>
<p data-mc-autonum="Examples: "><span>На это значение можно ссылаться в вашем скрипте:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">console.log( layout.myTextBox );</pre>
<p data-mc-autonum="Examples: "><span>В то время как:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">var myTextBox = {
    ref: "prop.myTextBox",
    ...
};</pre>
<p data-mc-autonum="Examples: "><span>Будет вызываться с использованием:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">console.log( layout.prop.myTextBox );</pre>
<blockquote>
<p data-mc-autonum="Examples: "><span>Добавление префиксов к вашим свойствам, как показано в последних примерах выше, позволяет легко перебирать все настраиваемые свойства. Это также гарантирует отсутствие конфликтов именования стандартных объектов </span><strong><span class="CommonComponentsQlik Sense">Qlik Sense</span></strong><span>.</span></p>
</blockquote>
<h2>Определение настраиваемых свойств</h2>
<h3>Custom string properties</h3>
<p>todo</p>
<h3>Custom integer properties</h3>
<p>todo</p>
<h3>Custom number properties</h3>
<p>todo</p>
<h3>Custom array properties</h3>
<p>todo</p>
<h3>Custom button properties</h3>
<p>todo</p>
<h3>Custom button group properties</h3>
<p>todo</p>
<h3>Custom check box properties</h3>
<p>todo</p>
<h3>Custom color-picker properties</h3>
<p>todo</p>
<h3>Custom drop down list properties</h3>
<p>todo</p>
<h3>Custom link properties</h3>
<p>todo</p>
<h3>Custom media properties</h3>
<p>todo</p>
<h3>Custom radio button properties</h3>
<p>todo</p>
<h3>Custom slider properties</h3>
<p>todo</p>
<h3>Custom range-slider properties</h3>
<p>todo</p>
<h3>Custom switch properties</h3>
<p>todo</p>
<h3>Custom text properties</h3>
<p>todo</p>
<h3>Custom textarea properties</h3>
<p>todo</p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/properties-panel-basics-qlik-extension/">Панель свойств расширения или Properties Panel</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/properties-panel-basics-qlik-extension/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Qlik Web Developer &#8211; Backend API для разработки Extensions</title>
		<link>https://qliksense.ivan-shamaev.ru/qlik-extensions-web-development-backend-api/</link>
					<comments>https://qliksense.ivan-shamaev.ru/qlik-extensions-web-development-backend-api/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Sat, 16 Jan 2021 12:42:03 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[Backend API]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[extension api]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[Qlik Web Developer]]></category>
		<category><![CDATA[Методы Qlik Sense Extension API]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2530</guid>

					<description><![CDATA[<p>Введение в Qlik Sense Backend API Backend API состоит из ряда методов и используется для взаимодействия с ассоциативным механизмом Qlik. Он предоставляет вспомогательные функции для вызовов ассоциативного механизма Qlik и доступ к данным ассоциативного механизма Qlik. Backend API &#8211; это оболочка для выбранных методов Qlik Engine JSON API, но с той разницей, что Backend API знает контекст, то есть<a class="moretag" href="https://qliksense.ivan-shamaev.ru/qlik-extensions-web-development-backend-api/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qlik-extensions-web-development-backend-api/">Qlik Web Developer &#8211; Backend API для разработки Extensions</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Введение в Qlik Sense Backend API</h1>
<p><span><strong>Backend API</strong> состоит из ряда методов и используется для взаимодействия с </span><span class="CommonComponentsEngineName"><span>ассоциативным механизмом Qlik</span></span><span>. Он предоставляет вспомогательные функции для вызовов </span><span class="CommonComponentsEngineName"><span>ассоциативного механизма Qlik</span></span><span> и доступ к данным </span><span class="CommonComponentsEngineName"><span>ассоциативного механизма Qlik</span></span><span>. </span></p>
<p><span><strong>Backend API</strong> &#8211; это оболочка для выбранных методов <span class="CommonComponentsProtocolName"><strong>Qlik Engine JSON API</strong>,</span> но с той разницей, что Backend API знает контекст, то есть текущее соединение <strong>WebSocket</strong> и приложение <span class="CommonComponentsQlik Sense">Qlik Sense</span>.</span></p>
<p><span>Backend API доступен для разработчиков расширений как </span><code><span class="syntax"><span>this.backendApi</span></span></code><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">this.backendApi.eachDataRow(function(rownum, row) {
    .....
});</pre>
<h2>Примеры использования</h2>
<h3>Selections</h3>
<p><span>Следующие методы <strong>Backend API</strong> доступны, когда вы работаете с выборками в универсальном объекте, стоящем за вашим расширением.</span></p>
<ul>
<li><code><span class="syntax">selectValues</span></code></li>
<li><code><span class="syntax">selectRange</span></code></li>
<li><code><span class="syntax">clearSelections</span></code></li>
<li><code><span class="syntax">hasSelections</span></code></li>
</ul>
<p><span>Используйте метод </span><code><span class="syntax"><span>selectValues</span></span></code><span> для выбора значений в этом объекте. Вызов вызывает перерисовку объекта.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">$element.find('li').on('click', function() {
    if(this.hasAttribute("data-value")) {
        var value = parseInt(this.getAttribute("data-value"), 10), dim = 0;
        self.backendApi.selectValues(dim, [value], true);
    }
});</pre>
<p><span>Метод </span><code><span class="syntax"><span>selectRange</span></span></code><span> выбирает значения в этом объекте, используя диапазоны.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">var range = {
    "qMeasureIx": 1,
    "qRange": {
        "qMin": 10,
        "qMax": 100,
        "qMinInclEq": true,
        "qMaxInclEq": true
    }
};
self.backendApi.selectRange( [range], false);</pre>
<p><span>Метод </span><code><span class="syntax"><span>hasSelections</span></span></code><span> можно использовать, чтобы узнать, есть ли неподтвержденные выборы для этого объекта.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">this.backendApi.hasSelections();</pre>
<p><span>Если для этого объекта есть неподтвержденные выборки, вы можете использовать метод </span><span class="syntax"><span><code>clearSelections</code>,</span></span><span> чтобы очистить их.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">this.backendApi.clearSelections();</pre>
<h3>Search</h3>
<p><span>При работе с поиском в объектах списка вы можете использовать следующие методы Backend API.</span></p>
<ul>
<li><code><span class="syntax">search</span></code></li>
<li><code><span class="syntax">acceptSearch</span></code></li>
<li><code><span class="syntax">abortSearch</span></code></li>
</ul>
<p><span>Используйте </span><span>метод </span><span class="syntax"><code>search</code> </span><span>для поиска термина в <strong>list object</strong>. Это приводит к обновленному <strong>layout</strong>, который содержит только совпадающие записи.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">this.backendApi.search("A");</pre>
<p><span>Метод </span><code><span class="syntax"><span>acceptSearch</span></span></code><span> принимает результат поиска и делает его выбранным в поле.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">this.backendApi.acceptSearch(false);</pre>
<p><span>Используйте метод </span><span class="syntax"><span><code>abortSearch</code>,</span></span><span> если поиск должен быть прерван. Это очищает существующий поиск и возвращает объект в состояние, в котором он находился до поиска.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">this.backendApi.abortSearch();</pre>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qlik-extensions-web-development-backend-api/">Qlik Web Developer &#8211; Backend API для разработки Extensions</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/qlik-extensions-web-development-backend-api/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Отладка visualization extension с помощью web developer tools</title>
		<link>https://qliksense.ivan-shamaev.ru/qlik-extension-debugging-and-web-developer-tools/</link>
					<comments>https://qliksense.ivan-shamaev.ru/qlik-extension-debugging-and-web-developer-tools/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 15 Jan 2021 21:37:39 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[extension api]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[Отладка QS Extension]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2520</guid>

					<description><![CDATA[<p>Отладка с помощью инструментов веб-разработчика Исторически сложилось так, что разработчики JavaScript часто использовали alert() для целей отладки, но это может восприниматься как раздражающее, поэтому вместо этого рекомендуется использовать console.log() для отправки данных в консоль браузера. Инструменты веб-разработчика Большинство веб-браузеров предлагают какой-то инструмент разработчика, но в этом разделе вы познакомитесь с некоторыми основными концепциями, основанными на Google<a class="moretag" href="https://qliksense.ivan-shamaev.ru/qlik-extension-debugging-and-web-developer-tools/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qlik-extension-debugging-and-web-developer-tools/">Отладка visualization extension с помощью web developer tools</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1><madcap:concept term="Building visualization extensions" xmlns:madcap="http://www.madcapsoftware.com/Schemas/MadCap.xsd"><span>Отладка с помощью инструментов веб-разработчика</span></madcap:concept></h1>
<p><span>Исторически сложилось так, что разработчики JavaScript часто использовали </span><code><span class="syntax"><span>alert()</span></span></code><span> для целей отладки, но это может восприниматься как раздражающее, поэтому вместо этого рекомендуется использовать </span><code><span class="syntax"><span>console.log()</span></span></code><span> для отправки данных в консоль браузера.</span></p>
<h2 id="anchor-1" tabindex="-1"><span>Инструменты веб-разработчика</span></h2>
<p><span>Большинство веб-браузеров предлагают какой-то инструмент разработчика, но в этом разделе вы познакомитесь с некоторыми основными концепциями, основанными на Google Chrome.</span></p>
<h3><span>Инструменты разработчика в вашем браузере</span></h3>
<p><span>Если вы разрабатываете расширения визуализации с помощью </span><strong><span class="CommonComponentsSenseDesktopName">Qlik Sense Desktop</span></strong><span>, вы можете использовать свой любимый браузер для целей отладки. Просто откройте </span><span class="CommonComponentsSenseDesktopName"><span>Qlik Sense Desktop</span></span><span> и оставьте его открытым. Затем откройте свой браузер и перейдите по </span><span class="path"><span>адресу <strong><a href="http://localhost:4848" target="_blank" rel="noopener">http://localhost:4848</a></strong></span></span><span>. Отобразится Hub, и оттуда вы сможете открыть инструменты разработчика браузера.</span></p>
<h3><span>Инструменты разработчика из </span><span class="CommonComponentsSenseDesktopName"><span>Qlik Sense Desktop</span></span></h3>
<p><span>Поскольку </span><span class="CommonComponentsSenseDesktopName"><span>Qlik Sense Desktop</span></span><span> использует Chromium в качестве встроенного браузера, вы можете получить доступ к Chrome DevTools из </span><span class="CommonComponentsSenseDesktopName"><span>Qlik Sense Desktop</span></span><span>. Нажмите </span><span class="ui_item_external"><span>Ctrl + Shift</span></span><span> и одновременно щелкните правой кнопкой мыши по листу, а затем выберите «</span><span class="ui_item_external"><span>Показать DevTools»</span></span><span> в диалоговом окне.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qlik_sense_devtools_ctrl_shift.jpg"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qlik_sense_devtools_ctrl_shift.jpg" alt="" width="1358" height="473" class="aligncenter size-full wp-image-2523" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qlik_sense_devtools_ctrl_shift.jpg 1358w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qlik_sense_devtools_ctrl_shift-300x104.jpg 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qlik_sense_devtools_ctrl_shift-1024x357.jpg 1024w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qlik_sense_devtools_ctrl_shift-768x267.jpg 768w" sizes="(max-width: 1358px) 100vw, 1358px" /></a></p>
<p><strong>Откроется окно devtools</strong></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/devtools_qlik_sense_desktop_using.jpg"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/devtools_qlik_sense_desktop_using.jpg" alt="" width="938" height="774" class="aligncenter size-full wp-image-2525" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/devtools_qlik_sense_desktop_using.jpg 938w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/devtools_qlik_sense_desktop_using-300x248.jpg 300w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/devtools_qlik_sense_desktop_using-768x634.jpg 768w" sizes="(max-width: 938px) 100vw, 938px" /></a></p>
<h2 id="anchor-2" tabindex="-1"><span>Отладка с помощью Chrome DevTools</span></h2>
<p><span>В этом разделе выделены три области, которые имеют большое значение при разработке расширений визуализации:</span></p>
<ul>
<li><span>Использование console</span></li>
<li>Inspect elements</li>
<li>Debugging</li>
</ul>
<h3><span>Использование консоли</span></h3>
<p><span>Как упоминалось выше, удобнее использовать console в веб DevTools вместо запуска предупреждений. Для этого используйте </span><code><span class="syntax"><span>console.info</span></span></code><span> или </span><span class="syntax"><span><code>console.log</code>,</span></span><span> чтобы передать что-нибудь в консоль.</span></p>
<p class="example" data-mc-autonum="Example: "><strong><span class="autonumber">Пример: </span></strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">paint: function ( $element, layout ) {

    var err = {
        message: 'Something went wrong',
        errCode: 'bla'
    };

    console.info( 'We are re-painting the extension' );
    console.error( 'Oops, we haven an error', err );
    console.log( 'We are here' );
    console.log( 'layout', layout );

}</pre>
<p><span>Рекомендуется потратить некоторое время на изучение более сложных концепций <code>console</code>, например:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">console.assert();
console.group();
console.groupCollapsed();
console.groupEnd();
console.table();</pre>
<h4><span>Некоторые соображения</span></h4>
<p><span>Функции </span><strong><span class="syntax">console.<span style="color: #333333;">xyz</span>()</span></strong><span> поддерживаются не всеми веб-браузерами, поэтому рекомендуется убедиться, что в коде не осталось </span><span class="syntax"><span><strong>console.xyz()</strong>,</span></span><span> когда он попадет в рабочую среду. Для этого есть несколько стратегий:</span></p>
<ul>
<li><span>Вручную удалите все </span><strong><span class="syntax">console.xyz()</span></strong><span> из кода перед развертыванием в производственной среде.</span></li>
<li><span>Оберните все ваши вызовы в консоль, чтобы они выполнялись только в том случае, если текущий веб-браузер поддерживает консольные вызовы.</span></li>
<li><span>Используйте инструменты, например <strong>Grunt</strong> или <strong>Gulp</strong>, для создания процесса развертывания, в котором все операторы консоли удаляются автоматически.</span></li>
</ul>
<h3>Inspect elements (<span>Осмотрите элементы)</span></h3>
<p><span>Манипуляции с объектной моделью документа (DOM) можно просмотреть с помощью инспектора элементов, который встречается в большинстве инструментов веб-разработчика. В Chrome DevTools вы получаете доступ к функции проверки элементов, щелкнув увеличительное стекло на панели инструментов.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/ui_extension_inspect_element_chrome_devtools.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/ui_extension_inspect_element_chrome_devtools.png" alt="" width="280" height="62" class="aligncenter size-full wp-image-2521" /></a></p>
<h3><span>Отладка</span></h3>
<p><span>Вы можете использовать developer tools для отладки в реальном времени, например:</span></p>
<ul>
<li><span>Chrome DevTools</span></li>
<li><span>Firebug</span></li>
<li><span>Инструменты разработчика F12 для Internet Explorer</span></li>
</ul>
<p>Для того, чтобы запустить режим debugging в расширении, необходимо написать команду <code>debugger;</code>.</p>
<p><strong>Пример:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">paint: function($element, layout) {
    
    console.log(layout);
    
    var hypercube = layout.qHyperCube;
    
    console.log(hypercube);
    
    debugger;
}</pre>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qlik-extension-debugging-and-web-developer-tools/">Отладка visualization extension с помощью web developer tools</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/qlik-extension-debugging-and-web-developer-tools/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Обзор Extension API и описание методов расширений</title>
		<link>https://qliksense.ivan-shamaev.ru/overview-qlik-extension-api-and-methods/</link>
					<comments>https://qliksense.ivan-shamaev.ru/overview-qlik-extension-api-and-methods/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Sat, 09 Jan 2021 20:42:37 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[extension api]]></category>
		<category><![CDATA[Methods Qlik Sense Extension API]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[Методы Qlik Sense Extension API]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2494</guid>

					<description><![CDATA[<p>Введение в Extension API Extension API состоит из методов и свойств, используемых для создания custom расширений визуализации (или custom visualization extensions). Обзор Visualization extension templates Для начала рассмотрим шаблоны Visualization extension templates. В dev-hub при создании Extension вам предлагают выбрать шаблон. Basic Visualization template Назовем наш Extension &#8220;1_BVT&#8221;. При инициализации<a class="moretag" href="https://qliksense.ivan-shamaev.ru/overview-qlik-extension-api-and-methods/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/overview-qlik-extension-api-and-methods/">Обзор Extension API и описание методов расширений</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Введение в Extension API</h1>
<p><span><strong>Extension API</strong> состоит из методов и свойств, используемых для создания custom расширений визуализации (или <strong>custom visualization extensions</strong>).</span></p>
<h2>Обзор Visualization extension templates</h2>
<p>Для начала рассмотрим шаблоны <strong>Visualization extension templates</strong>. В <strong>dev-hub</strong> при создании Extension вам предлагают выбрать шаблон.</p>
<h3>Basic Visualization template</h3>
<p>Назовем наш Extension <strong>&#8220;1_BVT&#8221;</strong>. При инициализации создадутся два файла:</p>
<p><strong>1_BVT.qext</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="json">{
    "name": "1_BVT",
    "description": "Basic empty visualization template",
    "type": "visualization",
    "version": "1.0.0",
    "icon": "extension",
    "author": "",
    "homepage": "",
    "keywords": "qlik-sense, visualization",
    "license": "",
    "repository": "",
    "dependencies": {
        "qlik-sense": "&gt;=3.0.x"
    }
}</pre>
<p><strong>1_BVT.js</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( [ "qlik"
],
function ( qlik) {

    return {
        support : {
            snapshot: true,
            export: true,
            exportData : false
        },
        paint: function ($element) {
            //add your rendering code here
            $element.html( "1_BVT" );
            //needed for export
            return qlik.Promise.resolve();
        }
    };

} );</pre>
<h3>Chart Template</h3>
<p>Назовем наш Extension <strong>&#8220;2_CT&#8221;</strong>. При инициализации создадутся 4 файла:</p>
<p><strong>2_CT.qext</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="json">{
    "name": "2_CT",
    "description": "Chart visualization template",
    "icon": "bar-chart-horizontal",
    "type": "visualization",
    "version": "1.0.0",
    "author": "",
    "homepage": "",
    "keywords": "qlik-sense, visualization",
    "license": "",
    "repository": "",
    "dependencies": {
        "qlik-sense": "&gt;=3.0.x"
    }
}</pre>
<p><strong>2_CT.js</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( ["qlik", "text!./2_CT.ng.html", "css!./2_CT.css"],
    function ( qlik, template ) {
        "use strict";
        return {
            template: template,
            initialProperties: {
                qHyperCubeDef: {
                    qDimensions: [],
                    qMeasures: [],
                    qInitialDataFetch: [{
                        qWidth: 2,
                        qHeight: 50
                    }]
                }
            },
            definition: {
                type: "items",
                component: "accordion",
                items: {
                    dimensions: {
                        uses: "dimensions",
                        min: 1,
                        max: 1
                    },
                    measures: {
                        uses: "measures",
                        min: 1,
                        max: 1
                    },
                    sorting: {
                        uses: "sorting"
                    }
                }
            },
            support: {
                snapshot: true,
                export: true,
                exportData: true
            },
            paint: function () {
                //needed for export
                this.$scope.selections = [];
                return qlik.Promise.resolve();
            },
            controller: ["$scope", "$element", function ( $scope ) {
                $scope.getPercent = function ( val ) {
                    return Math.round( (val * 100 / $scope.layout.qHyperCube.qMeasureInfo[0].qMax) * 100 ) / 100;
                };

                $scope.selections = [];

                $scope.sel = function ( $event ) {
                    if ( $event.currentTarget.hasAttribute( "data-row" ) ) {
                        var row = parseInt( $event.currentTarget.getAttribute( "data-row" ), 10 ), dim = 0,
                            cell = $scope.$parent.layout.qHyperCube.qDataPages[0].qMatrix[row][0];
                        if ( cell.qIsNull !== true ) {
                            cell.qState = (cell.qState === "S" ? "O" : "S");
                            if ( $scope.selections.indexOf( cell.qElemNumber ) === -1 ) {
                                $scope.selections.push( cell.qElemNumber );
                            } else {
                                $scope.selections.splice( $scope.selections.indexOf( cell.qElemNumber ), 1 );
                            }
                            $scope.selectValues( dim, [cell.qElemNumber], true );
                        }
                    }
                };
            }]
        };

    } );</pre>
<p><strong>2_CT.css</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="css">.qv-object-2_CT .css_bars_row {
    transition: all 0.3s ease;
    float: left;
    width: 98%;
    overflow: hidden;
    border: 1px solid #ccc;
    background-color: #f0f0f0;
    margin-bottom: 2px;
    border-radius: 0 10px 10px 0;
    -moz-border-radius: 0 10px 10px 0;
    cursor: pointer;
}

.qv-object-2_CT .css_bars_bar {
    float: left;
    clear: left;
    height: 30px;
    background-color: #5f5f5f;
}

.qv-object-2_CT .css_bars_bar span {
    font-weight: bold;
    float: left;
    margin-left: 5px;
    margin-right: 5px;
    margin-top: 7px;
    color: #f0f0f0;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 90%;
    white-space: nowrap;
}

.qv-object-2_CT .css_bars_per {
    position: relative;
}

.qv-object-2_CT .css_bars_per span {
    font-weight: bold;
    float: left;
    margin-right: 5px;
    margin-top: 5px;
    margin-left: 5px;
}

.qv-object-2_CT .css_bars_per span.over {
    position: absolute;
    right: 15px;
    color: #f0f0f0;
}

.qv-object-2_CT .css_bars_row:hover, .qv-object-2_CT .css_bars_row.selected {
    border: 1px solid #000;
}</pre>
<p><strong>2_CT.ng.html</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="html">&lt;div qv-extension style="height: 100%; position: relative; overflow: auto;"&gt;
    &lt;div class="css_bars_row" ng-repeat="item in layout.qHyperCube.qDataPages[0].qMatrix" title="{{item[0].qText}}" data-row="{{ $index }}"
         ng-click="sel($event)" data-value="{{ item[0].qElemNumber }}" ng-class="{selected: (item[0].qState) === 'S' || selections.indexOf(item[0].qElemNumber) !== -1 }"&gt;
        &lt;div class="css_bars_bar" ng-style="{'width':getPercent(item[1].qNum)+'%'}"&gt;&lt;span&gt;{{item[0].qText}}&lt;/span&gt;&lt;/div&gt;
        &lt;div class="css_bars_per"&gt;
            &lt;span ng-class="{over: (getPercent(item[1].qNum)&gt;95)}"&gt;{{getPercent(item[1].qNum)}} %&lt;/span&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<h3>Listbox template</h3>
<p>Назовем наш Extension &#8220;3_LBT&#8221;. При инициализации создадутся 3 файла:</p>
<p><strong>3_LBT.js</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( ["qlik", "jquery", "text!./style.css"], function ( qlik, $, cssContent ) {
    'use strict';
    $( "&lt;style&gt;" ).html( cssContent ).appendTo( "head" );
    return {
        initialProperties: {
            qListObjectDef: {
                qShowAlternatives: true,
                qFrequencyMode: "V",
                qInitialDataFetch: [{
                    qWidth: 2,
                    qHeight: 50
                }]
            }
        },
        definition: {
            type: "items",
            component: "accordion",
            items: {
                dimension: {
                    type: "items",
                    label: "Dimensions",
                    ref: "qListObjectDef",
                    min: 1,
                    max: 1,
                    items: {
                        label: {
                            type: "string",
                            ref: "qListObjectDef.qDef.qFieldLabels.0",
                            label: "Label",
                            show: true
                        },
                        libraryId: {
                            type: "string",
                            component: "library-item",
                            libraryItemType: "dimension",
                            ref: "qListObjectDef.qLibraryId",
                            label: "Dimension",
                            show: function ( data ) {
                                return data.qListObjectDef &amp;&amp; data.qListObjectDef.qLibraryId;
                            }
                        },
                        field: {
                            type: "string",
                            expression: "always",
                            expressionType: "dimension",
                            ref: "qListObjectDef.qDef.qFieldDefs.0",
                            label: "Field",
                            defaultValue: "=ValueList('A','B','C')",
                            show: function ( data ) {
                                return data.qListObjectDef &amp;&amp; !data.qListObjectDef.qLibraryId;
                            }
                        },
                        frequency: {
                            type: "string",
                            component: "dropdown",
                            label: "Frequency mode",
                            ref: "qListObjectDef.qFrequencyMode",
                            options: [{
                                value: "N",
                                label: "No frequency"
                            }, {
                                value: "V",
                                label: "Absolute value"
                            }, {
                                value: "P",
                                label: "Percent"
                            }, {
                                value: "R",
                                label: "Relative"
                            }],
                            defaultValue: "V"
                        }
                    }
                },
                settings: {
                    uses: "settings"
                }
            }
        },
        support : {
            snapshot: true,
            export: true,
            exportData : false
        },
        paint: function ( $element,layout ) {
            var self = this, html = "&lt;ul&gt;";
            layout.qListObject.qDataPages[0].qMatrix.forEach( function ( row ) {
                html += '&lt;li class="data state' + row[0].qState + '" data-value="' + row[0].qElemNumber + '"&gt;' + row[0].qText;
                if ( row[0].qFrequency ) {
                    html += '&lt;span&gt;' + row[0].qFrequency + '&lt;/span&gt;';
                }
                html += '&lt;/li&gt;';
            } );
            html += "&lt;/ul&gt;";
            $element.html( html );
            if ( this.selectionsEnabled ) {
                $element.find( 'li' ).on( 'click', function () {
                    if ( this.hasAttribute( "data-value" ) ) {
                        var value = parseInt( this.getAttribute( "data-value" ), 10 ), dim = 0;
                        self.selectValues( dim, [value], true );
                        this.classList.toggle("selected");
                    }
                } );
            }
            return qlik.Promise.resolve();
        }
    };
} );
</pre>
<p><strong>3_LBT.qext</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="json">{
    "name": "3_LBT",
    "description": "Listbox visualization template",
    "icon": "list",
    "type": "visualization",
    "version": "1.0.0",
    "author": "",
    "homepage": "",
    "keywords": "qlik-sense, visualization",
    "license": "",
    "repository": "",
    "dependencies": {
        "qlik-sense": "&gt;=3.0.x"
    }
}</pre>
<p><strong>style.css</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="css">.qv-object-3_LBT div.qv-object-content-container {
    overflow: auto;
}
.qv-object-3_LBT ul {
    list-style: none;
}
.qv-object-3_LBT li.data {
    padding: 4px;
    border-bottom: 1px solid #ddd;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* frequency */
.qv-object-3_LBT li.data span
{
    padding-left: 10px;
    font-style: italic;
    float:right;
}
/* colors when NOT in selection mode */

.qv-object-3_LBT li.stateS, .qv-object-3_LBT li.stateL {
    background-image: linear-gradient(top, #52cc52, #4dc04d);
    background-image: -o-linear-gradient(top, #52cc52, #4dc04d);
    background-image: -moz-linear-gradient(top, #52cc52, #4dc04d);
    background-image: -webkit-linear-gradient(top, #52cc52, #4dc04d);
    background-image: -ms-linear-gradient(top, #52cc52, #4dc04d);
    color: #fff;
}

.qv-object-3_LBT li.stateX, .qv-object-3_LBT li.stateXL, .qv-object-3_LBT li.stateXS {
    background-color: #A9A9A9;
    color: #fff;
}

.qv-object-3_LBT li.stateA {
    background-image: none;
    background-color: #ddd;
    color: #000;
}
/* colors when in selection mode */
.qv-object-3_LBT.qv-selections-active li {
    background-image: none;
    background-color: #ddd;
    color: #000;
}

.qv-object-3_LBT.qv-selections-active li.selected {
    background-image: linear-gradient(top, #52cc52, #4dc04d);
    background-image: -o-linear-gradient(top, #52cc52, #4dc04d);
    background-image: -moz-linear-gradient(top, #52cc52, #4dc04d);
    background-image: -webkit-linear-gradient(top, #52cc52, #4dc04d);
    background-image: -ms-linear-gradient(top, #52cc52, #4dc04d);
    color: #fff;
}</pre>
<h3>Angular Basic Visualization template</h3>
<p>Назовем наш Extension <strong>&#8220;4_ABVT&#8221;</strong>. При инициализации создадутся 3 файла:</p>
<p><strong>4_ABVT.qext</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="json">{
    "name": "4_ABVT",
    "description": "Basic empty visualization template based on angular.js",
    "type": "visualization",
    "version": "1.0.0",
    "author": "",
    "homepage": "",
    "keywords": "qlik-sense, visualization",
    "license": "",
    "repository": "",
    "dependencies": {
        "qlik-sense": "&gt;=3.0.x"
    }
}</pre>
<p><strong>4_ABVT.js</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( ["qlik", "text!./template.html"],
    function ( qlik, template ) {

        return {
            template: template,
            support: {
                snapshot: true,
                export: true,
                exportData: false
            },
            paint: function () {
                return qlik.Promise.resolve();
            },
            controller: ['$scope', function ( $scope ) {
                //add your rendering code here
                $scope.html = "Hello World";
            }]
        };

    } );</pre>
<p><strong>template.html</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="html">&lt;div qv-extension style="height: 100%; position: relative; overflow: auto;" class="ng-scope"&gt;
    {{ html }} 
&lt;/div&gt;</pre>
<h3>Angular Table template</h3>
<p>Назовем наш Extension <strong>&#8220;5_ATT&#8221;</strong>. При инициализации создадутся 4 файла:</p>
<p><strong>5_ATT.js</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">define( ["qlik","jquery", "text!./style.css", "text!./template.html"], function (qlik, $, cssContent, template ) {'use strict';
    $("&lt;style&gt;").html(cssContent).appendTo("head");
    return {
       template: template,
       initialProperties : {
            qHyperCubeDef : {
                qDimensions : [],
                qMeasures : [],
                qInitialDataFetch : [{
                    qWidth : 10,
                    qHeight : 50
                }]
            }
        },
        definition : {
            type : "items",
            component : "accordion",
            items : {
                dimensions : {
                    uses : "dimensions",
                    min : 1
                },
                measures : {
                    uses : "measures",
                    min : 0
                },
                sorting : {
                    uses : "sorting"
                },
                settings : {
                    uses : "settings",
                    items : {
                        initFetchRows : {
                            ref : "qHyperCubeDef.qInitialDataFetch.0.qHeight",
                            label : "Initial fetch rows",
                            type : "number",
                            defaultValue : 50
                        }
                    }
                }
            }
        },
        support : {
            snapshot: true,
            export: true,
            exportData : true
        },
        paint: function ( ) {
            //setup scope.table
            if ( !this.$scope.table ) {
                this.$scope.table = qlik.table( this );
            }
            return qlik.Promise.resolve();
        },
        controller: ['$scope', function (/*$scope*/) {
        }]
    };

} );
</pre>
<p><strong>5_ATT.qext</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="json">{
    "name": "5_ATT",
    "description": "Table visualization template based on angular.js",
    "icon": "table",
    "type": "visualization",
    "version": "1.0.0",
    "author": "",
    "homepage": "",
    "keywords": "qlik-sense, visualization",
    "license": "",
    "repository": "",
    "dependencies": {
        "qlik-sense": "&gt;=3.0.x"
    }
}</pre>
<p><strong>style.css</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="css">.qv-object-5_ATT div.qv-object-content-container {
    overflow: auto;
}
.qv-object-5_ATT td,
.qv-object-5_ATT th {
    border-top: 0px solid #fff;
    border-bottom: 1px solid #ddd;
    border-right: 1px solid #ddd;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
    cursor: default;
    font-size: 12px;
}
.qv-object-5_ATT td.numeric {
    text-align: right;
}
.qv-object-5_ATT button {
    width: 100%;
}</pre>
<p><strong>template.html</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="html">&lt;div qv-extension style="height: 100%; position: relative; overflow: auto;"&gt;
    &lt;table&gt;
        &lt;thead&gt;
        &lt;tr&gt;
            &lt;th ng-repeat="head in table.headers track by $index" ng-click="head.orderBy()"&gt;{{head.qFallbackTitle}}&lt;/th&gt;
        &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
        &lt;tr ng-repeat="row in table.rows track by $index"&gt;
            &lt;td ng-repeat="cell in row.cells track by $index" class="selectable" ng-class="{'selected':cell.selected,'numeric':cell.qNum}" ng-click="cell.select($event)"&gt;{{cell.qText}}&lt;/td&gt;
        &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
    &lt;button ng-if="table.rowCount&gt;table.rows.length" ng-click="table.getMoreData()" class="lui-button more"&gt;More...&lt;/button&gt;
&lt;/div&gt;
</pre>
<h3>Table template</h3>
<p>Назовем наш Extension <strong>&#8220;6_TT&#8221;</strong>. При инициализации создадутся 3 файла:</p>
<p><strong>6_TT.js</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">/*globals define*/
define( ["qlik", "jquery", "text!./style.css"], function ( qlik, $, cssContent ) {
    'use strict';
    $( "&lt;style&gt;" ).html( cssContent ).appendTo( "head" );
    function createRows ( rows, dimensionInfo ) {
        var html = "";
        rows.forEach( function ( row ) {
            html += '&lt;tr&gt;';
            row.forEach( function ( cell, key ) {
                if ( cell.qIsOtherCell ) {
                    cell.qText = dimensionInfo[key].othersLabel;
                }
                html += "&lt;td ";
                if ( !isNaN( cell.qNum ) ) {
                    html += "class='numeric'";
                }
                html += '&gt;' + cell.qText + '&lt;/td&gt;';
            } );
            html += '&lt;/tr&gt;';
        } );
        return html;
    }

    return {
        initialProperties: {
            qHyperCubeDef: {
                qDimensions: [],
                qMeasures: [],
                qInitialDataFetch: [{
                    qWidth: 10,
                    qHeight: 50
                }]
            }
        },
        definition: {
            type: "items",
            component: "accordion",
            items: {
                dimensions: {
                    uses: "dimensions",
                    min: 1
                },
                measures: {
                    uses: "measures",
                    min: 0
                },
                sorting: {
                    uses: "sorting"
                },
                settings: {
                    uses: "settings"
                }
            }
        },
        snapshot: {
            canTakeSnapshot: true
        },
        paint: function ( $element, layout ) {
            var html = "&lt;table&gt;&lt;thead&gt;&lt;tr&gt;", self = this,
                morebutton = false,
                hypercube = layout.qHyperCube,
                rowcount = hypercube.qDataPages[0].qMatrix.length,
                colcount = hypercube.qDimensionInfo.length + hypercube.qMeasureInfo.length;
            //render titles
            hypercube.qDimensionInfo.forEach( function ( cell ) {
                html += '&lt;th&gt;' + cell.qFallbackTitle + '&lt;/th&gt;';
            } );
            hypercube.qMeasureInfo.forEach( function ( cell ) {
                html += '&lt;th&gt;' + cell.qFallbackTitle + '&lt;/th&gt;';
            } );
            html += "&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;";
            //render data
            html += createRows( hypercube.qDataPages[0].qMatrix, hypercube.qDimensionInfo );
            html += "&lt;/tbody&gt;&lt;/table&gt;";
            //add 'more...' button
            if ( hypercube.qSize.qcy &gt; rowcount ) {
                html += "&lt;button class='more'&gt;More...&lt;/button&gt;";
                morebutton = true;
            }
            $element.html( html );
            if ( morebutton ) {
                $element.find( ".more" ).on( "click", function () {
                    var requestPage = [{
                        qTop: rowcount,
                        qLeft: 0,
                        qWidth: colcount,
                        qHeight: Math.min( 50, hypercube.qSize.qcy - rowcount )
                    }];
                    self.backendApi.getData( requestPage ).then( function ( dataPages ) {
                        rowcount += dataPages[0].qMatrix.length;
                        if ( rowcount &gt;= hypercube.qSize.qcy ) {
                            $element.find( ".more" ).hide();
                        }
                        var html = createRows( dataPages[0].qMatrix, hypercube.qDimensionInfo );
                        $element.find( "tbody" ).append( html );
                    } );
                } );
            }
            return qlik.Promise.resolve();
        }
    };
} );
</pre>
<p><strong>6_TT.qext</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="json">{
    "name": "6_TT",
    "description": "Table visualization template",
    "icon": "table",
    "type": "visualization",
    "version": "1.0.0",
    "author": "",
    "homepage": "",
    "keywords": "qlik-sense, visualization",
    "license": "",
    "repository": "",
    "dependencies": {
        "qlik-sense": "&gt;=3.0.x"
    }
}</pre>
<p><strong>style.css</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="css">.qv-object-6_TT div.qv-object-content-container {
    overflow: auto;
}
.qv-object-6_TT td,
.qv-object-6_TT th {
    border-top: 0px solid #fff;
    border-bottom: 1px solid #ddd;
    border-right: 1px solid #ddd;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
    cursor: default;
    font-size: 12px;
}
.qv-object-6_TT td.numeric {
    text-align: right;
}
.qv-object-6_TT button {
    width: 100%;
}</pre>
<h2>Структура расширения</h2>
<p>Как мы видим из примеров стандартных шаблонов экстеншенов для создания расширения необходимо минимум 2 файла &#8211; js и qext. Для более богатой функциональности добавляются css и html.</p>
<p><strong>Опишем зачем нужны файлы:</strong></p>
<ul>
<li><span style="color: #ff6600;"><em><strong>&lt;name_extension&gt;</strong></em></span>.<strong>js</strong> &#8211; это код Javascript &#8211; фактически это ядро вашего Extension. Здесь происходит отрисовка визуализации (например, в цикле заполняется html код с тегами при обходе гиперкуба qlik sense), настраивается логика работы с выборкой и другие действия.</li>
<li><span style="color: #ff6600;"><em><strong>&lt;name_extension&gt;</strong></em></span>.<strong>qext</strong> &#8211; <span><span style="color: #339966;"><strong>extension metadata file (QEXT)</strong></span> &#8211; файл JSON, который используется <span class="CommonComponentsQlik Sense">Qlik Sense</span> для идентификации расширения визуализации. В этом файле указывается название расширения, тип расширения, версия, автор, ключевые слова. И другие атрибуты, которые будут расмотрены в дальнейших разделах.</span></li>
<li><span style="color: #ff6600;"><em><strong>&lt;name_extension&gt;</strong></em></span>.<strong>css</strong> &#8211; в этом файле прописываются стили для кастомной визуализации (т.е. вашего экстеншена).</li>
<li><span style="color: #ff6600;"><em><strong>&lt;name_extension&gt;</strong></em></span>.<strong>html</strong> &#8211; шаблон html кода, который будет использоваться в js коде и заполняться внутри js кода (например в цикле). Этот прием используется, например, в Angular Framework.</li>
<li><strong>wbfolder.wbl<sup>*</sup></strong> (<span>не является обязательным</span>) &#8211; <span>Файл загрузки Workbench &#8211; используется редактором Extension &amp; Mashup и содержит список файлов, которые должны быть загружены в редактор dev-hub (без него вы не сможете открыть или продублировать расширение в dev-hub).</span><br />
<span>Когда вы сохраняете проект расширения или Mashup из редактора, WBL-файл автоматически создается и включается в проект. Если вы сделаете копию расширения или мэшапа, то будут скопированы только файлы, перечисленные в wbfolder.wbl.<br />
Добавляя дополнительные имена файлов &#8211; разделенные точкой с запятой и переносом строки &#8211; в wbfolder.wbl, вы также можете разрешить загрузку этих дополнительных файлов. При отсутствии файла может возникнуть ошибка <span style="color: #800080;"><em><strong>Incomplete visualization. The visualization is incomplete and cannot be opened or duplicated (wbfolder.wbl file missing).</strong></em></span></span></li>
</ul>
<p><strong>Рассмотрим процесс отрисовки экстеншена:</strong></p>
<p><span>Когда пользователь открывает лист, </span><span class="PrimaryGenericName"><span>Qlik Sense</span></span><span> извлекает визуализации на этом листе, а затем выполняет стандартный рабочий процесс для каждой визуализации.</span></p>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/Qlik_Sense_Extension_API_concepts_Overview.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/Qlik_Sense_Extension_API_concepts_Overview.png" alt="" width="536" height="698" class="aligncenter size-full wp-image-2504" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/Qlik_Sense_Extension_API_concepts_Overview.png 536w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/Qlik_Sense_Extension_API_concepts_Overview-230x300.png 230w" sizes="(max-width: 536px) 100vw, 536px" /></a></p>
<p>Пример <strong>Hello World</strong> можно посмотреть на сайте <strong><a href="http://qliksite.io/tutorials/qliksense-visualization-extensions/part-01/03-Lets-Get-Started--Hello-World-Example/" target="_blank" rel="noopener">http://qliksite.io/tutorials/qliksense-visualization-extensions/part-01/03-Lets-Get-Started&#8211;Hello-World-Example/</a></strong></p>
<h2>Схема работы JS кода в QS Extension</h2>
<p><code>define</code> <span>&#8211; это концепция, введенная </span><strong><a href="https://requirejs.org/" target="_blank" rel="noopener">RequireJS</a></strong><span><strong> </strong>для определения зависимостей в ваших файлах JavaScript. Идея состоит в том, чтобы загрузить внешние зависимости до того, как будет выполнен ваш основной скрипт. </span></p>
<p><span><strong>Зависимости</strong> – внешние модули (скрипты/библиотеки), которые необходимы для работы нашего расширения.</span></p>
<p><code>paint</code><span> &#8211; основной метод визуализации визуализации, который будет вызываться каждый раз, когда визуализация должна быть отрисована, либо из-за новых данных с сервера, либо из-за изменения размера.</span></p>
<p><span>Метод paint получает два параметра </span><code>$element</code><span>и </span><code>layout</code><span>.</span></p>
<table>
<thead>
<tr>
<th><strong>Параметр</strong></th>
<th><strong>Описание</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>$element</code></td>
<td><span>Оболочка jQuery, содержащая родительский элемент HTML, в котором должна отображаться визуализация.</span></td>
</tr>
<tr>
<td><code>layout</code></td>
<td><span>Данные и свойства для визуализации.</span></td>
</tr>
</tbody>
</table>
<p><a href="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qliksense_requirejs_define.png"><img loading="lazy" decoding="async" src="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qliksense_requirejs_define.png" alt="" width="674" height="882" class="aligncenter size-full wp-image-2507" srcset="https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qliksense_requirejs_define.png 674w, https://qliksense.ivan-shamaev.ru/wp-content/uploads/2021/01/qliksense_requirejs_define-229x300.png 229w" sizes="(max-width: 674px) 100vw, 674px" /></a></p>
<p>todo</p>
<h1>Видео &#8220;How to build Qlik Sense Visualization Extensions &#8211; Introduction&#8221;</h1>
<p><iframe title="How to build Qlik® Sense Visualization Extensions - 1. Introduction" width="750" height="422" src="https://www.youtube.com/embed/n7RICsLGiCE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p>
<h1>Методы Qlik Sense Extension API</h1>
<h2>beforeDestroy</h2>
<p><span>Выполняется до того, как объект будет уничтожен путем его удаления, переключения листа, открытия инструмента выделения или любых других средств удаления расширения. </span><span>Используйте этот метод для того, чтобы удалить привязки и предотвратить утечку памяти.</span></p>
<blockquote><p><span><strong>Утечка памяти</strong> — это, в широком смысле, фрагмент памяти, выделенной приложению, который больше не нужен этому приложению, но не может быть возвращён операционной системе для дальнейшего использования. Другими словами это — блок памяти, который захвачен приложением без намерения пользоваться этой памятью в будущем.</span></p>
<p><strong>Источник:</strong> <a href="https://habr.com/ru/company/ruvds/blog/495898/" target="_blank" rel="noopener">Практическое руководство по борьбе с утечками памяти в Node.js</a></p></blockquote>
<h2>mounted</h2>
<p><span>Выполняется один раз при инициализации объекта.</span></p>
<p><code><span>mounted($element)</span></code></p>
<h2>paint</h2>
<p><span>Отрисовывает (или render) визуализацию расширения. </span><span>Вызовите этот метод, когда необходимо отрисовать visualization extension либо из-за новых данных с сервера, либо из-за изменения размера расширения визуализации.</span></p>
<h3>Параметры метода paint</h3>
<h4>$element</h4>
<p><span>Оболочка jQuery, содержащая HTML-элемент, в котором должна отображаться визуализация.</span></p>
<h4>layout</h4>
<p><span>Данные и свойства для визуализации.</span></p>
<h4>layout.qHyperCube.qDimensionInfo</h4>
<p><span>Массив с данными об используемых dimensions. Включает <code>qFallbackTitle</code></span><span>, заголовок и </span><code><span class="syntax"><span>qCardinal</span></span></code><span> , количество различных значений.</span></p>
<h4>layout.qHyperCube.qMeasureInfo</h4>
<p><span>Массив с данными об используемых мерах. Включает </span><code><span class="syntax"><span>qFallbackTitle</span></span></code><span>, заголовок (title), </span><code><span class="syntax"><span>qCardinal</span></span></code><span>, количество различных значений, </span><code><span class="syntax"><span>qMin</span></span></code><span> и </span><code><span class="syntax"><span>qMax</span></span></code><span> для минимального и максимального значений.</span></p>
<h4>layout.qHyperCube.qDataPages[0].qMatrix</h4>
<p><span>Массив с данными из </span><span class="CommonComponentsQlik Sense"><span>Qlik Sense</span></span><span> . Каждому объекту соответствует строка в результате. Значения измерения (dimension) и меры (measure) являются объектами JavaScript в этом массиве.</span></p>
<h4>layout.qHyperCube.qDataPages[0].qMatrix[0..#dimensions – 1]</h4>
<p><span>Значения Dimension для строки результата. Каждый объект содержит текст ( </span><code><span class="syntax"><span>qText</span></span></code><span>), используемый для рендеринга, и значение ( </span><code><span class="syntax"><span>qElemNumber</span></span></code><span> ), используемое для selections, и состояние значения ( </span><code><span class="syntax"><span>qState</span></span></code><span> ).</span></p>
<h4>layout.qHyperCube.qDataPages[0].qMatrix[#dimensions..]</h4>
<p><span>Массив со значениями measure для строки результата. Каждый объект содержит данные, фактическое значение ( </span><code><span class="syntax"><span>qNum</span></span></code><span> ) и текст ( </span><code><span class="syntax"><span>qText</span></span></code><span> ), форматированное значение.</span></p>
<h4>layout.qHyperCube.qSize</h4>
<p><span>Общее количество строк (</span><code><span class="syntax"><span>qcy</span></span></code><span>) и столбцов (</span><code><span class="syntax"><span>qcx</span></span></code><span>) в результирующем наборе.</span></p>
<h4>layout.qInfo.qId</h4>
<p><span><code>qId</code> &#8211; Уникальный идентификатор объекта. </span><span>При необходимости полезно для создания уникального HTML-идентификатора.</span></p>
<h4>layout.qSelectionInfo</h4>
<p><span>Если пользователь находится в режиме выбора, это будет объект с двумя флагами: </span><code><span class="syntax"><span>qInSelections</span></span></code><span> и </span><code><span class="syntax"><span>qMadeSelections</span></span></code><span>.</span></p>
<h2>updateData</h2>
<p><span>Выполняется каждый раз при изменении layout или данных, например при осуществлении выборок или изменении свойств. </span><span>Получает новый layout и возвращает promise.</span></p>
<p><code><span>updateData(layout)</span></code></p>
<p>&nbsp;</p>
<h1>Properties Qlik Sense Extension API</h1>
<h2>initialProperties</h2>
<p><code><span>initialProperties()</span></code></p>
<p><span>Задает свойства, которые объект должен иметь при создании. Определите либо как гиперкуб ( </span><code><span class="syntax"><span>qHyperCubeDef</span></span></code><span> ), либо как объект списка ( </span><code><span class="syntax"><span>qListObjectDef</span></span></code><span> ).</span></p>
<p><span>Настройте все свойства и назначьте значения по умолчанию для <strong>custom properties</strong>.</span></p>
<p><span>Максимальное количество ячеек ( </span><code><span class="statement"><span>qWidth</span></span></code><span> * </span><code><span class="statement"><span>qHeight</span></span></code><span> ), разрешенное при исходной <span class="statement">выборке</span> данных, составляет 10 000. Получите дополнительные данные по частям с помощью метода </span><code><span class="syntax"><span>getData</span></span></code><span> в <strong>Backend API</strong>.</span></p>
<p><strong><span class="autonumber">Пример:</span> использование гиперкуба</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">initialProperties : {
    qHyperCubeDef : {
        qDimensions : [],
        qMeasures : [],
        qInitialDataFetch : [{
            qWidth : 2,
            qHeight : 50
        }]
    }
}</pre>
<p><strong><span class="autonumber">Пример</span>, в котором используется объект списка, а также определяются некоторые custom properties</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="js">initialProperties : {
    qListObjectDef : {
        qShowAlternatives : true,
        qFrequencyMode : "V",
        qInitialDataFetch : [{
            qWidth : 2,
            qHeight : 50
        }]
    },
    fixed : true,
    width : 25,
    percent : true,
    selectionMode : "CONFIRM"
}</pre>
<h3>Ограничение 10000 ячеек</h3>
<p>Ходят упорные слухи, что при работе с HyperCube с использованием клиентских API (в расширениях визуализации или мэшапах) можно загрузить только 10 000 ячеек данных.</p>
<p><span style="color: #ff9900;"><strong>Этот слух не соответствует действительности !!!</strong></span></p>
<p>Вместо этого верно, что вы можете получить только 10 000 записей на страницу данных из Engine, но вы, безусловно, можете запросить получение дополнительных страниц данных.<br />
Таким образом, разработчик полностью решает, сколько точек данных из источника данных используется в пользовательском интерфейсе.</p>
<h2>snapshot</h2>
<p><span>Включает или отключает возможность делать снимки расширения визуализации для использования в Data Storytelling.</span></p>
<p><code><span>snapshot(enable)</span></code></p>
<h2>export</h2>
<p><span>Включает или отключает возможность экспорта расширения визуализации как изображения или как <strong>PDF-файл.</strong> Это также позволяет включить расширение визуализации в <strong>экспорт из Storytelling</strong> (PowerPoint или PDF).</span></p>
<p><span>Если задано значение </span><code><span class="syntax"><span>true</span></span></code><span> , включены параметры контекстного меню <strong>«</strong></span><strong><span class="ui_item">Экспорт как изображение»</span></strong><span> и <strong>«</strong></span><strong><span class="ui_item">Экспорт в PDF»</span></strong><span> для расширения визуализации. Это также позволяет расширениям визуализации быть частью историй, экспортируемых в PowerPoint или PDF, в параметрах контекстного меню «</span><span class="ui_item"><span>Экспорт истории в PowerPoint»</span></span><span> и «</span><span class="ui_item"><span>Экспорт истории в PDF»</span></span><span>.</span></p>
<h2>exportData</h2>
<p><span>Включает или отключает возможность экспорта данных из расширения визуализации и сохранения их в файле XLSX. Если задано значение </span><code><span class="syntax"><span>true</span></span></code><span>, параметр контекстного меню <strong>«</strong></span><strong><span class="ui_item">Экспорт данных»</span></strong><span> включен для расширения визуализации.</span></p>
<h2>Пример</h2>
<pre class="EnlighterJSRAW" data-enlighter-language="js">var ext = {
    support: {
        snapshot: true,
        export: true,
        exportData: true
    }
};</pre>
<h1>Property definitions</h1>
<h2>Array</h2>
<p>todo</p>
<h2>Integer</h2>
<p>todo</p>
<h2>Number</h2>
<p>todo</p>
<h2>String</h2>
<p>todo</p>
<h2>Text</h2>
<p>todo</p>
<h2>Button</h2>
<p>todo</p>
<h2>Button group</h2>
<p>todo</p>
<h2>Check box</h2>
<p>todo</p>
<h2>Color-picker</h2>
<p>todo</p>
<h2>Drop down list</h2>
<p>todo</p>
<h2>Link</h2>
<p>todo</p>
<h2>Media</h2>
<p>todo</p>
<h2>Radio button</h2>
<p>todo</p>
<h2>Slider</h2>
<p>todo</p>
<h2>Range-slider</h2>
<p>todo</p>
<h2>Switch</h2>
<p>todo</p>
<h2>Textarea</h2>
<p>todo</p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/overview-qlik-extension-api-and-methods/">Обзор Extension API и описание методов расширений</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/overview-qlik-extension-api-and-methods/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Обзор функций Javascript в редакторе Qlik Sense Extensions</title>
		<link>https://qliksense.ivan-shamaev.ru/overview-javascript-functions-extensions/</link>
					<comments>https://qliksense.ivan-shamaev.ru/overview-javascript-functions-extensions/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Sat, 09 Jan 2021 20:22:39 +0000</pubDate>
				<category><![CDATA[Уровень 2]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[javascript qlik sense]]></category>
		<category><![CDATA[qlik sense api]]></category>
		<category><![CDATA[Qlik Sense Extension]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=2488</guid>

					<description><![CDATA[<p>== A == arguments &#8211; alert &#8211; показывает сообщение и ждёт, пока пользователь нажмёт кнопку «ОК» atob &#8211; Функция декодирует строку данных , которые были закодированы с помощью Base64 кодирования. var decodedData = scope.atob(encodedData); angular &#8211; addEventListener &#8211; способ назначения обработчиков на события с привязкой к элементу. Синтаксис: element.addEventListener(event, handler[, options]); event &#8211; Имя<a class="moretag" href="https://qliksense.ivan-shamaev.ru/overview-javascript-functions-extensions/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/overview-javascript-functions-extensions/">Обзор функций Javascript в редакторе Qlik Sense Extensions</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>== A ==</h2>
<ul>
<li><strong>arguments</strong> &#8211;</li>
<li><strong>alert </strong>&#8211; <span>показывает сообщение и ждёт, пока пользователь нажмёт кнопку «ОК»</span></li>
<li><strong>atob </strong>&#8211; <span>Функция декодирует строку данных , которые были закодированы с помощью </span><a href="https://developer.mozilla.org/en-US/docs/Glossary/Base64"><span>Base64</span></a><span> кодирования.</span>
<ul>
<li>
<pre class="brush: js notranslate"><code><span class="token keyword">var</span> decodedData <span class="token operator">=</span> scope<span class="token punctuation">.</span><span class="token function">atob</span><span class="token punctuation">(</span>encodedData<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</li>
</ul>
</li>
<li><strong>angular </strong>&#8211;</li>
<li><strong>addEventListener </strong>&#8211; способ назначения обработчиков на события с привязкой к элементу. Синтаксис:
<ul>
<li><code>element.addEventListener(event, handler[, options]);</code>
<ul>
<li><code>event</code> &#8211; Имя события, например<span> </span><code>"click"</code></li>
<li><code>handler</code> &#8211; Ссылка на функцию-обработчик</li>
<li><code>options</code> &#8211; Дополнительный объект со свойствами: <code>once</code><span>, <code>capture</code>, <code>passive</code>.</span></li>
</ul>
</li>
<li><span>Метод </span><code>addEventListener</code><span> позволяет добавлять несколько обработчиков на одно событие одного элемента</span>
<ul>
<li>
<pre class="EnlighterJSRAW" data-enlighter-language="js">function handler1() {
  alert('Спасибо!');
};

function handler2() {
  alert('Спасибо ещё раз!');
}

elem.onclick = () =&gt; alert("Привет");
elem.addEventListener("click", handler1); // Спасибо!
elem.addEventListener("click", handler2); // Спасибо ещё раз!</pre>
<p><strong></strong></li>
</ul>
</li>
</ul>
</li>
<li><strong>app </strong>&#8211;</li>
</ul>
<h2>== B ==</h2>
<ul>
<li><strong>blur </strong>&#8211;</li>
<li><strong>btoa </strong>&#8211; <span>Метод создает </span><a href="https://developer.mozilla.org/en-US/docs/Glossary/Base64"><span>Base64</span></a><span> закодированную ASCII строку из </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary"><span>двоичной строки</span></a> / Binary<span> (то есть </span><code>String</code> <span>объект , в котором каждый символ в строке рассматриваются как байты двоичных данных). Вы можете использовать этот метод для кодирования данных, которые в противном случае могут вызвать проблемы со связью, передать их, а затем использовать метод <code>atob()</code> для повторного декодирования данных.</span>
<ul>
<li>
<pre class="brush: js notranslate"><code><span class="token keyword">var</span> encodedData <span class="token operator">=</span> scope<span class="token punctuation">.</span><span class="token function">btoa</span><span class="token punctuation">(</span>stringToEncode<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</li>
</ul>
</li>
<li><strong>break </strong>&#8211;</li>
<li><strong>backendApi </strong>&#8211;</li>
</ul>
<h2>== C ==</h2>
<ul>
<li><strong>customElements </strong>&#8211;</li>
<li><strong>closed </strong>&#8211;</li>
<li><strong>clientInformation </strong>&#8211;</li>
<li><strong>crypto </strong>&#8211;</li>
<li><strong>cancelAnimationFrame </strong>&#8211;</li>
<li><strong>cancelIdleCallback </strong>&#8211;</li>
<li><strong>captureEvents </strong>&#8211;</li>
<li><strong>clearInterval </strong>&#8211; <span>отменяет синхронизированное, повторяющееся действие, которое было ранее установлено вызовом </span><code>setInterval()</code><span>.</span></li>
<li><strong>clearTimeout </strong>&#8211; <span>отменяет тайм &#8211; аут ранее установленного вызовом метода </span><code>setTimeout()</code><span>.</span></li>
<li><strong>close </strong>&#8211;</li>
<li><strong>confirm </strong>&#8211; <span>отображает диалоговое окно, которое содержит две кнопки (OK и Cancel), а так же опциональное (необязательное) текстовое сообщение.</span>
<ul>
<li><code>result = confirm(message);</code>
<ul>
<li><code>message</code><span> </span>опциональная (необязательная) строка, которая будет отображена в диалоговом окне.</li>
<li><code>result</code><span> </span>булево значение, указывающее на нажатую кнопку OK или Cancel (<code>true</code> означает OK).</li>
</ul>
</li>
</ul>
</li>
<li><strong>createImageBitmap</strong> &#8211; <span>Метод создает bitmap из источника, при необходимости можно использовать только часть источника. Метод существует в глобальной области как в окнах, так и в рабочих процессах. Он принимает множество различных источников изображений и возвращает </span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" data-flaw-src="{{domxref(&quot;Promise&quot;)}}"><code>Promise</code></a>, <span>которое <strong>resolve</strong> в </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap"><code>ImageBitmap</code></a><span>.</span></li>
<li><strong>chrome </strong>&#8211;</li>
<li><strong>caches </strong>&#8211;</li>
<li><strong>case </strong>&#8211;</li>
<li><strong>catch </strong>&#8211;</li>
<li><strong>continue </strong>&#8211;</li>
</ul>
<h2>== D ==</h2>
<ul>
<li><strong>dimensionInfo </strong>&#8211;</li>
<li><strong>document </strong>&#8211;</li>
<li><strong>devicePixelRatio </strong>&#8211;</li>
<li><strong>defaultStatus </strong>&#8211;</li>
<li><strong>dragomanClosure </strong>&#8211;</li>
<li><strong>define </strong>&#8211;</li>
<li><strong>debounceTimer </strong>&#8211;</li>
<li><strong>dispatchEvent </strong>&#8211;</li>
<li><strong>debugger </strong>&#8211;</li>
<li><strong>default </strong>&#8211;</li>
<li><strong>delete </strong>&#8211;</li>
<li><strong>do </strong>&#8211;</li>
</ul>
<h2>== E ==</h2>
<ul>
<li><strong>external </strong>&#8211;</li>
<li><strong>engineModuleGlobal </strong>&#8211;</li>
<li><strong>else </strong>&#8211;</li>
</ul>
<h2>== F ==</h2>
<ul>
<li><strong>frames </strong>&#8211;</li>
<li><strong>frameElement </strong>&#8211;</li>
<li><strong>fetch </strong>&#8211; <span class="seoSummary"><span>Метод </span><code>WindowOrWorkerGlobalScope</code> <span>Mixin начинается процесс извлечения ресурса из сети, возвращая обещание , которое выполняется , как только отклик доступен. </span></span><span>Обещание преобразуется в </span><code>Response</code> <span>объект, представляющий ответ на ваш запрос. Обещание </span><em><span>не</span></em><span> отклоняется при ошибках HTTP &#8211; оно отклоняется только при ошибках сети. Вы должны использовать </span><code>then</code> <span>обработчики для проверки ошибок HTTP.</span></li>
<li><strong>find </strong>&#8211;</li>
<li><strong>focus </strong>&#8211;</li>
<li><strong>false </strong>&#8211;</li>
<li><strong>finally </strong>&#8211;</li>
<li><strong>for </strong>&#8211;</li>
<li><strong>function </strong>&#8211;</li>
</ul>
<h2>== G ==</h2>
<ul>
<li><strong>getComputedStyle </strong>&#8211;</li>
<li><strong>getSelection </strong>&#8211;</li>
</ul>
<h2>== H ==</h2>
<ul>
<li><strong>html </strong>&#8211;</li>
<li><strong>history </strong>&#8211;</li>
</ul>
<h2>== I ==</h2>
<ul>
<li><strong>innerWidth </strong>&#8211;</li>
<li><strong>innerHeight </strong>&#8211;</li>
<li><strong>isSecureContext </strong>&#8211;</li>
<li><strong>indexedDB </strong>&#8211;</li>
<li><strong>if </strong>&#8211;</li>
<li><strong>in </strong>&#8211;</li>
<li><strong>instanceof </strong>&#8211;</li>
</ul>
<h2>== L ==</h2>
<ul>
<li><strong>location </strong>&#8211;</li>
<li><strong>locationbar </strong>&#8211;</li>
<li><strong>length </strong>&#8211;</li>
<li><strong>localStorage </strong>&#8211;</li>
<li><strong>layout </strong>&#8211;</li>
</ul>
<h2>== M ==</h2>
<ul>
<li><strong>menubar </strong>&#8211;</li>
<li><strong>matchMedia </strong>&#8211;</li>
<li><strong>moveBy </strong>&#8211;</li>
<li><strong>moveTo </strong>&#8211;</li>
</ul>
<h2>== O ==</h2>
<ul>
<li><strong>opener </strong>&#8211; Свойство <b>opener</b> возвращает ссылку на окно, которое открыло текущее. Когда Вы открываете новое окно с помощью open() Вы можете воспользоваться этим свойством, чтобы взаимодействовать с родительским окном из нового окна.
<ul>
<li>
<pre class="EnlighterJSRAW" data-enlighter-language="js">//Создадим новое окно win 
win = window.open();
//Выведем в новое окно текст
win.document.write("Текст нового окна");
//Теперь выведем текст в родительское окно с помощью свойства opener
win.opener.document.write("Текст родительского окна");</pre>
<p>&nbsp;</li>
</ul>
</li>
<li><strong>origin </strong>&#8211;</li>
<li><strong>outerWidth </strong>&#8211;</li>
<li><strong>outerHeight </strong>&#8211;</li>
<li><strong>onsearch </strong>&#8211;</li>
<li><strong>onappinstalled </strong>&#8211;</li>
<li><strong>onbeforeinstallprompt </strong>&#8211;</li>
<li><strong>onabort </strong>&#8211;</li>
<li><strong>onblur </strong>&#8211;</li>
<li><strong>oncancel </strong>&#8211;</li>
<li><strong>oncanplay</strong> &#8211;</li>
<li><strong>oncanplaythrough </strong>&#8211;</li>
<li><strong>onchange </strong>&#8211;</li>
<li><strong>onclick </strong>&#8211;</li>
<li><strong>onclose </strong>&#8211;</li>
<li><strong>oncontextmenu </strong>&#8211;</li>
<li><strong>oncuechange </strong>&#8211;</li>
<li><strong>ondblclick </strong>&#8211;</li>
<li><strong>ondrag </strong>&#8211;</li>
<li><strong>ondragend </strong>&#8211;</li>
<li><strong>ondragenter </strong>&#8211;</li>
<li><strong>ondragleave </strong>&#8211;</li>
<li><strong>ondragover </strong>&#8211;</li>
<li><strong>ondragstart </strong>&#8211;</li>
<li><strong>ondrop</strong> &#8211;</li>
<li><strong>ondurationchange </strong>&#8211;</li>
<li><strong>onemptied </strong>&#8211;</li>
<li><strong>onended </strong>&#8211;</li>
<li><strong>onerror </strong>&#8211;</li>
<li><strong>onfocus </strong>&#8211;</li>
<li><strong>onformdata </strong>&#8211;</li>
<li><strong>oninput </strong>&#8211;</li>
<li><strong>oninvalid </strong>&#8211;</li>
<li><strong>onkeydown </strong>&#8211;</li>
<li><strong>onkeypress </strong>&#8211;</li>
<li><strong>onkeyup </strong>&#8211;</li>
<li><strong>onload </strong>&#8211;</li>
<li><strong>onloadeddata </strong>&#8211;</li>
<li><strong>onloadedmetadata </strong>&#8211;</li>
<li><strong>onloadstart </strong>&#8211;</li>
<li><strong>onmousedown </strong>&#8211;</li>
<li><strong>onmouseenter </strong>&#8211;</li>
<li><strong>onmouseleave </strong>&#8211;</li>
<li><strong>onmousemove </strong>&#8211;</li>
<li><strong>onmouseout </strong>&#8211;</li>
<li><strong>onmouseover </strong>&#8211;</li>
<li><strong>onmouseup </strong>&#8211;</li>
<li><strong>onmousewheel </strong>&#8211;</li>
<li><strong>onpause </strong>&#8211;</li>
<li><strong>onplay </strong>&#8211;</li>
<li><strong>onplaying </strong>&#8211;</li>
<li><strong>onprogress </strong>&#8211;</li>
<li><strong>onratechange </strong>&#8211;</li>
<li><strong>onreset </strong>&#8211;</li>
<li><strong>onresize </strong>&#8211;</li>
<li><strong>onscroll </strong>&#8211;</li>
<li><strong>onseeked </strong>&#8211;</li>
<li><strong>onseeking </strong>&#8211;</li>
<li><strong>onselect </strong>&#8211;</li>
<li><strong>onstalled </strong>&#8211;</li>
<li><strong>onsubmit </strong>&#8211;</li>
<li><strong>onsuspend </strong>&#8211;</li>
<li><strong>ontimeupdate </strong>&#8211;</li>
<li><strong>ontoggle </strong>&#8211;</li>
<li><strong>onvolumechange </strong>&#8211;</li>
<li><strong>onwaiting </strong>&#8211;</li>
<li><strong>onwebkitanimationend </strong>&#8211;</li>
<li><strong>onwebkitanimationiteration </strong>&#8211;</li>
<li><strong>onwebkitanimationstart </strong>&#8211;</li>
<li><strong>onwebkitanimationend </strong>&#8211;</li>
<li><strong>onwheel </strong>&#8211;</li>
<li><strong>onauxclick </strong>&#8211;</li>
<li><strong>ongotpointercapture </strong>&#8211;</li>
<li><strong>onlostpointercapture </strong>&#8211;</li>
<li><strong>onpointerdown </strong>&#8211;</li>
<li><strong>onpointermove </strong>&#8211;</li>
<li><strong>onpointerup </strong>&#8211;</li>
<li><strong>onpointercancel </strong>&#8211;</li>
<li><strong>onpointerover </strong>&#8211;</li>
<li><strong>onpointerout </strong>&#8211;</li>
<li><strong>onpointerenter </strong>&#8211;</li>
<li><strong>onpointerleave </strong>&#8211;</li>
<li><strong>onselectstart </strong>&#8211;</li>
<li><strong>onselectionchange </strong>&#8211;</li>
<li><strong>onanimationend </strong>&#8211;</li>
<li><strong>onanimationiteration </strong>&#8211;</li>
<li><strong>onanimationstart </strong>&#8211;</li>
<li><strong>ontransitionend </strong>&#8211;</li>
<li><strong>onafterprint </strong>&#8211;</li>
<li><strong>onbeforeprint </strong>&#8211;</li>
<li><strong>onbeforeunload </strong>&#8211;</li>
<li><strong>onhashchange </strong>&#8211;</li>
<li><strong>onlanguagechange </strong>&#8211;</li>
<li><strong>onmessage </strong>&#8211;</li>
<li><strong>onmessageerror </strong>&#8211;</li>
<li><strong>onoffline </strong>&#8211;</li>
<li><strong>ononline </strong>&#8211;</li>
<li><strong>onpagehide </strong>&#8211;</li>
<li><strong>onpageshow </strong>&#8211;</li>
<li><strong>onpopstate </strong>&#8211;</li>
<li><strong>onrejectionhandled </strong>&#8211;</li>
<li><strong>onstorage </strong>&#8211;</li>
<li><strong>onunhandledrejection </strong>&#8211;</li>
<li><strong>onunload </strong>&#8211;</li>
<li><strong>open </strong>&#8211;</li>
<li><strong>ondevicemotion </strong>&#8211;</li>
<li><strong>ondeviceorientation </strong>&#8211;</li>
<li><strong>ondeviceorientationabsolute </strong>&#8211;</li>
<li><strong>onpointerrawupdate </strong>&#8211;</li>
<li><strong>openDatabase </strong>&#8211;</li>
</ul>
<h2>== P ==</h2>
<ul>
<li><strong>personalbar </strong>&#8211;</li>
<li><strong>parent </strong>&#8211;</li>
<li><strong>pageXOffset </strong>&#8211;</li>
<li><strong>pageYOffset </strong>&#8211;</li>
<li><strong>performance </strong>&#8211;</li>
<li><strong>postMessage </strong>&#8211;</li>
<li><strong>print </strong>&#8211;</li>
<li><strong>prompt </strong>&#8211; отображает диалоговое окно с необязательным запросом на ввод текста<span>: <code>result <span class="token operator">=</span> <span class="token function">prompt</span><span class="token punctuation">(</span>title<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token keyword">default</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></span>
<ul>
<li><span>Этот код отобразит модальное окно с текстом, полем для ввода текста и кнопками OK/Отмена.</span>
<ul>
<li><code>result</code> — это строка, содержащая текст, поступивший от пользователя или null.</li>
<li><code>title</code> &#8211; Текст для отображения в окне.</li>
<li><code>default</code> &#8211; Необязательный второй параметр, который устанавливает начальное значение в поле для текста в окне.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>== Q ==</h2>
<ul>
<li><strong>queueMicrotask </strong>&#8211; <span class="seoSummary"><span>Метод, который подвергается воздействие на </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window"><code>Window</code></a> <span>или </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/Worker"><code>Worker</code></a> <span>интерфейсе, в очередь microtask , которая будет выполнено в безопасное время до контроля возвращения в цикл обработки событий браузера. </span></span><span><strong>Микрозадача</strong> &#8211; это короткая функция, которая будет выполняться после того, как текущая задача завершит свою работу, и когда нет другого кода, ожидающего запуска, до того, как управление контекстом выполнения будет возвращено в цикл событий браузера. Это позволяет вашему коду выполняться без вмешательства в любой другой ожидающий выполнения код с потенциально более высоким приоритетом, но до того, как браузер восстановит контроль над контекстом выполнения, что может зависеть от работы, которую вам нужно выполнить.</span>
<ul>
<li>
<pre class="brush: js notranslate"><code>scope<span class="token punctuation">.</span><span class="token function">queueMicrotask</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</li>
</ul>
</li>
<li><strong>qJsonp </strong>&#8211;</li>
<li><strong>qvangularGlobal </strong>&#8211;</li>
<li><strong>qListObject </strong>&#8211; <span>является базовым списком и подходит, если вы хотите создать список всех значений из поля. Объект списка &#8211; это визуализация, содержащая одно измерение. При получении макета объекта списка ( <code><span class="syntax">qListObjectDef</span></code> ) <span class="syntax">отображаются</span> все значения. Если выбор применяется к объекту списка, выбранные значения отображаются вместе с исключенными и дополнительными значениями.</span>
<ul>
<li><strong><span class="autonumber">Пример:</span> горизонтальный </strong><span class="syntax"><span><strong>список</strong> <code>initialProperties</code></span></span></li>
<li>
<pre class="EnlighterJSRAW" data-enlighter-language="js">initialProperties : {  
            version : 1.0,  
            qListObjectDef : {  
                qShowAlternatives : true,  
                qFrequencyMode : "V",  
                qSortCriterias : {  
                    qSortByState : 1  
                },  
                qInitialDataFetch : [{  
                    qWidth : 2,  
                    qHeight : 50  
                }]  
            },  
            fixed: true,  
            width: 25,  
            percent: true,  
            selectionMode: "CONFIRM"  
}</pre>
<p>&nbsp;</li>
</ul>
</li>
<li><strong>qHyperCube </strong>&#8211;</li>
<li><strong>qlik </strong>&#8211;</li>
</ul>
<h2>== R ==</h2>
<ul>
<li><strong>rows </strong>&#8211;</li>
<li><strong>releaseEvents </strong>&#8211;</li>
<li><strong>requestAnimationFrame </strong>&#8211;</li>
<li><strong>requestIdleCallback </strong>&#8211;</li>
<li><strong>resizeBy </strong>&#8211;</li>
<li><strong>resizeTo </strong>&#8211;</li>
<li><strong>regeneratorRuntime </strong>&#8211;</li>
<li><strong>require </strong>&#8211;</li>
<li><strong>requirejs </strong>&#8211;</li>
<li><strong>removeEventListener </strong>&#8211;</li>
<li><strong>return </strong>&#8211;</li>
<li><strong>reply </strong>&#8211;</li>
</ul>
<h2>== S ==</h2>
<ul>
<li><strong>self </strong>&#8211;</li>
<li><strong>scrollbars </strong>&#8211;</li>
<li><strong>statusbar </strong>&#8211;</li>
<li><strong>status </strong>&#8211;</li>
<li><strong>screen </strong>&#8211;</li>
<li><strong>scrollX </strong>&#8211;</li>
<li><strong>scrollY </strong>&#8211;</li>
<li><strong>screenX </strong>&#8211;</li>
<li><strong>screenY </strong>&#8211;</li>
<li><strong>screenLeft </strong>&#8211;</li>
<li><strong>screenTop </strong>&#8211;</li>
<li><strong>styleMedia </strong>&#8211;</li>
<li><strong>sessionStorage </strong>&#8211;</li>
<li><strong>scroll </strong>&#8211;</li>
<li><strong>scrollBy </strong>&#8211;</li>
<li><strong>scrollTo </strong>&#8211;</li>
<li><strong>setInterval </strong>&#8211; <span class="seoSummary"><span>Метод, предложенный на </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window"><code>Window</code></a> <span>и </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/Worker"><code>Worker</code></a> <span>интерфейсах, неоднократно вызывает функцию или выполняет фрагмент кода, с фиксированной задержкой по времени между каждым вызовом. </span></span><span>Он возвращает идентификатор интервала, который однозначно определяет интервал, поэтому вы можете удалить его позже, позвонив </span><code>clearInterval()</code><span>. Этот метод определяется </span><a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope"><code>WindowOrWorkerGlobalScope</code></a> <span>миксином.</span>
<ul>
<li>
<pre class="brush: js notranslate"><code><span class="token keyword">var</span> intervalID <span class="token operator">=</span> scope<span class="token punctuation">.</span><span class="token function">setInterval</span><span class="token punctuation">(</span>func<span class="token punctuation">,</span> <span class="token punctuation">[</span>delay<span class="token punctuation">,</span> arg1<span class="token punctuation">,</span> arg2<span class="token punctuation">,</span> <span class="token operator">...</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</li>
</ul>
</li>
<li><strong>setTimeout </strong>&#8211; <span>Метод </span><code>WindowOrWorkerGlobalScope</code> <span>Mixin (и преемника </span><code>Window.setTimeout()</code><span>) устанавливает таймер , который выполняет функцию или указанный фрагмент кода один раз, когда таймер истекает.</span>
<ul>
<li>
<pre class="brush: js notranslate"><code><span class="token keyword">var</span> timeoutID <span class="token operator">=</span> scope<span class="token punctuation">.</span><span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">[</span><span class="token punctuation">,</span> delay<span class="token punctuation">,</span> arg1<span class="token punctuation">,</span> arg2<span class="token punctuation">,</span> <span class="token operator">...</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
</li>
</ul>
</li>
<li><strong>stop </strong>&#8211;</li>
<li><strong>showDirectory </strong>&#8211;</li>
<li><strong>showOpenFilePicker </strong>&#8211;</li>
<li><strong>showSaveFilePicker </strong>&#8211;</li>
<li><strong>speechSynthesis </strong>&#8211;</li>
<li><strong>switch </strong>&#8211;</li>
</ul>
<h2>== T ==</h2>
<ul>
<li><strong>this </strong>&#8211;</li>
<li><strong>toolbar </strong>&#8211;</li>
<li><strong>top </strong>&#8211;</li>
<li><strong>trustedTypes </strong>&#8211;</li>
<li><strong>throw </strong>&#8211;</li>
<li><strong>true </strong>&#8211;</li>
<li><strong>try </strong>&#8211;</li>
<li><strong>typeof </strong>&#8211;</li>
</ul>
<h2>== V ==</h2>
<ul>
<li><strong>visualViewport </strong>&#8211;</li>
<li><strong>var </strong>&#8211;</li>
<li><strong>void </strong>&#8211;</li>
</ul>
<h2>== W ==</h2>
<ul>
<li><strong>window </strong>&#8211;</li>
<li><strong>webkitStorageInfo </strong>&#8211;</li>
<li><strong>webkitCancelAnimationFrame </strong>&#8211;</li>
<li><strong>webkitRequestAnimationFrame </strong>&#8211;</li>
<li><strong>webkitRequestFileSystem </strong>&#8211;</li>
<li><strong>webkitResolveLocalFileSystemURL </strong>&#8211;</li>
<li><strong>webpackJsonpsensei_codearea </strong>&#8211;</li>
<li><strong>while </strong>&#8211;</li>
<li><strong>with </strong>&#8211;</li>
</ul>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/overview-javascript-functions-extensions/">Обзор функций Javascript в редакторе Qlik Sense Extensions</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/overview-javascript-functions-extensions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Qlik Sense November 2018 &#8211; What&#8217;s New</title>
		<link>https://qliksense.ivan-shamaev.ru/qlik-sense-november-2018-whats-new/</link>
					<comments>https://qliksense.ivan-shamaev.ru/qlik-sense-november-2018-whats-new/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 30 Nov 2018 06:19:00 +0000</pubDate>
				<category><![CDATA[Новости Qlik Sense]]></category>
		<category><![CDATA[Dashboard extension bundle]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[qlik sense]]></category>
		<category><![CDATA[qlik sense desktop]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[Qlik Sense November 2018]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=778</guid>

					<description><![CDATA[<p>Майк Таралло из Qlik рассказывает, что нового в последней версии Qlik Sense &#8211; ноябрь 2018 года. Precedent Machine Learning (Insight Advisor &#8211; Enterprise only) Dashboard Extension Bundle New Chart Map Layer Enhanced Pie Chart (2 measures &#8211; Rose, Polar) Alternate States Single Selections Set Analysis Expression Editor improvements Обязательно ознакомьтесь<a class="moretag" href="https://qliksense.ivan-shamaev.ru/qlik-sense-november-2018-whats-new/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qlik-sense-november-2018-whats-new/">Qlik Sense November 2018 &#8211; What&#8217;s New</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><iframe width="560" height="315" src="https://www.youtube.com/embed/t2JWSzFVwh8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="allowfullscreen"></iframe></p>
<p>Майк Таралло из Qlik рассказывает, что нового в последней версии Qlik Sense &#8211; ноябрь 2018 года.</p>
<ul>
<li>Precedent Machine Learning (Insight Advisor &#8211; Enterprise only)</li>
<li>Dashboard Extension Bundle</li>
<li>New Chart Map Layer</li>
<li>Enhanced Pie Chart (2 measures &#8211; Rose, Polar)</li>
<li>Alternate States</li>
<li>Single Selections</li>
<li>Set Analysis Expression Editor improvements</li>
</ul>
<p>Обязательно ознакомьтесь с нашими примечаниями к выпуску на сайте загрузки клиента Qlik.<br />
<strong><a href="https://community.qlik.com/t5/New-to-Qlik-Sense/Demonstration-Qlik-Sense-Apps-November-2018/m-p/1506305" target="_blank" rel="noopener">Demonstration Qlik Sense Apps November 2018</a></strong></p>
<h1><strong>Dashboard extension bundle &#8211; Qlik Sense</strong></h1>
<p>Официальный набор Extensions от Qlik, которые они будут поддерживать при переходе к новой версии.<br />
<iframe width="560" height="315" src="https://www.youtube.com/embed/XS_2Nqab4Ms" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="allowfullscreen"></iframe></p>
<p>Ссылки на описание расширений. <strong><span style="color: #ff0000;">НЕ УСТАНАВЛИВАЙТЕ РАСШИРЕНИЯ С GITHUB</span></strong>. Только через официальный инсталлятор Qlik Sense Desktop.</p>
<ul>
<li><a href="https://github.com/NOD507/SenseDateRangePicker"><strong>https://github.com/NOD507/SenseDateRangePicker</strong></a></li>
<li><strong><a href="https://github.com/stefanwalther/sense-navigation">https://github.com/stefanwalther/sense-navigation</a></strong></li>
<li><strong><a href="https://github.com/bohua/nprinting-sense-on-demand">https://github.com/bohua/nprinting-sense-on-demand</a></strong></li>
<li><strong><a href="https://github.com/fadyheiba/ShowHide">https://github.com/fadyheiba/ShowHide</a></strong></li>
<li><strong><a href="https://github.com/mhamano/Qlik-Sense-Tabs">https://github.com/mhamano/Qlik-Sense-Tabs</a></strong></li>
<li><strong><a href="https://github.com/erikwett/qsVariable">https://github.com/erikwett/qsVariable</a></strong></li>
</ul>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/qlik-sense-november-2018-whats-new/">Qlik Sense November 2018 &#8211; What&#8217;s New</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/qlik-sense-november-2018-whats-new/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Cookbook for PicassoJS Qlik Sense Extensions &#8211; School of Picasso JS</title>
		<link>https://qliksense.ivan-shamaev.ru/cookbook-for-picassojs-qlik-sense-extensions-school-of-picasso-js/</link>
					<comments>https://qliksense.ivan-shamaev.ru/cookbook-for-picassojs-qlik-sense-extensions-school-of-picasso-js/#respond</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Fri, 05 Oct 2018 21:34:15 +0000</pubDate>
				<category><![CDATA[Youtube подборки видео по тематикам Qlik Sense]]></category>
		<category><![CDATA[Cookbook]]></category>
		<category><![CDATA[picasso js qlik sense]]></category>
		<category><![CDATA[PicassoJS]]></category>
		<category><![CDATA[qlik sense]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[qlik sense youtube]]></category>
		<category><![CDATA[qliksense youtube]]></category>
		<category><![CDATA[School of Picasso JS]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=354</guid>

					<description><![CDATA[<p>Cookbook for PicassoJS Qlik Sense Extensions &#8211; School of Picasso JS Picasso JS https://picassojs.com/ &#8211; официальный сайт Picasso JS School of Picasso JS Part 1: Get started School of Picasso JS Part 2: Create Qlik Sense Extension School of Picasso JS Part 3: Simple Qlik2Go Extension for Qlik Sense School<a class="moretag" href="https://qliksense.ivan-shamaev.ru/cookbook-for-picassojs-qlik-sense-extensions-school-of-picasso-js/"> Читать дальше&#8230;</a></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/cookbook-for-picassojs-qlik-sense-extensions-school-of-picasso-js/">Cookbook for PicassoJS Qlik Sense Extensions &#8211; School of Picasso JS</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<blockquote><p><em>Cookbook for PicassoJS Qlik Sense Extensions &#8211; School of Picasso JS</em></p></blockquote>
<h2>Picasso JS</h2>
<p><a href="https://picassojs.com/" target="_blank" rel="noopener">https://picassojs.com/</a> &#8211; официальный сайт Picasso JS</p>
<h2><strong>School of Picasso JS Part 1: Get started</strong></h2>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/KRADE-GXCf4?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe></p>
<h2><strong>School of Picasso JS Part 2: Create Qlik Sense Extension</strong></h2>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/ZYjmO-oAFyM?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe></p>
<h2><strong>School of Picasso JS Part 3: Simple Qlik2Go Extension for Qlik Sense</strong></h2>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/4Nm447QHaCE?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe></p>
<h2><strong>School Of PicassoJS Part 4: Adding Brushing</strong></h2>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/hedEyOwrqvE?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe></p>
<h2><strong>Introducing Picasso Designer for Qlik Sense</strong></h2>
<p><strong>Picasso Designer</strong> &#8211; это расширение для построения сложных диаграмм, основанных на библиотеке Picasso.JS, без необходимости писать какой-либо код или понимать структуру Picasso JSON. В этом видео демонстрируется BETA версия Picasso Designer (<a href="https://github.com/AnalyticsEarth/aePicassoChart" target="_blank" rel="noopener">https://github.com/AnalyticsEarth/aePicassoChart</a>).<br />
<iframe width="560" height="315" src="https://www.youtube.com/embed/0tLm7Lf3TYc?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/cookbook-for-picassojs-qlik-sense-extensions-school-of-picasso-js/">Cookbook for PicassoJS Qlik Sense Extensions &#8211; School of Picasso JS</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/cookbook-for-picassojs-qlik-sense-extensions-school-of-picasso-js/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Подборка Видео по Qlik Sense Extensions</title>
		<link>https://qliksense.ivan-shamaev.ru/podborka-po-qlik-sense-extensions/</link>
					<comments>https://qliksense.ivan-shamaev.ru/podborka-po-qlik-sense-extensions/#comments</comments>
		
		<dc:creator><![CDATA[qliksense-expert]]></dc:creator>
		<pubDate>Wed, 03 Oct 2018 19:53:50 +0000</pubDate>
				<category><![CDATA[Youtube подборки видео по тематикам Qlik Sense]]></category>
		<category><![CDATA[qlik sense]]></category>
		<category><![CDATA[Qlik Sense Extensions]]></category>
		<category><![CDATA[Qlik Sense Расширения]]></category>
		<category><![CDATA[qliksense]]></category>
		<category><![CDATA[Подборка видео по Qlik Sense]]></category>
		<guid isPermaLink="false">https://qliksense.ivan-shamaev.ru/?p=330</guid>

					<description><![CDATA[<p>В этой статье приведена &#8220;Подборка Видео по Qlik Sense Extensions&#8221;. Как устанавливать Extensions на Qlik Sense, Как создавать расширения на Qlik Sense. Installing Extensions into Qlik Sense Building a Qlik Sense Extension, Week 1</p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/podborka-po-qlik-sense-extensions/">Подборка Видео по Qlik Sense Extensions</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>В этой статье приведена &#8220;Подборка Видео по Qlik Sense Extensions&#8221;. Как устанавливать Extensions на Qlik Sense, Как создавать расширения на Qlik Sense.</p>
<h2><strong>Installing Extensions into Qlik Sense</strong></h2>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/foSEjKoq8Mc?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe></p>
<h2><strong>Building a Qlik Sense Extension, Week 1</strong></h2>
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/0X4hXzfLftg?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe></p>
<p>Сообщение <a href="https://qliksense.ivan-shamaev.ru/podborka-po-qlik-sense-extensions/">Подборка Видео по Qlik Sense Extensions</a> появились сначала на <a href="https://qliksense.ivan-shamaev.ru">Qlik Sense - Обучение, учебник, онлайн курс</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://qliksense.ivan-shamaev.ru/podborka-po-qlik-sense-extensions/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
