PageSourceSearch

https://bitsbox.com/c123/c123.js

js bitsbox.com collected 2026-09-24 09:50:36 UTC 10,225 bytes, 351 lines download raw bytes

1//  Copyright: Copyright Scott Lininger.
2//  License: All Rights Reserved.
3
4/**
5 * @fileoverview  Provide the c123 namespace and general functions.
6 */
7
8
9
10/**
11 * Namespace where we'll hang everything off of. Note that at the end of this
12 * file we're making a number of things global.
13 * @namespace
14 */
15var c123 = c123 || {};
16
17
18/**
19 * Namespace where we'll store any localized strings.
20 * @namespace
21 */
22c123.strings = c123.strings || {};
23
24
25/**
26 * Maximum line width.
27 * @const
28 * @type {number}
29 */
30c123.MAX_LINE_WIDTH = 40;
31
32/**
33 * Minimum line width.
34 * @const
35 * @type {number}
36 */
37c123.MIN_LINE_WIDTH = 0;
38
39/**
40 * Default line width.
41 * @const
42 * @type {number}
43 */
44c123.INITIAL_LINE_WIDTH = 2;
45
46var LEFT = 'left';
47var DOWN = 'down';
48var RIGHT = 'right';
49var UP = 'up';
50var NORTH = 'north';
51var SOUTH = 'south';
52var EAST = 'east';
53var WEST = 'west';
54var CENTER = 'center';
55var NORTHEAST = 'northeast';
56var SOUTHEAST = 'southeast';
57var NORTHWEST = 'northwest';
58var SOUTHWEST = 'southwest';
59
60/**
61 * A list of valid fonts and their definitions.
62 */
63c123.fontList = {
64  'impact': 'Impact, Charcoal, sans-serif',
65  'palatino': '"Palatino Linotype", "Book Antiqua", Palatino, serif',
66  'tahoma': 'Tahoma, Geneva, sans-serif',
67  'roboto': 'roboto',
68  'sans': 'sans-serif',
69  'sans-serif': 'sans-serif',
70  'serif': 'serif',
71  'hand': 'cursive',
72  'mono': 'monospace',
73  'century': 'Century Gothic, sans-serif',
74  'lucida': '"Lucida Sans Unicode", "Lucida Grande", sans-serif',
75  'gadget': '"Arial Black", Gadget, sans-serif',
76  'times': '"Times New Roman", Times, serif',
77  'narrow': '"Arial Narrow", sans-serif',
78  'verdana': 'Verdana, Geneva, sans-serif',
79  'console': '"Lucida Console", Monaco, monospace',
80  'gill': '"Gill Sans", "Gill Sans MT", sans-serif',
81  'trebuchet': '"Trebuchet MS", Helvetica, sans-serif',
82  'courier': '"Courier New", Courier, monospace',
83  'arial': 'Arial, Helvetica, sans-serif',
84  'georgia': 'Georgia, Serif'
85};
86
87/**
88 * A collection of google fonts. This gets populated in the c123.Library
89 * constructor.
90 */
91c123.googleFonts = {};
92
93// TODO(jeff): Does this variable name make sense for up and down?
94var compassDirections = {'north': true, 'south': true, 'east': true,
95                         'west': true, 'northeast': true, 'southeast': true,
96                         'northwest': true, 'southwest': true, 'up': true,
97                         'down': true};
98
99
100
101/**
102 * Handy bind function.
103 * @param {Function} fn The function to be bound.
104 * @param {Object} selfObj The object to be bound as 'this'.
105 * @param {Array} var_args The arguments to be handed in to the bound function.
106 * @return {Function} The newly bound function.
107 */
108c123.bind = function(fn, selfObj, var_args) {
109  var boundArgs = fn.boundArgs_;
110  if (arguments.length > 2) {
111    var args = Array.prototype.slice.call(arguments, 2);
112    if (boundArgs) { args.unshift.apply(args, boundArgs); }
113    boundArgs = args;
114  }
115  selfObj = fn.boundSelf_ || selfObj;
116  fn = fn.boundFn_ || fn;
117  var newfn;
118  var context = selfObj || goog.global;
119  if (boundArgs) {
120    newfn = function() {
121      var args = Array.prototype.slice.call(arguments);
122      args.unshift.apply(args, boundArgs);
123      return fn.apply(context, args);
124    };
125  } else {
126    newfn = function() {
127      return fn.apply(context, arguments);
128    };
129  }
130  newfn.boundArgs_ = boundArgs;
131  newfn.boundSelf_ = selfObj;
132  newfn.boundFn_ = fn;
133  return newfn;
134};
135
136
137/**
138 * Handy inherits function. Here's what usage looks like.
139 *
140 * c123.Car = function(settings) {
141 *   this.fuel = 'gas';
142 *   this.wheels = 4;
143 * }
144 *
145 * c123.Tesla = function(settings) {
146 *   // Call the constructor code of the parent (optional).
147 *   c123.base(this, settings);
148 *   this.fuel = 'electric';
149 * }
150 * c123.inherits(c123.Tesla, c123.Car);
151 *
152 *
153 * @param {function} childCtor The child constructor.
154 * @param {function} parentCtor The parent constructor we want to inherit from.
155 */
156c123.inherits = function(childCtor, parentCtor) {
157  /**
158   * Temporary constructor for inherits.
159   */
160  function TempCtor() {
161  }
162  TempCtor.prototype = parentCtor.prototype;
163  childCtor.superClass_ = parentCtor.prototype;
164  childCtor.prototype = new TempCtor();
165  childCtor.prototype.constructor = childCtor;
166};
167
168
169/**
170 * Handy base function. Call from within the a constructor of child class and
171 * it'll run the code inside the parent's class constructor.
172 * See the c123.inherits function for an example.
173 * @param {Object} a The parent object.
174 * @param {Object} b The child object.
175 * @return {Object} The newly based object.
176 */
177c123.base = function(a, b) {
178  var c = arguments.callee.caller;
179  if (c.superClass_) {
180    return c.superClass_.constructor.apply(
181      a, Array.prototype.slice.call(arguments, 1));
182  }
183  for (var d = Array.prototype.slice.call(arguments, 2), e = false,
184      f = a.constructor;f;f = f.superClass_ && f.superClass_.constructor) {
185    if (f.prototype[b] === c) {
186      e = true;
187    } else if (e) {
188      return f.prototype[b].apply(a, d);
189    }
190  }
191  if (a[b] === c) {
192    return a.constructor.prototype[b].apply(a, d);
193  }
194  throw Error('c123.base called from a method of one name ' +
195              'to a method of a different name.');
196};
197
198/**
199 * Detects if the user's browser is IE of any kind, but not Edge.
200 * @param {string} opt_userAgent An optional user agent string. Useful for
201 *     unit testing.
202 * @return {Boolean} True if the user's browser is IE.
203 */
204c123.isIE = function(opt_userAgent) {
205  var userAgent = opt_userAgent || navigator.userAgent;
206  return userAgent.indexOf('MSIE ') > -1 ||
207         userAgent.indexOf('Trident') > -1;
208};
209
210/**
211 * Detects if the user's browser is MS Edge of any kind.
212 * @param {string} opt_userAgent An optional user agent string. Useful for
213 *     unit testing.
214 * @return {Boolean} True if the user's browser is MS Edge.
215 */
216c123.isEdge = function(opt_userAgent) {
217  var userAgent = opt_userAgent || navigator.userAgent;
218  return userAgent.indexOf('Edge') > -1;
219};
220
221
222/**
223 * Detects if the user's browser is netscape/firefox of any kind.
224 * @param {string} opt_userAgent An optional user agent string. Useful for
225 *     unit testing.
226 * @return {Boolean} True if the user's browser is firefox.
227 */
228c123.isFirefox = function(opt_userAgent) {
229  var userAgent = opt_userAgent || navigator.userAgent;
230  return userAgent.toLowerCase().indexOf('firefox') > -1;
231};
232
233
234/**
235 * Returns whether the code is able to access the top frame.
236 * @return {string} path The datastore path.
237 */
238c123.canAccessTopFrame = function() {
239  try {
240    // This code will fail if we try to access a top frame that doesn't match
241    // the domain the library is running within.
242    var topDocument = top.document;
243    if (topDocument) {
244      return true;
245    } else {
246      return false;
247    }
248  } catch(e) {
249    return false;
250  }
251};
252
253/**
254 * Returns true if the query string has offline=1 somewhere inside it.
255 * @return {boolean} Whether we're in offline mode.
256 */
257c123.isOfflineMode = function() {
258  return ('' + top.location.href).indexOf('offline=1') > -1;
259};
260
261
262/**
263 * Gets a query parameter value based on the variable name.
264 * @param {string} name The parameter's name.
265 * @return {string} The value, or undefined if there's no variable of that name.
266 */
267c123.getQueryParameter = function(name) {
268  var queryString = window.location.search.substr(1);
269  var parts = queryString.split('&');
270  for (var i = 0; i < parts.length; i++) {
271    var tuple = parts[i].split('=');
272    if (tuple[0] === name && tuple.length > 1) {
273      return decodeURIComponent(tuple[1]);
274    }
275  }
276  return undefined;
277};
278
279
280/**
281 * Stores the current language code, as passed on the query string as hl=.
282 * @return {string} The current language code, or 'en' if none is set.
283 */
284c123.language = (c123.getQueryParameter('hl') || 'en').toLowerCase();
285
286
287/**
288 * If a language code was passed in, load the appropriate API aliases.
289 */
290if (c123.language !== 'en' && codepops.createScriptTag) {
291  var base = 'l10n/' + c123.language + '/' + c123.language;
292  
293  codepops.createScriptTag({'src': base + '_colors.js', async: true});
294  codepops.createScriptTag({'src': base + '_fills.js', async: true});
295  codepops.createScriptTag({'src': base + '_songs.js', async: true});
296  codepops.createScriptTag({'src': base + '_sounds.js', async: true});
297  codepops.createScriptTag({'src': base + '_stamps.js', async: true});
298  codepops.createScriptTag({'src': base + '_ui.js', async: true});
299  codepops.createScriptTag({'src': base + '_library-1.3.js', async: true});
300}
301
302
303/**
304 * Make the Array forEach method be a bit more case insensitive.
305 */
306Array.prototype.foreach = Array.prototype.forEach;
307
308
309/**
310 * Checks if a font is available to be used on a web page.
311 * @param {String} fontName The font to check.
312 * @return {Boolean} Whether the font is available.
313 * @license MIT
314 * @copyright Sam Clarke 2013
315 * @author Sam Clarke <[email protected]>
316 * 
317 * See: https://www.samclarke.com/javascript-is-font-available/
318 */
319c123.isFontAvailable = function(fontName) {
320  var width;
321  var body = document.body;
322
323  var container = document.createElement('span');
324  container.innerHTML = Array(100).join('wi');
325  container.style.cssText = [
326    'position:absolute',
327    'width:auto',
328    'font-size:128px',
329    'left:-99999px'
330  ].join(' !important;');
331
332  var getWidth = function (fontFamily) {
333    container.style.fontFamily = fontFamily;
334
335    body.appendChild(container);
336    width = container.clientWidth;
337    body.removeChild(container);
338
339    return width;
340  };
341
342  // Pre compute the widths of monospace, serif & sans-serif
343  // to improve performance.
344  var monoWidth  = getWidth('monospace');
345  var serifWidth = getWidth('serif');
346  var sansWidth  = getWidth('sans-serif');
347  
348  return monoWidth !== getWidth(fontName + ',monospace') ||
349    sansWidth !== getWidth(fontName + ',sans-serif') ||
350    serifWidth !== getWidth(fontName + ',serif');
351};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.