', {
56 | 'href': gitbook.state.basePath + '/' + res.url,
57 | 'text': res.title
58 | });
59 |
60 | var content = res.body.trim();
61 | if (content.length > MAX_DESCRIPTION_SIZE) {
62 | content = content.slice(0, MAX_DESCRIPTION_SIZE).trim()+'...';
63 | }
64 | var $content = $('').html(content);
65 |
66 | $link.appendTo($title);
67 | $title.appendTo($li);
68 | $content.appendTo($li);
69 | $li.appendTo($searchList);
70 | });
71 | }
72 |
73 | function launchSearch(q) {
74 | // Add class for loading
75 | $body.addClass('with-search');
76 | $body.addClass('search-loading');
77 |
78 | // Launch search query
79 | throttle(gitbook.search.query(q, 0, MAX_RESULTS)
80 | .then(function(results) {
81 | displayResults(results);
82 | })
83 | .always(function() {
84 | $body.removeClass('search-loading');
85 | }), 1000);
86 | }
87 |
88 | function closeSearch() {
89 | $body.removeClass('with-search');
90 | $bookSearchResults.removeClass('open');
91 | }
92 |
93 | function launchSearchFromQueryString() {
94 | var q = getParameterByName('q');
95 | if (q && q.length > 0) {
96 | // Update search input
97 | $searchInput.val(q);
98 |
99 | // Launch search
100 | launchSearch(q);
101 | }
102 | }
103 |
104 | function bindSearch() {
105 | // Bind DOM
106 | $searchInput = $('#book-search-input input');
107 | $bookSearchResults = $('#book-search-results');
108 | $searchList = $bookSearchResults.find('.search-results-list');
109 | $searchTitle = $bookSearchResults.find('.search-results-title');
110 | $searchResultsCount = $searchTitle.find('.search-results-count');
111 | $searchQuery = $searchTitle.find('.search-query');
112 |
113 | // Launch query based on input content
114 | function handleUpdate() {
115 | var q = $searchInput.val();
116 |
117 | if (q.length == 0) {
118 | closeSearch();
119 | }
120 | else {
121 | launchSearch(q);
122 | }
123 | }
124 |
125 | // Detect true content change in search input
126 | // Workaround for IE < 9
127 | var propertyChangeUnbound = false;
128 | $searchInput.on('propertychange', function(e) {
129 | if (e.originalEvent.propertyName == 'value') {
130 | handleUpdate();
131 | }
132 | });
133 |
134 | // HTML5 (IE9 & others)
135 | $searchInput.on('input', function(e) {
136 | // Unbind propertychange event for IE9+
137 | if (!propertyChangeUnbound) {
138 | $(this).unbind('propertychange');
139 | propertyChangeUnbound = true;
140 | }
141 |
142 | handleUpdate();
143 | });
144 |
145 | // Push to history on blur
146 | $searchInput.on('blur', function(e) {
147 | // Update history state
148 | if (usePushState) {
149 | var uri = updateQueryString('q', $(this).val());
150 | history.pushState({ path: uri }, null, uri);
151 | }
152 | });
153 | }
154 |
155 | gitbook.events.on('page.change', function() {
156 | bindSearch();
157 | closeSearch();
158 |
159 | // Launch search based on query parameter
160 | if (gitbook.search.isInitialized()) {
161 | launchSearchFromQueryString();
162 | }
163 | });
164 |
165 | gitbook.events.on('search.ready', function() {
166 | bindSearch();
167 |
168 | // Launch search from query param at start
169 | launchSearchFromQueryString();
170 | });
171 |
172 | function getParameterByName(name) {
173 | var url = window.location.href;
174 | name = name.replace(/[\[\]]/g, '\\$&');
175 | var regex = new RegExp('[?&]' + name + '(=([^]*)|&|#|$)', 'i'),
176 | results = regex.exec(url);
177 | if (!results) return null;
178 | if (!results[2]) return '';
179 | return decodeURIComponent(results[2].replace(/\+/g, ' '));
180 | }
181 |
182 | function updateQueryString(key, value) {
183 | value = encodeURIComponent(value);
184 |
185 | var url = window.location.href;
186 | var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'),
187 | hash;
188 |
189 | if (re.test(url)) {
190 | if (typeof value !== 'undefined' && value !== null)
191 | return url.replace(re, '$1' + key + '=' + value + '$2$3');
192 | else {
193 | hash = url.split('#');
194 | url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
195 | if (typeof hash[1] !== 'undefined' && hash[1] !== null)
196 | url += '#' + hash[1];
197 | return url;
198 | }
199 | }
200 | else {
201 | if (typeof value !== 'undefined' && value !== null) {
202 | var separator = url.indexOf('?') !== -1 ? '&' : '?';
203 | hash = url.split('#');
204 | url = hash[0] + separator + key + '=' + value;
205 | if (typeof hash[1] !== 'undefined' && hash[1] !== null)
206 | url += '#' + hash[1];
207 | return url;
208 | }
209 | else
210 | return url;
211 | }
212 | }
213 | });
214 |
--------------------------------------------------------------------------------
/_book/gitbook/gitbook-plugin-fontsettings/fontsettings.js:
--------------------------------------------------------------------------------
1 | require(['gitbook', 'jquery'], function(gitbook, $) {
2 | // Configuration
3 | var MAX_SIZE = 4,
4 | MIN_SIZE = 0,
5 | BUTTON_ID;
6 |
7 | // Current fontsettings state
8 | var fontState;
9 |
10 | // Default themes
11 | var THEMES = [
12 | {
13 | config: 'white',
14 | text: 'White',
15 | id: 0
16 | },
17 | {
18 | config: 'sepia',
19 | text: 'Sepia',
20 | id: 1
21 | },
22 | {
23 | config: 'night',
24 | text: 'Night',
25 | id: 2
26 | }
27 | ];
28 |
29 | // Default font families
30 | var FAMILIES = [
31 | {
32 | config: 'serif',
33 | text: 'Serif',
34 | id: 0
35 | },
36 | {
37 | config: 'sans',
38 | text: 'Sans',
39 | id: 1
40 | }
41 | ];
42 |
43 | // Return configured themes
44 | function getThemes() {
45 | return THEMES;
46 | }
47 |
48 | // Modify configured themes
49 | function setThemes(themes) {
50 | THEMES = themes;
51 | updateButtons();
52 | }
53 |
54 | // Return configured font families
55 | function getFamilies() {
56 | return FAMILIES;
57 | }
58 |
59 | // Modify configured font families
60 | function setFamilies(families) {
61 | FAMILIES = families;
62 | updateButtons();
63 | }
64 |
65 | // Save current font settings
66 | function saveFontSettings() {
67 | gitbook.storage.set('fontState', fontState);
68 | update();
69 | }
70 |
71 | // Increase font size
72 | function enlargeFontSize(e) {
73 | e.preventDefault();
74 | if (fontState.size >= MAX_SIZE) return;
75 |
76 | fontState.size++;
77 | saveFontSettings();
78 | }
79 |
80 | // Decrease font size
81 | function reduceFontSize(e) {
82 | e.preventDefault();
83 | if (fontState.size <= MIN_SIZE) return;
84 |
85 | fontState.size--;
86 | saveFontSettings();
87 | }
88 |
89 | // Change font family
90 | function changeFontFamily(configName, e) {
91 | if (e && e instanceof Event) {
92 | e.preventDefault();
93 | }
94 |
95 | var familyId = getFontFamilyId(configName);
96 | fontState.family = familyId;
97 | saveFontSettings();
98 | }
99 |
100 | // Change type of color theme
101 | function changeColorTheme(configName, e) {
102 | if (e && e instanceof Event) {
103 | e.preventDefault();
104 | }
105 |
106 | var $book = gitbook.state.$book;
107 |
108 | // Remove currently applied color theme
109 | if (fontState.theme !== 0)
110 | $book.removeClass('color-theme-'+fontState.theme);
111 |
112 | // Set new color theme
113 | var themeId = getThemeId(configName);
114 | fontState.theme = themeId;
115 | if (fontState.theme !== 0)
116 | $book.addClass('color-theme-'+fontState.theme);
117 |
118 | saveFontSettings();
119 | }
120 |
121 | // Return the correct id for a font-family config key
122 | // Default to first font-family
123 | function getFontFamilyId(configName) {
124 | // Search for plugin configured font family
125 | var configFamily = $.grep(FAMILIES, function(family) {
126 | return family.config == configName;
127 | })[0];
128 | // Fallback to default font family
129 | return (!!configFamily)? configFamily.id : 0;
130 | }
131 |
132 | // Return the correct id for a theme config key
133 | // Default to first theme
134 | function getThemeId(configName) {
135 | // Search for plugin configured theme
136 | var configTheme = $.grep(THEMES, function(theme) {
137 | return theme.config == configName;
138 | })[0];
139 | // Fallback to default theme
140 | return (!!configTheme)? configTheme.id : 0;
141 | }
142 |
143 | function update() {
144 | var $book = gitbook.state.$book;
145 |
146 | $('.font-settings .font-family-list li').removeClass('active');
147 | $('.font-settings .font-family-list li:nth-child('+(fontState.family+1)+')').addClass('active');
148 |
149 | $book[0].className = $book[0].className.replace(/\bfont-\S+/g, '');
150 | $book.addClass('font-size-'+fontState.size);
151 | $book.addClass('font-family-'+fontState.family);
152 |
153 | if(fontState.theme !== 0) {
154 | $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, '');
155 | $book.addClass('color-theme-'+fontState.theme);
156 | }
157 | }
158 |
159 | function init(config) {
160 | // Search for plugin configured font family
161 | var configFamily = getFontFamilyId(config.family),
162 | configTheme = getThemeId(config.theme);
163 |
164 | // Instantiate font state object
165 | fontState = gitbook.storage.get('fontState', {
166 | size: config.size || 2,
167 | family: configFamily,
168 | theme: configTheme
169 | });
170 |
171 | update();
172 | }
173 |
174 | function updateButtons() {
175 | // Remove existing fontsettings buttons
176 | if (!!BUTTON_ID) {
177 | gitbook.toolbar.removeButton(BUTTON_ID);
178 | }
179 |
180 | // Create buttons in toolbar
181 | BUTTON_ID = gitbook.toolbar.createButton({
182 | icon: 'fa fa-font',
183 | label: 'Font Settings',
184 | className: 'font-settings',
185 | dropdown: [
186 | [
187 | {
188 | text: 'A',
189 | className: 'font-reduce',
190 | onClick: reduceFontSize
191 | },
192 | {
193 | text: 'A',
194 | className: 'font-enlarge',
195 | onClick: enlargeFontSize
196 | }
197 | ],
198 | $.map(FAMILIES, function(family) {
199 | family.onClick = function(e) {
200 | return changeFontFamily(family.config, e);
201 | };
202 |
203 | return family;
204 | }),
205 | $.map(THEMES, function(theme) {
206 | theme.onClick = function(e) {
207 | return changeColorTheme(theme.config, e);
208 | };
209 |
210 | return theme;
211 | })
212 | ]
213 | });
214 | }
215 |
216 | // Init configuration at start
217 | gitbook.events.bind('start', function(e, config) {
218 | var opts = config.fontsettings;
219 |
220 | // Generate buttons at start
221 | updateButtons();
222 |
223 | // Init current settings
224 | init(opts);
225 | });
226 |
227 | // Expose API
228 | gitbook.fontsettings = {
229 | enlargeFontSize: enlargeFontSize,
230 | reduceFontSize: reduceFontSize,
231 | setTheme: changeColorTheme,
232 | setFamily: changeFontFamily,
233 | getThemes: getThemes,
234 | setThemes: setThemes,
235 | getFamilies: getFamilies,
236 | setFamilies: setFamilies
237 | };
238 | });
239 |
240 |
241 |
--------------------------------------------------------------------------------
/ArchitectureComponents/DataBindingLibrary/数据(Data Binding)绑定库——使用可观察的数据对象.md:
--------------------------------------------------------------------------------
1 | # 数据(Data Binding)绑定库——使用可观察的数据对象
2 |
3 | 观察能力指的是当对象中的数据发生改变时,它能通知其他对象该更改的能力。数据绑定库允许你使对象、字段、集合编程可观察的。
4 |
5 | 任何普通旧对象( plain-old object )都可用于数据绑定,但修改对象不会自动导致UI更新。数据绑定可用于为数据对象提供在数据更改时通知其他对象(称为侦听器)的能力。有三种不同类型的可观察类:对象,字段和集合( [objects](https://developer.android.com/topic/libraries/data-binding/observability#observable_objects), [fields](https://developer.android.com/topic/libraries/data-binding/observability#observable_fields), [collections](https://developer.android.com/topic/libraries/data-binding/observability#observable_collections))。
6 |
7 | 当这些可观察的数据对象呗绑定到UI上并且数据对象发生改变,UI将会自动更新。
8 |
9 | ## 可观察的字段(fields)
10 |
11 | 一些需要的实现在创建实现(Implement)了 [`Observable`](https://developer.android.com/reference/android/databinding/Observable.html)接口的类时会被自动完成,如果你的类只有一些属性,这是不值得的。在这种情况下,您可以使用通用Observable类和以下基于原语的类来使字段可观察:
12 |
13 | - [`ObservableBoolean`](https://developer.android.com/reference/android/databinding/ObservableBoolean.html)
14 | - [`ObservableByte`](https://developer.android.com/reference/android/databinding/ObservableByte.html)
15 | - [`ObservableChar`](https://developer.android.com/reference/android/databinding/ObservableChar.html)
16 | - [`ObservableShort`](https://developer.android.com/reference/android/databinding/ObservableShort.html)
17 | - [`ObservableInt`](https://developer.android.com/reference/android/databinding/ObservableInt.html)
18 | - [`ObservableLong`](https://developer.android.com/reference/android/databinding/ObservableLong.html)
19 | - [`ObservableFloat`](https://developer.android.com/reference/android/databinding/ObservableFloat.html)
20 | - [`ObservableDouble`](https://developer.android.com/reference/android/databinding/ObservableDouble.html)
21 | - [`ObservableParcelable`](https://developer.android.com/reference/android/databinding/ObservableParcelable.html)
22 |
23 | 可观察字段个本身就含有单个可观察对象字段的可观察对象。原始版本在访问操作期间避免装箱和拆箱。要使用此机制,请在Java编程语言中创建public final属性或在Kotlin中创建只读属性,如以下示例所示:
24 |
25 | - kotlin
26 |
27 | - ```kotlin
28 | class User {
29 | val firstName = ObservableField()
30 | val lastName = ObservableField()
31 | val age = ObservableInt()
32 | }
33 | ```
34 |
35 | - java
36 |
37 | - ```java
38 | private static class User {
39 | public final ObservableField firstName = new ObservableField<>();
40 | public final ObservableField lastName = new ObservableField<>();
41 | public final ObservableInt age = new ObservableInt();
42 | }
43 | ```
44 |
45 | 要访问字段值,请使用get()和set()访问方法,如下所示:
46 |
47 | - kotlin
48 |
49 | ```kotlin
50 | user.firstName = "Google"
51 | val age = user.age
52 | ```
53 |
54 | - java
55 |
56 | ```java
57 | user.firstName.set("Google");
58 | int age = user.age.get();
59 | ```
60 |
61 | > 注意:Android Studio3.1及以上允许你使用LiveData对象替换可观察的字段,该做法为你的app带来了更多好处,想了解更多的信息,请参考[使用LiveData通知UI有关数据更改的信息](./数据(Data Binding)绑定库——将布局视图绑定到体系结构组件.md#use-livedata-to-notify-the-ui-about-data-changes)
62 |
63 | ## 可观察的集合(collections)
64 |
65 | 一些应用程序使用动态结构来保存数据。可观察集合(Observable collections)允许使用key访问这些结构,当键是引用类型(如String)时,[`ObservableArrayMap`](https://developer.android.com/reference/android/databinding/ObservableArrayMap.html)类很有用,如以下示例所示:
66 |
67 | - kotlin
68 |
69 | - ```kotlin
70 | ObservableArrayMap().apply {
71 | put("firstName", "Google")
72 | put("lastName", "Inc.")
73 | put("age", 17)
74 | }
75 | ```
76 |
77 | - java
78 |
79 | - ```java
80 | ObservableArrayMap user = new ObservableArrayMap<>();
81 | user.put("firstName", "Google");
82 | user.put("lastName", "Inc.");
83 | user.put("age", 17);
84 | ```
85 |
86 | 在layout文件中,map可以使用string类型的key被绑定:
87 |
88 | ```xml
89 |
90 |
91 |
92 |
93 | …
94 |
98 |
102 | ```
103 |
104 | [`ObservableArrayList`](https://developer.android.com/reference/android/databinding/ObservableArrayList.html)在key是integer类型的时候很有用,比如:
105 |
106 | - kotlin
107 |
108 | ```kotlin
109 | ObservableArrayList().apply {
110 | add("Google")
111 | add("Inc.")
112 | add(17)
113 | }
114 | ```
115 |
116 | - java
117 |
118 | ```java
119 | ObservableArrayList