Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

aui-node-debug.js 49KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220
  1. AUI.add('aui-node-base', function(A) {
  2. /**
  3. * aui-node-base A set of utility methods to the Node.
  4. *
  5. * @module aui-node
  6. * @submodule aui-node-base
  7. */
  8. var Lang = A.Lang,
  9. isArray = Lang.isArray,
  10. isFunction = Lang.isFunction,
  11. isObject = Lang.isObject,
  12. isString = Lang.isString,
  13. isUndefined = Lang.isUndefined,
  14. isValue = Lang.isValue,
  15. AArray = A.Array,
  16. Node = A.Node,
  17. NodeList = A.NodeList,
  18. getClassName = A.getClassName,
  19. getRegExp = A.DOM._getRegExp,
  20. prefix = Lang.String.prefix,
  21. CONFIG = A.config,
  22. DOC = CONFIG.doc,
  23. WIN = CONFIG.win,
  24. NODE_PROTO = Node.prototype,
  25. NODELIST_PROTO = NodeList.prototype,
  26. STR_EMPTY = '',
  27. ARRAY_EMPTY_STRINGS = [STR_EMPTY, STR_EMPTY],
  28. HELPER = 'helper',
  29. OFFSET = 'offset',
  30. CSS_HELPER_FORCE_OFFSET = getClassName(HELPER, 'force', OFFSET),
  31. CSS_HELPER_HIDDEN = getClassName(HELPER, 'hidden'),
  32. CSS_HELPER_UNSELECTABLE = getClassName(HELPER, 'unselectable'),
  33. CHILD_NODES = 'childNodes',
  34. CREATE_DOCUMENT_FRAGMENT = 'createDocumentFragment',
  35. INNER = 'inner',
  36. INNER_HTML = 'innerHTML',
  37. NEXT_SIBLING = 'nextSibling',
  38. NONE = 'none',
  39. OUTER = 'outer',
  40. PARENT_NODE = 'parentNode',
  41. REGION = 'region',
  42. SCRIPT = 'script',
  43. SUPPORT_CLONED_EVENTS = false,
  44. VALUE = 'value',
  45. MAP_BORDER = {
  46. b: 'borderBottomWidth',
  47. l: 'borderLeftWidth',
  48. r: 'borderRightWidth',
  49. t: 'borderTopWidth'
  50. },
  51. MAP_MARGIN = {
  52. b: 'marginBottom',
  53. l: 'marginLeft',
  54. r: 'marginRight',
  55. t: 'marginTop'
  56. },
  57. MAP_PADDING = {
  58. b: 'paddingBottom',
  59. l: 'paddingLeft',
  60. r: 'paddingRight',
  61. t: 'paddingTop'
  62. },
  63. prefixSelector = function(ns, id) {
  64. return '#' + prefix(ns, id);
  65. },
  66. formatSelectorNS = function(ns, selector) {
  67. return selector.replace(getRegExp('(#|\\[id=(\\\"|\\\'))(?!' + ns + ')', 'g'), '$1' + ns);
  68. };
  69. /*
  70. Parts of this file are used from jQuery (http://jquery.com)
  71. Dual-licensed under MIT/GPL
  72. */
  73. var div = DOC.createElement('div');
  74. div.style.display = 'none';
  75. div.innerHTML = ' <table></table>&nbsp;';
  76. if (div.attachEvent && div.fireEvent) {
  77. div.attachEvent(
  78. 'onclick',
  79. function(){
  80. SUPPORT_CLONED_EVENTS = true;
  81. div.detachEvent('onclick', arguments.callee);
  82. }
  83. );
  84. div.cloneNode(true).fireEvent('onclick');
  85. }
  86. var SUPPORT_OPTIONAL_TBODY = !div.getElementsByTagName('tbody').length;
  87. var REGEX_LEADING_WHITE_SPACE = /^\s+/,
  88. REGEX_IE8_ACTION = /=([^=\x27\x22>\s]+\/)>/g,
  89. REGEX_TAGNAME = /<([\w:]+)/;
  90. div = null;
  91. Node.cssId = prefixSelector;
  92. Node.formatSelectorNS = formatSelectorNS;
  93. /**
  94. * Augment the <a href="Node.html">YUI3 Node</a> with more util methods.
  95. *
  96. * Check the list of <a href="Node.html#methods">Methods</a> available for
  97. * AUI Node.
  98. *
  99. * @class A.Node
  100. * @constructor
  101. * @uses Node
  102. */
  103. A.mix(NODE_PROTO, {
  104. allNS: function(ns, selector) {
  105. var instance = this;
  106. return instance.all(formatSelectorNS(ns, selector));
  107. },
  108. /**
  109. * <p>Returns the current ancestors of the node element. If a selector is
  110. * specified, the ancestors are filtered to match the selector.</p>
  111. *
  112. * Example:
  113. *
  114. * <pre><code>
  115. * A.one('#nodeId').ancestors('div');
  116. * </code></pre>
  117. *
  118. * @method ancestors
  119. * @param {String} selector A selector to filter the ancestor elements against.
  120. * @return {NodeList}
  121. */
  122. ancestors: function(selector) {
  123. var instance = this;
  124. var ancestors = [];
  125. var currentEl = instance.getDOM();
  126. while (currentEl && currentEl.nodeType !== 9) {
  127. if (currentEl.nodeType === 1) {
  128. ancestors.push(currentEl);
  129. }
  130. currentEl = currentEl.parentNode;
  131. }
  132. var nodeList = new A.all(ancestors);
  133. if (selector) {
  134. nodeList = nodeList.filter(selector);
  135. }
  136. return nodeList;
  137. },
  138. /**
  139. * <p>Returns the current ancestors of the node element filtered by a className.
  140. * This is an optimized method for finding ancestors by a specific CSS class name.</p>
  141. *
  142. * Example:
  143. *
  144. * <pre><code>
  145. * A.one('#nodeId').ancestorsByClassName('aui-helper-hidden');
  146. * </code></pre>
  147. *
  148. * @method ancestors
  149. * @param {String} selector A selector to filter the ancestor elements against.
  150. * @return {NodeList}
  151. */
  152. ancestorsByClassName: function(className) {
  153. var instance = this;
  154. var ancestors = [];
  155. var cssRE = new RegExp('\\b' + className + '\\b');
  156. var currentEl = instance.getDOM();
  157. while (currentEl && currentEl.nodeType !== 9) {
  158. if (currentEl.nodeType === 1 && cssRE.test(currentEl.className)) {
  159. ancestors.push(currentEl);
  160. }
  161. currentEl = currentEl.parentNode;
  162. }
  163. return A.all(ancestors);
  164. },
  165. /**
  166. * <p>Insert the node instance to the end of the <code>selector</code>
  167. * element.</p>
  168. *
  169. * Example:
  170. *
  171. * <pre><code>var node = A.one('#nodeId');
  172. * // using another Node instance
  173. * var body = A.one('body');
  174. * node.appendTo(body);
  175. * // using a CSS selector
  176. * node.appendTo('#container');
  177. * </code></pre>
  178. *
  179. * @method appendTo
  180. * @chainable
  181. * @param {Node | String} selector A selector, element, HTML string, Node
  182. * @return {String}
  183. */
  184. appendTo: function(selector) {
  185. var instance = this;
  186. A.one(selector).append(instance);
  187. return instance;
  188. },
  189. /**
  190. * <p>Get or Set the value of an attribute for the first element in the
  191. * set of matched elements. If only the <code>name</code> is passed it
  192. * works as a getter.</p>
  193. *
  194. * Example:
  195. *
  196. * <pre><code>var node = A.one('#nodeId');
  197. * node.attr('title', 'Setting a new title attribute');
  198. * // Alert the value of the title attribute: 'Setting a new title attribute'
  199. * alert( node.attr('title') );
  200. * </code></pre>
  201. *
  202. * @method attr
  203. * @param {String} name The name of the attribute
  204. * @param {String} value The value of the attribute to be set. Optional.
  205. * @return {String}
  206. */
  207. attr: function(name, value) {
  208. var instance = this;
  209. if (!isUndefined(value)) {
  210. var el = instance.getDOM();
  211. if (name in el) {
  212. instance.set(name, value);
  213. }
  214. else {
  215. instance.setAttribute(name, value);
  216. }
  217. return instance;
  218. }
  219. else {
  220. if (isObject(name)) {
  221. for (var i in name) {
  222. instance.attr(i, name[i]);
  223. }
  224. return instance;
  225. }
  226. var currentValue = instance.get(name);
  227. if (!Lang.isValue(currentValue)) {
  228. currentValue = instance.getAttribute(name);
  229. }
  230. return currentValue;
  231. }
  232. },
  233. /**
  234. * Normalizes the behavior of cloning a node, which by default should not clone
  235. * the events that are attached to it.
  236. *
  237. * Example:
  238. *
  239. * <pre><code>var node = A.one('#nodeId');
  240. * node.clone().appendTo('body');
  241. * </code></pre>
  242. *
  243. * @method clone
  244. * @return {Node}
  245. */
  246. clone: (function() {
  247. var clone;
  248. if (SUPPORT_CLONED_EVENTS) {
  249. clone = function() {
  250. var el = this.getDOM();
  251. var clone;
  252. if (el.nodeType != 3) {
  253. var outerHTML = this.outerHTML();
  254. outerHTML = outerHTML.replace(REGEX_IE8_ACTION, '="$1">').replace(REGEX_LEADING_WHITE_SPACE, STR_EMPTY);
  255. clone = Node.create(outerHTML);
  256. }
  257. else {
  258. clone = A.one(el.cloneNode());
  259. }
  260. return clone;
  261. };
  262. }
  263. else {
  264. clone = function() {
  265. return this.cloneNode(true);
  266. };
  267. }
  268. return clone;
  269. })(),
  270. /**
  271. * <p>Centralize the current Node instance with the passed
  272. * <code>val</code> Array, Node, String, or Region, if not specified, the body will be
  273. * used.</p>
  274. *
  275. * Example:
  276. *
  277. * <pre><code>var node = A.one('#nodeId');
  278. * // Center the <code>node</code> with the <code>#container</code>.
  279. * node.center('#container');
  280. * </code></pre>
  281. *
  282. * @method center
  283. * @chainable
  284. * @param {Array | Node | Region | String} val Array, Node, String, or Region to center with
  285. */
  286. center: function(val) {
  287. var instance = this,
  288. nodeRegion = instance.get(REGION),
  289. x,
  290. y;
  291. if (isArray(val)) {
  292. x = val[0];
  293. y = val[1];
  294. }
  295. else {
  296. var region;
  297. if (isObject(val) && !A.instanceOf(val, A.Node)) {
  298. region = val;
  299. }
  300. else {
  301. region = (A.one(val) || A.getBody()).get(REGION);
  302. }
  303. x = region.left + (region.width / 2);
  304. y = region.top + (region.height / 2);
  305. }
  306. instance.setXY([x - (nodeRegion.width / 2), y - (nodeRegion.height / 2)]);
  307. },
  308. /**
  309. * <p>This method removes not only child (and other descendant) elements,
  310. * but also any text within the set of matched elements. This is because,
  311. * according to the DOM specification, any string of text within an element
  312. * is considered a child node of that element.</p>
  313. *
  314. * Example:
  315. *
  316. * <pre><code>var node = A.one('#nodeId');
  317. * node.empty();
  318. * </code></pre>
  319. *
  320. * @method empty
  321. * @chainable
  322. */
  323. empty: function() {
  324. var instance = this;
  325. instance.all('>*').remove().purge();
  326. var el = Node.getDOMNode(instance);
  327. while (el.firstChild) {
  328. el.removeChild(el.firstChild);
  329. }
  330. return instance;
  331. },
  332. /**
  333. * Retrieves the DOM node bound to a Node instance. See
  334. * <a href="Node.html#method_getDOMNode">getDOMNode</a>.
  335. *
  336. * @method getDOM
  337. * @return {HTMLNode} The DOM node bound to the Node instance.
  338. */
  339. getDOM: function() {
  340. var instance = this;
  341. return Node.getDOMNode(instance);
  342. },
  343. /**
  344. * Return the combined width of the border for the specified sides.
  345. *
  346. * @method getBorderWidth
  347. * @param {string} sides Can be t, r, b, l or any combination of
  348. * those to represent the top, right, bottom, or left sides.
  349. * @return {number}
  350. */
  351. getBorderWidth: function(sides) {
  352. var instance = this;
  353. return instance._getBoxStyleAsNumber(sides, MAP_BORDER);
  354. },
  355. /**
  356. * Gets the current center position of the node in page coordinates.
  357. * @method getCenterXY
  358. * @for Node
  359. * @return {Array} The XY position of the node
  360. */
  361. getCenterXY: function() {
  362. var instance = this;
  363. var region = instance.get(REGION);
  364. return [(region.left + region.width/2), (region.top + region.height/2)];
  365. },
  366. /**
  367. * Return the combined size of the margin for the specified sides.
  368. *
  369. * @method getMargin
  370. * @param {string} sides Can be t, r, b, l or any combination of
  371. * those to represent the top, right, bottom, or left sides.
  372. * @return {number}
  373. */
  374. getMargin: function(sides) {
  375. var instance = this;
  376. return instance._getBoxStyleAsNumber(sides, MAP_MARGIN);
  377. },
  378. /**
  379. * Return the combined width of the border for the specified sides.
  380. *
  381. * @method getPadding
  382. * @param {string} sides Can be t, r, b, l or any combination of
  383. * those to represent the top, right, bottom, or left sides.
  384. * @return {number}
  385. */
  386. getPadding: function(sides) {
  387. var instance = this;
  388. return instance._getBoxStyleAsNumber(sides, MAP_PADDING);
  389. },
  390. /**
  391. * Set the id of the Node instance if the object does not have one. The
  392. * generated id is based on a guid created by the
  393. * <a href="YUI.html#method_stamp">stamp</a> method.
  394. *
  395. * @method guid
  396. * @param {string} prefix optional guid prefix
  397. * @return {String} The current id of the node
  398. */
  399. guid: function(prefix) {
  400. var instance = this;
  401. var currentId = instance.get('id');
  402. if (!currentId) {
  403. currentId = A.stamp(instance);
  404. instance.set('id', currentId);
  405. }
  406. return currentId;
  407. },
  408. /**
  409. * Create a hover interaction.
  410. *
  411. * @method hover
  412. * @param {string} overFn
  413. * @param {string} outFn
  414. * @return {Node} The current Node instance
  415. */
  416. hover: function(overFn, outFn) {
  417. var instance = this;
  418. var hoverOptions;
  419. var defaultHoverOptions = instance._defaultHoverOptions;
  420. if (isObject(overFn, true)) {
  421. hoverOptions = overFn;
  422. hoverOptions = A.mix(hoverOptions, defaultHoverOptions);
  423. overFn = hoverOptions.over;
  424. outFn = hoverOptions.out;
  425. }
  426. else {
  427. hoverOptions = A.mix(
  428. {
  429. over: overFn,
  430. out: outFn
  431. },
  432. defaultHoverOptions
  433. );
  434. }
  435. instance._hoverOptions = hoverOptions;
  436. hoverOptions.overTask = A.debounce(instance._hoverOverTaskFn, null, instance);
  437. hoverOptions.outTask = A.debounce(instance._hoverOutTaskFn, null, instance);
  438. return new A.EventHandle(
  439. [
  440. instance.on(hoverOptions.overEventType, instance._hoverOverHandler, instance),
  441. instance.on(hoverOptions.outEventType, instance._hoverOutHandler, instance)
  442. ]
  443. );
  444. },
  445. /**
  446. * <p>Get or Set the HTML contents of the node. If the <code>value</code>
  447. * is passed it's set the content of the element, otherwise it works as a
  448. * getter for the current content.</p>
  449. *
  450. * Example:
  451. *
  452. * <pre><code>var node = A.one('#nodeId');
  453. * node.html('Setting new HTML');
  454. * // Alert the value of the current content
  455. * alert( node.html() );
  456. * </code></pre>
  457. *
  458. * @method html
  459. * @param {string} value A string of html to set as the content of the node instance.
  460. */
  461. html: function() {
  462. var args = arguments, length = args.length;
  463. if (length) {
  464. this.set(INNER_HTML, args[0]);
  465. }
  466. else {
  467. return this.get(INNER_HTML);
  468. }
  469. return this;
  470. },
  471. oneNS: function(ns, selector) {
  472. var instance = this;
  473. return instance.one(formatSelectorNS(ns, selector));
  474. },
  475. /**
  476. * Gets the outerHTML of a node, which islike innerHTML, except that it
  477. * actually contains the HTML of the node itself.
  478. *
  479. * @return {string} The outerHTML of the given element.
  480. */
  481. outerHTML: function() {
  482. var instance = this;
  483. var domEl = instance.getDOM();
  484. // IE, Opera and WebKit all have outerHTML.
  485. if ('outerHTML' in domEl) {
  486. return domEl.outerHTML;
  487. }
  488. var temp = Node.create('<div></div>').append(
  489. this.clone()
  490. );
  491. try {
  492. return temp.html();
  493. }
  494. catch(e) {}
  495. finally {
  496. temp = null;
  497. }
  498. },
  499. /**
  500. * <p>Inserts a <code>newNode</code> after the node instance (i.e., as the next
  501. * sibling). If the reference node has no parent, then does nothing.</p>
  502. *
  503. * Example:
  504. *
  505. * <pre><code>var titleNode = A.one('#titleNode');
  506. * var descriptionNode = A.one('#descriptionNode');
  507. * // the description is usually shown after the title
  508. * titleNode.placeAfter(descriptionNode);
  509. * </code></pre>
  510. *
  511. * @method placeAfter
  512. * @chainable
  513. * @param {Node} newNode Node to insert.
  514. */
  515. placeAfter: function(newNode) {
  516. var instance = this;
  517. return instance._place(newNode, instance.get(NEXT_SIBLING));
  518. },
  519. /**
  520. * <p>Inserts a <code>newNode</code> before the node instance (i.e., as the previous
  521. * sibling). If the reference node has no parent, then does nothing.</p>
  522. *
  523. * Example:
  524. *
  525. * <pre><code>var descriptionNode = A.one('#descriptionNode');
  526. * var titleNode = A.one('#titleNode');
  527. * // the title is usually shown before the description
  528. * descriptionNode.placeBefore(titleNode);
  529. * </code></pre>
  530. *
  531. * @method placeBefore
  532. * @chainable
  533. * @param {Node} newNode Node to insert.
  534. */
  535. placeBefore: function(newNode) {
  536. var instance = this;
  537. return instance._place(newNode, instance);
  538. },
  539. /**
  540. * <p>Inserts the node instance to the begining of the <code>selector</code>
  541. * node (i.e., insert before the <code>firstChild</code> of the
  542. * <code>selector</code>).</p>
  543. *
  544. * Example:
  545. *
  546. * <pre><code>var node = A.one('#nodeId');
  547. * node.prependTo('body');
  548. * </code></pre>
  549. *
  550. * @method prependTo
  551. * @chainable
  552. * @param {Node | String} selector A selector, element, HTML string, Node
  553. */
  554. prependTo: function(selector) {
  555. var instance = this;
  556. A.one(selector).prepend(instance);
  557. return instance;
  558. },
  559. /**
  560. * Add one or more CSS classes to an element and remove the class(es)
  561. * from the siblings of the element.
  562. *
  563. * @method radioClass
  564. * @chainable
  565. * @param {String} cssClass
  566. */
  567. radioClass: function(cssClass) {
  568. var instance = this;
  569. var siblings = instance.siblings();
  570. if (isString(cssClass)) {
  571. siblings.removeClass(cssClass);
  572. instance.addClass(cssClass);
  573. }
  574. else if (isArray(cssClass)) {
  575. var siblingNodes = siblings.getDOM();
  576. var regex = getRegExp('(?:^|\\s+)(?:' + cssClass.join('|') + ')(?=\\s+|$)', 'g');
  577. var node;
  578. for (var i = siblingNodes.length - 1; i >= 0; i--) {
  579. node = siblingNodes[i];
  580. node.className = node.className.replace(regex, '');
  581. }
  582. instance.addClass(cssClass.join(' '));
  583. }
  584. return instance;
  585. },
  586. /**
  587. * Generate an unique identifier and reset the id attribute of the node
  588. * instance using the new value. Invokes the
  589. * <a href="Node.html#method_guid">guid</a>.
  590. *
  591. * @method resetId
  592. * @chainable
  593. * @param {String} prefix Optional prefix for the guid.
  594. */
  595. resetId: function(prefix) {
  596. var instance = this;
  597. instance.attr('id', A.guid(prefix));
  598. return instance;
  599. },
  600. /**
  601. * Selects a substring of text inside of the input element.
  602. *
  603. * @method selectText
  604. * @param {Number} start The index to start the selection range from
  605. * @param {Number} end The index to end the selection range at
  606. */
  607. selectText: function(start, end) {
  608. var instance = this;
  609. var textField = instance.getDOM();
  610. var length = instance.val().length;
  611. end = isValue(end) ? end : length;
  612. start = isValue(start) ? start : 0;
  613. // Some form elements could throw a (NS_ERROR_FAILURE)
  614. // [nsIDOMNSHTMLInputElement.setSelectionRange] error when invoke the
  615. // setSelectionRange on firefox. Wrapping in a try/catch to prevent the error be thrown
  616. try {
  617. if (textField.setSelectionRange) {
  618. textField.setSelectionRange(start, end);
  619. }
  620. else if (textField.createTextRange) {
  621. var range = textField.createTextRange();
  622. range.moveStart('character', start);
  623. range.moveEnd('character', end - length);
  624. range.select();
  625. }
  626. else {
  627. textField.select();
  628. }
  629. if (textField != DOC.activeElement) {
  630. textField.focus();
  631. }
  632. }
  633. catch(e) {}
  634. return instance;
  635. },
  636. /**
  637. * Enables text selection for this element (normalized across browsers).
  638. *
  639. * @method selectable
  640. * @chainable
  641. */
  642. selectable: function() {
  643. var instance = this;
  644. instance.getDOM().unselectable = 'off';
  645. instance.detach('selectstart');
  646. instance.setStyles(
  647. {
  648. 'MozUserSelect': STR_EMPTY,
  649. 'KhtmlUserSelect': STR_EMPTY
  650. }
  651. );
  652. instance.removeClass(CSS_HELPER_UNSELECTABLE);
  653. return instance;
  654. },
  655. /**
  656. * <p>Stops the specified event(s) from bubbling and optionally prevents the
  657. * default action.</p>
  658. *
  659. * Example:
  660. *
  661. * <pre><code>var anchor = A.one('a#anchorId');
  662. * anchor.swallowEvent('click');
  663. * </code></pre>
  664. *
  665. * @method swallowEvent
  666. * @chainable
  667. * @param {String/Array} eventName an event or array of events to stop from bubbling
  668. * @param {Boolean} preventDefault (optional) true to prevent the default action too
  669. */
  670. swallowEvent: function(eventName, preventDefault) {
  671. var instance = this;
  672. var fn = function(event) {
  673. event.stopPropagation();
  674. if (preventDefault) {
  675. event.preventDefault();
  676. event.halt();
  677. }
  678. return false;
  679. };
  680. if(isArray(eventName)) {
  681. AArray.each(
  682. eventName,
  683. function(name) {
  684. instance.on(name, fn);
  685. }
  686. );
  687. return this;
  688. }
  689. else {
  690. instance.on(eventName, fn);
  691. }
  692. return instance;
  693. },
  694. /**
  695. * <p>Get or Set the combined text contents of the node instance,
  696. * including it's descendants. If the <code>text</code>
  697. * is passed it's set the content of the element, otherwise it works as a
  698. * getter for the current content.</p>
  699. *
  700. * Example:
  701. *
  702. * <pre><code>var node = A.one('#nodeId');
  703. * node.text('Setting new text content');
  704. * // Alert the value of the current content
  705. * alert( node.text() );
  706. * </code></pre>
  707. *
  708. * @method text
  709. * @param {String} text A string of text to set as the content of the node instance.
  710. */
  711. text: function(text) {
  712. var instance = this;
  713. var el = instance.getDOM();
  714. if (!isUndefined(text)) {
  715. text = A.DOM._getDoc(el).createTextNode(text);
  716. return instance.empty().append(text);
  717. }
  718. return instance._getText(el.childNodes);
  719. },
  720. /**
  721. * <p>Displays or hide the node instance.</p>
  722. *
  723. * <p><string>NOTE:</string> This method assume that your node were hidden
  724. * because of the 'aui-helper-hidden' css class were being used. This won't
  725. * manipulate the inline <code>style.display</code> property.</p>
  726. *
  727. * @method toggle
  728. * @chainable
  729. * @param {Boolean} on Whether to force the toggle. Optional.
  730. * @param {Function} callback A function to run after the visibility change. Optional.
  731. */
  732. toggle: function(on, callback) {
  733. var instance = this;
  734. instance._toggleView.apply(instance, arguments);
  735. return instance;
  736. },
  737. /**
  738. * Disables text selection for this element (normalized across browsers).
  739. *
  740. * @method unselectable
  741. * @chainable
  742. */
  743. unselectable: function() {
  744. var instance = this;
  745. instance.getDOM().unselectable = 'on';
  746. instance.swallowEvent('selectstart', true);
  747. instance.setStyles(
  748. {
  749. 'MozUserSelect': NONE,
  750. 'KhtmlUserSelect': NONE
  751. }
  752. );
  753. instance.addClass(CSS_HELPER_UNSELECTABLE);
  754. return instance;
  755. },
  756. /**
  757. * <p>Get or Set the value attribute of the node instance. If the
  758. * <code>value</code> is passed it's set the value of the element,
  759. * otherwise it works as a getter for the current value.</p>
  760. *
  761. * Example:
  762. *
  763. * <pre><code>var input = A.one('#inputId');
  764. * input.val('Setting new input value');
  765. * // Alert the value of the input
  766. * alert( input.val() );
  767. * </code></pre>
  768. *
  769. * @method val
  770. * @param {string} value Value to be set. Optional.
  771. */
  772. val: function(value) {
  773. var instance = this;
  774. if (isUndefined(value)) {
  775. return instance.get(VALUE);
  776. }
  777. else {
  778. return instance.set(VALUE, value);
  779. }
  780. },
  781. /**
  782. * Return the combined size of the box style for the specified sides.
  783. *
  784. * @method _getBoxStyleAsNumber
  785. * @param {string} sides Can be t, r, b, l or any combination of
  786. * those to represent the top, right, bottom, or left sides.
  787. * @param {string} map An object mapping mapping the "sides" param to the a CSS value to retrieve
  788. * @return {number}
  789. */
  790. _getBoxStyleAsNumber: function(sides, map) {
  791. var instance = this;
  792. var sidesArray = sides.match(/\w/g);
  793. var value = 0;
  794. var side;
  795. var sideKey;
  796. for (var i = sidesArray.length - 1; i >= 0; i--) {
  797. sideKey = sidesArray[i];
  798. side = 0;
  799. if (sideKey) {
  800. side = parseFloat(instance.getComputedStyle(map[sideKey]));
  801. side = Math.abs(side);
  802. value += side || 0;
  803. }
  804. }
  805. return value;
  806. },
  807. /**
  808. * Extract text content from the passed nodes.
  809. *
  810. * @method _getText
  811. * @private
  812. * @param {Native NodeList} childNodes
  813. */
  814. _getText: function(childNodes) {
  815. var instance = this;
  816. var length = childNodes.length;
  817. var childNode;
  818. var str = [];
  819. for (var i = 0; i < length; i++) {
  820. childNode = childNodes[i];
  821. if (childNode && childNode.nodeType != 8) {
  822. if (childNode.nodeType != 1) {
  823. str.push(childNode.nodeValue);
  824. }
  825. if (childNode.childNodes) {
  826. str.push(instance._getText(childNode.childNodes));
  827. }
  828. }
  829. }
  830. return str.join(STR_EMPTY);
  831. },
  832. /**
  833. * The event handler for the "out" function that is fired for events attached via the hover method.
  834. *
  835. * @method _hoverOutHandler
  836. * @private
  837. * @param {EventFacade} event
  838. */
  839. _hoverOutHandler: function(event) {
  840. var instance = this;
  841. var hoverOptions = instance._hoverOptions;
  842. hoverOptions.outTask.delay(hoverOptions.outDelay, event);
  843. },
  844. /**
  845. * The event handler for the "over" function that is fired for events attached via the hover method.
  846. *
  847. * @method _hoverOverHandler
  848. * @private
  849. * @param {EventFacade} event
  850. */
  851. _hoverOverHandler: function(event) {
  852. var instance = this;
  853. var hoverOptions = instance._hoverOptions;
  854. hoverOptions.overTask.delay(hoverOptions.overDelay, event);
  855. },
  856. /**
  857. * Cancels the over task, and fires the users custom "out" function for the hover method
  858. *
  859. * @method _hoverOverHandler
  860. * @private
  861. * @param {EventFacade} event
  862. */
  863. _hoverOutTaskFn: function(event) {
  864. var instance = this;
  865. var hoverOptions = instance._hoverOptions;
  866. hoverOptions.overTask.cancel();
  867. hoverOptions.out.apply(hoverOptions.context || event.currentTarget, arguments);
  868. },
  869. /**
  870. * Cancels the out task, and fires the users custom "over" function for the hover method
  871. *
  872. * @method _hoverOverHandler
  873. * @private
  874. * @param {EventFacade} event
  875. */
  876. _hoverOverTaskFn: function(event) {
  877. var instance = this;
  878. var hoverOptions = instance._hoverOptions;
  879. hoverOptions.outTask.cancel();
  880. hoverOptions.over.apply(hoverOptions.context || event.currentTarget, arguments);
  881. },
  882. /**
  883. * Place a node or html string at a specific location
  884. *
  885. * @method _place
  886. * @private
  887. * @param {Node|String} newNode
  888. * @param {Node} refNode
  889. */
  890. _place: function(newNode, refNode) {
  891. var instance = this;
  892. var parent = instance.get(PARENT_NODE);
  893. if (parent) {
  894. if (isString(newNode)) {
  895. newNode = Node.create(newNode);
  896. }
  897. parent.insertBefore(newNode, refNode);
  898. }
  899. return instance;
  900. },
  901. _defaultHoverOptions: {
  902. overEventType: 'mouseenter',
  903. outEventType: 'mouseleave',
  904. overDelay: 0,
  905. outDelay: 0,
  906. over: Lang.emptyFn,
  907. out: Lang.emptyFn
  908. }
  909. }, true);
  910. NODE_PROTO.__show = NODE_PROTO._show;
  911. NODE_PROTO.__hide = NODE_PROTO._hide;
  912. NODE_PROTO.__isHidden = NODE_PROTO._isHidden;
  913. NODE_PROTO._isHidden = function() {
  914. var instance = this;
  915. return NODE_PROTO.__isHidden.call(instance) || instance.hasClass(instance._hideClass || CSS_HELPER_HIDDEN);
  916. };
  917. /**
  918. * <p>Hide the node adding a css class on it. If <code>cssClass</code> is not
  919. * passed as argument, the className 'aui-helper-hidden' will be used by
  920. * default.</p>
  921. *
  922. * <p><string>NOTE:</string> This method assume that your node were visible
  923. * because the absence of 'aui-helper-hidden' css class. This won't
  924. * manipulate the inline <code>style.display</code> property.</p>
  925. *
  926. * @method hide
  927. * @chainable
  928. * @param {string} cssClass Class name to hide the element. Optional.
  929. */
  930. NODE_PROTO._hide = function() {
  931. var instance = this;
  932. instance.addClass(instance._hideClass || CSS_HELPER_HIDDEN);
  933. return instance;
  934. };
  935. /**
  936. * <p>Show the node removing a css class used to hide it. Use the same
  937. * className added using the <a href="A.Node.html#method_hide">hide</a>
  938. * method. If <code>cssClass</code> is not passed as argument, the
  939. * className 'aui-helper-hidden' will be used by default.</p>
  940. *
  941. * <p><string>NOTE:</string> This method assume that your node were hidden
  942. * because of the 'aui-helper-hidden' css class were being used. This won't
  943. * manipulate the inline <code>style.display</code> property.</p>
  944. *
  945. * @method show
  946. * @chainable
  947. * @param {string} cssClass Class name to hide the element. Optional.
  948. */
  949. NODE_PROTO._show = function() {
  950. var instance = this;
  951. instance.removeClass(instance._hideClass || CSS_HELPER_HIDDEN);
  952. return instance;
  953. };
  954. /**
  955. * Returns the width of the content, not including
  956. * the padding, border or margin. If a width is passed,
  957. * the node's overall width is set to that size.
  958. *
  959. * Example:
  960. *
  961. * <pre><code>var node = A.one('#nodeId');
  962. * node.width(); //returns content width
  963. * node.width(100); // sets box width
  964. * </code></pre>
  965. *
  966. * @method width
  967. * @return {number}
  968. */
  969. /**
  970. * Returns the height of the content, not including
  971. * the padding, border or margin. If a height is passed,
  972. * the node's overall height is set to that size.
  973. *
  974. * Example:
  975. *
  976. * <pre><code>var node = A.one('#nodeId');
  977. * node.height(); //returns content height
  978. * node.height(100); // sets box height
  979. * </code></pre>
  980. *
  981. * @method height
  982. * @return {number}
  983. */
  984. /**
  985. * Returns the size of the box from inside of the border,
  986. * which is the offsetWidth plus the padding on the left and right.
  987. *
  988. * Example:
  989. *
  990. * <pre><code>var node = A.one('#nodeId');
  991. * node.innerWidth();
  992. * </code></pre>
  993. *
  994. * @method innerWidth
  995. * @return {number}
  996. */
  997. /**
  998. * Returns the size of the box from inside of the border,
  999. * which is offsetHeight plus the padding on the top and bottom.
  1000. *
  1001. * Example:
  1002. *
  1003. * <pre><code>var node = A.one('#nodeId');
  1004. * node.innerHeight();
  1005. * </code></pre>
  1006. *
  1007. * @method innerHeight
  1008. * @return {number}
  1009. */
  1010. /**
  1011. * Returns the outer width of the box including the border,
  1012. * if true is passed as the first argument, the margin is included.
  1013. *
  1014. * Example:
  1015. *
  1016. * <pre><code>var node = A.one('#nodeId');
  1017. * node.outerWidth();
  1018. * node.outerWidth(true); // includes margin
  1019. * </code></pre>
  1020. *
  1021. * @method outerWidth
  1022. * @return {number}
  1023. */
  1024. /**
  1025. * Returns the outer height of the box including the border,
  1026. * if true is passed as the first argument, the margin is included.
  1027. *
  1028. * Example:
  1029. *
  1030. * <pre><code>var node = A.one('#nodeId');
  1031. * node.outerHeight();
  1032. * node.outerHeight(true); // includes margin
  1033. * </code></pre>
  1034. *
  1035. * @method outerHeight
  1036. * @return {number}
  1037. */
  1038. A.each(
  1039. ['Height', 'Width'],
  1040. function(item, index, collection) {
  1041. var sides = index ? 'lr' : 'tb';
  1042. var dimensionType = item.toLowerCase();
  1043. NODE_PROTO[dimensionType] = function(size) {
  1044. var instance = this;
  1045. var returnValue = instance;
  1046. if (isUndefined(size)) {
  1047. var node = instance._node;
  1048. var dimension;
  1049. if (node) {
  1050. if ((!node.tagName && node.nodeType === 9) || node.alert) {
  1051. dimension = instance.get(REGION)[dimensionType];
  1052. }
  1053. else {
  1054. dimension = instance.get(OFFSET + item);
  1055. var previous = {};
  1056. var styleObj = node.style;
  1057. if (!dimension) {
  1058. instance.addClass(CSS_HELPER_FORCE_OFFSET);
  1059. dimension = instance.get(OFFSET + item);
  1060. instance.removeClass(CSS_HELPER_FORCE_OFFSET);
  1061. }
  1062. if (dimension) {
  1063. dimension -= (instance.getPadding(sides) + instance.getBorderWidth(sides));
  1064. }
  1065. }
  1066. }
  1067. returnValue = dimension;
  1068. }
  1069. else {
  1070. instance.setStyle(dimensionType, size);
  1071. }
  1072. return returnValue;
  1073. };
  1074. NODE_PROTO[INNER + item] = function() {
  1075. var instance = this;
  1076. return instance[dimensionType]() + instance.getPadding(sides);
  1077. };
  1078. NODE_PROTO[OUTER + item] = function(margin) {
  1079. var instance = this;
  1080. var innerSize = instance[INNER + item]();
  1081. var borderSize = instance.getBorderWidth(sides);
  1082. var size = innerSize + borderSize;
  1083. if (margin) {
  1084. size += instance.getMargin(sides);
  1085. }
  1086. return size;
  1087. };
  1088. }
  1089. );
  1090. if (!SUPPORT_OPTIONAL_TBODY) {
  1091. A.DOM._ADD_HTML = A.DOM.addHTML;
  1092. A.DOM.addHTML = function(node, content, where) {
  1093. var nodeName = (node.nodeName && node.nodeName.toLowerCase()) || STR_EMPTY;
  1094. var tagName = STR_EMPTY;
  1095. if (!isUndefined(content)) {
  1096. if (isString(content)) {
  1097. tagName = (REGEX_TAGNAME.exec(content) || ARRAY_EMPTY_STRINGS)[1];
  1098. }
  1099. else if (content.nodeType && content.nodeType == 11 && content.childNodes.length) { // a doc frag
  1100. tagName = content.childNodes[0].nodeName;
  1101. }
  1102. else if (content.nodeName) { // a node
  1103. tagName = content.nodeName;
  1104. }
  1105. tagName = tagName && tagName.toLowerCase();
  1106. }
  1107. if (nodeName == 'table' && tagName == 'tr') {
  1108. node = node.getElementsByTagName('tbody')[0] || node.appendChild(node.ownerDocument.createElement('tbody'));
  1109. var whereNodeName = ((where && where.nodeName) || STR_EMPTY).toLowerCase();
  1110. // Assuming if the "where" is a tbody node,
  1111. // we're trying to prepend to a table. Attempt to
  1112. // grab the first child of the tbody.
  1113. if (whereNodeName == 'tbody' && where.childNodes.length > 0) {
  1114. where = where.firstChild;
  1115. }
  1116. }
  1117. return A.DOM._ADD_HTML(node, content, where);
  1118. };
  1119. }
  1120. /**
  1121. * Augment the <a href="NodeList.html">YUI3 NodeList</a> with more util methods.
  1122. *
  1123. * Check the list of <a href="NodeList.html#methods">Methods</a> available for
  1124. * AUI NodeList.
  1125. *
  1126. * @class A.NodeList
  1127. * @constructor
  1128. * @uses A.Node
  1129. */
  1130. NodeList.importMethod(
  1131. NODE_PROTO,
  1132. [
  1133. 'after',
  1134. 'appendTo',
  1135. 'attr',
  1136. 'before',
  1137. 'empty',
  1138. 'hover',
  1139. 'html',
  1140. 'innerHeight',
  1141. 'innerWidth',
  1142. 'outerHeight',
  1143. 'outerHTML',
  1144. 'outerWidth',
  1145. 'prepend',
  1146. 'prependTo',
  1147. 'purge',
  1148. 'selectText',
  1149. 'selectable',
  1150. 'text',
  1151. 'toggle',
  1152. 'unselectable',
  1153. 'val'
  1154. ]
  1155. );
  1156. A.mix(
  1157. NODELIST_PROTO,
  1158. {
  1159. /**
  1160. * See <a href="Node.html#method_all">Node all</a>.
  1161. *
  1162. * @method all
  1163. */
  1164. all: function(selector) {
  1165. var instance = this;
  1166. var newNodeList = [];
  1167. var nodes = instance._nodes;
  1168. var length = nodes.length;
  1169. var subList;
  1170. for (var i = 0; i < length; i++) {
  1171. subList = A.Selector.query(selector, nodes[i]);
  1172. if (subList && subList.length) {
  1173. newNodeList.push.apply(newNodeList, subList);
  1174. }
  1175. }
  1176. newNodeList = AArray.unique(newNodeList);
  1177. return A.all(newNodeList);
  1178. },
  1179. allNS: function(ns, selector) {
  1180. var instance = this;
  1181. return instance.all(formatSelectorNS(ns, selector));
  1182. },
  1183. /**
  1184. * Returns the first element in the node list collection.
  1185. *
  1186. * @method first
  1187. * @return {Node}
  1188. */
  1189. first: function() {
  1190. var instance = this;
  1191. return instance.item(0);
  1192. },
  1193. /**
  1194. * See <a href="Node.html#method_getDOM">Node getDOM</a>.
  1195. *
  1196. * @method getDOM
  1197. */
  1198. getDOM: function() {
  1199. var instance = this;
  1200. return NodeList.getDOMNodes(this);
  1201. },
  1202. /**
  1203. * Returns the last element in the node list collection.
  1204. *
  1205. * @method last
  1206. * @return {Node}
  1207. */
  1208. last: function() {
  1209. var instance = this;
  1210. return instance.item(instance._nodes.length - 1);
  1211. },
  1212. /**
  1213. * See <a href="Node.html#method_one">Node one</a>.
  1214. *
  1215. * @method one
  1216. */
  1217. one: function(selector) {
  1218. var instance = this;
  1219. var newNode = null;
  1220. var nodes = instance._nodes;
  1221. var length = nodes.length;
  1222. for (var i = 0; i < length; i++) {
  1223. newNode = A.Selector.query(selector, nodes[i], true);
  1224. if (newNode) {
  1225. newNode = A.one(newNode);
  1226. break;
  1227. }
  1228. }
  1229. return newNode;
  1230. },
  1231. oneNS: function(ns, selector) {
  1232. var instance = this;
  1233. return instance.one(formatSelectorNS(ns, selector));
  1234. }
  1235. }
  1236. );
  1237. NODELIST_PROTO.__filter = NODELIST_PROTO.filter;
  1238. NODELIST_PROTO.filter = function(value, context) {
  1239. var instance = this;
  1240. var newNodeList;
  1241. if (isFunction(value)) {
  1242. var nodes = [];
  1243. instance.each(
  1244. function(item, index, collection) {
  1245. if (value.call(context || item, item, index, collection)) {
  1246. nodes.push(item._node);
  1247. }
  1248. }
  1249. );
  1250. newNodeList = A.all(nodes);
  1251. }
  1252. else {
  1253. newNodeList = NODELIST_PROTO.__filter.call(instance, value);
  1254. }
  1255. return newNodeList;
  1256. };
  1257. A.mix(
  1258. NodeList,
  1259. {
  1260. create: function(html) {
  1261. var docFrag = A.getDoc().invoke(CREATE_DOCUMENT_FRAGMENT);
  1262. return docFrag.append(html).get(CHILD_NODES);
  1263. }
  1264. }
  1265. );
  1266. A.mix(
  1267. A,
  1268. {
  1269. /**
  1270. * Get the body node. Shortcut to <code>A.one('body')</code>.
  1271. *
  1272. * @method getBody
  1273. */
  1274. getBody: function() {
  1275. var instance = this;
  1276. if (!instance._bodyNode) {
  1277. instance._bodyNode = A.one(DOC.body);
  1278. }
  1279. return instance._bodyNode;
  1280. },
  1281. /**
  1282. * Get the document node. Shortcut to <code>A.one(document)</code>.
  1283. *
  1284. * @method getDoc
  1285. */
  1286. getDoc: function() {
  1287. var instance = this;
  1288. if (!instance._documentNode) {
  1289. instance._documentNode = A.one(DOC);
  1290. }
  1291. return instance._documentNode;
  1292. },
  1293. /**
  1294. * Get the window node. Shortcut to <code>A.one(window)</code>.
  1295. *
  1296. * @method getWin
  1297. */
  1298. getWin: function() {
  1299. var instance = this;
  1300. if (!instance._windowNode) {
  1301. instance._windowNode = A.one(WIN);
  1302. }
  1303. return instance._windowNode;
  1304. }
  1305. }
  1306. );
  1307. A.queryNS = function(ns, selector, methodName) {
  1308. return A[methodName || 'one'](formatSelectorNS(ns, selector));
  1309. };
  1310. A.oneNS = A.queryNS;
  1311. A.allNS = function(ns, selector) {
  1312. return A.queryNS(ns, selector, 'all');
  1313. }
  1314. A.byIdNS = function(ns, id) {
  1315. return A.one(prefixSelector(ns, id));
  1316. };
  1317. // Patch for http://yuilibrary.com/projects/yui3/ticket/2531537
  1318. var addMethod = NodeList.addMethod;
  1319. AArray.each(
  1320. ['hide', 'show'],
  1321. function(item, index, collection) {
  1322. addMethod(
  1323. item,
  1324. function() {
  1325. return this[item].apply(this, arguments);
  1326. }
  1327. );
  1328. }
  1329. );
  1330. }, '@VERSION@' ,{requires:['array-extras','aui-base-lang','aui-classnamemanager','node']});
  1331. AUI.add('aui-node-html5', function(A) {
  1332. /**
  1333. * aui-node-html5 provides support for HTML shiv natively on the Alloy dom
  1334. * methods. The HTML5 shiv just affects IE.
  1335. *
  1336. * @module aui-node
  1337. * @submodule aui-node-html5
  1338. */
  1339. if (A.UA.ie) {
  1340. /**
  1341. * <p>An object that encapsulates util methods for HTML5 shiving.</p>
  1342. * <h2>What is a "shiv"?</h1>
  1343. * <p>To the world, a shiv is a slang term for a sharp object used as a
  1344. * knife-like weapon. To Internet Explorer, a shiv is a script that, when
  1345. * executed, forces the browser to recognize HTML5 elements.</p>
  1346. *
  1347. * @class A.HTML5
  1348. */
  1349. var HTML5 = A.namespace('HTML5'),
  1350. DOM_create = A.DOM._create;
  1351. if (!HTML5._fragHTML5Shived) {
  1352. /**
  1353. * A global DocumentFragment already HTML5 shived, for performance
  1354. * reasons. (i.e., all nodes and its HTML5 children appended to this
  1355. * fragment iherits the styles on IE).
  1356. *
  1357. * @property A.HTML._fragHTML5Shived
  1358. * @type DocumentFragment (shived)
  1359. * @protected
  1360. */
  1361. HTML5._fragHTML5Shived = YUI.AUI.html5shiv(
  1362. A.config.doc.createDocumentFragment()
  1363. );
  1364. }
  1365. A.mix(
  1366. HTML5,
  1367. {
  1368. /**
  1369. * Receives a <code>frag</code> and a HTML content. This method
  1370. * shivs the HTML5 nodes appended to a Node or fragment which is not
  1371. * on the document yet.
  1372. *
  1373. * @method IECreateFix
  1374. * @param {Node | DocumentFragment} frag Fragment to be fixed.
  1375. * @param {String} content HTML to be set (using innerHTML) on the <code>frag</code>.
  1376. * @return {Node | DocumentFragment}
  1377. */
  1378. IECreateFix: function(frag, content) {
  1379. var shivedFrag = HTML5._fragHTML5Shived;
  1380. shivedFrag.appendChild(frag);
  1381. frag.innerHTML = content;
  1382. shivedFrag.removeChild(frag);
  1383. return frag;
  1384. },
  1385. /**
  1386. * AOP listener to the A.DOM._create method. This method
  1387. * intercepts all the calls to the A.DOM._create and append the
  1388. * generated fragment to <a
  1389. * href="A.HTML5.html#property_A.HTML._fragHTML5Shived">A.HTML._fragHTML5Shived</a>,
  1390. * this fixes the IE bug for painting the HTML5 nodes on the HTML
  1391. * fragment.
  1392. *
  1393. * @method _doBeforeCreate
  1394. * @param {String} html HTML content
  1395. * @param {String} doc
  1396. * @param {String} tag
  1397. * @protected
  1398. * @return {DocumentFragment}
  1399. */
  1400. _doBeforeCreate: function(html, doc, tag) {
  1401. var createdFrag = DOM_create.apply(this, arguments);
  1402. var shivedFrag = HTML5.IECreateFix(createdFrag, html);
  1403. return new A.Do.Halt(null, shivedFrag);
  1404. }
  1405. }
  1406. );
  1407. A.Do.before(HTML5._doBeforeCreate, A.DOM, '_create', A.DOM);
  1408. }
  1409. }, '@VERSION@' ,{requires:['collection','aui-base']});
  1410. AUI.add('aui-node-html5-print', function(A) {
  1411. var CONFIG = A.config,
  1412. DOC = CONFIG.doc,
  1413. WIN = CONFIG.win,
  1414. UA = A.UA,
  1415. IE = UA.ie,
  1416. isShivDisabled = function() {
  1417. return WIN.AUI_HTML5_IE === false;
  1418. };
  1419. if (!IE || IE >= 9 || isShivDisabled()) {
  1420. return;
  1421. }
  1422. var BUFFER_CSS_TEXT = [],
  1423. CSS_PRINTFIX = 'aui-printfix',
  1424. CSS_PRINTFIX_PREFIX = 'aui-printfix-',
  1425. LOCATION = WIN.location,
  1426. DOMAIN = LOCATION.protocol + '//' + LOCATION.host,
  1427. GLOBAL_AUI = YUI.AUI,
  1428. HTML = DOC.documentElement,
  1429. HTML5_ELEMENTS = GLOBAL_AUI.HTML5_ELEMENTS,
  1430. HTML5_ELEMENTS_LENGTH = HTML5_ELEMENTS.length,
  1431. HTML5_ELEMENTS_LIST = HTML5_ELEMENTS.join('|'),
  1432. REGEX_CLONE_NODE_CLEANUP = new RegExp('<(/?):(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
  1433. REGEX_ELEMENTS = new RegExp('(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
  1434. REGEX_ELEMENTS_FAST = new RegExp('\\b(' + HTML5_ELEMENTS_LIST + ')\\b', 'i'),
  1435. REGEX_PRINT_MEDIA = /print|all/,
  1436. REGEX_RULE = new RegExp('(^|[^\\n{}]*?\\s)(' + HTML5_ELEMENTS_LIST + ').*?{([^}]*)}', 'gim'),
  1437. REGEX_TAG = new RegExp('<(\/*)(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
  1438. SELECTOR_REPLACE_RULE = '.' + CSS_PRINTFIX_PREFIX + '$1',
  1439. STR_ALL = 'all',
  1440. STR_BLANK = ' ',
  1441. STR_EMPTY = '',
  1442. STR_BRACKET_OPEN = '{',
  1443. STR_BRACKET_CLOSE = '}',
  1444. STR_CHECKBOX = 'checkbox',
  1445. STR_CHECKED = 'checked',
  1446. STR_HTTPS = 'https',
  1447. STR_IFRAME = 'IFRAME',
  1448. STR_INPUT = 'INPUT',
  1449. STR_OPTION = 'OPTION',
  1450. STR_RADIO = 'radio',
  1451. STR_SELECTED = 'selected',
  1452. STR_STAR = '*',
  1453. STR_URL = 'url(',
  1454. STR_URL_DOMAIN = STR_URL + DOMAIN,
  1455. TAG_REPLACE_ORIGINAL = '<$1$2',
  1456. TAG_REPLACE_FONT = '<$1font';
  1457. var html5shiv = GLOBAL_AUI.html5shiv,
  1458. // Yes, IE does this wackiness; converting an object
  1459. // to a string should never result in undefined, but
  1460. // IE's styleSheet object sometimes becomes inaccessible
  1461. // after trying to print the second time
  1462. isStylesheetDefined = function(obj) {
  1463. return obj && (obj + STR_EMPTY !== undefined);
  1464. },
  1465. toggleNode = function(node, origNode, prop) {
  1466. var state = origNode[prop];
  1467. if (state) {
  1468. node.setAttribute(prop, state);
  1469. }
  1470. else {
  1471. node.removeAttribute(prop);
  1472. }
  1473. };
  1474. html5shiv(DOC);
  1475. var PrintFix = function() {
  1476. var afterPrint = function() {
  1477. if (isShivDisabled()) {
  1478. destroy();
  1479. }
  1480. else {
  1481. PrintFix.onAfterPrint();
  1482. }
  1483. };
  1484. var beforePrint = function() {
  1485. if (isShivDisabled()) {
  1486. destroy();
  1487. }
  1488. else {
  1489. PrintFix.onBeforePrint();
  1490. }
  1491. };
  1492. var destroy = function() {
  1493. WIN.detachEvent('onafterprint', afterPrint);
  1494. WIN.detachEvent('onbeforeprint', beforePrint);
  1495. };
  1496. var init = function() {
  1497. WIN.attachEvent('onafterprint', afterPrint);
  1498. WIN.attachEvent('onbeforeprint', beforePrint);
  1499. };
  1500. init();
  1501. PrintFix.destroy = destroy;
  1502. PrintFix.init = init;
  1503. };
  1504. A.mix(
  1505. PrintFix,
  1506. {
  1507. onAfterPrint: function() {
  1508. var instance = this;
  1509. instance.restoreHTML();
  1510. var styleSheet = instance._getStyleSheet();
  1511. styleSheet.styleSheet.cssText = STR_EMPTY;
  1512. },
  1513. onBeforePrint: function() {
  1514. var instance = this;
  1515. var styleSheet = instance._getStyleSheet();
  1516. var cssRules = instance._getAllCSSText();
  1517. styleSheet.styleSheet.cssText = instance.parseCSS(cssRules);
  1518. instance.writeHTML();
  1519. },
  1520. parseCSS: function(cssText) {
  1521. var instance = this;
  1522. var css = STR_EMPTY;
  1523. var rules = cssText.match(REGEX_RULE);
  1524. if (rules) {
  1525. css = rules.join('\n').replace(REGEX_ELEMENTS, SELECTOR_REPLACE_RULE);
  1526. }
  1527. return css;
  1528. },
  1529. restoreHTML: function() {
  1530. var instance = this;
  1531. var bodyClone = instance._getBodyClone();
  1532. var bodyEl = instance._getBodyEl();
  1533. var newNodes = bodyClone.getElementsByTagName(STR_IFRAME);
  1534. var originalNodes = bodyEl.getElementsByTagName(STR_IFRAME);
  1535. var length = originalNodes.length;
  1536. // Moving IFRAME nodes back to their original position
  1537. if (length == newNodes.length) {
  1538. while (length--) {
  1539. var newNode = newNodes[length];
  1540. var originalNode = originalNodes[length];
  1541. originalNode.swapNode(newNode);
  1542. }
  1543. }
  1544. bodyClone.innerHTML = STR_EMPTY;
  1545. HTML.removeChild(bodyClone);
  1546. HTML.appendChild(bodyEl);
  1547. },
  1548. writeHTML: function() {
  1549. var instance = this;
  1550. var i = -1;
  1551. var j;
  1552. var bodyEl = instance._getBodyEl();
  1553. var html5Element;
  1554. var cssClass;
  1555. var nodeList;
  1556. var nodeListLength;
  1557. var node;
  1558. var buffer = [];
  1559. while (++i < HTML5_ELEMENTS_LENGTH) {
  1560. html5Element = HTML5_ELEMENTS[i];
  1561. nodeList = DOC.getElementsByTagName(html5Element);
  1562. nodeListLength = nodeList.length;
  1563. j = -1;
  1564. while (++j < nodeListLength) {
  1565. node = nodeList[j];
  1566. cssClass = node.className;
  1567. if (cssClass.indexOf(CSS_PRINTFIX_PREFIX) == -1) {
  1568. buffer[0] = CSS_PRINTFIX_PREFIX + html5Element;
  1569. buffer[1] = cssClass;
  1570. node.className = buffer.join(STR_BLANK);
  1571. }
  1572. }
  1573. }
  1574. var docFrag = instance._getDocFrag();
  1575. var bodyClone = instance._getBodyClone();
  1576. docFrag.appendChild(bodyEl);
  1577. HTML.appendChild(bodyClone);
  1578. bodyClone.className = bodyEl.className;
  1579. bodyClone.id = bodyEl.id;
  1580. var originalNodes = bodyEl.getElementsByTagName(STR_STAR);
  1581. var length = originalNodes.length;
  1582. // IE will throw a mixed content warning when using https
  1583. // and calling clone node if the body contains elements with
  1584. // an inline background-image style that is relative to the domain.
  1585. if (UA.secure) {
  1586. var bodyElStyle = bodyEl.style;
  1587. var elStyle;
  1588. var backgroundImage;
  1589. bodyElStyle.display = 'none';
  1590. for (i = 0; i < length; i++) {
  1591. elStyle = originalNodes[i].style;
  1592. backgroundImage = elStyle.backgroundImage;
  1593. if (backgroundImage &&
  1594. backgroundImage.indexOf(STR_URL) > -1 &&
  1595. backgroundImage.indexOf(STR_HTTPS) == -1) {
  1596. elStyle.backgroundImage = backgroundImage.replace(STR_URL, STR_URL_DOMAIN);
  1597. }
  1598. }
  1599. bodyElStyle.display = STR_EMPTY;
  1600. }
  1601. var bodyElClone = bodyEl.cloneNode(true);
  1602. var newNodes = bodyElClone.getElementsByTagName(STR_STAR);
  1603. if (length == newNodes.length) {
  1604. while (length--) {
  1605. var newNode = newNodes[length];
  1606. var newNodeName = newNode.nodeName;
  1607. if (newNodeName == STR_INPUT || newNodeName == STR_OPTION || newNodeName == STR_IFRAME) {
  1608. var originalNode = originalNodes[length];
  1609. var originalNodeName = originalNode.nodeName;
  1610. if (originalNodeName == newNodeName) {
  1611. var prop = null;
  1612. if (newNodeName == STR_OPTION) {
  1613. prop = STR_SELECTED;
  1614. }
  1615. else if (newNodeName == STR_INPUT && (newNode.type == STR_CHECKBOX || newNode.type == STR_RADIO)) {
  1616. prop = STR_CHECKED;
  1617. }
  1618. else if (newNodeName == STR_IFRAME) {
  1619. newNode.src = STR_EMPTY;
  1620. }
  1621. if (prop !== null) {
  1622. toggleNode(newNode, originalNode, prop);
  1623. }
  1624. }
  1625. }
  1626. }
  1627. }
  1628. var bodyHTML = bodyElClone.innerHTML;
  1629. bodyHTML = bodyHTML.replace(REGEX_CLONE_NODE_CLEANUP, TAG_REPLACE_ORIGINAL).replace(REGEX_TAG, TAG_REPLACE_FONT);
  1630. bodyClone.innerHTML = bodyHTML;
  1631. // Post processing the DOM in order to move IFRAME nodes
  1632. newNodes = bodyClone.getElementsByTagName(STR_IFRAME);
  1633. originalNodes = bodyEl.getElementsByTagName(STR_IFRAME);
  1634. length = originalNodes.length;
  1635. if (length == newNodes.length) {
  1636. while (length--) {
  1637. var newNode = newNodes[length];
  1638. var originalNode = originalNodes[length];
  1639. // According to quirksmode.org, swapNode is supported on all major IE versions
  1640. originalNode.swapNode(newNode);
  1641. }
  1642. }
  1643. },
  1644. _getAllCSSText: function() {
  1645. var instance = this;
  1646. var buffer = [];
  1647. var styleSheets = instance._getAllStyleSheets(DOC.styleSheets, STR_ALL);
  1648. var rule;
  1649. var cssText;
  1650. for (var i = 0; styleSheet = styleSheets[i]; i++) {
  1651. var rules = styleSheet.rules;
  1652. if (rules && rules.length) {
  1653. for (var j = 0, ruleLength = rules.length; j < ruleLength; j++) {
  1654. rule = rules[j];
  1655. if (!rule.href) {
  1656. cssText = instance._getCSSTextFromRule(rule);
  1657. buffer.push(cssText);
  1658. }
  1659. }
  1660. }
  1661. }
  1662. return buffer.join(STR_BLANK);
  1663. },
  1664. _getCSSTextFromRule: function(rule) {
  1665. var instance = this;
  1666. var cssText = STR_EMPTY;
  1667. var ruleStyle = rule.style;
  1668. var ruleCSSText;
  1669. var ruleSelectorText;
  1670. if (ruleStyle && (ruleCSSText = ruleStyle.cssText) && (ruleSelectorText = rule.selectorText) && REGEX_ELEMENTS_FAST.test(ruleSelectorText)) {
  1671. BUFFER_CSS_TEXT.length = 0;
  1672. BUFFER_CSS_TEXT.push(ruleSelectorText, STR_BRACKET_OPEN, ruleCSSText, STR_BRACKET_CLOSE);
  1673. cssText = BUFFER_CSS_TEXT.join(STR_BLANK);
  1674. }
  1675. return cssText;
  1676. },
  1677. _getAllStyleSheets: function(styleSheet, mediaType, level, buffer) {
  1678. var instance = this;
  1679. level = level || 1;
  1680. buffer = buffer || [];
  1681. var i;
  1682. if (isStylesheetDefined(styleSheet)) {
  1683. var imports = styleSheet.imports;
  1684. mediaType = styleSheet.mediaType || mediaType;
  1685. if (REGEX_PRINT_MEDIA.test(mediaType)) {
  1686. var length;
  1687. // IE can crash when trying to access imports more than 3 levels deep
  1688. if (level <= 3 && isStylesheetDefined(imports) && imports.length) {
  1689. for (i = 0, length = imports.length; i < length; i++) {
  1690. instance._getAllStyleSheets(imports[i], mediaType, level + 1, buffer);
  1691. }
  1692. }
  1693. else if (styleSheet.length) {
  1694. for (i = 0, length = styleSheet.length; i < length; i++) {
  1695. instance._getAllStyleSheets(styleSheet[i], mediaType, level, buffer);
  1696. }
  1697. }
  1698. else {
  1699. var rules = styleSheet.rules;
  1700. var ruleStyleSheet;
  1701. if (rules && rules.length) {
  1702. for (i = 0, length = rules.length; i < length; i++) {
  1703. ruleStyleSheet = rules[i].styleSheet;
  1704. if (ruleStyleSheet) {
  1705. instance._getAllStyleSheets(ruleStyleSheet, mediaType, level, buffer);
  1706. }
  1707. }
  1708. }
  1709. }
  1710. if (!styleSheet.disabled && styleSheet.rules) {
  1711. buffer.push(styleSheet);
  1712. }
  1713. }
  1714. }
  1715. mediaType = STR_ALL;
  1716. return buffer;
  1717. },
  1718. _getBodyEl: function() {
  1719. var instance = this;
  1720. var bodyEl = instance._bodyEl;
  1721. if (!bodyEl) {
  1722. bodyEl = DOC.body;
  1723. instance._bodyEl = bodyEl;
  1724. }
  1725. return bodyEl;
  1726. },
  1727. _getBodyClone: function() {
  1728. var instance = this;
  1729. var bodyClone = instance._bodyClone;
  1730. if (!bodyClone) {
  1731. bodyClone = DOC.createElement('body');
  1732. instance._bodyClone = bodyClone;
  1733. }
  1734. return bodyClone;
  1735. },
  1736. _getDocFrag: function() {
  1737. var instance = this;
  1738. var docFrag = instance._docFrag;
  1739. if (!docFrag) {
  1740. docFrag = DOC.createDocumentFragment();
  1741. html5shiv(docFrag);
  1742. instance._docFrag = docFrag;
  1743. }
  1744. return docFrag;
  1745. },
  1746. _getStyleSheet: function() {
  1747. var instance = this;
  1748. var styleSheet = instance._styleSheet;
  1749. if (!styleSheet) {
  1750. styleSheet = DOC.createElement('style');
  1751. var head = DOC.documentElement.firstChild;
  1752. head.insertBefore(styleSheet, head.firstChild);
  1753. styleSheet.media = 'print';
  1754. styleSheet.className = CSS_PRINTFIX;
  1755. instance._styleSheet = styleSheet;
  1756. }
  1757. return styleSheet;
  1758. }
  1759. }
  1760. );
  1761. A.namespace('HTML5').PrintFix = PrintFix;
  1762. PrintFix();
  1763. }, '@VERSION@' ,{requires:['aui-node-html5']});
  1764. AUI.add('aui-node', function(A){}, '@VERSION@' ,{skinnable:false, use:['aui-node-base','aui-node-html5','aui-node-html5-print']});